わかりましたので、再帰関数を使用して 1 枚の地形をランダムに生成し、与えられた 4 つのポイントを分割する小さなプログラムを開発しています。地形はクワッドで構成されています。各再帰で見つかった中心点にはランダムな高さの値が与えられ、すべての頂点が配列に保存され、描画時にループされます。
もともと、スタックに頂点を格納するために使用する 2D 配列を定義していましたが、細分化の数によっては、これが非常に大きくなる可能性があります。たとえば、深度が 3 の場合、256 個の頂点が生成されます。そこで、この配列を可能な限りヒープ上に定義することで、より大きな地形のシートに対してより効率的になることにしました。Terrain クラスでは、次の float ポインターの配列を定義します。
float* vertices[];
次に、このクラスのコンストラクターで、ヒープ上のサイズを初期化するために次のことを行います。4 を与えられたサブディビジョンの数に 1 を乗じると、256 となり、作成される頂点の数になります。
int vertexCount = pow(4.0, subdivisions+1);
*vertices = new float[vertexCount];
次に、これらの各ポインターは、次のように定義されたヒープ内の float 値の配列を指します。
for(int i = 0; i<vertexCount + 1; i++)
{
float* temp = new float[3];
vertices[i] = temp;
delete temp;
temp = 0;
}
地形を作成するために使用される再帰関数は次のようになります。
void Terrain::Subdivide(float* a, float* b, float* c, float* d, int subdivisions, float maxHeight)
{
if(subdivisions>0)
{
float e[3];
float f[3];
float g[3];
float h[3];
float centre[3];
int i = 0;
srand(time(NULL));
for(i = 0; i<3; i++) if(i!= 1) e[i] = (a[i]+b[i])/2;
for(i = 0; i<3; i++) if(i!= 1) f[i] = (b[i]+c[i])/2;
for(i = 0; i<3; i++) if(i!= 1) g[i] = (c[i]+d[i])/2;
for(i = 0; i<3; i++) if(i!= 1) h[i] = (d[i]+a[i])/2;
centre[0] = (h[0]+f[0])/2;
centre[2] = (e[2]+g[2])/2;
e[1] = 0;
f[1] = 0;
g[1] = 0;
h[1] = 0;
centre[1] = (float)rand()/((float)RAND_MAX/maxHeight);
Subdivide(a, e, centre, h, subdivisions-1 , maxHeight);
Subdivide(e, b, f, centre, subdivisions-1, maxHeight);
Subdivide(centre, f, c, g, subdivisions-1, maxHeight);
Subdivide(h, centre, g, d, subdivisions-1, maxHeight);
}
else
{
int i = 0;
for(i = 0; i<3; i++) {vertices[vertexCounter][i] = a[i];} vertexCounter++;
for(i = 0; i<3; i++) {vertices[vertexCounter][i] = b[i];} vertexCounter++;
for(i = 0; i<3; i++) {vertices[vertexCounter][i] = c[i];} vertexCounter++;
for(i = 0; i<3; i++) {vertices[vertexCounter][i] = d[i];} vertexCounter++;
}
}
このコードは、頂点をスタック上の 2D 配列として定義するだけで動作するように見えますが (他の場所でいくつかの変更を加えています)、このコードは、メイン関数で glutInit を呼び出すときに、次の行の Glut.h で未処理の例外を生成します: (行486)
static void APIENTRY glutInit_ATEXIT_HACK(int *argcp, char **argv) { __glutInitWithExit(argcp, argv, exit); }
私は何度もコードを調べましたが、どこに問題があるのか わかりません.TerrainクラスではなくGlut.hから例外をスローする必要があることはさらに奇妙です. 誰かがここで何か間違ったことを見ることができますか?