1
0
Fork 0

cWormNestCaves rewritten using cGridStructGen.

Ref.: #987.
This commit is contained in:
Mattes D 2014-05-09 11:16:13 +02:00
parent 14543aa3fc
commit 95ead1128f
2 changed files with 29 additions and 223 deletions

View File

@ -122,27 +122,19 @@ typedef std::vector<cCaveTunnel *> cCaveTunnels;
/// A collection of connected tunnels, possibly branching.
class cStructGenWormNestCaves::cCaveSystem
class cStructGenWormNestCaves::cCaveSystem :
public cGridStructGen::cStructure
{
typedef cGridStructGen::cStructure super;
public:
// The generating block position; is read directly in cStructGenWormNestCaves::GetCavesForChunk()
int m_BlockX;
int m_BlockZ;
cCaveSystem(int a_BlockX, int a_BlockZ, int a_MaxOffset, int a_Size, cNoise & a_Noise);
cCaveSystem(int a_OriginX, int a_OriginZ, int a_MaxOffset, 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
);
#ifdef _DEBUG
AString ExportAsSVG(int a_Color, int a_OffsetX, int a_OffsetZ) const;
#endif // _DEBUG
protected:
int m_Size;
cCaveTunnels m_Tunnels;
@ -157,6 +149,9 @@ protected:
/// Returns a radius based on the location provided.
int GetRadius(cNoise & a_Noise, int a_OriginX, int a_OriginY, int a_OriginZ);
// cGridStructGen::cStructure overrides:
virtual void DrawIntoChunk(cChunkDesc & a_ChunkDesc) override;
} ;
@ -586,17 +581,16 @@ AString cCaveTunnel::ExportAsSVG(int a_Color, int a_OffsetX, int a_OffsetZ) cons
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cStructGenWormNestCaves::cCaveSystem:
cStructGenWormNestCaves::cCaveSystem::cCaveSystem(int a_BlockX, int a_BlockZ, int a_MaxOffset, int a_Size, cNoise & a_Noise) :
m_BlockX(a_BlockX),
m_BlockZ(a_BlockZ),
cStructGenWormNestCaves::cCaveSystem::cCaveSystem(int a_OriginX, int a_OriginZ, int a_MaxOffset, int a_Size, cNoise & a_Noise) :
super(a_OriginX, a_OriginZ),
m_Size(a_Size)
{
int Num = 1 + a_Noise.IntNoise2DInt(a_BlockX, a_BlockZ) % 3;
int Num = 1 + a_Noise.IntNoise2DInt(a_OriginX, a_OriginZ) % 3;
for (int i = 0; i < Num; i++)
{
int OriginX = a_BlockX + (a_Noise.IntNoise3DInt(13 * a_BlockX, 17 * a_BlockZ, 11 * i) / 19) % a_MaxOffset;
int OriginZ = a_BlockZ + (a_Noise.IntNoise3DInt(17 * a_BlockX, 13 * a_BlockZ, 11 * i) / 23) % a_MaxOffset;
int OriginY = 20 + (a_Noise.IntNoise3DInt(19 * a_BlockX, 13 * a_BlockZ, 11 * i) / 17) % 20;
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,
@ -622,15 +616,15 @@ cStructGenWormNestCaves::cCaveSystem::~cCaveSystem()
void cStructGenWormNestCaves::cCaveSystem::ProcessChunk(
int a_ChunkX, int a_ChunkZ,
cChunkDef::BlockTypes & a_BlockTypes,
cChunkDef::HeightMap & a_HeightMap
)
void cStructGenWormNestCaves::cCaveSystem::DrawIntoChunk(cChunkDesc & a_ChunkDesc)
{
int ChunkX = a_ChunkDesc.GetChunkX();
int ChunkZ = a_ChunkDesc.GetChunkZ();
cChunkDef::BlockTypes & BlockTypes = a_ChunkDesc.GetBlockTypes();
cChunkDef::HeightMap & HeightMap = a_ChunkDesc.GetHeightMap();
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);
(*itr)->ProcessChunk(ChunkX, ChunkZ, BlockTypes, HeightMap);
} // for itr - m_Tunnels[]
}
@ -638,53 +632,6 @@ void cStructGenWormNestCaves::cCaveSystem::ProcessChunk(
#ifdef _DEBUG
AString cStructGenWormNestCaves::cCaveSystem::ExportAsSVG(int a_Color, int a_OffsetX, int a_OffsetZ) const
{
AString SVG;
SVG.reserve(512 * 1024);
for (cCaveTunnels::const_iterator itr = m_Tunnels.begin(), end = m_Tunnels.end(); itr != end; ++itr)
{
SVG.append((*itr)->ExportAsSVG(a_Color, a_OffsetX, a_OffsetZ));
} // for itr - m_Tunnels[]
// Base point highlight:
AppendPrintf(SVG, "<path style=\"fill:none;stroke:#ff0000;stroke-width:1px;\"\nd=\"M %d,%d L %d,%d\"/>\n",
a_OffsetX + m_BlockX - 5, a_OffsetZ + m_BlockZ, a_OffsetX + m_BlockX + 5, a_OffsetZ + m_BlockZ
);
AppendPrintf(SVG, "<path style=\"fill:none;stroke:#ff0000;stroke-width:1px;\"\nd=\"M %d,%d L %d,%d\"/>\n",
a_OffsetX + m_BlockX, a_OffsetZ + m_BlockZ - 5, a_OffsetX + m_BlockX, a_OffsetZ + m_BlockZ + 5
);
// A gray line from the base point to the first point of the ravine, for identification:
AppendPrintf(SVG, "<path style=\"fill:none;stroke:#cfcfcf;stroke-width:1px;\"\nd=\"M %d,%d L %d,%d\"/>\n",
a_OffsetX + m_BlockX, a_OffsetZ + m_BlockZ,
a_OffsetX + m_Tunnels.front()->m_Points.front().m_BlockX,
a_OffsetZ + m_Tunnels.front()->m_Points.front().m_BlockZ
);
// Offset guides:
if (a_OffsetX > 0)
{
AppendPrintf(SVG, "<path style=\"fill:none;stroke:#0000ff;stroke-width:1px;\"\nd=\"M %d,0 L %d,1024\"/>\n",
a_OffsetX, a_OffsetX
);
}
if (a_OffsetZ > 0)
{
AppendPrintf(SVG, "<path style=\"fill:none;stroke:#0000ff;stroke-width:1px;\"\nd=\"M 0,%d L 1024,%d\"/>\n",
a_OffsetZ, a_OffsetZ
);
}
return SVG;
}
#endif // _DEBUG
void cStructGenWormNestCaves::cCaveSystem::Clear(void)
{
for (cCaveTunnels::const_iterator itr = m_Tunnels.begin(), end = m_Tunnels.end(); itr != end; ++itr)
@ -750,142 +697,9 @@ int cStructGenWormNestCaves::cCaveSystem::GetRadius(cNoise & a_Noise, int a_Orig
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cStructGenWormNestCaves:
cStructGenWormNestCaves::~cStructGenWormNestCaves()
cGridStructGen::cStructurePtr cStructGenWormNestCaves::CreateStructure(int a_OriginX, int a_OriginZ)
{
ClearCache();
}
void cStructGenWormNestCaves::ClearCache(void)
{
for (cCaveSystems::const_iterator itr = m_Cache.begin(), end = m_Cache.end(); itr != end; ++itr)
{
delete *itr;
} // for itr - m_Cache[]
m_Cache.clear();
}
void cStructGenWormNestCaves::GenFinish(cChunkDesc & a_ChunkDesc)
{
int ChunkX = a_ChunkDesc.GetChunkX();
int ChunkZ = a_ChunkDesc.GetChunkZ();
cCaveSystems Caves;
GetCavesForChunk(ChunkX, ChunkZ, Caves);
for (cCaveSystems::const_iterator itr = Caves.begin(); itr != Caves.end(); ++itr)
{
(*itr)->ProcessChunk(ChunkX, ChunkZ, a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap());
} // for itr - Caves[]
}
void cStructGenWormNestCaves::GetCavesForChunk(int a_ChunkX, int a_ChunkZ, cStructGenWormNestCaves::cCaveSystems & a_Caves)
{
int BaseX = a_ChunkX * cChunkDef::Width / m_Grid;
int BaseZ = a_ChunkZ * cChunkDef::Width / m_Grid;
if (BaseX < 0)
{
--BaseX;
}
if (BaseZ < 0)
{
--BaseZ;
}
BaseX -= NEIGHBORHOOD_SIZE / 2;
BaseZ -= NEIGHBORHOOD_SIZE / 2;
// Walk the cache, move each cave system that we want into a_Caves:
int StartX = BaseX * m_Grid;
int EndX = (BaseX + NEIGHBORHOOD_SIZE + 1) * m_Grid;
int StartZ = BaseZ * m_Grid;
int EndZ = (BaseZ + NEIGHBORHOOD_SIZE + 1) * m_Grid;
for (cCaveSystems::iterator itr = m_Cache.begin(), end = m_Cache.end(); itr != end;)
{
if (
((*itr)->m_BlockX >= StartX) && ((*itr)->m_BlockX < EndX) &&
((*itr)->m_BlockZ >= StartZ) && ((*itr)->m_BlockZ < EndZ)
)
{
// want
a_Caves.push_back(*itr);
itr = m_Cache.erase(itr);
}
else
{
// don't want
++itr;
}
} // for itr - m_Cache[]
for (int x = 0; x < NEIGHBORHOOD_SIZE; x++)
{
int RealX = (BaseX + x) * m_Grid;
for (int z = 0; z < NEIGHBORHOOD_SIZE; z++)
{
int RealZ = (BaseZ + z) * m_Grid;
bool Found = false;
for (cCaveSystems::const_iterator itr = a_Caves.begin(), end = a_Caves.end(); itr != end; ++itr)
{
if (((*itr)->m_BlockX == RealX) && ((*itr)->m_BlockZ == RealZ))
{
Found = true;
break;
}
}
if (!Found)
{
a_Caves.push_back(new cCaveSystem(RealX, RealZ, m_MaxOffset, m_Size, m_Noise));
}
}
}
// Copy a_Caves into m_Cache to the beginning:
cCaveSystems CavesCopy(a_Caves);
m_Cache.splice(m_Cache.begin(), CavesCopy, CavesCopy.begin(), CavesCopy.end());
// Trim the cache if it's too long:
if (m_Cache.size() > 100)
{
cCaveSystems::iterator itr = m_Cache.begin();
std::advance(itr, 100);
for (cCaveSystems::iterator end = m_Cache.end(); itr != end; ++itr)
{
delete *itr;
}
itr = m_Cache.begin();
std::advance(itr, 100);
m_Cache.erase(itr, m_Cache.end());
}
/*
// Uncomment this block for debugging the caves' shapes in 2D using an SVG export
#ifdef _DEBUG
AString SVG;
SVG.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1024\" height = \"1024\">\n");
SVG.reserve(2 * 1024 * 1024);
for (cCaveSystems::const_iterator itr = a_Caves.begin(), end = a_Caves.end(); itr != end; ++itr)
{
int Color = 0x10 * abs((*itr)->m_BlockX / m_Grid);
Color |= 0x1000 * abs((*itr)->m_BlockZ / m_Grid);
SVG.append((*itr)->ExportAsSVG(Color, 512, 512));
}
SVG.append("</svg>\n");
AString fnam;
Printf(fnam, "wnc\\%03d_%03d.svg", a_ChunkX, a_ChunkZ);
cFile File(fnam, cFile::fmWrite);
File.Write(SVG.c_str(), SVG.size());
#endif // _DEBUG
//*/
return cStructurePtr(new cCaveSystem(a_OriginX, a_OriginZ, m_MaxOffset, m_Size, m_Noise));
}

View File

@ -12,7 +12,7 @@
#pragma once
#include "ComposableGenerator.h"
#include "GridStructGen.h"
#include "../Noise.h"
@ -64,10 +64,12 @@ protected:
class cStructGenWormNestCaves :
public cFinishGen
public cGridStructGen
{
typedef cGridStructGen super;
public:
cStructGenWormNestCaves(int a_Seed, int a_Size = 64, int a_Grid = 96, int a_MaxOffset = 128) :
super(a_Seed, a_Grid, a_Grid, a_Size + a_MaxOffset, a_Size + a_MaxOffset, 100),
m_Noise(a_Seed),
m_Size(a_Size),
m_MaxOffset(a_MaxOffset),
@ -75,26 +77,16 @@ public:
{
}
~cStructGenWormNestCaves();
protected:
class cCaveSystem; // fwd: Caves.cpp
typedef std::list<cCaveSystem *> cCaveSystems;
cNoise m_Noise;
int m_Size; // relative size of the cave systems' caves. Average number of blocks of each initial tunnel
int m_MaxOffset; // maximum offset of the cave nest origin from the grid cell the nest belongs to
int m_Grid; // average spacing of the nests
cCaveSystems 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, cCaveSystems & a_Caves);
// cFinishGen override:
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
// cGridStructGen override:
virtual cStructurePtr CreateStructure(int a_OriginX, int a_OriginZ) override;
} ;