void cNoise3DGenerator::GenerateNoiseArray(int a_ChunkX, int a_ChunkZ, NOISE_DATATYPE * a_OutNoise) { NOISE_DATATYPE NoiseO[DIM_X * DIM_Y * DIM_Z]; // Output for the Perlin noise NOISE_DATATYPE NoiseW[DIM_X * DIM_Y * DIM_Z]; // Workspace that the noise calculation can use and trash // Our noise array has different layout, XZY, instead of regular chunk's XYZ, that's why the coords are "renamed" NOISE_DATATYPE StartX = ((NOISE_DATATYPE)(a_ChunkX * cChunkDef::Width)) / m_FrequencyX; NOISE_DATATYPE EndX = ((NOISE_DATATYPE)((a_ChunkX + 1) * cChunkDef::Width)) / m_FrequencyX; NOISE_DATATYPE StartZ = ((NOISE_DATATYPE)(a_ChunkZ * cChunkDef::Width)) / m_FrequencyZ; NOISE_DATATYPE EndZ = ((NOISE_DATATYPE)((a_ChunkZ + 1) * cChunkDef::Width)) / m_FrequencyZ; NOISE_DATATYPE StartY = 0; NOISE_DATATYPE EndY = ((NOISE_DATATYPE)256) / m_FrequencyY; m_Perlin.Generate3D(NoiseO, DIM_X, DIM_Y, DIM_Z, StartX, EndX, StartY, EndY, StartZ, EndZ, NoiseW); // DEBUG: Debug3DNoise(NoiseO, DIM_X, DIM_Y, DIM_Z, Printf("Chunk_%d_%d_orig", a_ChunkX, a_ChunkZ)); // Precalculate a "height" array: NOISE_DATATYPE Height[DIM_X * DIM_Z]; // Output for the cubic noise heightmap ("source") m_Cubic.Generate2D(Height, DIM_X, DIM_Z, StartX / 5, EndX / 5, StartZ / 5, EndZ / 5); for (size_t i = 0; i < ARRAYCOUNT(Height); i++) { Height[i] = Height[i] * m_HeightAmplification; } // Modify the noise by height data: for (int y = 0; y < DIM_Y; y++) { NOISE_DATATYPE AddHeight = (y * UPSCALE_Y - m_MidPoint) / 30; // AddHeight *= AddHeight * AddHeight; for (int z = 0; z < DIM_Z; z++) { NOISE_DATATYPE * CurRow = &(NoiseO[y * DIM_X + z * DIM_X * DIM_Y]); for (int x = 0; x < DIM_X; x++) { CurRow[x] += AddHeight + Height[x + DIM_X * z]; } } } // DEBUG: Debug3DNoise(NoiseO, DIM_X, DIM_Y, DIM_Z, Printf("Chunk_%d_%d_hei", a_ChunkX, a_ChunkZ)); // Upscale the Perlin noise into full-blown chunk dimensions: LinearUpscale3DArray( NoiseO, DIM_X, DIM_Y, DIM_Z, a_OutNoise, UPSCALE_X, UPSCALE_Y, UPSCALE_Z ); // DEBUG: Debug3DNoise(a_OutNoise, 17, 257, 17, Printf("Chunk_%d_%d_lerp", a_ChunkX, a_ChunkZ)); }
void cDistortedHeightmap::GenerateHeightArray(void) { // Generate distortion noise: NOISE_DATATYPE DistortNoiseX[DIM_X * DIM_Y * DIM_Z]; NOISE_DATATYPE DistortNoiseZ[DIM_X * DIM_Y * DIM_Z]; NOISE_DATATYPE Workspace[DIM_X * DIM_Y * DIM_Z]; NOISE_DATATYPE StartX = ((NOISE_DATATYPE)(m_CurChunkX * cChunkDef::Width)) / m_FrequencyX; NOISE_DATATYPE EndX = ((NOISE_DATATYPE)((m_CurChunkX + 1) * cChunkDef::Width - 1)) / m_FrequencyX; NOISE_DATATYPE StartY = 0; NOISE_DATATYPE EndY = ((NOISE_DATATYPE)(257)) / m_FrequencyY; NOISE_DATATYPE StartZ = ((NOISE_DATATYPE)(m_CurChunkZ * cChunkDef::Width)) / m_FrequencyZ; NOISE_DATATYPE EndZ = ((NOISE_DATATYPE)((m_CurChunkZ + 1) * cChunkDef::Width - 1)) / m_FrequencyZ; m_NoiseDistortX.Generate3D(DistortNoiseX, DIM_X, DIM_Y, DIM_Z, StartX, EndX, StartY, EndY, StartZ, EndZ, Workspace); m_NoiseDistortZ.Generate3D(DistortNoiseZ, DIM_X, DIM_Y, DIM_Z, StartX, EndX, StartY, EndY, StartZ, EndZ, Workspace); // The distorted heightmap, before linear upscaling NOISE_DATATYPE DistHei[DIM_X * DIM_Y * DIM_Z]; // Distort the heightmap using the distortion: for (int z = 0; z < DIM_Z; z++) { int AmpIdx = z * DIM_X; for (int y = 0; y < DIM_Y; y++) { int NoiseArrayIdx = z * DIM_X * DIM_Y + y * DIM_X; for (int x = 0; x < DIM_X; x++) { NOISE_DATATYPE DistX = DistortNoiseX[NoiseArrayIdx + x] * m_DistortAmpX[AmpIdx + x]; NOISE_DATATYPE DistZ = DistortNoiseZ[NoiseArrayIdx + x] * m_DistortAmpZ[AmpIdx + x]; DistX += (NOISE_DATATYPE)(m_CurChunkX * cChunkDef::Width + x * INTERPOL_X); DistZ += (NOISE_DATATYPE)(m_CurChunkZ * cChunkDef::Width + z * INTERPOL_Z); // Adding 0.5 helps alleviate the interpolation artifacts DistHei[NoiseArrayIdx + x] = (NOISE_DATATYPE)GetHeightmapAt(DistX, DistZ) + (NOISE_DATATYPE)0.5; } } } // Upscale the distorted heightmap into full dimensions: LinearUpscale3DArray( DistHei, DIM_X, DIM_Y, DIM_Z, m_DistortedHeightmap, INTERPOL_X, INTERPOL_Y, INTERPOL_Z ); // DEBUG: Debug3DNoise(m_DistortedHeightmap, 17, 257, 17, Printf("DistortedHeightmap_%d_%d", m_CurChunkX, m_CurChunkZ)); }
// cTerrainShapeGen override: virtual void GenShape(int a_ChunkX, int a_ChunkZ, cChunkDesc::Shape & a_Shape) override { // Generate the two heightmaps: cChunkDef::HeightMap heightsA; cChunkDef::HeightMap heightsB; m_HeightA.GenHeightMap(a_ChunkX, a_ChunkZ, heightsA); m_HeightB.GenHeightMap(a_ChunkX, a_ChunkZ, heightsB); // Generate the choice noise: NOISE_DATATYPE smallChoice[33 * 5 * 5]; NOISE_DATATYPE workspace[33 * 5 * 5]; NOISE_DATATYPE startX = 0; NOISE_DATATYPE endX = 256 * m_FrequencyY; NOISE_DATATYPE startY = a_ChunkX * cChunkDef::Width * m_FrequencyX; NOISE_DATATYPE endY = (a_ChunkX * cChunkDef::Width + cChunkDef::Width + 1) * m_FrequencyX; NOISE_DATATYPE startZ = a_ChunkZ * cChunkDef::Width * m_FrequencyZ; NOISE_DATATYPE endZ = (a_ChunkZ * cChunkDef::Width + cChunkDef::Width + 1) * m_FrequencyZ; m_Choice.Generate3D(smallChoice, 33, 5, 5, startX, endX, startY, endY, startZ, endZ, workspace); NOISE_DATATYPE choice[257 * 17 * 17]; LinearUpscale3DArray(smallChoice, 33, 5, 5, choice, 8, 4, 4); // Generate the shape: int idxShape = 0; for (int z = 0; z < cChunkDef::Width; z++) { for (int x = 0; x < cChunkDef::Width; x++) { int idxChoice = 257 * 17 * z + 257 * x; NOISE_DATATYPE heightA = static_cast<NOISE_DATATYPE>(cChunkDef::GetHeight(heightsA, x, z)); NOISE_DATATYPE heightB = static_cast<NOISE_DATATYPE>(cChunkDef::GetHeight(heightsB, x, z)); for (int y = 0; y < cChunkDef::Height; y++) { int height = static_cast<int>(ClampedLerp(heightA, heightB, choice[idxChoice++])); a_Shape[idxShape++] = (y < height) ? 1 : 0; } } // for x } // for z }
/// Generates the m_NoiseArray array for the current chunk void cEndGen::GenerateNoiseArray(void) { NOISE_DATATYPE NoiseData[DIM_X * DIM_Y * DIM_Z]; // [x + DIM_X * z + DIM_X * DIM_Z * y] NOISE_DATATYPE Workspace[DIM_X * DIM_Y * DIM_Z]; // [x + DIM_X * z + DIM_X * DIM_Z * y] // Generate the downscaled noise: NOISE_DATATYPE StartX = ((NOISE_DATATYPE)(m_LastChunkX * cChunkDef::Width)) / m_FrequencyX; NOISE_DATATYPE EndX = ((NOISE_DATATYPE)((m_LastChunkX + 1) * cChunkDef::Width)) / m_FrequencyX; NOISE_DATATYPE StartZ = ((NOISE_DATATYPE)(m_LastChunkZ * cChunkDef::Width)) / m_FrequencyZ; NOISE_DATATYPE EndZ = ((NOISE_DATATYPE)((m_LastChunkZ + 1) * cChunkDef::Width)) / m_FrequencyZ; NOISE_DATATYPE StartY = 0; NOISE_DATATYPE EndY = ((NOISE_DATATYPE)257) / m_FrequencyY; m_Perlin.Generate3D(NoiseData, DIM_X, DIM_Z, DIM_Y, StartX, EndX, StartZ, EndZ, StartY, EndY, Workspace); // Add distance: int idx = 0; for (int y = 0; y < DIM_Y; y++) { NOISE_DATATYPE ValY = (NOISE_DATATYPE)(2 * INTERPOL_Y * y - m_IslandSizeY) / m_IslandSizeY; ValY = ValY * ValY; for (int z = 0; z < DIM_Z; z++) { NOISE_DATATYPE ValZ = (NOISE_DATATYPE)(m_LastChunkZ * cChunkDef::Width + (z * cChunkDef::Width / (DIM_Z - 1))) / m_IslandSizeZ; ValZ = ValZ * ValZ; for (int x = 0; x < DIM_X; x++) { // NOISE_DATATYPE ValX = StartX + (EndX - StartX) * x / (DIM_X - 1); NOISE_DATATYPE ValX = (NOISE_DATATYPE)(m_LastChunkX * cChunkDef::Width + (x * cChunkDef::Width / (DIM_X - 1))) / m_IslandSizeX; ValX = ValX * ValX; NoiseData[idx++] += ValX + ValZ + ValY; } // for x } // for z } // for y // Upscale into real chunk size: LinearUpscale3DArray(NoiseData, DIM_X, DIM_Z, DIM_Y, m_NoiseArray, INTERPOL_X, INTERPOL_Z, INTERPOL_Y); }