diff --git a/source/Generating/Noise3DGenerator.cpp b/source/Generating/Noise3DGenerator.cpp index 42a0d70d9..79138aa9f 100644 --- a/source/Generating/Noise3DGenerator.cpp +++ b/source/Generating/Noise3DGenerator.cpp @@ -61,14 +61,36 @@ void Debug3DNoise(NOISE_DATATYPE * a_Noise, int a_SizeX, int a_SizeY, int a_Size f2.Write(buf, a_SizeX); } // for y } // if (XZ file open) - //*/ - } +void Debug2DNoise(NOISE_DATATYPE * a_Noise, int a_SizeX, int a_SizeY, const AString & a_FileNameBase) +{ + const int BUF_SIZE = 512; + ASSERT(a_SizeX <= BUF_SIZE); // Just stretch it, if needed + + cFile f1; + if (f1.Open(Printf("%s (%d).grab", a_FileNameBase.c_str(), a_SizeX), cFile::fmWrite)) + { + for (int y = 0; y < a_SizeY; y++) + { + int idx = y * a_SizeX; + unsigned char buf[BUF_SIZE]; + for (int x = 0; x < a_SizeX; x++) + { + buf[x] = (unsigned char)(std::min(255, std::max(0, (int)(128 + 32 * a_Noise[idx++])))); + } + f1.Write(buf, a_SizeX); + } // for y + } // if (file open) +} + + + + /* // Perform an automatic test of upscaling upon program start (use breakpoints to debug): @@ -78,6 +100,7 @@ public: Test(void) { DoTest1(); + DoTest2(); } @@ -88,11 +111,26 @@ public: { In[i] = (float)(i % 5); } - Debug3DNoise(In, 3, 3, 3, "Upscale in"); + Debug3DNoise(In, 3, 3, 3, "Upscale3D in"); float Out[17 * 33 * 35]; LinearUpscale3DArray(In, 3, 3, 3, Out, 8, 16, 17); - Debug3DNoise(Out, 17, 33, 35, "Upscale test"); + Debug3DNoise(Out, 17, 33, 35, "Upscale3D test"); } + + + void DoTest2(void) + { + float In[3 * 3]; + for (int i = 0; i < ARRAYCOUNT(In); i++) + { + In[i] = (float)(i % 5); + } + Debug2DNoise(In, 3, 3, "Upscale2D in"); + float Out[17 * 33]; + LinearUpscale2DArray(In, 3, 3, Out, 8, 16); + Debug2DNoise(Out, 17, 33, "Upscale2D test"); + } + } gTest; //*/ diff --git a/source/LinearUpscale.h b/source/LinearUpscale.h index 60aa005bd..9f40b5d81 100644 --- a/source/LinearUpscale.h +++ b/source/LinearUpscale.h @@ -88,49 +88,59 @@ template void LinearUpscale2DArray( int a_UpscaleX, int a_UpscaleY ///< 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; + ASSERT(a_Src != NULL); ASSERT(a_Dst != NULL); ASSERT(a_SrcSizeX > 0); ASSERT(a_SrcSizeY > 0); ASSERT(a_UpscaleX > 0); ASSERT(a_UpscaleY > 0); + ASSERT(a_UpscaleX <= MAX_UPSCALE_X); + ASSERT(a_UpscaleY <= MAX_UPSCALE_Y); - // First interpolate columns (same-Y) where the anchor points are: - int idx = 0; - for (int y = 0; y < a_SrcSizeY; y++) + // Pre-calculate the upscaling ratios: + TYPE RatioX[MAX_UPSCALE_X]; + TYPE RatioY[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; + } + + // Interpolate each XY cell: + int DstSizeX = (a_SrcSizeX - 1) * a_UpscaleX + 1; + int DstSizeY = (a_SrcSizeY - 1) * a_UpscaleY + 1; + for (int y = 0; y < (a_SrcSizeY - 1); y++) { int DstY = y * a_UpscaleY; - for (int x = 0; x < a_SrcSizeX; x++) + int idx = y * a_SrcSizeX; + for (int x = 0; x < (a_SrcSizeX - 1); x++, idx++) { 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; + TYPE LoXLoY = a_Src[idx]; + TYPE LoXHiY = a_Src[idx + a_SrcSizeX]; + TYPE HiXLoY = a_Src[idx + 1]; + TYPE HiXHiY = a_Src[idx + 1 + a_SrcSizeX]; for (int CellY = 0; CellY <= a_UpscaleY; CellY++) { - a_Dst[DstX + (DstY + CellY) * a_SizeY] = StartValue + Diff * CellY / a_AnchorStepY; + int DestIdx = (DstY + CellY) * DstSizeX + DstX; + ASSERT(DestIdx + a_UpscaleX < DstSizeX * DstSizeY); + TYPE LoXInY = LoXLoY + (LoXHiY - LoXLoY) * RatioY[CellY]; + TYPE HiXInY = HiXLoY + (HiXHiY - HiXLoY) * RatioY[CellY]; + for (int CellX = 0; CellX <= a_UpscaleX; CellX++, DestIdx++) + { + a_Dst[DestIdx] = LoXInY + (HiXInY - LoXInY) * RatioX[CellX]; + } } // 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; - } - } } diff --git a/source/Noise.cpp b/source/Noise.cpp index 87b3bd4a5..333dc8333 100644 --- a/source/Noise.cpp +++ b/source/Noise.cpp @@ -570,7 +570,7 @@ void cCubicNoise::Generate2D( m_NumSingleY++; } m_NumCalls++; - #endif _DEBUG + #endif // _DEBUG // Calculate query values using Cell: int FromY = 0;