From 3f30d5dfd29484c0201118ff525863d8ce266aa8 Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Sun, 22 Jul 2012 18:51:38 +0000 Subject: Added a new cave generator: DualRidgeCaves ( somewhat like http://www.gamedev.net/blog/33/entry-2227887-more-on-minecraft-type-world-gen/ ) git-svn-id: http://mc-server.googlecode.com/svn/trunk@694 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/Caves.cpp | 369 +++++++++++++++++++++++++++++++++++++++++++++ source/Caves.h | 116 ++++++++++++++ source/StructGen.cpp | 66 -------- source/StructGen.h | 25 --- source/cChunkGenerator.cpp | 13 ++ 5 files changed, 498 insertions(+), 91 deletions(-) create mode 100644 source/Caves.cpp create mode 100644 source/Caves.h (limited to 'source') diff --git a/source/Caves.cpp b/source/Caves.cpp new file mode 100644 index 000000000..1f7453389 --- /dev/null +++ b/source/Caves.cpp @@ -0,0 +1,369 @@ + +// Caves.cpp + +// Implements the various cave structure generators: +// - cStructGenWormNestCaves +// - cStructGenMarbleCaves +// - cStructGenNetherCaves + +#include "Globals.h" +#include "Caves.h" + + + + + +struct cDefPoint +{ + int m_BlockX; + int m_BlockZ; + int m_Radius; + + cDefPoint(int a_BlockX, int a_BlockZ, int a_Radius) : + m_BlockX(a_BlockX), + m_BlockZ(a_BlockZ), + m_Radius(a_Radius) + { + } +} ; + +typedef std::vector cDefPoints; + + + + + +/// A single non-branching tunnel +class cCaveTunnel +{ + cDefPoints m_Points; + + /// Generates the shaping defpoints for the ravine, based on the ravine block coords and noise + void GenerateBaseDefPoints(int a_BlockX, int a_BlockZ, int a_Size, cNoise & a_Noise); + + /// Refines (adds and smooths) defpoints from a_Src into a_Dst + void RefineDefPoints(const cDefPoints & a_Src, cDefPoints & a_Dst); + + /// Does one round of smoothing, two passes of RefineDefPoints() + void Smooth(void); + + /// Linearly interpolates the points so that the maximum distance between two neighbors is max 1 block + void FinishLinear(void); + +public: + // Coords for which the ravine was generated (not necessarily the center) + int m_BlockX; + int m_BlockZ; + + cCaveTunnel(int a_BlockStartX, int a_BlockStartZ, int a_Size, cNoise & a_Noise); + + /// Carves the tunnel into the chunk specified + void ProcessChunk( + int a_ChunkX, int a_ChunkZ, + cChunkDef::BlockTypes & a_BlockTypes, + cChunkDef::HeightMap & a_HeightMap + ); +} ; + +typedef std::vector cCaveTunnels; + + + + + +/// A collection of connected tunnels, possibly branching. +class cStructGenWormNestCaves::cCaveSystem +{ +public: + cCaveSystem(int a_BlockX, int a_BlockZ, int a_Size, cNoise & a_Noise); + ~cCaveSystem(); + + /// Carves the cave system into the chunk specified + void ProcessChunk( + int a_ChunkX, int a_ChunkZ, + cChunkDef::BlockTypes & a_BlockTypes, + cChunkDef::HeightMap & a_HeightMap + ); + +protected: + int m_BlockX; + int m_BlockZ; + cCaveTunnels m_Tunnels; + + void Clear(void); +} ; + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cCaveTunnel: + +void cCaveTunnel::ProcessChunk( + int a_ChunkX, int a_ChunkZ, + cChunkDef::BlockTypes & a_BlockTypes, + cChunkDef::HeightMap & a_HeightMap +) +{ + // TODO +} + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cStructGenWormNestCaves::cCaveSystem: + +cStructGenWormNestCaves::cCaveSystem::cCaveSystem(int a_BlockX, int a_BlockZ, int a_Size, cNoise & a_Noise) : + m_BlockX(a_BlockX), + m_BlockZ(a_BlockZ) +{ + // TODO: Generate a cave system +} + + + + + +cStructGenWormNestCaves::cCaveSystem::~cCaveSystem() +{ + Clear(); +} + + + + + + +void cStructGenWormNestCaves::cCaveSystem::Clear(void) +{ + // TODO +} + + + + + +void cStructGenWormNestCaves::cCaveSystem::ProcessChunk( + int a_ChunkX, int a_ChunkZ, + cChunkDef::BlockTypes & a_BlockTypes, + cChunkDef::HeightMap & a_HeightMap +) +{ + for (cCaveTunnels::const_iterator itr = m_Tunnels.begin(), end = m_Tunnels.end(); itr != end; ++itr) + { + (*itr)->ProcessChunk(a_ChunkX, a_ChunkZ, a_BlockTypes, a_HeightMap); + } // for itr - m_Tunnels[] +} + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cStructGenWormNestCaves: + +cStructGenWormNestCaves::~cStructGenWormNestCaves() +{ + ClearCache(); +} + + + + + +void cStructGenWormNestCaves::ClearCache(void) +{ + for (cCaves::const_iterator itr = m_Cache.begin(), end = m_Cache.end(); itr != end; ++itr) + { + delete *itr; + } // for itr - m_Cache[] + m_Cache.clear(); +} + + + + + +void cStructGenWormNestCaves::GenStructures( + int a_ChunkX, int a_ChunkZ, + cChunkDef::BlockTypes & a_BlockTypes, // Block types to read and change + cChunkDef::BlockNibbles & a_BlockMeta, // Block meta to read and change + cChunkDef::HeightMap & a_HeightMap, // Height map to read and change by the current data + cEntityList & a_Entities, // Entities may be added or deleted + cBlockEntityList & a_BlockEntities // Block entities may be added or deleted +) +{ + cCaves Caves; + GetCavesForChunk(a_ChunkX, a_ChunkZ, Caves); + for (cCaves::const_iterator itr = Caves.begin(); itr != Caves.end(); ++itr) + { + (*itr)->ProcessChunk(a_ChunkX, a_ChunkZ, a_BlockTypes, a_HeightMap); + } // for itr - Caves[] +} + + + + + +void cStructGenWormNestCaves::GetCavesForChunk(int a_ChunkX, int a_ChunkZ, cStructGenWormNestCaves::cCaves & a_Caves) +{ + // TODO: Implement proper caching + // - don't destroy caves that are reusable + // - don't create caves that are already in the cache + + ClearCache(); + + int BaseX = a_ChunkX * cChunkDef::Width / m_Size; + int BaseZ = a_ChunkZ * cChunkDef::Width / m_Size; + if (BaseX < 0) + { + --BaseX; + } + if (BaseZ < 0) + { + --BaseZ; + } + BaseX -= 4; + BaseZ -= 4; + for (int x = 0; x < 8; x++) + { + int RealX = (BaseX + x) * m_Size; + for (int z = 0; z < 8; z++) + { + int RealZ = (BaseZ + z) * m_Size; + m_Cache.push_back(new cCaveSystem(RealX, RealZ, m_Size, m_Noise)); + } + } + a_Caves = m_Cache; +} + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cStructGenMarbleCaves: + +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; +} + + + + + +void cStructGenMarbleCaves::GenStructures( + int a_ChunkX, int a_ChunkZ, + cChunkDef::BlockTypes & a_BlockTypes, // Block types to read and change + cChunkDef::BlockNibbles & a_BlockMeta, // Block meta to read and change + cChunkDef::HeightMap & a_HeightMap, // Height map to read and change by the current data + cEntityList & a_Entities, // Entities may be added or deleted + cBlockEntityList & a_BlockEntities // Block entities may be added or deleted +) +{ + cNoise Noise(m_Seed); + for (int z = 0; z < cChunkDef::Width; z++) + { + const float zz = (float)(a_ChunkZ * cChunkDef::Width + z); + for (int x = 0; x < cChunkDef::Width; x++) + { + const float xx = (float)(a_ChunkX * cChunkDef::Width + x); + + int Top = cChunkDef::GetHeight(a_HeightMap, x, z); + for (int y = 1; y < Top; ++y ) + { + if (cChunkDef::GetBlock(a_BlockTypes, x, y, z) != E_BLOCK_STONE) + { + continue; + } + + const float yy = (float)y; + const float WaveNoise = 1; + if (cosf(GetMarbleNoise(xx, yy * 0.5f, zz, Noise)) * fabs(cosf(yy * 0.2f + WaveNoise * 2) * 0.75f + WaveNoise) > 0.0005f) + { + if (y > 4) + { + cChunkDef::SetBlock(a_BlockTypes, x, y, z, E_BLOCK_AIR); + } + else + { + cChunkDef::SetBlock(a_BlockTypes, x, y, z, E_BLOCK_STATIONARY_LAVA); + } + } + } // for y + } // for x + } // for z +} + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cStructGenDualRidgeCaves: + +void cStructGenDualRidgeCaves::GenStructures( + int a_ChunkX, int a_ChunkZ, + cChunkDef::BlockTypes & a_BlockTypes, // Block types to read and change + cChunkDef::BlockNibbles & a_BlockMeta, // Block meta to read and change + cChunkDef::HeightMap & a_HeightMap, // Height map to read and change by the current data + cEntityList & a_Entities, // Entities may be added or deleted + cBlockEntityList & a_BlockEntities // Block entities may be added or deleted +) +{ + cNoise Noise1(m_Seed); + cNoise Noise2(2 * m_Seed + 19999); + for (int z = 0; z < cChunkDef::Width; z++) + { + const float zz = (float)(a_ChunkZ * cChunkDef::Width + z) / 10; + for (int x = 0; x < cChunkDef::Width; x++) + { + const float xx = (float)(a_ChunkX * cChunkDef::Width + x) / 10; + + int Top = cChunkDef::GetHeight(a_HeightMap, x, z); + for (int y = 1; y <= Top; ++y) + { + /* + if (cChunkDef::GetBlock(a_BlockTypes, x, y, z) != E_BLOCK_STONE) + { + continue; + } + */ + + const float yy = (float)y / 10; + const float WaveNoise = 1; + float n1 = Noise1.CubicNoise3D(xx, yy, zz); + float n2 = Noise2.CubicNoise3D(xx, yy, zz); + float n3 = Noise1.CubicNoise3D(xx * 4, yy * 4, zz * 4) / 4; + float n4 = Noise2.CubicNoise3D(xx * 4, yy * 4, zz * 4) / 4; + if ((abs(n1 + n3) * abs(n2 + n4)) > m_Threshold) + { + if (y > 10) + { + cChunkDef::SetBlock(a_BlockTypes, x, y, z, E_BLOCK_AIR); + } + else + { + cChunkDef::SetBlock(a_BlockTypes, x, y, z, E_BLOCK_STATIONARY_LAVA); + } + } + } // for y + } // for x + } // for z +} + + + + diff --git a/source/Caves.h b/source/Caves.h new file mode 100644 index 000000000..ec3ecdf0f --- /dev/null +++ b/source/Caves.h @@ -0,0 +1,116 @@ + +// Caves.h + +// Interfaces to the various cave structure generators: +// - cStructGenWormNestCaves +// - cStructGenMarbleCaves +// - cStructGenNetherCaves + + + + + +#pragma once + +#include "cChunkGenerator.h" +#include "cNoise.h" + + + + + +class cStructGenMarbleCaves : + public cStructureGen +{ +public: + cStructGenMarbleCaves(int a_Seed) : m_Seed(a_Seed) {} + +protected: + + int m_Seed; + + // cStructureGen override: + virtual void GenStructures( + int a_ChunkX, int a_ChunkZ, + cChunkDef::BlockTypes & a_BlockTypes, // Block types to read and change + cChunkDef::BlockNibbles & a_BlockMeta, // Block meta to read and change + cChunkDef::HeightMap & a_HeightMap, // Height map to read and change by the current data + cEntityList & a_Entities, // Entities may be added or deleted + cBlockEntityList & a_BlockEntities // Block entities may be added or deleted + ) override; +} ; + + + + + +class cStructGenDualRidgeCaves : + public cStructureGen +{ +public: + cStructGenDualRidgeCaves(int a_Seed, float a_Threshold) : + m_Seed(a_Seed), + m_Threshold(a_Threshold) + { + } + +protected: + + int m_Seed; + float m_Threshold; + + // cStructureGen override: + virtual void GenStructures( + int a_ChunkX, int a_ChunkZ, + cChunkDef::BlockTypes & a_BlockTypes, // Block types to read and change + cChunkDef::BlockNibbles & a_BlockMeta, // Block meta to read and change + cChunkDef::HeightMap & a_HeightMap, // Height map to read and change by the current data + cEntityList & a_Entities, // Entities may be added or deleted + cBlockEntityList & a_BlockEntities // Block entities may be added or deleted + ) override; +} ; + + + + + +class cStructGenWormNestCaves : + public cStructureGen +{ +public: + cStructGenWormNestCaves(int a_Seed, int a_Size = 128) : + m_Noise(a_Seed), + m_Size(128) + { + } + + ~cStructGenWormNestCaves(); + +protected: + class cCaveSystem; // fwd: Caves.cpp + typedef std::list cCaves; + + cNoise m_Noise; + int m_Size; // relative size, in blocks, of the nests produced. Also used for spacing. + cCaves m_Cache; + + /// Clears everything from the cache + void ClearCache(void); + + /// Returns all caves that *may* intersect the given chunk. All the caves are valid until the next call to this function. + void GetCavesForChunk(int a_ChunkX, int a_ChunkZ, cCaves & a_Caves); + + // cStructGen override: + virtual void GenStructures( + int a_ChunkX, int a_ChunkZ, + cChunkDef::BlockTypes & a_BlockTypes, // Block types to read and change + cChunkDef::BlockNibbles & a_BlockMeta, // Block meta to read and change + cChunkDef::HeightMap & a_HeightMap, // Height map to read and change by the current data + cEntityList & a_Entities, // Entities may be added or deleted + cBlockEntityList & a_BlockEntities // Block entities may be added or deleted + ) override; +} ; + + + + diff --git a/source/StructGen.cpp b/source/StructGen.cpp index a97da1a53..ba70aa2c5 100644 --- a/source/StructGen.cpp +++ b/source/StructGen.cpp @@ -295,72 +295,6 @@ int cStructGenTrees::GetNumTrees( -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// cStructGenMarbleCaves: - -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; -} - - - - - -void cStructGenMarbleCaves::GenStructures( - int a_ChunkX, int a_ChunkZ, - cChunkDef::BlockTypes & a_BlockTypes, // Block types to read and change - cChunkDef::BlockNibbles & a_BlockMeta, // Block meta to read and change - cChunkDef::HeightMap & a_HeightMap, // Height map to read and change by the current data - cEntityList & a_Entities, // Entities may be added or deleted - cBlockEntityList & a_BlockEntities // Block entities may be added or deleted -) -{ - cNoise Noise(m_Seed); - for (int z = 0; z < cChunkDef::Width; z++) - { - const float zz = (float)(a_ChunkZ * cChunkDef::Width + z); - for (int x = 0; x < cChunkDef::Width; x++) - { - const float xx = (float)(a_ChunkX * cChunkDef::Width + x); - - int Top = cChunkDef::GetHeight(a_HeightMap, x, z); - for (int y = 1; y < Top; ++y ) - { - if (cChunkDef::GetBlock(a_BlockTypes, x, y, z) != E_BLOCK_STONE) - { - continue; - } - - const float yy = (float)y; - const float WaveNoise = 1; - if (cosf(GetMarbleNoise(xx, yy * 0.5f, zz, Noise)) * fabs(cosf(yy * 0.2f + WaveNoise * 2) * 0.75f + WaveNoise) > 0.0005f) - { - if (y > 4) - { - cChunkDef::SetBlock(a_BlockTypes, x, y, z, E_BLOCK_AIR); - } - else - { - cChunkDef::SetBlock(a_BlockTypes, x, y, z, E_BLOCK_STATIONARY_LAVA); - } - } - } // for y - } // for x - } // for z -} - - - - - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cStructGenOreNests: diff --git a/source/StructGen.h b/source/StructGen.h index e34724e20..0a28d84a3 100644 --- a/source/StructGen.h +++ b/source/StructGen.h @@ -83,31 +83,6 @@ protected: -class cStructGenMarbleCaves : - public cStructureGen -{ -public: - cStructGenMarbleCaves(int a_Seed) : m_Seed(a_Seed) {} - -protected: - - int m_Seed; - - // cStructureGen override: - virtual void GenStructures( - int a_ChunkX, int a_ChunkZ, - cChunkDef::BlockTypes & a_BlockTypes, // Block types to read and change - cChunkDef::BlockNibbles & a_BlockMeta, // Block meta to read and change - cChunkDef::HeightMap & a_HeightMap, // Height map to read and change by the current data - cEntityList & a_Entities, // Entities may be added or deleted - cBlockEntityList & a_BlockEntities // Block entities may be added or deleted - ) override; -} ; - - - - - class cStructGenOreNests : public cStructureGen { diff --git a/source/cChunkGenerator.cpp b/source/cChunkGenerator.cpp index 01e2f37f1..3e8a6e9e9 100644 --- a/source/cChunkGenerator.cpp +++ b/source/cChunkGenerator.cpp @@ -13,6 +13,7 @@ #include "cPluginManager.h" #include "cLuaChunk.h" #include "Ravines.h" +#include "Caves.h" @@ -312,6 +313,11 @@ void cChunkGenerator::InitStructureGens(cIniFile & a_IniFile) { m_StructureGens.push_back(new cStructGenMarbleCaves(m_Seed)); } + else if (NoCaseCompare(*itr, "dualridgecaves") == 0) + { + float Threshold = (float)a_IniFile.GetValueSetF("Generator", "DualRidgeCavesThreshold", 0.3); + m_StructureGens.push_back(new cStructGenDualRidgeCaves(m_Seed, Threshold)); + } else if (NoCaseCompare(*itr, "orenests") == 0) { m_StructureGens.push_back(new cStructGenOreNests(m_Seed)); @@ -320,6 +326,13 @@ void cChunkGenerator::InitStructureGens(cIniFile & a_IniFile) { m_StructureGens.push_back(new cStructGenRavines(m_Seed, 128)); } + /* + // TODO: Not implemented yet; need a name + else if (NoCaseCompare(*itr, "caves") == 0) + { + m_StructureGens.push_back(new cStructGenWormNestCaves(m_Seed)); + } + */ else { LOGWARNING("Unknown structure generator: \"%s\". Ignoring.", itr->c_str()); -- cgit v1.2.3