void TerrainData::init(udword s, float o, float w, float c, bool flat, const Point* pos) { release(); size = s; offset = o; width = w; chaos = c; nbVerts = size*size; nbFaces = (size-1)*(size-1)*2; //////// // Initialize terrain vertices verts = new Point[nbVerts]; for(udword y=0;y<size;y++) { for(udword x=0;x<size;x++) { verts[x+y*size] = Point(float(x)-(float(size-1)*0.5f), 0.0f, float(y)-(float(size-1)*0.5f)) * width; } } // Initialize terrain colors { colors = new Point[nbVerts]; for(udword y=0;y<size;y++) { for(udword x=0;x<size;x++) { colors[x+y*size] = Point(0.5f, 0.4f, 0.2f); } } } // Initialize terrain faces faces = new udword[nbFaces*3]; udword k = 0; for(udword j=0;j<size-1;j++) { for(udword i=0;i<size-1;i++) { // Create first triangle faces[k++] = i + j*size; faces[k++] = i + (j+1)*size; faces[k++] = i+1 + (j+1)*size; // Create second triangle faces[k++] = i + j*size; faces[k++] = i+1 + (j+1)*size; faces[k++] = i+1 + j*size; } } struct Local { static void _Compute(bool* done, Point* field, udword x0, udword y0, udword currentSize, float value, udword initSize) { // Compute new size currentSize>>=1; if(!currentSize) return; // Compute new heights float v0 = (value * float(rand()-RAND_MAX_OVER_TWO) * ONE_OVER_RAND_MAX); float v1 = (value * float(rand()-RAND_MAX_OVER_TWO) * ONE_OVER_RAND_MAX); float v2 = (value * float(rand()-RAND_MAX_OVER_TWO) * ONE_OVER_RAND_MAX); float v3 = (value * float(rand()-RAND_MAX_OVER_TWO) * ONE_OVER_RAND_MAX); float v4 = (value * float(rand()-RAND_MAX_OVER_TWO) * ONE_OVER_RAND_MAX); udword x1 = (x0+currentSize) % initSize; udword x2 = (x0+currentSize+currentSize) % initSize; udword y1 = (y0+currentSize) % initSize; udword y2 = (y0+currentSize+currentSize) % initSize; if(!done[x1 + y0*initSize]) field[x1 + y0*initSize].y = v0 + 0.5f * (field[x0 + y0*initSize].y + field[x2 + y0*initSize].y); if(!done[x0 + y1*initSize]) field[x0 + y1*initSize].y = v1 + 0.5f * (field[x0 + y0*initSize].y + field[x0 + y2*initSize].y); if(!done[x2 + y1*initSize]) field[x2 + y1*initSize].y = v2 + 0.5f * (field[x2 + y0*initSize].y + field[x2 + y2*initSize].y); if(!done[x1 + y2*initSize]) field[x1 + y2*initSize].y = v3 + 0.5f * (field[x0 + y2*initSize].y + field[x2 + y2*initSize].y); if(!done[x1 + y1*initSize]) field[x1 + y1*initSize].y = v4 + 0.5f * (field[x0 + y1*initSize].y + field[x2 + y1*initSize].y); done[x1 + y0*initSize] = true; done[x0 + y1*initSize] = true; done[x2 + y1*initSize] = true; done[x1 + y2*initSize] = true; done[x1 + y1*initSize] = true; // Recurse through 4 corners value *= 0.5f; _Compute(done, field, x0, y0, currentSize, value, initSize); _Compute(done, field, x0, y1, currentSize, value, initSize); _Compute(done, field, x1, y0, currentSize, value, initSize); _Compute(done, field, x1, y1, currentSize, value, initSize); } };
void TerrainData::init(NxU32 s, NxF32 o, NxF32 w, NxF32 c, bool flat, const NxVec3* pos) { release(); size = s; offset = o; width = w; chaos = c; nbVerts = size*size; nbFaces = (size-1)*(size-1)*2; //////// // Initialize terrain vertices verts = new NxVec3[nbVerts]; for(NxU32 y=0;y<size;y++) { for(NxU32 x=0;x<size;x++) { verts[x+y*size] = NxVec3(NxF32(x)-(NxF32(size-1)*0.5f), 0.0f, NxF32(y)-(NxF32(size-1)*0.5f)) * width; } } // Initialize terrain colors { colors = new NxVec3[nbVerts]; for(NxU32 y=0;y<size;y++) { for(NxU32 x=0;x<size;x++) { colors[x+y*size] = NxVec3(0.5f, 0.4f, 0.2f); } } } // Initialize terrain faces faces = new NxU32[nbFaces*3]; NxU32 k = 0; for(NxU32 j=0;j<size-1;j++) { for(NxU32 i=0;i<size-1;i++) { // Create first triangle faces[k++] = i + j*size; faces[k++] = i + (j+1)*size; faces[k++] = i+1 + (j+1)*size; // Create second triangle faces[k++] = i + j*size; faces[k++] = i+1 + (j+1)*size; faces[k++] = i+1 + j*size; } } struct Local { static void _Compute(bool* done, NxVec3* field, NxU32 x0, NxU32 y0, NxU32 currentSize, NxF32 value, NxU32 initSize) { // Compute new size currentSize>>=1; if(!currentSize) return; // Compute new heights NxF32 v0 = (value * NxF32(rand()-RAND_MAX_OVER_TWO) * ONE_OVER_RAND_MAX); NxF32 v1 = (value * NxF32(rand()-RAND_MAX_OVER_TWO) * ONE_OVER_RAND_MAX); NxF32 v2 = (value * NxF32(rand()-RAND_MAX_OVER_TWO) * ONE_OVER_RAND_MAX); NxF32 v3 = (value * NxF32(rand()-RAND_MAX_OVER_TWO) * ONE_OVER_RAND_MAX); NxF32 v4 = (value * NxF32(rand()-RAND_MAX_OVER_TWO) * ONE_OVER_RAND_MAX); NxU32 x1 = (x0+currentSize) % initSize; NxU32 x2 = (x0+currentSize+currentSize) % initSize; NxU32 y1 = (y0+currentSize) % initSize; NxU32 y2 = (y0+currentSize+currentSize) % initSize; if(!done[x1 + y0*initSize]) field[x1 + y0*initSize].y = v0 + 0.5f * (field[x0 + y0*initSize].y + field[x2 + y0*initSize].y); if(!done[x0 + y1*initSize]) field[x0 + y1*initSize].y = v1 + 0.5f * (field[x0 + y0*initSize].y + field[x0 + y2*initSize].y); if(!done[x2 + y1*initSize]) field[x2 + y1*initSize].y = v2 + 0.5f * (field[x2 + y0*initSize].y + field[x2 + y2*initSize].y); if(!done[x1 + y2*initSize]) field[x1 + y2*initSize].y = v3 + 0.5f * (field[x0 + y2*initSize].y + field[x2 + y2*initSize].y); if(!done[x1 + y1*initSize]) field[x1 + y1*initSize].y = v4 + 0.5f * (field[x0 + y1*initSize].y + field[x2 + y1*initSize].y); done[x1 + y0*initSize] = true; done[x0 + y1*initSize] = true; done[x2 + y1*initSize] = true; done[x1 + y2*initSize] = true; done[x1 + y1*initSize] = true; // Recurse through 4 corners value *= 0.5f; _Compute(done, field, x0, y0, currentSize, value, initSize); _Compute(done, field, x0, y1, currentSize, value, initSize); _Compute(done, field, x1, y0, currentSize, value, initSize); _Compute(done, field, x1, y1, currentSize, value, initSize); } };