Noise3D generator is now using linear upscaling
Measured 30% performance increase. git-svn-id: http://mc-server.googlecode.com/svn/trunk@1482 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
parent
07cfe8ee35
commit
464dcc3764
@ -340,8 +340,8 @@ void cBioGenDistortedVoronoi::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::B
|
|||||||
Distort(BaseX + x * 4, BaseZ + z * 4, DistortX[4 * x][4 * z], DistortZ[4 * x][4 * z]);
|
Distort(BaseX + x * 4, BaseZ + z * 4, DistortX[4 * x][4 * z], DistortZ[4 * x][4 * z]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayLinearUpscale2DInPlace(&DistortX[0][0], cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4);
|
LinearUpscale2DArrayInPlace(&DistortX[0][0], cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4);
|
||||||
ArrayLinearUpscale2DInPlace(&DistortZ[0][0], cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4);
|
LinearUpscale2DArrayInPlace(&DistortZ[0][0], cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4);
|
||||||
|
|
||||||
for (int z = 0; z < cChunkDef::Width; z++)
|
for (int z = 0; z < cChunkDef::Width; z++)
|
||||||
{
|
{
|
||||||
@ -447,8 +447,8 @@ void cBioGenMultiStepMap::DecideOceanLandMushroom(int a_ChunkX, int a_ChunkZ, cC
|
|||||||
{
|
{
|
||||||
Distort(BaseX + x * 4, BaseZ + z * 4, DistortX[4 * x][4 * z], DistortZ[4 * x][4 * z], DistortSize);
|
Distort(BaseX + x * 4, BaseZ + z * 4, DistortX[4 * x][4 * z], DistortZ[4 * x][4 * z], DistortSize);
|
||||||
}
|
}
|
||||||
ArrayLinearUpscale2DInPlace(&DistortX[0][0], cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4);
|
LinearUpscale2DArrayInPlace(&DistortX[0][0], cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4);
|
||||||
ArrayLinearUpscale2DInPlace(&DistortZ[0][0], cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4);
|
LinearUpscale2DArrayInPlace(&DistortZ[0][0], cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4);
|
||||||
|
|
||||||
// Prepare a 9x9 area of neighboring cell seeds
|
// Prepare a 9x9 area of neighboring cell seeds
|
||||||
// (assuming that 7x7 cell area is larger than a chunk being generated)
|
// (assuming that 7x7 cell area is larger than a chunk being generated)
|
||||||
@ -621,8 +621,8 @@ void cBioGenMultiStepMap::BuildTemperatureHumidityMaps(int a_ChunkX, int a_Chunk
|
|||||||
HumidityMap[x + 17 * z] = NoiseH;
|
HumidityMap[x + 17 * z] = NoiseH;
|
||||||
} // for x
|
} // for x
|
||||||
} // for z
|
} // for z
|
||||||
ArrayLinearUpscale2DInPlace(TemperatureMap, 17, 17, 8, 8);
|
LinearUpscale2DArrayInPlace(TemperatureMap, 17, 17, 8, 8);
|
||||||
ArrayLinearUpscale2DInPlace(HumidityMap, 17, 17, 8, 8);
|
LinearUpscale2DArrayInPlace(HumidityMap, 17, 17, 8, 8);
|
||||||
|
|
||||||
// Re-map into integral values in [0 .. 255] range:
|
// Re-map into integral values in [0 .. 255] range:
|
||||||
for (int idx = 0; idx < ARRAYCOUNT(a_TemperatureMap); idx++)
|
for (int idx = 0; idx < ARRAYCOUNT(a_TemperatureMap); idx++)
|
||||||
|
@ -442,7 +442,7 @@ void cCompoGenNether::ComposeTerrain(cChunkDesc & a_ChunkDesc)
|
|||||||
m_Noise2.IntNoise3DInt(BaseX + INTERPOL_X * x, 0, BaseZ + INTERPOL_Z * z) /
|
m_Noise2.IntNoise3DInt(BaseX + INTERPOL_X * x, 0, BaseZ + INTERPOL_Z * z) /
|
||||||
256;
|
256;
|
||||||
} // for x, z - FloorLo[]
|
} // for x, z - FloorLo[]
|
||||||
ArrayLinearUpscale2DInPlace(FloorLo, 17, 17, INTERPOL_X, INTERPOL_Z);
|
LinearUpscale2DArrayInPlace(FloorLo, 17, 17, INTERPOL_X, INTERPOL_Z);
|
||||||
|
|
||||||
// Interpolate segments:
|
// Interpolate segments:
|
||||||
for (int Segment = 0; Segment < MaxHeight; Segment += SEGMENT_HEIGHT)
|
for (int Segment = 0; Segment < MaxHeight; Segment += SEGMENT_HEIGHT)
|
||||||
@ -455,7 +455,7 @@ void cCompoGenNether::ComposeTerrain(cChunkDesc & a_ChunkDesc)
|
|||||||
m_Noise2.IntNoise3DInt(BaseX + INTERPOL_Z * x, Segment + SEGMENT_HEIGHT, BaseZ + INTERPOL_Z * z) /
|
m_Noise2.IntNoise3DInt(BaseX + INTERPOL_Z * x, Segment + SEGMENT_HEIGHT, BaseZ + INTERPOL_Z * z) /
|
||||||
256;
|
256;
|
||||||
} // for x, z - FloorLo[]
|
} // for x, z - FloorLo[]
|
||||||
ArrayLinearUpscale2DInPlace(FloorHi, 17, 17, INTERPOL_X, INTERPOL_Z);
|
LinearUpscale2DArrayInPlace(FloorHi, 17, 17, INTERPOL_X, INTERPOL_Z);
|
||||||
|
|
||||||
// Interpolate between FloorLo and FloorHi:
|
// Interpolate between FloorLo and FloorHi:
|
||||||
for (int z = 0; z < 16; z++) for (int x = 0; x < 16; x++)
|
for (int z = 0; z < 16; z++) for (int x = 0; x < 16; x++)
|
||||||
|
@ -158,7 +158,7 @@ void cDistortedHeightmap::GenerateHeightArray(void)
|
|||||||
CurFloor[idx + x * INTERPOL_X] = (NOISE_DATATYPE)GetHeightmapAt(DistX, DistZ) + (NOISE_DATATYPE)0.5;
|
CurFloor[idx + x * INTERPOL_X] = (NOISE_DATATYPE)GetHeightmapAt(DistX, DistZ) + (NOISE_DATATYPE)0.5;
|
||||||
} // for x
|
} // for x
|
||||||
} // for z
|
} // for z
|
||||||
ArrayLinearUpscale2DInPlace(CurFloor, 17, 17, INTERPOL_X, INTERPOL_Z);
|
LinearUpscale2DArrayInPlace(CurFloor, 17, 17, INTERPOL_X, INTERPOL_Z);
|
||||||
} // for y
|
} // for y
|
||||||
|
|
||||||
// Finish the 3D linear interpolation by interpolating between each XZ-floors on the Y axis
|
// Finish the 3D linear interpolation by interpolating between each XZ-floors on the Y axis
|
||||||
@ -381,8 +381,8 @@ void cDistortedHeightmap::UpdateDistortAmps(void)
|
|||||||
GetDistortAmpsAt(Biomes, x, z, m_DistortAmpX[x + 17 * z], m_DistortAmpZ[x + 17 * z]);
|
GetDistortAmpsAt(Biomes, x, z, m_DistortAmpX[x + 17 * z], m_DistortAmpZ[x + 17 * z]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ArrayLinearUpscale2DInPlace(m_DistortAmpX, 17, 17, STEPX, STEPZ);
|
LinearUpscale2DArrayInPlace(m_DistortAmpX, 17, 17, STEPX, STEPZ);
|
||||||
ArrayLinearUpscale2DInPlace(m_DistortAmpZ, 17, 17, STEPX, STEPZ);
|
LinearUpscale2DArrayInPlace(m_DistortAmpZ, 17, 17, STEPX, STEPZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -266,7 +266,7 @@ void cHeiGenBiomal::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMa
|
|||||||
Height[x + 17 * z] = GetHeightAt(x, z, a_ChunkX, a_ChunkZ, Biomes);
|
Height[x + 17 * z] = GetHeightAt(x, z, a_ChunkX, a_ChunkZ, Biomes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ArrayLinearUpscale2DInPlace(Height, 17, 17, STEPX, STEPZ);
|
LinearUpscale2DArrayInPlace(Height, 17, 17, STEPX, STEPZ);
|
||||||
|
|
||||||
// Copy into the heightmap
|
// Copy into the heightmap
|
||||||
for (int z = 0; z < cChunkDef::Width; z++)
|
for (int z = 0; z < cChunkDef::Width; z++)
|
||||||
|
@ -31,7 +31,7 @@ void Debug3DNoise(NOISE_DATATYPE * a_Noise, int a_SizeX, int a_SizeY, int a_Size
|
|||||||
unsigned char buf[BUF_SIZE];
|
unsigned char buf[BUF_SIZE];
|
||||||
for (int x = 0; x < a_SizeX; x++)
|
for (int x = 0; x < a_SizeX; x++)
|
||||||
{
|
{
|
||||||
buf[x] = (unsigned char)(std::min(256, std::max(0, (int)(128 + 32 * a_Noise[idx++]))));
|
buf[x] = (unsigned char)(std::min(255, std::max(0, (int)(128 + 32 * a_Noise[idx++]))));
|
||||||
}
|
}
|
||||||
f1.Write(buf, a_SizeX);
|
f1.Write(buf, a_SizeX);
|
||||||
} // for y
|
} // for y
|
||||||
@ -52,7 +52,7 @@ void Debug3DNoise(NOISE_DATATYPE * a_Noise, int a_SizeX, int a_SizeY, int a_Size
|
|||||||
unsigned char buf[BUF_SIZE];
|
unsigned char buf[BUF_SIZE];
|
||||||
for (int x = 0; x < a_SizeX; x++)
|
for (int x = 0; x < a_SizeX; x++)
|
||||||
{
|
{
|
||||||
buf[x] = (unsigned char)(std::min(256, std::max(0, (int)(128 + 32 * a_Noise[idx++]))));
|
buf[x] = (unsigned char)(std::min(255, std::max(0, (int)(128 + 32 * a_Noise[idx++]))));
|
||||||
}
|
}
|
||||||
f2.Write(buf, a_SizeX);
|
f2.Write(buf, a_SizeX);
|
||||||
} // for z
|
} // for z
|
||||||
@ -69,6 +69,37 @@ void Debug3DNoise(NOISE_DATATYPE * a_Noise, int a_SizeX, int a_SizeY, int a_Size
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Perform an automatic test of upscaling upon program start (use breakpoints to debug):
|
||||||
|
|
||||||
|
class Test
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Test(void)
|
||||||
|
{
|
||||||
|
DoTest1();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DoTest1(void)
|
||||||
|
{
|
||||||
|
float In[3 * 3 * 3];
|
||||||
|
for (int i = 0; i < ARRAYCOUNT(In); i++)
|
||||||
|
{
|
||||||
|
In[i] = (float)(i % 5);
|
||||||
|
}
|
||||||
|
Debug3DNoise(In, 3, 3, 3, "Upscale in");
|
||||||
|
float Out[17 * 33 * 35];
|
||||||
|
LinearUpscale3DArray(In, 3, 3, 3, Out, 8, 16, 17);
|
||||||
|
Debug3DNoise(Out, 17, 33, 35, "Upscale test");
|
||||||
|
}
|
||||||
|
} gTest;
|
||||||
|
//*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// cNoise3DGenerator:
|
// cNoise3DGenerator:
|
||||||
|
|
||||||
@ -190,15 +221,15 @@ void cNoise3DGenerator::GenerateBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::Bi
|
|||||||
|
|
||||||
void cNoise3DGenerator::DoGenerate(int a_ChunkX, int a_ChunkZ, cChunkDesc & a_ChunkDesc)
|
void cNoise3DGenerator::DoGenerate(int a_ChunkX, int a_ChunkZ, cChunkDesc & a_ChunkDesc)
|
||||||
{
|
{
|
||||||
NOISE_DATATYPE Noise[cChunkDef::Width * cChunkDef::Height * cChunkDef::Width];
|
NOISE_DATATYPE Noise[17 * 257 * 17];
|
||||||
GenerateNoiseArray(a_ChunkX, a_ChunkZ, Noise);
|
GenerateNoiseArray(a_ChunkX, a_ChunkZ, Noise);
|
||||||
|
|
||||||
// Output noise into chunk:
|
// Output noise into chunk:
|
||||||
int idx = 0;
|
|
||||||
for (int z = 0; z < cChunkDef::Width; z++)
|
for (int z = 0; z < cChunkDef::Width; z++)
|
||||||
{
|
{
|
||||||
for (int y = 0; y < cChunkDef::Height; y++)
|
for (int y = 0; y < cChunkDef::Height; y++)
|
||||||
{
|
{
|
||||||
|
int idx = z * 17 * 257 + y * 17;
|
||||||
for (int x = 0; x < cChunkDef::Width; x++)
|
for (int x = 0; x < cChunkDef::Width; x++)
|
||||||
{
|
{
|
||||||
NOISE_DATATYPE n = Noise[idx++];
|
NOISE_DATATYPE n = Noise[idx++];
|
||||||
@ -226,8 +257,8 @@ void cNoise3DGenerator::DoGenerate(int a_ChunkX, int a_ChunkZ, cChunkDesc & a_Ch
|
|||||||
|
|
||||||
void cNoise3DGenerator::GenerateNoiseArray(int a_ChunkX, int a_ChunkZ, NOISE_DATATYPE * a_OutNoise)
|
void cNoise3DGenerator::GenerateNoiseArray(int a_ChunkX, int a_ChunkZ, NOISE_DATATYPE * a_OutNoise)
|
||||||
{
|
{
|
||||||
NOISE_DATATYPE NoiseO[DIMX * DIMY * DIMZ]; // Output for the Perlin noise
|
NOISE_DATATYPE NoiseO[DIM_X * DIM_Y * DIM_Z]; // Output for the Perlin noise
|
||||||
NOISE_DATATYPE NoiseW[DIMX * DIMY * DIMZ]; // Workspace that the noise calculation can use and trash
|
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"
|
// 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 StartX = ((NOISE_DATATYPE)(a_ChunkX * cChunkDef::Width)) / m_FrequencyX;
|
||||||
@ -237,51 +268,42 @@ void cNoise3DGenerator::GenerateNoiseArray(int a_ChunkX, int a_ChunkZ, NOISE_DAT
|
|||||||
NOISE_DATATYPE StartY = 0;
|
NOISE_DATATYPE StartY = 0;
|
||||||
NOISE_DATATYPE EndY = ((NOISE_DATATYPE)256) / m_FrequencyY;
|
NOISE_DATATYPE EndY = ((NOISE_DATATYPE)256) / m_FrequencyY;
|
||||||
|
|
||||||
m_Perlin.Generate3D(NoiseO, DIMX, DIMY, DIMZ, StartX, EndX, StartY, EndY, StartZ, EndZ, NoiseW);
|
m_Perlin.Generate3D(NoiseO, DIM_X, DIM_Y, DIM_Z, StartX, EndX, StartY, EndY, StartZ, EndZ, NoiseW);
|
||||||
|
|
||||||
// DEBUG: Debug3DNoise(NoiseO, DIMX, DIMY, DIMZ, Printf("Chunk_%d_%d_orig", a_ChunkX, a_ChunkZ));
|
// DEBUG: Debug3DNoise(NoiseO, DIM_X, DIM_Y, DIM_Z, Printf("Chunk_%d_%d_orig", a_ChunkX, a_ChunkZ));
|
||||||
|
|
||||||
// Linearly interpolate the Perlin noise into full-blown chunk dimensions:
|
|
||||||
LinearInterpolate3DArray(
|
|
||||||
NoiseO, DIMX, DIMY, DIMZ,
|
|
||||||
a_OutNoise, cChunkDef::Width, cChunkDef::Height, cChunkDef::Width
|
|
||||||
);
|
|
||||||
|
|
||||||
// DEBUG: Debug3DNoise(a_OutNoise, cChunkDef::Width, cChunkDef::Height, cChunkDef::Width, Printf("Chunk_%d_%d_lerp", a_ChunkX, a_ChunkZ));
|
|
||||||
|
|
||||||
// Modify the noise to account for the wanted elevation:
|
|
||||||
|
|
||||||
// Precalculate a "height" array:
|
// Precalculate a "height" array:
|
||||||
NOISE_DATATYPE Test1 = 0;
|
NOISE_DATATYPE Height[DIM_X * DIM_Z]; // Output for the cubic noise heightmap ("source")
|
||||||
NOISE_DATATYPE HeightS[DIMX * DIMZ]; // Output for the cubic noise heightmap ("source")
|
m_Cubic.Generate2D(Height, DIM_X, DIM_Z, StartX / 25, EndX / 25, StartZ / 25, EndZ / 25);
|
||||||
NOISE_DATATYPE Test2 = 0;
|
|
||||||
NOISE_DATATYPE Height[cChunkDef::Width * cChunkDef::Width]; // Lerp-ed heightmap [x + Width * z]
|
|
||||||
m_Cubic.Generate2D(HeightS, DIMX, DIMZ, StartX / 25, EndX / 25, StartZ / 25, EndZ / 25);
|
|
||||||
LinearInterpolate2DArray(
|
|
||||||
HeightS, DIMX, DIMZ,
|
|
||||||
Height, cChunkDef::Width, cChunkDef::Width
|
|
||||||
);
|
|
||||||
for (int i = 0; i < ARRAYCOUNT(Height); i++)
|
for (int i = 0; i < ARRAYCOUNT(Height); i++)
|
||||||
{
|
{
|
||||||
Height[i] = abs(Height[i]) * m_HeightAmplification + 1;
|
Height[i] = abs(Height[i]) * m_HeightAmplification + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modify noise by height data
|
// Modify the noise by height data:
|
||||||
for (int y = 0; y < cChunkDef::Height; y++)
|
for (int y = 0; y < DIM_Y; y++)
|
||||||
{
|
{
|
||||||
NOISE_DATATYPE AddHeight = (y - m_MidPoint) / 20;
|
NOISE_DATATYPE AddHeight = (y * UPSCALE_Y - m_MidPoint) / 20;
|
||||||
AddHeight *= AddHeight * AddHeight;
|
AddHeight *= AddHeight * AddHeight;
|
||||||
for (int z = 0; z < cChunkDef::Width; z++)
|
for (int z = 0; z < DIM_Z; z++)
|
||||||
{
|
{
|
||||||
NOISE_DATATYPE * CurRow = &(a_OutNoise[y * cChunkDef::Width + z * cChunkDef::Width * cChunkDef::Height]);
|
NOISE_DATATYPE * CurRow = &(NoiseO[y * DIM_X + z * DIM_X * DIM_Y]);
|
||||||
for (int x = 0; x < cChunkDef::Width; x++)
|
for (int x = 0; x < DIM_X; x++)
|
||||||
{
|
{
|
||||||
CurRow[x] += AddHeight / Height[x + cChunkDef::Width * z];
|
CurRow[x] += AddHeight / Height[x + DIM_X * z];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DEBUG: Debug3DNoise(a_OutNoise, cChunkDef::Width, cChunkDef::Height, cChunkDef::Width, Printf("Chunk_%d_%d", a_ChunkX, a_ChunkZ);
|
// 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -444,7 +466,7 @@ void cNoise3DComposable::GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_ChunkZ)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Linear-interpolate this XZ floor:
|
// Linear-interpolate this XZ floor:
|
||||||
ArrayLinearUpscale2DInPlace(CurFloor, 17, 17, UPSCALE_X, UPSCALE_Z);
|
LinearUpscale2DArrayInPlace(CurFloor, 17, 17, UPSCALE_X, UPSCALE_Z);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finish the 3D linear interpolation by interpolating between each XZ-floors on the Y axis
|
// Finish the 3D linear interpolation by interpolating between each XZ-floors on the Y axis
|
||||||
|
@ -29,10 +29,15 @@ public:
|
|||||||
virtual void DoGenerate(int a_ChunkX, int a_ChunkZ, cChunkDesc & a_ChunkDesc) override;
|
virtual void DoGenerate(int a_ChunkX, int a_ChunkZ, cChunkDesc & a_ChunkDesc) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Linear interpolation dimensions:
|
// Linear interpolation step sizes, must be divisors of cChunkDef::Width and cChunkDef::Height, respectively:
|
||||||
static const int DIMX = 5;
|
static const int UPSCALE_X = 8;
|
||||||
static const int DIMY = 65;
|
static const int UPSCALE_Y = 4;
|
||||||
static const int DIMZ = 5;
|
static const int UPSCALE_Z = 8;
|
||||||
|
|
||||||
|
// Linear interpolation buffer dimensions, calculated from the step sizes:
|
||||||
|
static const int DIM_X = 1 + cChunkDef::Width / UPSCALE_X;
|
||||||
|
static const int DIM_Y = 1 + cChunkDef::Height / UPSCALE_Y;
|
||||||
|
static const int DIM_Z = 1 + cChunkDef::Width / UPSCALE_Z;
|
||||||
|
|
||||||
cPerlinNoise m_Perlin; // The base 3D noise source for the actual composition
|
cPerlinNoise m_Perlin; // The base 3D noise source for the actual composition
|
||||||
cCubicNoise m_Cubic; // The noise used for heightmap directing
|
cCubicNoise m_Cubic; // The noise used for heightmap directing
|
||||||
|
@ -559,7 +559,7 @@ void cStructGenDirectOverhangs::GenStructures(cChunkDesc & a_ChunkDesc)
|
|||||||
m_Noise2.IntNoise3DInt(BaseX + INTERPOL_X * x, BaseY, BaseZ + INTERPOL_Z * z) /
|
m_Noise2.IntNoise3DInt(BaseX + INTERPOL_X * x, BaseY, BaseZ + INTERPOL_Z * z) /
|
||||||
256;
|
256;
|
||||||
} // for x, z - FloorLo[]
|
} // for x, z - FloorLo[]
|
||||||
ArrayLinearUpscale2DInPlace(FloorLo, 17, 17, INTERPOL_X, INTERPOL_Z);
|
LinearUpscale2DArrayInPlace(FloorLo, 17, 17, INTERPOL_X, INTERPOL_Z);
|
||||||
|
|
||||||
// Interpolate segments:
|
// Interpolate segments:
|
||||||
for (int Segment = BaseY; Segment < MaxHeight; Segment += SEGMENT_HEIGHT)
|
for (int Segment = BaseY; Segment < MaxHeight; Segment += SEGMENT_HEIGHT)
|
||||||
@ -572,7 +572,7 @@ void cStructGenDirectOverhangs::GenStructures(cChunkDesc & a_ChunkDesc)
|
|||||||
m_Noise2.IntNoise3DInt(BaseX + INTERPOL_Z * x, Segment + SEGMENT_HEIGHT, BaseZ + INTERPOL_Z * z) /
|
m_Noise2.IntNoise3DInt(BaseX + INTERPOL_Z * x, Segment + SEGMENT_HEIGHT, BaseZ + INTERPOL_Z * z) /
|
||||||
256;
|
256;
|
||||||
} // for x, z - FloorLo[]
|
} // for x, z - FloorLo[]
|
||||||
ArrayLinearUpscale2DInPlace(FloorHi, 17, 17, INTERPOL_X, INTERPOL_Z);
|
LinearUpscale2DArrayInPlace(FloorHi, 17, 17, INTERPOL_X, INTERPOL_Z);
|
||||||
|
|
||||||
// Interpolate between FloorLo and FloorHi:
|
// Interpolate between FloorLo and FloorHi:
|
||||||
for (int z = 0; z < 16; z++) for (int x = 0; x < 16; x++)
|
for (int z = 0; z < 16; z++) for (int x = 0; x < 16; x++)
|
||||||
|
@ -26,8 +26,11 @@ Regular upscaling takes two arrays and "moves" the input from src to dst; src is
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Linearly interpolates values in the array between the equidistant anchor points; universal data type
|
/**
|
||||||
template<typename TYPE> void ArrayLinearUpscale2DInPlace(
|
Linearly interpolates values in the array between the equidistant anchor points (upscales).
|
||||||
|
Works in-place (input is already present at the correct output coords)
|
||||||
|
*/
|
||||||
|
template<typename TYPE> void LinearUpscale2DArrayInPlace(
|
||||||
TYPE * a_Array,
|
TYPE * a_Array,
|
||||||
int a_SizeX, int a_SizeY, // Dimensions of the array
|
int a_SizeX, int a_SizeY, // Dimensions of the array
|
||||||
int a_AnchorStepX, int a_AnchorStepY // Distances between the anchor points in each direction
|
int a_AnchorStepX, int a_AnchorStepY // Distances between the anchor points in each direction
|
||||||
@ -74,3 +77,158 @@ template<typename TYPE> void ArrayLinearUpscale2DInPlace(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Linearly interpolates values in the array between the equidistant anchor points (upscales).
|
||||||
|
Works on two arrays, input is packed and output is to be completely constructed.
|
||||||
|
*/
|
||||||
|
template<typename TYPE> void LinearUpscale2DArray(
|
||||||
|
TYPE * a_Src, ///< Source array of size a_SrcSizeX x a_SrcSizeY
|
||||||
|
int a_SrcSizeX, int a_SrcSizeY, ///< Dimensions of the src array
|
||||||
|
TYPE * a_Dst, ///< Dest array, of size (a_SrcSizeX * a_UpscaleX + 1) x (a_SrcSizeY * a_UpscaleY + 1)
|
||||||
|
int a_UpscaleX, int a_UpscaleY ///< Upscale factor for each direction
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ASSERT(a_Src != NULL);
|
||||||
|
ASSERT(a_Dst != NULL);
|
||||||
|
ASSERT(a_SrcSizeX > 0);
|
||||||
|
ASSERT(a_SrcSizeY > 0);
|
||||||
|
ASSERT(a_UpscaleX > 0);
|
||||||
|
ASSERT(a_UpscaleY > 0);
|
||||||
|
|
||||||
|
// First interpolate columns (same-Y) where the anchor points are:
|
||||||
|
int idx = 0;
|
||||||
|
for (int y = 0; y < a_SrcSizeY; y++)
|
||||||
|
{
|
||||||
|
int DstY = y * a_UpscaleY;
|
||||||
|
for (int x = 0; x < a_SrcSizeX; x++)
|
||||||
|
{
|
||||||
|
int DstX = x * a_UpscaleX;
|
||||||
|
TYPE StartValue = a_Src[idx]; // [x, y]
|
||||||
|
TYPE EndValue = a_Src[idx + a_SrcSizeX]; // [x, y + 1]
|
||||||
|
TYPE Diff = EndValue - StartValue;
|
||||||
|
for (int CellY = 0; CellY <= a_UpscaleY; CellY++)
|
||||||
|
{
|
||||||
|
a_Dst[DstX + (DstY + CellY) * a_SizeY] = StartValue + Diff * CellY / a_AnchorStepY;
|
||||||
|
} // for CellY
|
||||||
|
} // for x
|
||||||
|
} // for y
|
||||||
|
|
||||||
|
// Now interpolate in rows (same-X), each row already has valid values in the anchor columns
|
||||||
|
int DstSizeY = a_SizeY * a_UpscaleY;
|
||||||
|
int DstSizeX = a_SizeX * a_UpscaleX;
|
||||||
|
for (int y = 0; y < DstSizeY; y++)
|
||||||
|
{
|
||||||
|
int Idx = y * DstSizeX;
|
||||||
|
for (int x = 0; x < a_SizeX; x++)
|
||||||
|
{
|
||||||
|
TYPE StartValue = a_Dst[Idx]; // [x, y] in the src coords
|
||||||
|
TYPE EndValue = a_Dst[Idx + a_UpscaleX]; // [x + 1, y] in the src coords
|
||||||
|
TYPE Diff = EndValue - StartValue;
|
||||||
|
for (int CellX = 0; CellX <= a_UpscaleX; CellX++)
|
||||||
|
{
|
||||||
|
a_Dst[Idx + CellX] = StartValue + CellX * Diff / a_UpscaleX;
|
||||||
|
} // for CellY
|
||||||
|
Idx += a_UpscaleX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Linearly interpolates values in the array between the equidistant anchor points (upscales).
|
||||||
|
Works on two arrays, input is packed and output is to be completely constructed.
|
||||||
|
*/
|
||||||
|
template<typename TYPE> void LinearUpscale3DArray(
|
||||||
|
TYPE * a_Src, ///< Source array of size a_SrcSizeX x a_SrcSizeY x a_SrcSizeZ
|
||||||
|
int a_SrcSizeX, int a_SrcSizeY, int a_SrcSizeZ, ///< Dimensions of the src array
|
||||||
|
TYPE * a_Dst, ///< Dest array, of size (a_SrcSizeX * a_UpscaleX + 1) x (a_SrcSizeY * a_UpscaleY + 1) x (a_SrcSizeZ * a_UpscaleZ + 1)
|
||||||
|
int a_UpscaleX, int a_UpscaleY, int a_UpscaleZ ///< Upscale factor for each direction
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// For optimization reasons, we're storing the upscaling ratios in a fixed-size arrays of these sizes
|
||||||
|
// Feel free to enlarge them if needed, but keep in mind that they're on the stack
|
||||||
|
const int MAX_UPSCALE_X = 128;
|
||||||
|
const int MAX_UPSCALE_Y = 128;
|
||||||
|
const int MAX_UPSCALE_Z = 128;
|
||||||
|
|
||||||
|
ASSERT(a_Src != NULL);
|
||||||
|
ASSERT(a_Dst != NULL);
|
||||||
|
ASSERT(a_SrcSizeX > 0);
|
||||||
|
ASSERT(a_SrcSizeY > 0);
|
||||||
|
ASSERT(a_SrcSizeZ > 0);
|
||||||
|
ASSERT(a_UpscaleX > 0);
|
||||||
|
ASSERT(a_UpscaleY > 0);
|
||||||
|
ASSERT(a_UpscaleZ > 0);
|
||||||
|
ASSERT(a_UpscaleX <= MAX_UPSCALE_X);
|
||||||
|
ASSERT(a_UpscaleY <= MAX_UPSCALE_Y);
|
||||||
|
ASSERT(a_UpscaleZ <= MAX_UPSCALE_Z);
|
||||||
|
|
||||||
|
// Pre-calculate the upscaling ratios:
|
||||||
|
TYPE RatioX[MAX_UPSCALE_X];
|
||||||
|
TYPE RatioY[MAX_UPSCALE_Y];
|
||||||
|
TYPE RatioZ[MAX_UPSCALE_Y];
|
||||||
|
for (int x = 0; x <= a_UpscaleX; x++)
|
||||||
|
{
|
||||||
|
RatioX[x] = (TYPE)x / a_UpscaleX;
|
||||||
|
}
|
||||||
|
for (int y = 0; y <= a_UpscaleY; y++)
|
||||||
|
{
|
||||||
|
RatioY[y] = (TYPE)y / a_UpscaleY;
|
||||||
|
}
|
||||||
|
for (int z = 0; z <= a_UpscaleZ; z++)
|
||||||
|
{
|
||||||
|
RatioZ[z] = (TYPE)z / a_UpscaleZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interpolate each XYZ cell:
|
||||||
|
int DstSizeX = (a_SrcSizeX - 1) * a_UpscaleX + 1;
|
||||||
|
int DstSizeY = (a_SrcSizeY - 1) * a_UpscaleY + 1;
|
||||||
|
int DstSizeZ = (a_SrcSizeZ - 1) * a_UpscaleZ + 1;
|
||||||
|
for (int z = 0; z < (a_SrcSizeZ - 1); z++)
|
||||||
|
{
|
||||||
|
int DstZ = z * a_UpscaleZ;
|
||||||
|
for (int y = 0; y < (a_SrcSizeY - 1); y++)
|
||||||
|
{
|
||||||
|
int DstY = y * a_UpscaleY;
|
||||||
|
int idx = y * a_SrcSizeX + z * a_SrcSizeX * a_SrcSizeY;
|
||||||
|
for (int x = 0; x < (a_SrcSizeX - 1); x++, idx++)
|
||||||
|
{
|
||||||
|
int DstX = x * a_UpscaleX;
|
||||||
|
TYPE LoXLoYLoZ = a_Src[idx];
|
||||||
|
TYPE LoXLoYHiZ = a_Src[idx + a_SrcSizeX * a_SrcSizeY];
|
||||||
|
TYPE LoXHiYLoZ = a_Src[idx + a_SrcSizeX];
|
||||||
|
TYPE LoXHiYHiZ = a_Src[idx + a_SrcSizeX + a_SrcSizeX * a_SrcSizeY];
|
||||||
|
TYPE HiXLoYLoZ = a_Src[idx + 1];
|
||||||
|
TYPE HiXLoYHiZ = a_Src[idx + 1 + a_SrcSizeX * a_SrcSizeY];
|
||||||
|
TYPE HiXHiYLoZ = a_Src[idx + 1 + a_SrcSizeX];
|
||||||
|
TYPE HiXHiYHiZ = a_Src[idx + 1 + a_SrcSizeX + a_SrcSizeX * a_SrcSizeY];
|
||||||
|
for (int CellZ = 0; CellZ <= a_UpscaleZ; CellZ++)
|
||||||
|
{
|
||||||
|
TYPE LoXLoYInZ = LoXLoYLoZ + (LoXLoYHiZ - LoXLoYLoZ) * RatioZ[CellZ];
|
||||||
|
TYPE LoXHiYInZ = LoXHiYLoZ + (LoXHiYHiZ - LoXHiYLoZ) * RatioZ[CellZ];
|
||||||
|
TYPE HiXLoYInZ = HiXLoYLoZ + (HiXLoYHiZ - HiXLoYLoZ) * RatioZ[CellZ];
|
||||||
|
TYPE HiXHiYInZ = HiXHiYLoZ + (HiXHiYHiZ - HiXHiYLoZ) * RatioZ[CellZ];
|
||||||
|
for (int CellY = 0; CellY <= a_UpscaleY; CellY++)
|
||||||
|
{
|
||||||
|
int DestIdx = (DstZ + CellZ) * DstSizeX * DstSizeY + (DstY + CellY) * DstSizeX + DstX;
|
||||||
|
ASSERT(DestIdx + a_UpscaleX < DstSizeX * DstSizeY * DstSizeZ);
|
||||||
|
TYPE LoXInY = LoXLoYInZ + (LoXHiYInZ - LoXLoYInZ) * RatioY[CellY];
|
||||||
|
TYPE HiXInY = HiXLoYInZ + (HiXHiYInZ - HiXLoYInZ) * RatioY[CellY];
|
||||||
|
for (int CellX = 0; CellX <= a_UpscaleX; CellX++, DestIdx++)
|
||||||
|
{
|
||||||
|
a_Dst[DestIdx] = LoXInY + (HiXInY - LoXInY) * RatioX[CellX];
|
||||||
|
}
|
||||||
|
} // for CellY
|
||||||
|
} // for CellZ
|
||||||
|
} // for x
|
||||||
|
} // for y
|
||||||
|
} // for z
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user