void GetDarkoakTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { // Pick a height int Height = 5 + (a_Noise.IntNoise3DInt(a_BlockX + 32 * a_Seq, a_BlockY, a_BlockZ + 32 * a_Seq) / 11) % 4; // Create the trunk for (int i = 0; i < Height; i++) { a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD)); a_LogBlocks.push_back(sSetBlock(a_BlockX + 1, a_BlockY + i, a_BlockZ, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD)); a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ + 1, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD)); a_LogBlocks.push_back(sSetBlock(a_BlockX + 1, a_BlockY + i, a_BlockZ + 1, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD)); } // Create branches for (int i = 0; i < 3; i++) { int x = (a_Noise.IntNoise3DInt(a_BlockX + 32 * a_Seq, a_BlockY * i, a_BlockZ + 32 * a_Seq) % 3) - 1; int z = (a_Noise.IntNoise3DInt(a_BlockX - 32 * a_Seq, a_BlockY * i, a_BlockZ - 32 * a_Seq) % 3) - 1; // The branches would end up in the trunk. if ((x >= a_BlockX) && (x <= a_BlockX + 1) && (z >= a_BlockZ) && (z <= a_BlockZ + 1)) { NOISE_DATATYPE Val1 = a_Noise.IntNoise2D(x, z); if (Val1 < 0) { x = a_BlockX + ((Val1 < -0.5) ? -1 : 3); } else { z = a_BlockZ + ((Val1 < 0.5) ? -1 : 3); } } int y = Height - (a_Noise.IntNoise3DInt(a_BlockX + x, a_BlockY * i, a_BlockZ - z) % (Height - (Height / 4))); for (int Y = y; Y < Height; Y++) { a_LogBlocks.push_back(sSetBlock(a_BlockX + x, a_BlockY + Y, a_BlockZ + z, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD)); } } int hei = a_BlockY + Height - 2; // The lower two leaves layers are BigO4 with log in the middle and possibly corners: for (int i = 0; i < 2; i++) { PushCoordBlocks(a_BlockX, hei, a_BlockZ, a_OtherBlocks, BigO4, ARRAYCOUNT(BigO4), E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD); PushCornerBlocks(a_BlockX, hei, a_BlockZ, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 3, E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD); hei++; } // for i < 2 // The top leaves layer is a BigO3 with leaves in the middle and possibly corners: PushCoordBlocks(a_BlockX, hei, a_BlockZ, a_OtherBlocks, BigO3, ARRAYCOUNT(BigO3), E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD); PushCornerBlocks(a_BlockX, hei, a_BlockZ, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 3, E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD); a_OtherBlocks.push_back(sSetBlock(a_BlockX, hei, a_BlockZ, E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD)); }
void GetBirchTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { int Height = 5 + (a_Noise.IntNoise3DInt(a_BlockX + 64 * a_Seq, a_BlockY, a_BlockZ) % 3); // Prealloc, so that we don't realloc too often later: a_LogBlocks.reserve(Height); a_OtherBlocks.reserve(80); // The entire trunk, out of logs: for (int i = Height - 1; i >= 0; --i) { a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ, E_BLOCK_LOG, E_META_LOG_BIRCH)); } int h = a_BlockY + Height; // Top layer - just the Plus: PushCoordBlocks(a_BlockX, h, a_BlockZ, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_BIRCH); a_OtherBlocks.push_back(sSetBlock(a_BlockX, h, a_BlockZ, E_BLOCK_LEAVES, E_META_LEAVES_BIRCH)); // There's no log at this layer h--; // Second layer - log, Plus and maybe Corners: PushCoordBlocks (a_BlockX, h, a_BlockZ, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_BIRCH); PushCornerBlocks(a_BlockX, h, a_BlockZ, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 1, E_BLOCK_LEAVES, E_META_LEAVES_BIRCH); h--; // Third and fourth layers - BigO2 and maybe 2*Corners: for (int Row = 0; Row < 2; Row++) { PushCoordBlocks (a_BlockX, h, a_BlockZ, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_LEAVES, E_META_LEAVES_BIRCH); PushCornerBlocks(a_BlockX, h, a_BlockZ, a_Seq, a_Noise, 0x3fffffff + Row * 0x10000000, a_OtherBlocks, 2, E_BLOCK_LEAVES, E_META_LEAVES_BIRCH); h--; } // for Row - 2* }
void GetJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { if (a_Noise.IntNoise3DInt(a_BlockX + 32 * a_Seq, a_BlockY + 32 * a_Seq, a_BlockZ) < 0x60000000) { GetSmallJungleTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } else { GetLargeJungleTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } }
static float GetMarbleNoise( float x, float y, float z, cNoise & a_Noise ) { static const float PI_2 = 1.57079633f; float oct1 = (a_Noise.CubicNoise3D(x * 0.1f, y * 0.1f, z * 0.1f )) * 4; oct1 = oct1 * oct1 * oct1; if (oct1 < 0.f) oct1 = PI_2; if (oct1 > PI_2) oct1 = PI_2; return oct1; }
cStructGenWormNestCaves::cCaveSystem::cCaveSystem(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ, int a_MaxOffset, int a_Size, cNoise & a_Noise) : super(a_GridX, a_GridZ, a_OriginX, a_OriginZ), m_Size(a_Size) { int Num = 1 + a_Noise.IntNoise2DInt(a_OriginX, a_OriginZ) % 3; for (int i = 0; i < Num; i++) { int OriginX = a_OriginX + (a_Noise.IntNoise3DInt(13 * a_OriginX, 17 * a_OriginZ, 11 * i) / 19) % a_MaxOffset; int OriginZ = a_OriginZ + (a_Noise.IntNoise3DInt(17 * a_OriginX, 13 * a_OriginZ, 11 * i) / 23) % a_MaxOffset; int OriginY = 20 + (a_Noise.IntNoise3DInt(19 * a_OriginX, 13 * a_OriginZ, 11 * i) / 17) % 20; // Generate three branches from the origin point: // The tunnels generated depend on X, Y, Z and Branches, // for the same set of numbers it generates the same offsets! // That's why we add a +1 to X in the third line GenerateTunnelsFromPoint(OriginX, OriginY, OriginZ, a_Noise, 3); GenerateTunnelsFromPoint(OriginX, OriginY, OriginZ, a_Noise, 2); GenerateTunnelsFromPoint(OriginX + 1, OriginY, OriginZ, a_Noise, 3); } }
void GetConiferTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { // Half chance for a spruce, half for a pine: if (a_Noise.IntNoise3DInt(a_BlockX + 64 * a_Seq, a_BlockY, a_BlockZ + 32 * a_Seq) < 0x40000000) { GetSpruceTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } else { GetPineTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } }
void InitPerHeightRadius(int a_GridX, int a_GridZ) { int h = 0; while (h < cChunkDef::Height) { m_Noise.SetSeed(m_Seed + h); int rnd = m_Noise.IntNoise2DInt(a_GridX, a_GridZ) / 13; int NumBlocks = (rnd % 3) + 2; rnd = rnd / 4; float Val = (float)(rnd % 256) / 128 - 1; // Random float in range [-1, +1] if (h + NumBlocks > cChunkDef::Height) { NumBlocks = cChunkDef::Height - h; } for (int i = 0; i < NumBlocks; i++) { m_PerHeightRadius[h + i] = Val; } h += NumBlocks; } }
void cStructGenWormNestCaves::cCaveSystem::GenerateTunnelsFromPoint( int a_OriginX, int a_OriginY, int a_OriginZ, cNoise & a_Noise, int a_NumSegments ) { int DoubleSize = m_Size * 2; int Radius = GetRadius(a_Noise, a_OriginX + a_OriginY, a_OriginY + a_OriginZ, a_OriginZ + a_OriginX); for (int i = a_NumSegments - 1; i >= 0; --i) { int EndX = a_OriginX + (((a_Noise.IntNoise3DInt(a_OriginX, a_OriginY, a_OriginZ + 11 * a_NumSegments) / 7) % DoubleSize) - m_Size) / 2; int EndY = a_OriginY + (((a_Noise.IntNoise3DInt(a_OriginY, 13 * a_NumSegments, a_OriginZ + a_OriginX) / 7) % DoubleSize) - m_Size) / 4; int EndZ = a_OriginZ + (((a_Noise.IntNoise3DInt(a_OriginZ + 17 * a_NumSegments, a_OriginX, a_OriginY) / 7) % DoubleSize) - m_Size) / 2; int EndR = GetRadius(a_Noise, a_OriginX + 7 * i, a_OriginY + 11 * i, a_OriginZ + a_OriginX); m_Tunnels.push_back(new cCaveTunnel(a_OriginX, a_OriginY, a_OriginZ, Radius, EndX, EndY, EndZ, EndR, a_Noise)); GenerateTunnelsFromPoint(EndX, EndY, EndZ, a_Noise, i); a_OriginX = EndX; a_OriginY = EndY; a_OriginZ = EndZ; Radius = EndR; } // for i - a_NumSegments }
inline void PushCornerBlocks(int a_BlockX, int a_Height, int a_BlockZ, int a_Seq, cNoise & a_Noise, int a_Chance, sSetBlockVector & a_Blocks, int a_CornersDist, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) { for (size_t i = 0; i < ARRAYCOUNT(Corners); i++) { int x = a_BlockX + Corners[i].x; int z = a_BlockZ + Corners[i].z; if (a_Noise.IntNoise3DInt(x + 64 * a_Seq, a_Height, z + 64 * a_Seq) <= a_Chance) { a_Blocks.push_back(sSetBlock(x, a_Height, z, a_BlockType, a_Meta)); } } // for i - Corners[] }
void GetSmallJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { // Vines are around the BigO3, but not in the corners; need proper meta for direction static const sMetaCoords Vines[] = { {-2, -4, 1}, {-1, -4, 1}, {0, -4, 1}, {1, -4, 1}, {2, -4, 1}, // North face {-2, 4, 4}, {-1, 4, 4}, {0, 4, 4}, {1, 4, 4}, {2, 4, 4}, // South face {4, -2, 2}, {4, -1, 2}, {4, 0, 2}, {4, 1, 2}, {4, 2, 2}, // East face {-4, -2, 8}, {-4, -1, 8}, {-4, 0, 8}, {-4, 1, 8}, // West face // TODO: proper metas and height: {0, 1, 1}, {0, -1, 4}, {-1, 0, 2}, {1, 1, 8}, // Around the tunk } ; int Height = 7 + (a_Noise.IntNoise3DInt(a_BlockX + 5 * a_Seq, a_BlockY, a_BlockZ + 5 * a_Seq) / 5) % 3; a_LogBlocks.reserve(Height); a_OtherBlocks.reserve( 2 * ARRAYCOUNT(BigO3) + // O3 layer, 2x 2 * ARRAYCOUNT(BigO2) + // O2 layer, 2x ARRAYCOUNT(BigO1) + 1 + // Plus on the top Height * ARRAYCOUNT(Vines) + // Vines 50 // some safety ); for (int i = 0; i < Height; i++) { a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ, E_BLOCK_LOG, E_META_LOG_JUNGLE)); } int hei = a_BlockY + Height - 3; // Put vines around the lowermost leaves layer: PushSomeColumns(a_BlockX, hei, a_BlockZ, Height, a_Seq, a_Noise, 0x3fffffff, a_OtherBlocks, Vines, ARRAYCOUNT(Vines), E_BLOCK_VINES); // The lower two leaves layers are BigO3 with log in the middle and possibly corners: for (int i = 0; i < 2; i++) { PushCoordBlocks(a_BlockX, hei, a_BlockZ, a_OtherBlocks, BigO3, ARRAYCOUNT(BigO3), E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE); PushCornerBlocks(a_BlockX, hei, a_BlockZ, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 3, E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE); hei++; } // for i - 2* // Two layers of BigO2 leaves, possibly with corners: for (int i = 0; i < 1; i++) { PushCoordBlocks(a_BlockX, hei, a_BlockZ, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE); PushCornerBlocks(a_BlockX, hei, a_BlockZ, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 2, E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE); hei++; } // for i - 2* // Top plus, all leaves: PushCoordBlocks(a_BlockX, hei, a_BlockZ, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE); a_OtherBlocks.push_back(sSetBlock(a_BlockX, hei, a_BlockZ, E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE)); }
void cStructGenRavines::cRavine::GenerateBaseDefPoints(int a_BlockX, int a_BlockZ, int a_Size, cNoise & a_Noise) { // Modify the size slightly to have different-sized ravines (1 / 2 to 1 / 1 of a_Size): a_Size = (512 + ((a_Noise.IntNoise3DInt(19 * a_BlockX, 11 * a_BlockZ, a_BlockX + a_BlockZ) / 17) % 512)) * a_Size / 1024; // The complete offset of the ravine from its cellpoint, up to 2 * a_Size in each direction int OffsetX = (((a_Noise.IntNoise3DInt(50 * a_BlockX, 30 * a_BlockZ, 0) / 9) % (2 * a_Size)) + ((a_Noise.IntNoise3DInt(30 * a_BlockX, 50 * a_BlockZ, 1000) / 7) % (2 * a_Size)) - 2 * a_Size) / 2; int OffsetZ = (((a_Noise.IntNoise3DInt(50 * a_BlockX, 30 * a_BlockZ, 2000) / 7) % (2 * a_Size)) + ((a_Noise.IntNoise3DInt(30 * a_BlockX, 50 * a_BlockZ, 3000) / 9) % (2 * a_Size)) - 2 * a_Size) / 2; int CenterX = a_BlockX + OffsetX; int CenterZ = a_BlockZ + OffsetZ; // Get the base angle in which the ravine "axis" goes: float Angle = static_cast<float>((static_cast<float>((a_Noise.IntNoise3DInt(20 * a_BlockX, 70 * a_BlockZ, 6000) / 9) % 16384)) / 16384.0 * M_PI); float xc = sinf(Angle); float zc = cosf(Angle); // Calculate the definition points and radii: int MaxRadius = static_cast<int>(sqrt(12.0 + ((a_Noise.IntNoise2DInt(61 * a_BlockX, 97 * a_BlockZ) / 13) % a_Size) / 16)); int Top = 32 + ((a_Noise.IntNoise2DInt(13 * a_BlockX, 17 * a_BlockZ) / 23) % 32); int Bottom = 5 + ((a_Noise.IntNoise2DInt(17 * a_BlockX, 29 * a_BlockZ) / 13) % 32); int Mid = (Top + Bottom) / 2; int DefinitionPointX = CenterX - static_cast<int>(xc * a_Size / 2); int DefinitionPointZ = CenterZ - static_cast<int>(zc * a_Size / 2); m_Points.push_back(cRavDefPoint(DefinitionPointX, DefinitionPointZ, 0, (Mid + Top) / 2, (Mid + Bottom) / 2)); for (int i = 1; i < NUM_RAVINE_POINTS - 1; i++) { int LineX = CenterX + static_cast<int>(xc * a_Size * (i - NUM_RAVINE_POINTS / 2) / NUM_RAVINE_POINTS); int LineZ = CenterZ + static_cast<int>(zc * a_Size * (i - NUM_RAVINE_POINTS / 2) / NUM_RAVINE_POINTS); // Amplitude is the amount of blocks that this point is away from the ravine "axis" int Amplitude = (a_Noise.IntNoise3DInt(70 * a_BlockX, 20 * a_BlockZ + 31 * i, 10000 * i) / 9) % a_Size; Amplitude = Amplitude / 4 - a_Size / 8; // Amplitude is in interval [-a_Size / 4, a_Size / 4] int PointX = LineX + static_cast<int>(zc * Amplitude); int PointZ = LineZ - static_cast<int>(xc * Amplitude); int Radius = MaxRadius - abs(i - NUM_RAVINE_POINTS / 2); // TODO: better radius function int ThisTop = Top + ((a_Noise.IntNoise3DInt(7 * a_BlockX, 19 * a_BlockZ, i * 31) / 13) % 8) - 4; int ThisBottom = Bottom + ((a_Noise.IntNoise3DInt(19 * a_BlockX, 7 * a_BlockZ, i * 31) / 13) % 8) - 4; m_Points.push_back(cRavDefPoint(PointX, PointZ, Radius, ThisTop, ThisBottom)); } // for i - m_Points[] DefinitionPointX = CenterX + static_cast<int>(xc * a_Size / 2); DefinitionPointZ = CenterZ + static_cast<int>(zc * a_Size / 2); m_Points.push_back(cRavDefPoint(DefinitionPointX, DefinitionPointZ, 0, Mid, Mid)); }
inline void PushSomeColumns(int a_BlockX, int a_Height, int a_BlockZ, int a_ColumnHeight, int a_Seq, cNoise & a_Noise, int a_Chance, sSetBlockVector & a_Blocks, const sMetaCoords * a_Coords, size_t a_NumCoords, BLOCKTYPE a_BlockType) { for (size_t i = 0; i < a_NumCoords; i++) { int x = a_BlockX + a_Coords[i].x; int z = a_BlockZ + a_Coords[i].z; if (a_Noise.IntNoise3DInt(x + 64 * a_Seq, a_Height + i, z + 64 * a_Seq) <= a_Chance) { for (int j = 0; j < a_ColumnHeight; j++) { a_Blocks.push_back(sSetBlock(x, a_Height - j, z, a_BlockType, a_Coords[i].Meta)); } } } // for i - a_Coords[] }
void GetPineTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { // Tall, little leaves on top. The top leaves are arranged in a shape of two cones joined by their bases. // There can be one or two layers representing the cone bases (SameSizeMax) int MyRandom = a_Noise.IntNoise3DInt(a_BlockX + 32 * a_Seq, a_BlockY, a_BlockZ + 32 * a_Seq) / 8; int TrunkHeight = 8 + (MyRandom % 3); int SameSizeMax = ((MyRandom & 8) == 0) ? 1 : 0; MyRandom >>= 3; int NumLeavesLayers = 2 + (MyRandom % 3); // Number of layers that have leaves in them if (NumLeavesLayers == 2) { SameSizeMax = 0; } // Pre-allocate the vector: a_LogBlocks.reserve(TrunkHeight); a_OtherBlocks.reserve(NumLeavesLayers * 25); // The entire trunk, out of logs: for (int i = TrunkHeight; i >= 0; --i) { a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ, E_BLOCK_LOG, E_META_LOG_CONIFER)); } int h = a_BlockY + TrunkHeight + 2; // Top layer - just a single leaves block: a_OtherBlocks.push_back(sSetBlock(a_BlockX, h, a_BlockZ, E_BLOCK_LEAVES, E_META_LEAVES_CONIFER)); h--; // One more layer is above the trunk, push the central leaves: a_OtherBlocks.push_back(sSetBlock(a_BlockX, h, a_BlockZ, E_BLOCK_LEAVES, E_META_LEAVES_CONIFER)); // Layers expanding in size, then collapsing again: // LOGD("Generating %d layers of pine leaves, SameSizeMax = %d", NumLeavesLayers, SameSizeMax); for (int i = 0; i < NumLeavesLayers; ++i) { int LayerSize = std::min(i, NumLeavesLayers - i + SameSizeMax - 1); // LOGD("LayerSize %d: %d", i, LayerSize); if (LayerSize < 0) { break; } ASSERT(LayerSize < ARRAYCOUNT(BigOs)); PushCoordBlocks(a_BlockX, h, a_BlockZ, a_OtherBlocks, BigOs[LayerSize].Coords, BigOs[LayerSize].Count, E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); h--; } }
int cStructGenWormNestCaves::cCaveSystem::GetRadius(cNoise & a_Noise, int a_OriginX, int a_OriginY, int a_OriginZ) { // Instead of a flat distribution noise function, we need to shape it, so that most caves are smallish and only a few select are large int rnd = a_Noise.IntNoise3DInt(a_OriginX, a_OriginY, a_OriginZ) / 11; /* // Not good enough: // The algorithm of choice: emulate gauss-distribution noise by adding 3 flat noises, then fold it in half using absolute value. // To save on processing, use one random value and extract 3 bytes to be separately added as the gaussian noise int sum = (rnd & 0xff) + ((rnd >> 8) & 0xff) + ((rnd >> 16) & 0xff); // sum is now a gaussian-distribution noise within [0 .. 767], with center at 384. // We want mapping 384 -> 3, 0 -> 19, 768 -> 19, so divide by 24 to get [0 .. 31] with center at 16, then use abs() to fold around the center int res = 3 + abs((sum / 24) - 16); */ // Algorithm of choice: random value in the range of zero to random value - heavily towards zero int res = MIN_RADIUS + (rnd >> 8) % ((rnd % (MAX_RADIUS - MIN_RADIUS)) + 1); return res; }
void GetLargeJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { // TODO: Generate proper jungle trees with branches // Vines are around the BigO4, but not in the corners; need proper meta for direction static const sMetaCoords Vines[] = { {-2, -5, 1}, {-1, -5, 1}, {0, -5, 1}, {1, -5, 1}, {2, -5, 1}, // North face {-2, 5, 4}, {-1, 5, 4}, {0, 5, 4}, {1, 5, 4}, {2, 5, 4}, // South face {5, -2, 2}, {5, -1, 2}, {5, 0, 2}, {5, 1, 2}, {5, 2, 2}, // East face {-5, -2, 8}, {-5, -1, 8}, {-5, 0, 8}, {-5, 1, 8}, {-5, 2, 8}, // West face // TODO: vines around the trunk, proper metas and height } ; int Height = 24 + (a_Noise.IntNoise3DInt(a_BlockX + 32 * a_Seq, a_BlockY, a_BlockZ + 32 * a_Seq) / 11) % 24; a_LogBlocks.reserve(Height * 4); a_OtherBlocks.reserve(2 * ARRAYCOUNT(BigO4) + ARRAYCOUNT(BigO3) + Height * ARRAYCOUNT(Vines) + 50); for (int i = 0; i < Height; i++) { a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ, E_BLOCK_LOG, E_META_LOG_JUNGLE)); a_LogBlocks.push_back(sSetBlock(a_BlockX + 1, a_BlockY + i, a_BlockZ, E_BLOCK_LOG, E_META_LOG_JUNGLE)); a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ + 1, E_BLOCK_LOG, E_META_LOG_JUNGLE)); a_LogBlocks.push_back(sSetBlock(a_BlockX + 1, a_BlockY + i, a_BlockZ + 1, E_BLOCK_LOG, E_META_LOG_JUNGLE)); } int hei = a_BlockY + Height - 2; // Put vines around the lowermost leaves layer: PushSomeColumns(a_BlockX, hei, a_BlockZ, Height, a_Seq, a_Noise, 0x3fffffff, a_OtherBlocks, Vines, ARRAYCOUNT(Vines), E_BLOCK_VINES); // The lower two leaves layers are BigO4 with log in the middle and possibly corners: for (int i = 0; i < 2; i++) { PushCoordBlocks(a_BlockX, hei, a_BlockZ, a_OtherBlocks, BigO4, ARRAYCOUNT(BigO4), E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE); PushCornerBlocks(a_BlockX, hei, a_BlockZ, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 3, E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE); hei++; } // for i - 2* // The top leaves layer is a BigO3 with leaves in the middle and possibly corners: PushCoordBlocks(a_BlockX, hei, a_BlockZ, a_OtherBlocks, BigO3, ARRAYCOUNT(BigO3), E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE); PushCornerBlocks(a_BlockX, hei, a_BlockZ, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 3, E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE); a_OtherBlocks.push_back(sSetBlock(a_BlockX, hei, a_BlockZ, E_BLOCK_LEAVES, E_META_LEAVES_JUNGLE)); }
void GetSwampTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { // Vines are around the BigO3, but not in the corners; need proper meta for direction static const sMetaCoords Vines[] = { {-2, -4, 1}, {-1, -4, 1}, {0, -4, 1}, {1, -4, 1}, {2, -4, 1}, // North face {-2, 4, 4}, {-1, 4, 4}, {0, 4, 4}, {1, 4, 4}, {2, 4, 4}, // South face {4, -2, 2}, {4, -1, 2}, {4, 0, 2}, {4, 1, 2}, {4, 2, 2}, // East face {-4, -2, 8}, {-4, -1, 8}, {-4, 0, 8}, {-4, 1, 8}, {-4, 2, 8}, // West face } ; int Height = 3 + (a_Noise.IntNoise3DInt(a_BlockX + 32 * a_Seq, a_BlockY, a_BlockZ + 32 * a_Seq) / 8) % 3; a_LogBlocks.reserve(Height); a_OtherBlocks.reserve(2 * ARRAYCOUNT(BigO2) + 2 * ARRAYCOUNT(BigO3) + Height * ARRAYCOUNT(Vines) + 20); for (int i = 0; i < Height; i++) { a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ, E_BLOCK_LOG, E_META_LOG_APPLE)); } int hei = a_BlockY + Height - 2; // Put vines around the lowermost leaves layer: PushSomeColumns(a_BlockX, hei, a_BlockZ, Height, a_Seq, a_Noise, 0x3fffffff, a_OtherBlocks, Vines, ARRAYCOUNT(Vines), E_BLOCK_VINES); // The lower two leaves layers are BigO3 with log in the middle and possibly corners: for (int i = 0; i < 2; i++) { PushCoordBlocks(a_BlockX, hei, a_BlockZ, a_OtherBlocks, BigO3, ARRAYCOUNT(BigO3), E_BLOCK_LEAVES, E_META_LEAVES_APPLE); PushCornerBlocks(a_BlockX, hei, a_BlockZ, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 3, E_BLOCK_LEAVES, E_META_LEAVES_APPLE); hei++; } // for i - 2* // The upper two leaves layers are BigO2 with leaves in the middle and possibly corners: for (int i = 0; i < 2; i++) { PushCoordBlocks(a_BlockX, hei, a_BlockZ, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_LEAVES, E_META_LEAVES_APPLE); PushCornerBlocks(a_BlockX, hei, a_BlockZ, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 3, E_BLOCK_LEAVES, E_META_LEAVES_APPLE); a_OtherBlocks.push_back(sSetBlock(a_BlockX, hei, a_BlockZ, E_BLOCK_LEAVES, E_META_LEAVES_APPLE)); hei++; } // for i - 2* }
virtual int GetPieceWeight( const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece ) override { // Check against the density: if (a_ExistingConnector.m_Type == 1) { const Vector3i & Coords = a_PlacedPiece.GetRotatedConnector(a_ExistingConnector).m_Pos; int rnd = (m_Noise.IntNoise3DInt(Coords.x, Coords.y, Coords.z) / 7) % 100; if (rnd > m_Density) { return 0; } } // Density check passed, relay to m_Prefabs: return m_Prefabs.GetPieceWeight(a_PlacedPiece, a_ExistingConnector, a_NewPiece); }
void cCaveTunnel::Randomize(cNoise & a_Noise) { // Repeat 4 times: for (int i = 0; i < 4; i++) { // For each already present point, insert a point in between it and its predecessor, shifted randomly. cCaveDefPoint & Point = m_Points.front(); int PrevX = Point.m_BlockX; int PrevY = Point.m_BlockY; int PrevZ = Point.m_BlockZ; int PrevR = Point.m_Radius; cCaveDefPoints Pts; Pts.reserve(m_Points.size() * 2 + 1); Pts.push_back(Point); for (cCaveDefPoints::const_iterator itr = m_Points.begin() + 1, end = m_Points.end(); itr != end; ++itr) { int Random = a_Noise.IntNoise3DInt(PrevX, PrevY, PrevZ + i) / 11; int len = (PrevX - itr->m_BlockX) * (PrevX - itr->m_BlockX); len += (PrevY - itr->m_BlockY) * (PrevY - itr->m_BlockY); len += (PrevZ - itr->m_BlockZ) * (PrevZ - itr->m_BlockZ); len = 3 * static_cast<int>(sqrt(static_cast<double>(len))) / 4; int Rad = std::min(MAX_RADIUS, std::max(MIN_RADIUS, (PrevR + itr->m_Radius) / 2 + (Random % 3) - 1)); Random /= 4; int x = (itr->m_BlockX + PrevX) / 2 + (Random % (len + 1) - len / 2); Random /= 256; int y = (itr->m_BlockY + PrevY) / 2 + (Random % (len / 2 + 1) - len / 4); Random /= 256; int z = (itr->m_BlockZ + PrevZ) / 2 + (Random % (len + 1) - len / 2); Pts.push_back(cCaveDefPoint(x, y, z, Rad)); Pts.push_back(*itr); PrevX = itr->m_BlockX; PrevY = itr->m_BlockY; PrevZ = itr->m_BlockZ; PrevR = itr->m_Radius; } std::swap(Pts, m_Points); } }
/** Returns the pattern to use for an ocean floor in the specified column. The returned pattern is guaranteed to be 256 blocks long. */ const cPattern::BlockInfo * ChooseOceanFloorPattern(int a_ChunkX, int a_ChunkZ, int a_RelX, int a_RelZ) { // Frequencies for the ocean floor selecting noise: const NOISE_DATATYPE FrequencyX = 3; const NOISE_DATATYPE FrequencyZ = 3; // Select the ocean-floor pattern to use: NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(a_ChunkX * cChunkDef::Width + a_RelX)) / FrequencyX; NOISE_DATATYPE NoiseY = ((NOISE_DATATYPE)(a_ChunkZ * cChunkDef::Width + a_RelZ)) / FrequencyZ; NOISE_DATATYPE Val = m_OceanFloorSelect.CubicNoise2D(NoiseX, NoiseY); if (Val < -0.95) { return patOFClay.Get(); } else if (Val < 0) { return patOFSand.Get(); } else { return patDirt.Get(); } }
/** Recursively subdivides the line between the points of the specified index. Sets the midpoint to the center of the line plus or minus a random offset, then calls itself for each half of the new line. */ void SubdivideLine(int a_Idx1, int a_Idx2) { // Calculate the midpoint: const sRavineDefPoint & p1 = m_DefPoints[a_Idx1]; const sRavineDefPoint & p2 = m_DefPoints[a_Idx2]; float MidX = (p1.m_X + p2.m_X) / 2; float MidZ = (p1.m_Z + p2.m_Z) / 2; float MidR = (p1.m_Radius + p2.m_Radius) / 2 + 0.1f; float MidT = (p1.m_Top + p2.m_Top) / 2; float MidB = (p1.m_Bottom + p2.m_Bottom) / 2; // Adjust the midpoint by a small amount of perpendicular vector in a random one of its two directions: float dx = p2.m_X - p1.m_X; float dz = p2.m_Z - p1.m_Z; if ((m_Noise.IntNoise2DInt((int)MidX, (int)MidZ) / 11) % 2 == 0) { MidX += dz * m_Roughness; MidZ -= dx * m_Roughness; } else { MidX -= dz * m_Roughness; MidZ += dx * m_Roughness; } int MidIdx = (a_Idx1 + a_Idx2) / 2; m_DefPoints[MidIdx].Set(MidX, MidZ, MidR, MidT, MidB); // Recurse the two halves, if they are worth recursing: if (MidIdx - a_Idx1 > 1) { SubdivideLine(a_Idx1, MidIdx); } if (a_Idx2 - MidIdx > 1) { SubdivideLine(MidIdx, a_Idx2); } }
void GetAcaciaTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { // Calculate a base height int Height = 2 + (a_Noise.IntNoise3DInt(a_BlockX, a_BlockY, a_BlockZ) / 11 % 3); // Create the trunk for (int i = 0; i < Height; i++) { a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ, E_BLOCK_NEW_LOG, E_META_NEW_LOG_ACACIA_WOOD)); } // Array with possible directions for a branch to go to. const Vector3i AvailableDirections[] = { { -1, 1, 0 }, { 0, 1, -1 }, { -1, 1, 1 }, { -1, 1, -1 }, { 1, 1, 1 }, { 1, 1, -1 }, { 1, 1, 0 }, { 0, 1, 1 }, }; // Set the starting point of the branch Vector3i BranchPos = Vector3i(a_BlockX, a_BlockY + Height - 1, a_BlockZ); // Get a direction for the trunk to go to. Vector3i BranchDirection = AvailableDirections[a_Noise.IntNoise3DInt(a_BlockX, a_BlockY, a_BlockZ) % 8]; // Calculate a height for the branch between 1 and 3 int BranchHeight = a_Noise.IntNoise3DInt(a_BlockX, a_BlockY, a_BlockZ) % 3 + 1; // Place the logs of the branch. for (int i = 0; i < BranchHeight; i++) { BranchPos = BranchPos + BranchDirection; a_LogBlocks.push_back(sSetBlock(BranchPos.x, BranchPos.y, BranchPos.z, E_BLOCK_NEW_LOG, E_META_NEW_LOG_ACACIA_WOOD)); } // Add the leaves to the top of the branch PushCoordBlocks(BranchPos.x, BranchPos.y, BranchPos.z, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_ACACIA_WOOD); PushCoordBlocks(BranchPos.x, BranchPos.y + 1, BranchPos.z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_ACACIA_WOOD); a_OtherBlocks.push_back(sSetBlock(BranchPos.x, BranchPos.y + 1, BranchPos.z, E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_ACACIA_WOOD)); // Choose if we have to add another branch bool TwoTop = (a_Noise.IntNoise3D(a_BlockX, a_BlockY, a_BlockZ) < 0 ? true : false); if (!TwoTop) { return; } // Reset the starting point of the branch BranchPos = Vector3i(a_BlockX, a_BlockY + Height - 1, a_BlockZ); // Invert the direction of the previous branch. BranchDirection = Vector3d(-BranchDirection.x, 1, -BranchDirection.z); // Calculate a new height for the second branch BranchHeight = a_Noise.IntNoise3DInt(a_BlockX * a_Seq, a_BlockY * a_Seq * 10, a_BlockZ * a_Seq) % 3 + 1; // Place the logs in the same way as the first branch for (int i = 0; i < BranchHeight; i++) { BranchPos = BranchPos + BranchDirection; a_LogBlocks.push_back(sSetBlock(BranchPos.x, BranchPos.y, BranchPos.z, E_BLOCK_NEW_LOG, E_META_NEW_LOG_ACACIA_WOOD)); } // And add the leaves ontop of the second branch PushCoordBlocks(BranchPos.x, BranchPos.y, BranchPos.z, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_ACACIA_WOOD); PushCoordBlocks(BranchPos.x, BranchPos.y + 1, BranchPos.z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_ACACIA_WOOD); a_OtherBlocks.push_back(sSetBlock(BranchPos.x, BranchPos.y + 1, BranchPos.z, E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_ACACIA_WOOD)); }
void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, EMCSBiome a_Biome, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { switch (a_Biome) { case biPlains: case biExtremeHills: case biExtremeHillsEdge: case biForest: case biMushroomIsland: case biMushroomShore: case biForestHills: case biDeepOcean: case biStoneBeach: case biColdBeach: { // Apple or birch trees: if (a_Noise.IntNoise3DInt(a_BlockX, a_BlockY + 16 * a_Seq, a_BlockZ + 16 * a_Seq) < 0x5fffffff) { GetAppleTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } else { GetBirchTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } break; } case biTaiga: case biIcePlains: case biIceMountains: case biTaigaHills: { // Conifers GetConiferTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); break; } case biSwampland: { // Swamp trees: GetSwampTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); break; } case biJungle: case biJungleHills: case biJungleEdge: { // Apple bushes, large jungle trees, small jungle trees if (a_Noise.IntNoise3DInt(a_BlockX, a_BlockY + 16 * a_Seq, a_BlockZ + 16 * a_Seq) < 0x6fffffff) { GetAppleBushImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } else { GetJungleTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } break; } case biBirchForest: case biBirchForestHills: { GetBirchTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); break; } case biRoofedForest: case biColdTaiga: case biColdTaigaHills: case biMegaTaiga: case biMegaTaigaHills: case biExtremeHillsPlus: case biSavanna: case biSavannaPlateau: case biMesa: case biMesaPlateauF: case biMesaPlateau: case biSunflowerPlains: case biDesertM: case biExtremeHillsM: case biFlowerForest: case biTaigaM: case biSwamplandM: case biIcePlainsSpikes: case biJungleM: case biJungleEdgeM: case biBirchForestM: case biBirchForestHillsM: case biRoofedForestM: case biColdTaigaM: case biMegaSpruceTaiga: case biMegaSpruceTaigaHills: case biExtremeHillsPlusM: case biSavannaM: case biSavannaPlateauM: case biMesaBryce: case biMesaPlateauFM: case biMesaPlateauM: { // TODO: These need their special trees GetBirchTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); break; } } }
void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, EMCSBiome a_Biome, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { switch (a_Biome) { case biPlains: case biExtremeHills: case biExtremeHillsEdge: case biForest: case biMushroomIsland: case biMushroomShore: case biForestHills: case biDeepOcean: case biStoneBeach: case biColdBeach: { // Apple or birch trees: if (a_Noise.IntNoise3DInt(a_BlockX, a_BlockY + 16 * a_Seq, a_BlockZ + 16 * a_Seq) < 0x5fffffff) { GetAppleTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } else { GetBirchTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } return; } case biTaiga: case biIcePlains: case biIceMountains: case biTaigaHills: { // Conifers GetConiferTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); return; } case biSwamplandM: case biSwampland: { // Swamp trees: GetSwampTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); return; } case biJungle: case biJungleHills: case biJungleEdge: { // Apple bushes, large jungle trees, small jungle trees if (a_Noise.IntNoise3DInt(a_BlockX, a_BlockY + 16 * a_Seq, a_BlockZ + 16 * a_Seq) < 0x6fffffff) { GetAppleBushImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } else { bool IsLarge = a_Noise.IntNoise3DInt(a_BlockX + 32 * a_Seq, a_BlockY + 32 * a_Seq, a_BlockZ) < 0x60000000; GetJungleTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks, IsLarge); } return; } case biBirchForest: case biBirchForestHills: { GetBirchTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); return; } case biBirchForestM: case biBirchForestHillsM: { GetTallBirchTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); return; } case biColdTaiga: case biColdTaigaHills: case biMegaTaiga: case biMegaTaigaHills: case biExtremeHillsPlus: case biSunflowerPlains: case biDesertM: case biExtremeHillsM: case biFlowerForest: case biTaigaM: case biIcePlainsSpikes: case biJungleM: case biJungleEdgeM: case biColdTaigaM: case biMegaSpruceTaiga: case biMegaSpruceTaigaHills: case biExtremeHillsPlusM: { // TODO: These need their special trees GetBirchTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); return; } case biSavanna: case biSavannaPlateau: case biSavannaM: case biSavannaPlateauM: { GetAcaciaTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); return; } case biRoofedForest: case biRoofedForestM: { GetDarkoakTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); return; } case biMesa: case biMesaPlateauF: case biMesaPlateau: case biMesaBryce: case biMesaPlateauFM: case biMesaPlateauM: { GetSmallAppleTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks); } case biDesert: case biDesertHills: case biRiver: case biBeach: case biHell: case biSky: case biOcean: case biFrozenOcean: case biFrozenRiver: case biVariant: case biNumBiomes: case biNumVariantBiomes: case biInvalidBiome: { // These biomes have no trees, or are non-biome members of the enum. return; } } ASSERT(!"Invalid biome type!"); }
/** Fills the specified column with mesa pattern, based on the column height */ void FillColumnMesa(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelZ, const Byte * a_ShapeColumn) { // Frequencies for the clay floor noise: const NOISE_DATATYPE FrequencyX = 50; const NOISE_DATATYPE FrequencyZ = 50; int Top = a_ChunkDesc.GetHeight(a_RelX, a_RelZ); if (Top < m_SeaLevel) { // The terrain is below sealevel, handle as regular ocean with red sand floor: FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, patOFOrangeClay.Get(), a_ShapeColumn); return; } NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(a_ChunkDesc.GetChunkX() * cChunkDef::Width + a_RelX)) / FrequencyX; NOISE_DATATYPE NoiseY = ((NOISE_DATATYPE)(a_ChunkDesc.GetChunkZ() * cChunkDef::Width + a_RelZ)) / FrequencyZ; int ClayFloor = m_SeaLevel - 6 + (int)(4.f * m_MesaFloor.CubicNoise2D(NoiseX, NoiseY)); if (ClayFloor >= Top) { ClayFloor = Top - 1; } if (Top - m_SeaLevel < 5) { // Simple case: top is red sand, then hardened clay down to ClayFloor, then stone: a_ChunkDesc.SetBlockTypeMeta(a_RelX, Top, a_RelZ, E_BLOCK_SAND, E_META_SAND_RED); for (int y = Top - 1; y >= ClayFloor; y--) { a_ChunkDesc.SetBlockType(a_RelX, y, a_RelZ, E_BLOCK_HARDENED_CLAY); } for (int y = ClayFloor - 1; y > 0; y--) { a_ChunkDesc.SetBlockType(a_RelX, y, a_RelZ, E_BLOCK_STONE); } a_ChunkDesc.SetBlockType(a_RelX, 0, a_RelZ, E_BLOCK_BEDROCK); return; } // Difficult case: use the mesa pattern and watch for overhangs: int PatternIdx = cChunkDef::Height - (Top - ClayFloor); // We want the block at index ClayFloor to be pattern's 256th block (first stone) const cPattern::BlockInfo * Pattern = m_MesaPattern; bool HasHadWater = false; for (int y = Top; y > 0; y--) { if (a_ShapeColumn[y] > 0) { // "ground" part, use the pattern: a_ChunkDesc.SetBlockTypeMeta(a_RelX, y, a_RelZ, Pattern[PatternIdx].m_BlockType, Pattern[PatternIdx].m_BlockMeta); PatternIdx++; continue; } if (y >= m_SeaLevel) { // "air" part, do nothing continue; } // "water" part, fill with water and choose new pattern for ocean floor, if not chosen already: PatternIdx = 0; a_ChunkDesc.SetBlockType(a_RelX, y, a_RelZ, E_BLOCK_STATIONARY_WATER); if (HasHadWater) { continue; } // Select the ocean-floor pattern to use: Pattern = ChooseOceanFloorPattern(a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ(), a_RelX, a_RelZ); HasHadWater = true; } // for y a_ChunkDesc.SetBlockType(a_RelX, 0, a_RelZ, E_BLOCK_BEDROCK); EMCSBiome MesaVersion = a_ChunkDesc.GetBiome(a_RelX, a_RelZ); if ((MesaVersion == biMesaPlateauF) || (MesaVersion == biMesaPlateauFM)) { if (Top < 95 + static_cast<int>(m_MesaFloor.CubicNoise2D(NoiseY * 2, NoiseX * 2) * 6)) { return; } BLOCKTYPE Block = (m_MesaFloor.CubicNoise2D(NoiseX * 4, NoiseY * 4) < 0) ? E_BLOCK_DIRT : E_BLOCK_GRASS; NIBBLETYPE Meta = (Block == E_BLOCK_GRASS) ? 0 : 1; a_ChunkDesc.SetBlockTypeMeta(a_RelX, Top, a_RelZ, Block, Meta); } }
void GetLargeAppleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { int Height = 7 + a_Noise.IntNoise3DInt(a_BlockX, a_BlockY, a_BlockZ) % 4; // Array with possible directions for a branch to go to. const Vector3d AvailableDirections[] = { { -1, 0, 0 }, { 0, 0, -1 }, { -1, 0, 1 }, { -1, 0, -1 }, { 1, 0, 1 }, { 1, 0, -1 }, { 1, 0, 0 }, { 0, 0, 1 }, { -0.5, 0, 0 }, { 0, 0, -0.5 }, { -0.5, 0, 0.5 }, { -0.5, 0, -0.5 }, { 0.5, 0, 0.5 }, { 0.5, 0, -0.5 }, { 0.5, 0, 0 }, { 0, 0, 0.5 }, { -1, 0.5, 0 }, { 0, 0.5, -1 }, { -1, 0.5, 1 }, { -1, 0.5, -1 }, { 1, 0.5, 1 }, { 1, 0.5, -1 }, { 1, 0.5, 0 }, { 0, 0.5, 1 }, { -0.5, 0.5, 0 }, { 0, 0.5, -0.5 }, { -0.5, 0.5, 0.5 }, { -0.5, 0.5, -0.5 }, { 0.5, 0.5, 0.5 }, { 0.5, 0.5, -0.5 }, { 0.5, 0.5, 0 }, { 0, 0.5, 0.5 }, }; // Create branches for (int i = 4; i < Height; i++) { // Get a direction for the trunk to go to. Vector3d BranchStartDirection = AvailableDirections[static_cast<size_t>(a_Noise.IntNoise3DInt(a_BlockX, a_BlockY + i, a_BlockZ)) % ARRAYCOUNT(AvailableDirections)]; Vector3d BranchDirection = AvailableDirections[static_cast<size_t>(a_Noise.IntNoise3DInt(a_BlockX, a_BlockY / i, a_BlockZ)) % ARRAYCOUNT(AvailableDirections)] / 3; int BranchLength = 2 + a_Noise.IntNoise3DInt(a_BlockX * a_Seq, a_BlockY * a_Seq, a_BlockZ * a_Seq) % 3; GetLargeAppleTreeBranch(a_BlockX, a_BlockY + i, a_BlockZ, BranchLength, BranchStartDirection, BranchDirection, a_BlockY + Height, a_Noise, a_LogBlocks); } // Place leaves around each log block for (auto itr : a_LogBlocks) { // Get the log's X and Z coordinates int X = itr.GetX(); int Z = itr.GetZ(); a_OtherBlocks.push_back(sSetBlock(X, itr.m_RelY - 2, Z, E_BLOCK_LEAVES, E_META_LEAVES_APPLE)); PushCoordBlocks(X, itr.m_RelY - 2, Z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_APPLE); for (int y = -1; y <= 1; y++) { PushCoordBlocks (X, itr.m_RelY + y, Z, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_LEAVES, E_META_LEAVES_APPLE); } PushCoordBlocks(X, itr.m_RelY + 2, Z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_APPLE); a_OtherBlocks.push_back(sSetBlock(X, itr.m_RelY + 2, Z, E_BLOCK_LEAVES, E_META_LEAVES_APPLE)); } // Trunk: for (int i = 0; i < Height; i++) { a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ, E_BLOCK_LOG, E_META_LOG_APPLE)); } }
void GetSpruceTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks) { // Spruces have a top section with layer sizes of (0, 1, 0) or only (1, 0), // then 1 - 3 sections of ascending sizes (1, 2) [most often], (1, 3) or (1, 2, 3) // and an optional bottom section of size 1, followed by 1 - 3 clear trunk blocks // We'll use bits from this number as partial random numbers; but the noise function has mod8 irregularities // (each of the mod8 remainders has a very different chance of occurrence) - that's why we divide by 8 int MyRandom = a_Noise.IntNoise3DInt(a_BlockX + 32 * a_Seq, a_BlockY + 32 * a_Seq, a_BlockZ) / 8; static const int sHeights[] = {1, 2, 2, 3}; int Height = sHeights[MyRandom & 3]; MyRandom >>= 2; // Prealloc, so that we don't realloc too often later: a_LogBlocks.reserve(Height); a_OtherBlocks.reserve(180); // Clear trunk blocks: for (int i = 0; i < Height; i++) { a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ, E_BLOCK_LOG, E_META_LOG_CONIFER)); } Height += a_BlockY; // Optional size-1 bottom leaves layer: if ((MyRandom & 1) == 0) { PushCoordBlocks(a_BlockX, Height, a_BlockZ, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); a_OtherBlocks.push_back(sSetBlock(a_BlockX, Height, a_BlockZ, E_BLOCK_LOG, E_META_LOG_CONIFER)); Height++; } MyRandom >>= 1; // 1 to 3 sections of leaves layers: static const int sNumSections[] = {1, 2, 2, 3}; int NumSections = sNumSections[MyRandom & 3]; MyRandom >>= 2; for (int i = 0; i < NumSections; i++) { switch (MyRandom & 3) // SectionType; (1, 2) twice as often as the other two { case 0: case 1: { PushCoordBlocks(a_BlockX, Height, a_BlockZ, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); PushCoordBlocks(a_BlockX, Height + 1, a_BlockZ, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); a_LogBlocks.push_back(sSetBlock(a_BlockX, Height, a_BlockZ, E_BLOCK_LOG, E_META_LOG_CONIFER)); a_LogBlocks.push_back(sSetBlock(a_BlockX, Height + 1, a_BlockZ, E_BLOCK_LOG, E_META_LOG_CONIFER)); Height += 2; break; } case 2: { PushCoordBlocks(a_BlockX, Height, a_BlockZ, a_OtherBlocks, BigO3, ARRAYCOUNT(BigO3), E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); PushCoordBlocks(a_BlockX, Height + 1, a_BlockZ, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); a_LogBlocks.push_back(sSetBlock(a_BlockX, Height, a_BlockZ, E_BLOCK_LOG, E_META_LOG_CONIFER)); a_LogBlocks.push_back(sSetBlock(a_BlockX, Height + 1, a_BlockZ, E_BLOCK_LOG, E_META_LOG_CONIFER)); Height += 2; break; } case 3: { PushCoordBlocks(a_BlockX, Height, a_BlockZ, a_OtherBlocks, BigO3, ARRAYCOUNT(BigO3), E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); PushCoordBlocks(a_BlockX, Height + 1, a_BlockZ, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); PushCoordBlocks(a_BlockX, Height + 2, a_BlockZ, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); a_LogBlocks.push_back(sSetBlock(a_BlockX, Height, a_BlockZ, E_BLOCK_LOG, E_META_LOG_CONIFER)); a_LogBlocks.push_back(sSetBlock(a_BlockX, Height + 1, a_BlockZ, E_BLOCK_LOG, E_META_LOG_CONIFER)); a_LogBlocks.push_back(sSetBlock(a_BlockX, Height + 2, a_BlockZ, E_BLOCK_LOG, E_META_LOG_CONIFER)); Height += 3; break; } } // switch (SectionType) MyRandom >>= 2; } // for i - Sections if ((MyRandom & 1) == 0) { // (0, 1, 0) top: a_LogBlocks.push_back (sSetBlock(a_BlockX, Height, a_BlockZ, E_BLOCK_LOG, E_META_LOG_CONIFER)); PushCoordBlocks (a_BlockX, Height + 1, a_BlockZ, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); a_OtherBlocks.push_back(sSetBlock(a_BlockX, Height + 1, a_BlockZ, E_BLOCK_LEAVES, E_META_LEAVES_CONIFER)); a_OtherBlocks.push_back(sSetBlock(a_BlockX, Height + 2, a_BlockZ, E_BLOCK_LEAVES, E_META_LEAVES_CONIFER)); } else { // (1, 0) top: a_OtherBlocks.push_back(sSetBlock(a_BlockX, Height, a_BlockZ, E_BLOCK_LEAVES, E_META_LEAVES_CONIFER)); PushCoordBlocks (a_BlockX, Height + 1, a_BlockZ, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_LEAVES, E_META_LEAVES_CONIFER); a_OtherBlocks.push_back(sSetBlock(a_BlockX, Height + 1, a_BlockZ, E_BLOCK_LEAVES, E_META_LEAVES_CONIFER)); } }
/** Composes a single column in a_ChunkDesc. Chooses what to do based on the biome in that column. */ void ComposeColumn(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelZ, const Byte * a_ShapeColumn) { // Frequencies for the podzol floor selecting noise: const NOISE_DATATYPE FrequencyX = 8; const NOISE_DATATYPE FrequencyZ = 8; EMCSBiome Biome = a_ChunkDesc.GetBiome(a_RelX, a_RelZ); switch (Biome) { case biOcean: case biPlains: case biForest: case biTaiga: case biSwampland: case biRiver: case biFrozenOcean: case biFrozenRiver: case biIcePlains: case biIceMountains: case biForestHills: case biTaigaHills: case biExtremeHillsEdge: case biExtremeHillsPlus: case biExtremeHills: case biJungle: case biJungleHills: case biJungleEdge: case biDeepOcean: case biStoneBeach: case biColdBeach: case biBirchForest: case biBirchForestHills: case biRoofedForest: case biColdTaiga: case biColdTaigaHills: case biSavanna: case biSavannaPlateau: case biSunflowerPlains: case biFlowerForest: case biTaigaM: case biSwamplandM: case biIcePlainsSpikes: case biJungleM: case biJungleEdgeM: case biBirchForestM: case biBirchForestHillsM: case biRoofedForestM: case biColdTaigaM: case biSavannaM: case biSavannaPlateauM: { FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, patGrass.Get(), a_ShapeColumn); return; } case biMegaTaiga: case biMegaTaigaHills: case biMegaSpruceTaiga: case biMegaSpruceTaigaHills: { // Select the pattern to use - podzol, grass or grassless dirt: NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(a_ChunkDesc.GetChunkX() * cChunkDef::Width + a_RelX)) / FrequencyX; NOISE_DATATYPE NoiseY = ((NOISE_DATATYPE)(a_ChunkDesc.GetChunkZ() * cChunkDef::Width + a_RelZ)) / FrequencyZ; NOISE_DATATYPE Val = m_OceanFloorSelect.CubicNoise2D(NoiseX, NoiseY); const cPattern::BlockInfo * Pattern = (Val < -0.9) ? patGrassLess.Get() : ((Val > 0) ? patPodzol.Get() : patGrass.Get()); FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, Pattern, a_ShapeColumn); return; } case biDesertHills: case biDesert: case biDesertM: case biBeach: { FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, patSand.Get(), a_ShapeColumn); return; } case biMushroomIsland: case biMushroomShore: { FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, patMycelium.Get(), a_ShapeColumn); return; } case biMesa: case biMesaPlateauF: case biMesaPlateau: case biMesaBryce: case biMesaPlateauFM: case biMesaPlateauM: { // Mesa biomes need special handling, because they don't follow the usual "4 blocks from top pattern", // instead, they provide a "from bottom" pattern with varying base height, // usually 4 blocks below the ocean level FillColumnMesa(a_ChunkDesc, a_RelX, a_RelZ, a_ShapeColumn); return; } case biExtremeHillsPlusM: case biExtremeHillsM: { // Select the pattern to use - gravel, stone or grass: NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(a_ChunkDesc.GetChunkX() * cChunkDef::Width + a_RelX)) / FrequencyX; NOISE_DATATYPE NoiseY = ((NOISE_DATATYPE)(a_ChunkDesc.GetChunkZ() * cChunkDef::Width + a_RelZ)) / FrequencyZ; NOISE_DATATYPE Val = m_OceanFloorSelect.CubicNoise2D(NoiseX, NoiseY); const cPattern::BlockInfo * Pattern = (Val < 0.0) ? patStone.Get() : patGrass.Get(); FillColumnPattern(a_ChunkDesc, a_RelX, a_RelZ, Pattern, a_ShapeColumn); return; } case biInvalidBiome: case biHell: case biSky: case biNumBiomes: case biVariant: case biNumVariantBiomes: { ASSERT(!"Unhandled biome"); return; } } // switch (Biome) }