From 0a904793ee03739a9fa44fe15d1fc4fb50eaad9d Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 12 Apr 2017 13:51:32 +1000 Subject: [PATCH] Port more of NotchyGen --- src/Client/Compiler.h | 7 +- src/Client/Funcs.h | 5 +- src/Client/Noise.c | 14 +-- src/Client/Noise.h | 6 +- src/Client/NotchyGenerator.c | 197 +++++++++++++++++++++++++++++++++-- src/Client/NotchyGenerator.h | 12 ++- src/Client/Random.c | 4 +- src/Client/Random.h | 4 +- src/Client/Typedefs.h | 3 + 9 files changed, 225 insertions(+), 27 deletions(-) diff --git a/src/Client/Compiler.h b/src/Client/Compiler.h index 45230be18..e43c54829 100644 --- a/src/Client/Compiler.h +++ b/src/Client/Compiler.h @@ -9,11 +9,14 @@ // defined with this macro as being exported. #ifdef CLIENT_EXPORTS -#define CLIENT_API __declspec(dllexport) +#define CLIENT_FUNC __declspec(dllexport) #else -#define CLIENT_API __declspec(dllimport) +#define CLIENT_FUNC __declspec(dllimport) #endif +#define EXPORT_FUNC __declspec(dllexport) +#define IMPORT_FUNC __declspec(dllimport) + /* #include "Client.h" diff --git a/src/Client/Funcs.h b/src/Client/Funcs.h index 16b261425..25d8e7653 100644 --- a/src/Client/Funcs.h +++ b/src/Client/Funcs.h @@ -1,6 +1,7 @@ #ifndef CS_FUNCS_H #define CS_FUNCS_H -#define min(x, y) (x) < (y) ? (x) : (y) -#define max(x, y) (x) > (y) ? (x) : (y) +#define min(x, y) ((x) < (y) ? (x) : (y)) +#define max(x, y) ((x) > (y) ? (x) : (y)) +#define abs(x) (x >= 0 ? x : -x) #endif \ No newline at end of file diff --git a/src/Client/Noise.c b/src/Client/Noise.c index 06f16f8b1..9fec335ac 100644 --- a/src/Client/Noise.c +++ b/src/Client/Noise.c @@ -7,7 +7,7 @@ void ImprovedNoise_Init(UInt8* p, Random* rnd) { } for (Int32 i = 0; i < 256; i++) { - Int32 j = Random_NextRange(rnd, i, 256); + Int32 j = Random_Range(rnd, i, 256); UInt8 temp = p[i]; p[i] = p[j]; p[j] = temp; } @@ -16,7 +16,7 @@ void ImprovedNoise_Init(UInt8* p, Random* rnd) { } } -Real32 ImprovedNoise_Compute(UInt8* p, Real32 x, Real32 y) { +Real32 ImprovedNoise_Calc(UInt8* p, Real32 x, Real32 y) { Int32 xFloor = x >= 0 ? (Int32)x : (Int32)x - 1; Int32 yFloor = y >= 0 ? (Int32)y : (Int32)y - 1; Int32 X = xFloor & 0xFF, Y = yFloor & 0xFF; @@ -55,12 +55,12 @@ void OctaveNoise_Init(OctaveNoise* n, Random* rnd, Int32 octaves) { } } -Real32 OctaveNoise_Compute(OctaveNoise* n, Real32 x, Real32 y) { +Real32 OctaveNoise_Calc(OctaveNoise* n, Real32 x, Real32 y) { Real32 amplitude = 1, freq = 1; Real32 sum = 0; for (Int32 i = 0; i < n->octaves; i++) { - sum += ImprovedNoise_Compute(n->p[i], x * freq, y * freq) * amplitude; + sum += ImprovedNoise_Calc(n->p[i], x * freq, y * freq) * amplitude; amplitude *= 2.0; freq *= 0.5; } @@ -73,7 +73,7 @@ void CombinedNoise_Init(CombinedNoise* n, Random* rnd, Int32 octaves1, Int32 oct OctaveNoise_Init(&n->noise2, rnd, octaves2); } -Real32 CombinedNoise_Compute(CombinedNoise* n, Real32 x, Real32 y) { - Real32 offset = OctaveNoise_Compute(&n->noise2, x, y); - return OctaveNoise_Compute(&n->noise1, x + offset, y); +Real32 CombinedNoise_Calc(CombinedNoise* n, Real32 x, Real32 y) { + Real32 offset = OctaveNoise_Calc(&n->noise2, x, y); + return OctaveNoise_Calc(&n->noise1, x + offset, y); } \ No newline at end of file diff --git a/src/Client/Noise.h b/src/Client/Noise.h index cf7be012b..20a8667f3 100644 --- a/src/Client/Noise.h +++ b/src/Client/Noise.h @@ -5,7 +5,7 @@ #define NOISE_TABLE_SIZE 512 void ImprovedNoise_Init(UInt8* p, Random* rnd); -Real32 ImprovedNoise_Compute(UInt8* p, Real32 x, Real32 y); +Real32 ImprovedNoise_Calc(UInt8* p, Real32 x, Real32 y); /* since we need structure to be a fixed size */ @@ -15,7 +15,7 @@ typedef struct { Int32 octaves; } OctaveNoise; void OctaveNoise_Init(OctaveNoise* n, Random* rnd, Int32 octaves); -Real32 OctaveNoise_Compute(OctaveNoise* n, Real32 x, Real32 y); +Real32 OctaveNoise_Calc(OctaveNoise* n, Real32 x, Real32 y); typedef struct { @@ -23,6 +23,6 @@ typedef struct { OctaveNoise noise2; } CombinedNoise; void CombinedNoise_Init(CombinedNoise* n, Random* rnd, Int32 octaves1, Int32 octaves2); -Real32 CombinedNoise_Compute(CombinedNoise* n, Real32 x, Real32 y); +Real32 CombinedNoise_Calc(CombinedNoise* n, Real32 x, Real32 y); #endif \ No newline at end of file diff --git a/src/Client/NotchyGenerator.c b/src/Client/NotchyGenerator.c index 56027e45b..b808291b8 100644 --- a/src/Client/NotchyGenerator.c +++ b/src/Client/NotchyGenerator.c @@ -15,7 +15,7 @@ Real32 CurrentProgress; /* Internal variables */ Int32 Width, Height, Length; -Int32 waterLevel, oneY, minHeight; +Int32 waterLevel, oneY, volume, minHeight; BlockID* Blocks; Int16* Heightmap; Random rnd; @@ -26,6 +26,7 @@ void NotchyGen_Init(Int32 width, Int32 height, Int32 length, Blocks = blocks; Heightmap = heightmap; oneY = Width * Length; + volume = Width * Length * Height; waterLevel = Height / 2; Random_Init(&rnd, seed); minHeight = Height; @@ -47,10 +48,10 @@ void NotchyGen_CreateHeightmap() { for (Int32 z = 0; z < Length; z++) { CurrentProgress = (Real32)z / Length; for (Int32 x = 0; x < Width; x++) { - Real32 hLow = CombinedNoise_Compute(&n1, x * 1.3f, z * 1.3f) / 6 - 4, height = hLow; + Real32 hLow = CombinedNoise_Calc(&n1, x * 1.3f, z * 1.3f) / 6 - 4, height = hLow; - if (OctaveNoise_Compute(&n3, x, z) <= 0) { - Real32 hHigh = CombinedNoise_Compute(&n2, x * 1.3f, z * 1.3f) / 5 + 6; + if (OctaveNoise_Calc(&n3, x, z) <= 0) { + Real32 hHigh = CombinedNoise_Calc(&n2, x * 1.3f, z * 1.3f) / 5 + 6; height = max(hLow, hHigh); } @@ -75,7 +76,7 @@ void NotchyGen_CreateStrata() { for (Int32 z = 0; z < Length; z++) { CurrentProgress = (Real32)z / Length; for (Int32 x = 0; x < Width; x++) { - Int32 dirtThickness = (Int32)(OctaveNoise_Compute(&n, x, z) / 24 - 4); + Int32 dirtThickness = (Int32)(OctaveNoise_Calc(&n, x, z) / 24 - 4); Int32 dirtHeight = Heightmap[hMapIndex++]; Int32 stoneHeight = dirtHeight + dirtThickness; @@ -100,7 +101,7 @@ Int32 NotchyGen_CreateStrataFast() { /* Make lava layer at bottom */ Int32 mapIndex = 0; for (Int32 z = 0; z < Length; z++) - for (int x = 0; x < Width; x++) + for (Int32 x = 0; x < Width; x++) { Blocks[mapIndex++] = Block_Lava; } @@ -117,4 +118,188 @@ Int32 NotchyGen_CreateStrataFast() { Blocks[mapIndex++] = Block_Stone; } return stoneHeight; +} + +void NotchyGen_CreateSurfaceLayer() { + OctaveNoise n1, n2; + OctaveNoise_Init(&n1, &rnd, 8); + OctaveNoise_Init(&n2, &rnd, 8); + //CurrentState = "Creating surface"; + /* TODO: update heightmap */ + + Int32 hMapIndex = 0; + for (Int32 z = 0; z < Length; z++) { + CurrentProgress = (Real32)z / Length; + for (Int32 x = 0; x < Width; x++) { + Int32 y = Heightmap[hMapIndex++]; + if (y < 0 || y >= Height) continue; + + Int32 index = (y * Length + z) * Width + x; + BlockID blockAbove = y >= (Height - 1) ? Block_Air : Blocks[index + oneY]; + if (blockAbove == Block_Water && (OctaveNoise_Calc(&n2, x, z) > 12)) { + Blocks[index] = Block_Gravel; + } else if (blockAbove == Block_Air) { + Blocks[index] = (y <= waterLevel && (OctaveNoise_Calc(&n1, x, z) > 8)) ? Block_Sand : Block_Grass; + } + } + } +} + +void NotchyGen_PlantFlowers() { + Int32 numPatches = Width * Length / 3000; + //CurrentState = "Planting flowers"; + + for (Int32 i = 0; i < numPatches; i++) { + CurrentProgress = (Real32)i / numPatches; + BlockID type = (BlockID)(Block_Dandelion + Random_Next(&rnd, 2)); + Int32 patchX = Random_Next(&rnd, Width), patchZ = Random_Next(&rnd, Length); + for (Int32 j = 0; j < 10; j++) { + Int32 flowerX = patchX, flowerZ = patchZ; + for (Int32 k = 0; k < 5; k++) { + flowerX += Random_Next(&rnd, 6) - Random_Next(&rnd, 6); + flowerZ += Random_Next(&rnd, 6) - Random_Next(&rnd, 6); + if (flowerX < 0 || flowerZ < 0 || flowerX >= Width || flowerZ >= Length) + continue; + + Int32 flowerY = Heightmap[flowerZ * Width + flowerX] + 1; + if (flowerY <= 0 || flowerY >= Height) continue; + + Int32 index = (flowerY * Length + flowerZ) * Width + flowerX; + if (Blocks[index] == Block_Air && Blocks[index - oneY] == Block_Grass) + Blocks[index] = type; + } + } + } +} + +void NotchyGen_PlantMushrooms() { + Int32 numPatches = volume / 2000; + //CurrentState = "Planting mushrooms"; + + for (Int32 i = 0; i < numPatches; i++) { + CurrentProgress = (Real32)i / numPatches; + BlockID type = (BlockID)(Block_BrownMushroom + Random_Next(&rnd, 2)); + Int32 patchX = Random_Next(&rnd, Width); + Int32 patchY = Random_Next(&rnd, Height); + Int32 patchZ = Random_Next(&rnd, Length); + + for (Int32 j = 0; j < 20; j++) { + Int32 mushX = patchX, mushY = patchY, mushZ = patchZ; + for (Int32 k = 0; k < 5; k++) { + mushX += Random_Next(&rnd, 6) - Random_Next(&rnd, 6); + mushZ += Random_Next(&rnd, 6) - Random_Next(&rnd, 6); + if (mushX < 0 || mushZ < 0 || mushX >= Width || mushZ >= Length) + continue; + + Int32 solidHeight = Heightmap[mushZ * Width + mushX]; + if (mushY >= (solidHeight - 1)) + continue; + + Int32 index = (mushY * Length + mushZ) * Width + mushX; + if (Blocks[index] == Block_Air && Blocks[index - oneY] == Block_Stone) + Blocks[index] = type; + } + } + } +} + +void NotchyGen_PlantTrees() { + Int32 numPatches = Width * Length / 4000; + //CurrentState = "Planting trees"; + + for (Int32 i = 0; i < numPatches; i++) { + CurrentProgress = (Real32)i / numPatches; + Int32 patchX = Random_Next(&rnd, Width), patchZ = Random_Next(&rnd, Length); + + for (Int32 j = 0; j < 20; j++) { + Int32 treeX = patchX, treeZ = patchZ; + for (Int32 k = 0; k < 20; k++) { + treeX += Random_Next(&rnd, 6) - Random_Next(&rnd, 6); + treeZ += Random_Next(&rnd, 6) - Random_Next(&rnd, 6); + if (treeX < 0 || treeZ < 0 || treeX >= Width || + treeZ >= Length || Random_Float(&rnd) >= 0.25) + continue; + + Int32 treeY = Heightmap[treeZ * Width + treeX] + 1; + Int32 treeHeight = 5 + Random_Next(&rnd, 3); + + Int32 index = (treeY * Length + treeZ) * Width + treeX; + BlockID blockUnder = treeY > 0 ? Blocks[index - oneY] : Block_Air; + + if (blockUnder == Block_Grass && NotchyGen_CanGrowTree(treeX, treeY, treeZ, treeHeight)) { + NotchyGen_GrowTree(treeX, treeY, treeZ, treeHeight); + } + } + } + } +} + +bool NotchyGen_CanGrowTree(Int32 treeX, Int32 treeY, Int32 treeZ, Int32 treeHeight) { + // check tree base + Int32 baseHeight = treeHeight - 4; + for (Int32 y = treeY; y < treeY + baseHeight; y++) + for (Int32 z = treeZ - 1; z <= treeZ + 1; z++) + for (Int32 x = treeX - 1; x <= treeX + 1; x++) + { + if (x < 0 || y < 0 || z < 0 || x >= Width || y >= Height || z >= Length) + return false; + Int32 index = (y * Length + z) * Width + x; + if (Blocks[index] != 0) return false; + } + + // and also check canopy + for (Int32 y = treeY + baseHeight; y < treeY + treeHeight; y++) + for (Int32 z = treeZ - 2; z <= treeZ + 2; z++) + for (Int32 x = treeX - 2; x <= treeX + 2; x++) + { + if (x < 0 || y < 0 || z < 0 || x >= Width || y >= Height || z >= Length) + return false; + Int32 index = (y * Length + z) * Width + x; + if (Blocks[index] != 0) return false; + } + return true; +} + +void Notchy_GenTree(Int32 treeX, Int32 treeY, Int32 treeZ, Int32 height) { + Int32 baseHeight = height - 4; + Int32 index = 0; + + // leaves bottom layer + for (Int32 y = treeY + baseHeight; y < treeY + baseHeight + 2; y++) + for (Int32 zz = -2; zz <= 2; zz++) + for (Int32 xx = -2; xx <= 2; xx++) + { + Int32 x = xx + treeX, z = zz + treeZ; + index = (y * Length + z) * Width + x; + + if (abs(xx) == 2 && abs(zz) == 2) { + if (Random_Float(&rnd) >= 0.5f) + Blocks[index] = Block_Leaves; + } else { + Blocks[index] = Block_Leaves; + } + } + + // leaves top layer + Int32 bottomY = treeY + baseHeight + 2; + for (Int32 y = treeY + baseHeight + 2; y < treeY + height; y++) + for (Int32 zz = -1; zz <= 1; zz++) + for (Int32 xx = -1; xx <= 1; xx++) + { + Int32 x = xx + treeX, z = zz + treeZ; + index = (y * Length + z) * Width + x; + + if (xx == 0 || zz == 0) { + Blocks[index] = Block_Leaves; + } else if (y == bottomY && Random_Float(&rnd) >= 0.5f) { + Blocks[index] = Block_Leaves; + } + } + + // then place trunk + index = (treeY * Length + treeZ) * Width + treeX; + for (Int32 y = 0; y < height - 1; y++) { + Blocks[index] = Block_Log; + index += oneY; + } } \ No newline at end of file diff --git a/src/Client/NotchyGenerator.h b/src/Client/NotchyGenerator.h index 9c794e4b3..23e1a40b6 100644 --- a/src/Client/NotchyGenerator.h +++ b/src/Client/NotchyGenerator.h @@ -3,10 +3,16 @@ #include "Compiler.h" #include "Typedefs.h" -CLIENT_API void NotchyGen_Init(Int32 width, Int32 height, Int32 length, +CLIENT_FUNC void NotchyGen_Init(Int32 width, Int32 height, Int32 length, Int32 seed, BlockID* blocks, Int16* heightmap); -CLIENT_API void NotchyGen_CreateHeightmap(); -CLIENT_API void NotchyGen_CreateStrata(); +CLIENT_FUNC void NotchyGen_CreateHeightmap(); +CLIENT_FUNC void NotchyGen_CreateStrata(); Int32 NotchyGen_CreateStrataFast(); +CLIENT_FUNC void NotchyGen_CreateSurfaceLayer(); +CLIENT_FUNC void NotchyGen_PlantFlowers(); +CLIENT_FUNC void NotchyGen_PlantMushrooms(); +CLIENT_FUNC void NotchyGen_PlantTrees(); +bool NotchyGen_CanGrowTree(Int32 treeX, Int32 treeY, Int32 treeZ, Int32 treeHeight); +void Notchy_GenTree(Int32 treeX, Int32 treeY, Int32 treeZ, Int32 height); #endif \ No newline at end of file diff --git a/src/Client/Random.c b/src/Client/Random.c index 6e316dbd7..846b971a8 100644 --- a/src/Client/Random.c +++ b/src/Client/Random.c @@ -9,7 +9,7 @@ void Random_Init(Random* seed, Int32 seedInit) { *seed = (seedInit ^ value) & mask; } -Int32 Random_NextRange(Random* seed, Int32 min, Int32 max) { +Int32 Random_Range(Random* seed, Int32 min, Int32 max) { return min + Random_Next(seed, max - min); } @@ -29,7 +29,7 @@ Int32 Random_Next(Random* seed, Int32 n) { return val; } -Real32 Random_NextFloat(Random* seed) { +Real32 Random_Float(Random* seed) { *seed = (*seed * value + 0xBLL) & mask; Int32 raw = (Int32)((UInt64)*seed >> (48 - 24)); return raw / ((Real32)(1 << 24)); diff --git a/src/Client/Random.h b/src/Client/Random.h index e866a5a6f..869246ebb 100644 --- a/src/Client/Random.h +++ b/src/Client/Random.h @@ -6,7 +6,7 @@ typedef Int64 Random; void Random_Init(Random* rnd, Int32 seed); -Int32 Random_NextRange(Random* rnd, Int32 min, Int32 max); +Int32 Random_Range(Random* rnd, Int32 min, Int32 max); Int32 Random_Next(Random* rnd, Int32 n); -Real32 Random_NextFloat(Random* rnd); +Real32 Random_Float(Random* rnd); #endif \ No newline at end of file diff --git a/src/Client/Typedefs.h b/src/Client/Typedefs.h index 5ca914a1c..3e6a17d03 100644 --- a/src/Client/Typedefs.h +++ b/src/Client/Typedefs.h @@ -15,6 +15,9 @@ typedef signed __int64 Int64; typedef float Real32; typedef double Real64; +typedef UInt8 bool; +#define true 1 +#define false 0 typedef UInt8 BlockID; typedef UInt8 EntityID;