commit
7e71f1f7dc
@ -35,13 +35,6 @@ reduced in complexity in order for this generator to be useful, so the caves' sh
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// How many nests in each direction are generated for a given chunk. Must be an even number
|
|
||||||
#define NEIGHBORHOOD_SIZE 8
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const int MIN_RADIUS = 3;
|
const int MIN_RADIUS = 3;
|
||||||
const int MAX_RADIUS = 8;
|
const int MAX_RADIUS = 8;
|
||||||
|
|
||||||
@ -122,27 +115,19 @@ typedef std::vector<cCaveTunnel *> cCaveTunnels;
|
|||||||
|
|
||||||
|
|
||||||
/// A collection of connected tunnels, possibly branching.
|
/// A collection of connected tunnels, possibly branching.
|
||||||
class cStructGenWormNestCaves::cCaveSystem
|
class cStructGenWormNestCaves::cCaveSystem :
|
||||||
|
public cGridStructGen::cStructure
|
||||||
{
|
{
|
||||||
|
typedef cGridStructGen::cStructure super;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// The generating block position; is read directly in cStructGenWormNestCaves::GetCavesForChunk()
|
// The generating block position; is read directly in cStructGenWormNestCaves::GetCavesForChunk()
|
||||||
int m_BlockX;
|
int m_BlockX;
|
||||||
int m_BlockZ;
|
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();
|
~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:
|
protected:
|
||||||
int m_Size;
|
int m_Size;
|
||||||
cCaveTunnels m_Tunnels;
|
cCaveTunnels m_Tunnels;
|
||||||
@ -157,6 +142,9 @@ protected:
|
|||||||
|
|
||||||
/// Returns a radius based on the location provided.
|
/// Returns a radius based on the location provided.
|
||||||
int GetRadius(cNoise & a_Noise, int a_OriginX, int a_OriginY, int a_OriginZ);
|
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 +574,16 @@ AString cCaveTunnel::ExportAsSVG(int a_Color, int a_OffsetX, int a_OffsetZ) cons
|
|||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// cStructGenWormNestCaves::cCaveSystem:
|
// cStructGenWormNestCaves::cCaveSystem:
|
||||||
|
|
||||||
cStructGenWormNestCaves::cCaveSystem::cCaveSystem(int a_BlockX, int a_BlockZ, int a_MaxOffset, int a_Size, cNoise & a_Noise) :
|
cStructGenWormNestCaves::cCaveSystem::cCaveSystem(int a_OriginX, int a_OriginZ, int a_MaxOffset, int a_Size, cNoise & a_Noise) :
|
||||||
m_BlockX(a_BlockX),
|
super(a_OriginX, a_OriginZ),
|
||||||
m_BlockZ(a_BlockZ),
|
|
||||||
m_Size(a_Size)
|
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++)
|
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 OriginX = a_OriginX + (a_Noise.IntNoise3DInt(13 * a_OriginX, 17 * a_OriginZ, 11 * i) / 19) % a_MaxOffset;
|
||||||
int OriginZ = a_BlockZ + (a_Noise.IntNoise3DInt(17 * a_BlockX, 13 * a_BlockZ, 11 * i) / 23) % 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_BlockX, 13 * a_BlockZ, 11 * i) / 17) % 20;
|
int OriginY = 20 + (a_Noise.IntNoise3DInt(19 * a_OriginX, 13 * a_OriginZ, 11 * i) / 17) % 20;
|
||||||
|
|
||||||
// Generate three branches from the origin point:
|
// Generate three branches from the origin point:
|
||||||
// The tunnels generated depend on X, Y, Z and Branches,
|
// The tunnels generated depend on X, Y, Z and Branches,
|
||||||
@ -622,15 +609,15 @@ cStructGenWormNestCaves::cCaveSystem::~cCaveSystem()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cStructGenWormNestCaves::cCaveSystem::ProcessChunk(
|
void cStructGenWormNestCaves::cCaveSystem::DrawIntoChunk(cChunkDesc & a_ChunkDesc)
|
||||||
int a_ChunkX, int a_ChunkZ,
|
|
||||||
cChunkDef::BlockTypes & a_BlockTypes,
|
|
||||||
cChunkDef::HeightMap & a_HeightMap
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
|
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)
|
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[]
|
} // for itr - m_Tunnels[]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -638,53 +625,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)
|
void cStructGenWormNestCaves::cCaveSystem::Clear(void)
|
||||||
{
|
{
|
||||||
for (cCaveTunnels::const_iterator itr = m_Tunnels.begin(), end = m_Tunnels.end(); itr != end; ++itr)
|
for (cCaveTunnels::const_iterator itr = m_Tunnels.begin(), end = m_Tunnels.end(); itr != end; ++itr)
|
||||||
@ -750,142 +690,9 @@ int cStructGenWormNestCaves::cCaveSystem::GetRadius(cNoise & a_Noise, int a_Orig
|
|||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// cStructGenWormNestCaves:
|
// cStructGenWormNestCaves:
|
||||||
|
|
||||||
cStructGenWormNestCaves::~cStructGenWormNestCaves()
|
cGridStructGen::cStructurePtr cStructGenWormNestCaves::CreateStructure(int a_OriginX, int a_OriginZ)
|
||||||
{
|
{
|
||||||
ClearCache();
|
return cStructurePtr(new cCaveSystem(a_OriginX, a_OriginZ, m_MaxOffset, m_Size, m_Noise));
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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
|
|
||||||
//*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ComposableGenerator.h"
|
#include "GridStructGen.h"
|
||||||
#include "../Noise.h"
|
#include "../Noise.h"
|
||||||
|
|
||||||
|
|
||||||
@ -64,10 +64,12 @@ protected:
|
|||||||
|
|
||||||
|
|
||||||
class cStructGenWormNestCaves :
|
class cStructGenWormNestCaves :
|
||||||
public cFinishGen
|
public cGridStructGen
|
||||||
{
|
{
|
||||||
|
typedef cGridStructGen super;
|
||||||
public:
|
public:
|
||||||
cStructGenWormNestCaves(int a_Seed, int a_Size = 64, int a_Grid = 96, int a_MaxOffset = 128) :
|
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_Noise(a_Seed),
|
||||||
m_Size(a_Size),
|
m_Size(a_Size),
|
||||||
m_MaxOffset(a_MaxOffset),
|
m_MaxOffset(a_MaxOffset),
|
||||||
@ -75,26 +77,16 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
~cStructGenWormNestCaves();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
class cCaveSystem; // fwd: Caves.cpp
|
class cCaveSystem; // fwd: Caves.cpp
|
||||||
typedef std::list<cCaveSystem *> cCaveSystems;
|
|
||||||
|
|
||||||
cNoise m_Noise;
|
cNoise m_Noise;
|
||||||
int m_Size; // relative size of the cave systems' caves. Average number of blocks of each initial tunnel
|
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_MaxOffset; // maximum offset of the cave nest origin from the grid cell the nest belongs to
|
||||||
int m_Grid; // average spacing of the nests
|
int m_Grid; // average spacing of the nests
|
||||||
cCaveSystems m_Cache;
|
|
||||||
|
|
||||||
/// Clears everything from the cache
|
// cGridStructGen override:
|
||||||
void ClearCache(void);
|
virtual cStructurePtr CreateStructure(int a_OriginX, int a_OriginZ) override;
|
||||||
|
|
||||||
/// 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);
|
|
||||||
|
|
||||||
// cStructGen override:
|
|
||||||
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
|
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
126
src/Generating/GridStructGen.cpp
Normal file
126
src/Generating/GridStructGen.cpp
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
|
||||||
|
// GridStructGen.cpp
|
||||||
|
|
||||||
|
// Implements the cGridStructGen class representing a common base class for structure generators that place structures in a semi-random grid
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "GridStructGen.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cGridStructGen::cGridStructGen(
|
||||||
|
int a_Seed,
|
||||||
|
int a_GridSizeX, int a_GridSizeZ,
|
||||||
|
int a_MaxStructureSizeX, int a_MaxStructureSizeZ,
|
||||||
|
size_t a_MaxCacheSize
|
||||||
|
) :
|
||||||
|
m_Seed(a_Seed),
|
||||||
|
m_GridSizeX(a_GridSizeX),
|
||||||
|
m_GridSizeZ(a_GridSizeZ),
|
||||||
|
m_MaxStructureSizeX(a_MaxStructureSizeX),
|
||||||
|
m_MaxStructureSizeZ(a_MaxStructureSizeZ),
|
||||||
|
m_MaxCacheSize(a_MaxCacheSize)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cGridStructGen::GetStructuresForChunk(int a_ChunkX, int a_ChunkZ, cStructurePtrs & a_Structures)
|
||||||
|
{
|
||||||
|
// Calculate the min and max grid coords of the structures to be returned:
|
||||||
|
int MinBlockX = a_ChunkX * cChunkDef::Width - m_MaxStructureSizeX;
|
||||||
|
int MinBlockZ = a_ChunkZ * cChunkDef::Width - m_MaxStructureSizeZ;
|
||||||
|
int MaxBlockX = a_ChunkX * cChunkDef::Width + m_MaxStructureSizeX + cChunkDef::Width - 1;
|
||||||
|
int MaxBlockZ = a_ChunkZ * cChunkDef::Width + m_MaxStructureSizeZ + cChunkDef::Width - 1;
|
||||||
|
int MinGridX = MinBlockX / m_GridSizeX;
|
||||||
|
int MinGridZ = MinBlockZ / m_GridSizeZ;
|
||||||
|
int MaxGridX = (MaxBlockX + m_GridSizeX - 1) / m_GridSizeX;
|
||||||
|
int MaxGridZ = (MaxBlockZ + m_GridSizeZ - 1) / m_GridSizeZ;
|
||||||
|
int MinX = MinGridX * m_GridSizeX;
|
||||||
|
int MaxX = MaxGridX * m_GridSizeX;
|
||||||
|
int MinZ = MinGridZ * m_GridSizeZ;
|
||||||
|
int MaxZ = MaxGridZ * m_GridSizeZ;
|
||||||
|
|
||||||
|
// Walk the cache, move each structure that we want into a_Structures:
|
||||||
|
for (cStructurePtrs::iterator itr = m_Cache.begin(), end = m_Cache.end(); itr != end;)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
((*itr)->m_OriginX >= MinX) && ((*itr)->m_OriginX < MaxX) &&
|
||||||
|
((*itr)->m_OriginZ >= MinZ) && ((*itr)->m_OriginZ < MaxZ)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// want
|
||||||
|
a_Structures.push_back(*itr);
|
||||||
|
itr = m_Cache.erase(itr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// don't want
|
||||||
|
++itr;
|
||||||
|
}
|
||||||
|
} // for itr - m_Cache[]
|
||||||
|
|
||||||
|
// Create those structures that haven't been in the cache:
|
||||||
|
for (int x = MinGridX; x < MaxGridX; x++)
|
||||||
|
{
|
||||||
|
int OriginX = x * m_GridSizeX;
|
||||||
|
for (int z = MinGridZ; z < MaxGridZ; z++)
|
||||||
|
{
|
||||||
|
int OriginZ = z * m_GridSizeZ;
|
||||||
|
bool Found = false;
|
||||||
|
for (cStructurePtrs::const_iterator itr = a_Structures.begin(), end = a_Structures.end(); itr != end; ++itr)
|
||||||
|
{
|
||||||
|
if (((*itr)->m_OriginX == OriginX) && ((*itr)->m_OriginZ == OriginZ))
|
||||||
|
{
|
||||||
|
Found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // for itr - a_Structures[]
|
||||||
|
if (!Found)
|
||||||
|
{
|
||||||
|
a_Structures.push_back(CreateStructure(OriginX, OriginZ));
|
||||||
|
}
|
||||||
|
} // for z
|
||||||
|
} // for x
|
||||||
|
|
||||||
|
// Copy a_Forts into m_Cache to the beginning:
|
||||||
|
cStructurePtrs StructuresCopy (a_Structures);
|
||||||
|
m_Cache.splice(m_Cache.begin(), StructuresCopy, StructuresCopy.begin(), StructuresCopy.end());
|
||||||
|
|
||||||
|
// Trim the cache if it's too long:
|
||||||
|
size_t CacheSize = 0;
|
||||||
|
for (cStructurePtrs::iterator itr = m_Cache.begin(), end = m_Cache.end(); itr != end; ++itr)
|
||||||
|
{
|
||||||
|
CacheSize += (*itr)->GetCacheCost();
|
||||||
|
if (CacheSize > m_MaxCacheSize)
|
||||||
|
{
|
||||||
|
// Erase all items from this one till the cache end
|
||||||
|
m_Cache.erase(itr, m_Cache.end());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cGridStructGen::GenFinish(cChunkDesc & a_ChunkDesc)
|
||||||
|
{
|
||||||
|
int ChunkX = a_ChunkDesc.GetChunkX();
|
||||||
|
int ChunkZ = a_ChunkDesc.GetChunkZ();
|
||||||
|
cStructurePtrs Structures;
|
||||||
|
GetStructuresForChunk(ChunkX, ChunkZ, Structures);
|
||||||
|
for (cStructurePtrs::const_iterator itr = Structures.begin(); itr != Structures.end(); ++itr)
|
||||||
|
{
|
||||||
|
(*itr)->DrawIntoChunk(a_ChunkDesc);
|
||||||
|
} // for itr - Structures[]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
124
src/Generating/GridStructGen.h
Normal file
124
src/Generating/GridStructGen.h
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
|
||||||
|
// GridStructGen.h
|
||||||
|
|
||||||
|
// Declares the cGridStructGen class representing a common base class for structure generators that place structures in a semi-random grid
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ComposableGenerator.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Generates structures in a semi-random grid.
|
||||||
|
Defines a grid in the XZ space with predefined cell size in each direction. Each cell then receives exactly
|
||||||
|
one structure (provided by the descendant class). The structure is placed within the cell, but doesn't need
|
||||||
|
to be bounded by the cell, it can be well outside the cell; the generator uses the MaxStructureSize parameter
|
||||||
|
to determine how far away from the cell the structure can be at most.
|
||||||
|
This class provides a cache for the structures generated for successive chunks and manages that cache. It
|
||||||
|
also provides the cFinishGen override that uses the cache to actually generate the structure into chunk data.
|
||||||
|
|
||||||
|
After generating each chunk the cache is checked for size, each item in the cache has a cost associated with
|
||||||
|
it and the cache is trimmed (from its least-recently-used end) so that the sum of the cost in the cache is
|
||||||
|
less than m_MaxCacheSize
|
||||||
|
|
||||||
|
To use this class, declare a descendant class that implements the overridable methods, then create an
|
||||||
|
instance of that class. The descendant must provide the CreateStructure() function that is called to generate
|
||||||
|
a structure at the specific grid cell.
|
||||||
|
|
||||||
|
The descendant must use a specific cStructure descendant to provide the actual structure that gets generated.
|
||||||
|
The structure must provide the DrawIntoChunk() function that generates the structure into the chunk data, and
|
||||||
|
can override the GetCacheCost() function that returns the cost of that structure in the cache.
|
||||||
|
*/
|
||||||
|
class cGridStructGen :
|
||||||
|
public cFinishGen
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cGridStructGen(
|
||||||
|
int a_Seed,
|
||||||
|
int a_GridSizeX, int a_GridSizeZ,
|
||||||
|
int a_MaxStructureSizeX, int a_MaxStructureSizeZ,
|
||||||
|
size_t a_MaxCacheSize
|
||||||
|
);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/** Represents a single structure that occupies the grid point. Knows how to draw itself into a chunk. */
|
||||||
|
class cStructure
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** The origin (the coords of the gridpoint for which the structure is generated) */
|
||||||
|
int m_OriginX, m_OriginZ;
|
||||||
|
|
||||||
|
|
||||||
|
/** Creates a structure that has its originset at the specified coords. */
|
||||||
|
cStructure (int a_OriginX, int a_OriginZ) :
|
||||||
|
m_OriginX(a_OriginX),
|
||||||
|
m_OriginZ(a_OriginZ)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force a virtual destructor in descendants:
|
||||||
|
virtual ~cStructure() {}
|
||||||
|
|
||||||
|
/** Draws self into the specified chunk */
|
||||||
|
virtual void DrawIntoChunk(cChunkDesc & a_ChunkDesc) = 0;
|
||||||
|
|
||||||
|
/** Returns the cost of keeping this structure in the cache */
|
||||||
|
virtual size_t GetCacheCost(void) const { return 1; }
|
||||||
|
} ;
|
||||||
|
typedef SharedPtr<cStructure> cStructurePtr;
|
||||||
|
typedef std::list<cStructurePtr> cStructurePtrs;
|
||||||
|
|
||||||
|
|
||||||
|
/** Seed for generating the semi-random grid. */
|
||||||
|
int m_Seed;
|
||||||
|
|
||||||
|
/** The size of each grid's cell in the X axis */
|
||||||
|
int m_GridSizeX;
|
||||||
|
|
||||||
|
/** The size of each grid's cell in the Z axis */
|
||||||
|
int m_GridSizeZ;
|
||||||
|
|
||||||
|
/** Maximum theoretical size of the structure in the X axis.
|
||||||
|
This limits the structures considered for a single chunk, so the lesser the number, the better performance.
|
||||||
|
Structures large than this may get cropped. */
|
||||||
|
int m_MaxStructureSizeX;
|
||||||
|
|
||||||
|
/** Maximum theoretical size of the structure in the Z axis.
|
||||||
|
This limits the structures considered for a single chunk, so the lesser the number, the better performance.
|
||||||
|
Structures large than this may get cropped. */
|
||||||
|
int m_MaxStructureSizeZ;
|
||||||
|
|
||||||
|
/** Maximum allowed sum of costs for items in the cache. Items that are over this cost are removed from the
|
||||||
|
cache, oldest-first */
|
||||||
|
size_t m_MaxCacheSize;
|
||||||
|
|
||||||
|
/** Cache for the most recently generated structures, ordered by the recentness. */
|
||||||
|
cStructurePtrs m_Cache;
|
||||||
|
|
||||||
|
|
||||||
|
/** Clears everything from the cache */
|
||||||
|
void ClearCache(void);
|
||||||
|
|
||||||
|
/** Returns all structures that may intersect the given chunk.
|
||||||
|
The structures are considered as intersecting iff their bounding box (defined by m_MaxStructureSize)
|
||||||
|
around their gridpoint intersects the chunk. */
|
||||||
|
void GetStructuresForChunk(int a_ChunkX, int a_ChunkZ, cStructurePtrs & a_Structures);
|
||||||
|
|
||||||
|
// cFinishGen overrides:
|
||||||
|
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
|
||||||
|
|
||||||
|
// Functions for the descendants to override:
|
||||||
|
/** Create a new structure at the specified gridpoint */
|
||||||
|
virtual cStructurePtr CreateStructure(int a_OriginX, int a_OriginZ) = 0;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -25,12 +25,6 @@ in a depth-first processing. Each of the descendants will branch randomly, if no
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static const int NEIGHBORHOOD_SIZE = 3;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cMineShaft abstract
|
class cMineShaft abstract
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -234,10 +228,12 @@ protected:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cStructGenMineShafts::cMineShaftSystem
|
class cStructGenMineShafts::cMineShaftSystem :
|
||||||
|
public cGridStructGen::cStructure
|
||||||
{
|
{
|
||||||
|
typedef cGridStructGen::cStructure super;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int m_BlockX, m_BlockZ; ///< The pivot point on which the system is generated
|
|
||||||
int m_GridSize; ///< Maximum offset of the dirtroom from grid center, * 2, in each direction
|
int m_GridSize; ///< Maximum offset of the dirtroom from grid center, * 2, in each direction
|
||||||
int m_MaxRecursion; ///< Maximum recursion level (initialized from cStructGenMineShafts::m_MaxRecursion)
|
int m_MaxRecursion; ///< Maximum recursion level (initialized from cStructGenMineShafts::m_MaxRecursion)
|
||||||
int m_ProbLevelCorridor; ///< Probability level of a branch object being the corridor
|
int m_ProbLevelCorridor; ///< Probability level of a branch object being the corridor
|
||||||
@ -249,17 +245,15 @@ public:
|
|||||||
cMineShafts m_MineShafts; ///< List of cMineShaft descendants that comprise this system
|
cMineShafts m_MineShafts; ///< List of cMineShaft descendants that comprise this system
|
||||||
cCuboid m_BoundingBox; ///< Bounding box into which all of the components need to fit
|
cCuboid m_BoundingBox; ///< Bounding box into which all of the components need to fit
|
||||||
|
|
||||||
/// Creates and generates the entire system
|
|
||||||
|
/** Creates and generates the entire system */
|
||||||
cMineShaftSystem(
|
cMineShaftSystem(
|
||||||
int a_BlockX, int a_BlockZ, int a_GridSize, int a_MaxSystemSize, cNoise & a_Noise,
|
int a_OriginX, int a_OriginZ, int a_GridSize, int a_MaxSystemSize, cNoise & a_Noise,
|
||||||
int a_ProbLevelCorridor, int a_ProbLevelCrossing, int a_ProbLevelStaircase
|
int a_ProbLevelCorridor, int a_ProbLevelCrossing, int a_ProbLevelStaircase
|
||||||
);
|
);
|
||||||
|
|
||||||
~cMineShaftSystem();
|
~cMineShaftSystem();
|
||||||
|
|
||||||
/// Carves the system into the chunk data
|
|
||||||
void ProcessChunk(cChunkDesc & a_Chunk);
|
|
||||||
|
|
||||||
/** Creates new cMineShaft descendant connected at the specified point, heading the specified direction,
|
/** Creates new cMineShaft descendant connected at the specified point, heading the specified direction,
|
||||||
if it fits, appends it to the list and calls its AppendBranches()
|
if it fits, appends it to the list and calls its AppendBranches()
|
||||||
*/
|
*/
|
||||||
@ -269,8 +263,11 @@ public:
|
|||||||
int a_RecursionLevel
|
int a_RecursionLevel
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Returns true if none of the objects in m_MineShafts intersect with the specified bounding box and the bounding box is valid
|
/** Returns true if none of the objects in m_MineShafts intersect with the specified bounding box and the bounding box is valid */
|
||||||
bool CanAppend(const cCuboid & a_BoundingBox);
|
bool CanAppend(const cCuboid & a_BoundingBox);
|
||||||
|
|
||||||
|
// cGridStructGen::cStructure overrides:
|
||||||
|
virtual void DrawIntoChunk(cChunkDesc & a_Chunk);
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
@ -281,11 +278,10 @@ public:
|
|||||||
// cStructGenMineShafts::cMineShaftSystem:
|
// cStructGenMineShafts::cMineShaftSystem:
|
||||||
|
|
||||||
cStructGenMineShafts::cMineShaftSystem::cMineShaftSystem(
|
cStructGenMineShafts::cMineShaftSystem::cMineShaftSystem(
|
||||||
int a_BlockX, int a_BlockZ, int a_GridSize, int a_MaxSystemSize, cNoise & a_Noise,
|
int a_OriginX, int a_OriginZ, int a_GridSize, int a_MaxSystemSize, cNoise & a_Noise,
|
||||||
int a_ProbLevelCorridor, int a_ProbLevelCrossing, int a_ProbLevelStaircase
|
int a_ProbLevelCorridor, int a_ProbLevelCrossing, int a_ProbLevelStaircase
|
||||||
) :
|
) :
|
||||||
m_BlockX(a_BlockX),
|
super(a_OriginX, a_OriginZ),
|
||||||
m_BlockZ(a_BlockZ),
|
|
||||||
m_GridSize(a_GridSize),
|
m_GridSize(a_GridSize),
|
||||||
m_MaxRecursion(8), // TODO: settable
|
m_MaxRecursion(8), // TODO: settable
|
||||||
m_ProbLevelCorridor(a_ProbLevelCorridor),
|
m_ProbLevelCorridor(a_ProbLevelCorridor),
|
||||||
@ -330,7 +326,7 @@ cStructGenMineShafts::cMineShaftSystem::~cMineShaftSystem()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cStructGenMineShafts::cMineShaftSystem::ProcessChunk(cChunkDesc & a_Chunk)
|
void cStructGenMineShafts::cMineShaftSystem::DrawIntoChunk(cChunkDesc & a_Chunk)
|
||||||
{
|
{
|
||||||
for (cMineShafts::const_iterator itr = m_MineShafts.begin(), end = m_MineShafts.end(); itr != end; ++itr)
|
for (cMineShafts::const_iterator itr = m_MineShafts.begin(), end = m_MineShafts.end(); itr != end; ++itr)
|
||||||
{
|
{
|
||||||
@ -409,15 +405,15 @@ cMineShaftDirtRoom::cMineShaftDirtRoom(cStructGenMineShafts::cMineShaftSystem &
|
|||||||
super(a_Parent, mskDirtRoom)
|
super(a_Parent, mskDirtRoom)
|
||||||
{
|
{
|
||||||
// Make the room of random size, min 10 x 4 x 10; max 18 x 12 x 18:
|
// Make the room of random size, min 10 x 4 x 10; max 18 x 12 x 18:
|
||||||
int rnd = a_Noise.IntNoise3DInt(a_Parent.m_BlockX, 0, a_Parent.m_BlockZ) / 7;
|
int rnd = a_Noise.IntNoise3DInt(a_Parent.m_OriginX, 0, a_Parent.m_OriginZ) / 7;
|
||||||
int OfsX = (rnd % a_Parent.m_GridSize) - a_Parent.m_GridSize / 2;
|
int OfsX = (rnd % a_Parent.m_GridSize) - a_Parent.m_GridSize / 2;
|
||||||
rnd >>= 12;
|
rnd >>= 12;
|
||||||
int OfsZ = (rnd % a_Parent.m_GridSize) - a_Parent.m_GridSize / 2;
|
int OfsZ = (rnd % a_Parent.m_GridSize) - a_Parent.m_GridSize / 2;
|
||||||
rnd = a_Noise.IntNoise3DInt(a_Parent.m_BlockX, 1000, a_Parent.m_BlockZ) / 11;
|
rnd = a_Noise.IntNoise3DInt(a_Parent.m_OriginX, 1000, a_Parent.m_OriginZ) / 11;
|
||||||
m_BoundingBox.p1.x = a_Parent.m_BlockX + OfsX;
|
m_BoundingBox.p1.x = a_Parent.m_OriginX + OfsX;
|
||||||
m_BoundingBox.p2.x = m_BoundingBox.p1.x + 10 + (rnd % 8);
|
m_BoundingBox.p2.x = m_BoundingBox.p1.x + 10 + (rnd % 8);
|
||||||
rnd >>= 4;
|
rnd >>= 4;
|
||||||
m_BoundingBox.p1.z = a_Parent.m_BlockZ + OfsZ;
|
m_BoundingBox.p1.z = a_Parent.m_OriginZ + OfsZ;
|
||||||
m_BoundingBox.p2.z = m_BoundingBox.p1.z + 10 + (rnd % 8);
|
m_BoundingBox.p2.z = m_BoundingBox.p1.z + 10 + (rnd % 8);
|
||||||
rnd >>= 4;
|
rnd >>= 4;
|
||||||
m_BoundingBox.p1.y = 20;
|
m_BoundingBox.p1.y = 20;
|
||||||
@ -1287,6 +1283,7 @@ cStructGenMineShafts::cStructGenMineShafts(
|
|||||||
int a_Seed, int a_GridSize, int a_MaxSystemSize,
|
int a_Seed, int a_GridSize, int a_MaxSystemSize,
|
||||||
int a_ChanceCorridor, int a_ChanceCrossing, int a_ChanceStaircase
|
int a_ChanceCorridor, int a_ChanceCrossing, int a_ChanceStaircase
|
||||||
) :
|
) :
|
||||||
|
super(a_Seed, a_GridSize, a_GridSize, 120 + a_MaxSystemSize * 10, 120 + a_MaxSystemSize * 10, 100),
|
||||||
m_Noise(a_Seed),
|
m_Noise(a_Seed),
|
||||||
m_GridSize(a_GridSize),
|
m_GridSize(a_GridSize),
|
||||||
m_MaxSystemSize(a_MaxSystemSize),
|
m_MaxSystemSize(a_MaxSystemSize),
|
||||||
@ -1300,125 +1297,9 @@ cStructGenMineShafts::cStructGenMineShafts(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
cStructGenMineShafts::~cStructGenMineShafts()
|
cGridStructGen::cStructurePtr cStructGenMineShafts::CreateStructure(int a_OriginX, int a_OriginZ)
|
||||||
{
|
{
|
||||||
ClearCache();
|
return cStructurePtr(new cMineShaftSystem(a_OriginX, a_OriginZ, m_GridSize, m_MaxSystemSize, m_Noise, m_ProbLevelCorridor, m_ProbLevelCrossing, m_ProbLevelStaircase));
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cStructGenMineShafts::ClearCache(void)
|
|
||||||
{
|
|
||||||
for (cMineShaftSystems::const_iterator itr = m_Cache.begin(), end = m_Cache.end(); itr != end; ++itr)
|
|
||||||
{
|
|
||||||
delete *itr;
|
|
||||||
} // for itr - m_Cache[]
|
|
||||||
m_Cache.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cStructGenMineShafts::GetMineShaftSystemsForChunk(
|
|
||||||
int a_ChunkX, int a_ChunkZ,
|
|
||||||
cStructGenMineShafts::cMineShaftSystems & a_MineShafts
|
|
||||||
)
|
|
||||||
{
|
|
||||||
int BaseX = a_ChunkX * cChunkDef::Width / m_GridSize;
|
|
||||||
int BaseZ = a_ChunkZ * cChunkDef::Width / m_GridSize;
|
|
||||||
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_Mineshafts:
|
|
||||||
int StartX = BaseX * m_GridSize;
|
|
||||||
int EndX = (BaseX + NEIGHBORHOOD_SIZE + 1) * m_GridSize;
|
|
||||||
int StartZ = BaseZ * m_GridSize;
|
|
||||||
int EndZ = (BaseZ + NEIGHBORHOOD_SIZE + 1) * m_GridSize;
|
|
||||||
for (cMineShaftSystems::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_MineShafts.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_GridSize;
|
|
||||||
for (int z = 0; z < NEIGHBORHOOD_SIZE; z++)
|
|
||||||
{
|
|
||||||
int RealZ = (BaseZ + z) * m_GridSize;
|
|
||||||
bool Found = false;
|
|
||||||
for (cMineShaftSystems::const_iterator itr = a_MineShafts.begin(), end = a_MineShafts.end(); itr != end; ++itr)
|
|
||||||
{
|
|
||||||
if (((*itr)->m_BlockX == RealX) && ((*itr)->m_BlockZ == RealZ))
|
|
||||||
{
|
|
||||||
Found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} // for itr - a_Mineshafts
|
|
||||||
if (!Found)
|
|
||||||
{
|
|
||||||
a_MineShafts.push_back(new cMineShaftSystem(RealX, RealZ, m_GridSize, m_MaxSystemSize, m_Noise, m_ProbLevelCorridor, m_ProbLevelCrossing, m_ProbLevelStaircase));
|
|
||||||
}
|
|
||||||
} // for z
|
|
||||||
} // for x
|
|
||||||
|
|
||||||
// Copy a_MineShafts into m_Cache to the beginning:
|
|
||||||
cMineShaftSystems MineShaftsCopy(a_MineShafts);
|
|
||||||
m_Cache.splice(m_Cache.begin(), MineShaftsCopy, MineShaftsCopy.begin(), MineShaftsCopy.end());
|
|
||||||
|
|
||||||
// Trim the cache if it's too long:
|
|
||||||
if (m_Cache.size() > 100)
|
|
||||||
{
|
|
||||||
cMineShaftSystems::iterator itr = m_Cache.begin();
|
|
||||||
std::advance(itr, 100);
|
|
||||||
for (cMineShaftSystems::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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cStructGenMineShafts::GenFinish(cChunkDesc & a_ChunkDesc)
|
|
||||||
{
|
|
||||||
int ChunkX = a_ChunkDesc.GetChunkX();
|
|
||||||
int ChunkZ = a_ChunkDesc.GetChunkZ();
|
|
||||||
cMineShaftSystems MineShafts;
|
|
||||||
GetMineShaftSystemsForChunk(ChunkX, ChunkZ, MineShafts);
|
|
||||||
for (cMineShaftSystems::const_iterator itr = MineShafts.begin(); itr != MineShafts.end(); ++itr)
|
|
||||||
{
|
|
||||||
(*itr)->ProcessChunk(a_ChunkDesc);
|
|
||||||
} // for itr - MineShafts[]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ComposableGenerator.h"
|
#include "GridStructGen.h"
|
||||||
#include "../Noise.h"
|
#include "../Noise.h"
|
||||||
|
|
||||||
|
|
||||||
@ -17,16 +17,16 @@
|
|||||||
|
|
||||||
|
|
||||||
class cStructGenMineShafts :
|
class cStructGenMineShafts :
|
||||||
public cFinishGen
|
public cGridStructGen
|
||||||
{
|
{
|
||||||
|
typedef cGridStructGen super;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cStructGenMineShafts(
|
cStructGenMineShafts(
|
||||||
int a_Seed, int a_GridSize, int a_MaxSystemSize,
|
int a_Seed, int a_GridSize, int a_MaxSystemSize,
|
||||||
int a_ChanceCorridor, int a_ChanceCrossing, int a_ChanceStaircase
|
int a_ChanceCorridor, int a_ChanceCrossing, int a_ChanceStaircase
|
||||||
);
|
);
|
||||||
|
|
||||||
virtual ~cStructGenMineShafts();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class cMineShaft;
|
friend class cMineShaft;
|
||||||
friend class cMineShaftDirtRoom;
|
friend class cMineShaftDirtRoom;
|
||||||
@ -34,26 +34,16 @@ protected:
|
|||||||
friend class cMineShaftCrossing;
|
friend class cMineShaftCrossing;
|
||||||
friend class cMineShaftStaircase;
|
friend class cMineShaftStaircase;
|
||||||
class cMineShaftSystem; // fwd: MineShafts.cpp
|
class cMineShaftSystem; // fwd: MineShafts.cpp
|
||||||
typedef std::list<cMineShaftSystem *> cMineShaftSystems;
|
|
||||||
|
|
||||||
cNoise m_Noise;
|
cNoise m_Noise;
|
||||||
int m_GridSize; ///< Average spacing of the systems
|
int m_GridSize; ///< Average spacing of the systems
|
||||||
int m_MaxSystemSize; ///< Maximum blcok size of a mineshaft system
|
int m_MaxSystemSize; ///< Maximum blcok size of a mineshaft system
|
||||||
int m_ProbLevelCorridor; ///< Probability level of a branch object being the corridor
|
int m_ProbLevelCorridor; ///< Probability level of a branch object being the corridor
|
||||||
int m_ProbLevelCrossing; ///< Probability level of a branch object being the crossing, minus Corridor
|
int m_ProbLevelCrossing; ///< Probability level of a branch object being the crossing, minus Corridor
|
||||||
int m_ProbLevelStaircase; ///< Probability level of a branch object being the staircase, minus Crossing
|
int m_ProbLevelStaircase; ///< Probability level of a branch object being the staircase, minus Crossing
|
||||||
cMineShaftSystems m_Cache; ///< Cache of the most recently used systems. MoveToFront used.
|
|
||||||
|
|
||||||
/// Clears everything from the cache
|
// cGridStructGen overrides:
|
||||||
void ClearCache(void);
|
virtual cStructurePtr CreateStructure(int a_OriginX, int a_OriginZ) override;
|
||||||
|
|
||||||
/** Returns all systems that *may* intersect the given chunk.
|
|
||||||
All the systems are valid until the next call to this function (which may delete some of the pointers).
|
|
||||||
*/
|
|
||||||
void GetMineShaftSystemsForChunk(int a_ChunkX, int a_ChunkZ, cMineShaftSystems & a_MineShaftSystems);
|
|
||||||
|
|
||||||
// cFinishGen overrides:
|
|
||||||
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
|
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,29 +11,24 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static const int NEIGHBORHOOD_SIZE = 3;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// cNetherFortGen::cNetherFort:
|
// cNetherFortGen::cNetherFort:
|
||||||
|
|
||||||
class cNetherFortGen::cNetherFort
|
class cNetherFortGen::cNetherFort :
|
||||||
|
public cGridStructGen::cStructure
|
||||||
{
|
{
|
||||||
|
typedef cGridStructGen::cStructure super;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cNetherFortGen & m_ParentGen;
|
cNetherFortGen & m_ParentGen;
|
||||||
int m_BlockX, m_BlockZ;
|
|
||||||
int m_GridSize;
|
int m_GridSize;
|
||||||
int m_Seed;
|
int m_Seed;
|
||||||
cPlacedPieces m_Pieces;
|
cPlacedPieces m_Pieces;
|
||||||
|
|
||||||
|
|
||||||
cNetherFort(cNetherFortGen & a_ParentGen, int a_BlockX, int a_BlockZ, int a_GridSize, int a_MaxDepth, int a_Seed) :
|
cNetherFort(cNetherFortGen & a_ParentGen, int a_OriginX, int a_OriginZ, int a_GridSize, int a_MaxDepth, int a_Seed) :
|
||||||
|
super(a_OriginX, a_OriginZ),
|
||||||
m_ParentGen(a_ParentGen),
|
m_ParentGen(a_ParentGen),
|
||||||
m_BlockX(a_BlockX),
|
|
||||||
m_BlockZ(a_BlockZ),
|
|
||||||
m_GridSize(a_GridSize),
|
m_GridSize(a_GridSize),
|
||||||
m_Seed(a_Seed)
|
m_Seed(a_Seed)
|
||||||
{
|
{
|
||||||
@ -43,8 +38,8 @@ public:
|
|||||||
// Generate pieces:
|
// Generate pieces:
|
||||||
for (int i = 0; m_Pieces.size() < (size_t)(a_MaxDepth * a_MaxDepth / 8 + a_MaxDepth); i++)
|
for (int i = 0; m_Pieces.size() < (size_t)(a_MaxDepth * a_MaxDepth / 8 + a_MaxDepth); i++)
|
||||||
{
|
{
|
||||||
cBFSPieceGenerator pg(m_ParentGen, a_Seed + i);
|
cBFSPieceGenerator pg(cNetherFortGen::m_PiecePool, a_Seed + i);
|
||||||
pg.PlacePieces(a_BlockX, BlockY, a_BlockZ, a_MaxDepth, m_Pieces);
|
pg.PlacePieces(a_OriginX, BlockY, a_OriginZ, a_MaxDepth, m_Pieces);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +51,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
/** Carves the system into the chunk data */
|
/** Carves the system into the chunk data */
|
||||||
void ProcessChunk(cChunkDesc & a_Chunk)
|
virtual void DrawIntoChunk(cChunkDesc & a_Chunk)
|
||||||
{
|
{
|
||||||
for (cPlacedPieces::const_iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr)
|
for (cPlacedPieces::const_iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr)
|
||||||
{
|
{
|
||||||
@ -107,214 +102,30 @@ public:
|
|||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// cNetherFortGen:
|
// cNetherFortGen:
|
||||||
|
|
||||||
|
cPrefabPiecePool cNetherFortGen::m_PiecePool(g_NetherFortPrefabs, g_NetherFortPrefabsCount, g_NetherFortStartingPrefabs, g_NetherFortStartingPrefabsCount);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cNetherFortGen::cNetherFortGen(int a_Seed, int a_GridSize, int a_MaxDepth) :
|
cNetherFortGen::cNetherFortGen(int a_Seed, int a_GridSize, int a_MaxDepth) :
|
||||||
m_Seed(a_Seed),
|
super(a_Seed, a_GridSize, a_GridSize, a_MaxDepth * 10, a_MaxDepth * 10, 200),
|
||||||
m_Noise(a_Seed),
|
|
||||||
m_GridSize(a_GridSize),
|
|
||||||
m_MaxDepth(a_MaxDepth)
|
m_MaxDepth(a_MaxDepth)
|
||||||
{
|
{
|
||||||
// Initialize the prefabs:
|
|
||||||
for (size_t i = 0; i < g_NetherFortPrefabsCount; i++)
|
|
||||||
{
|
|
||||||
cPrefab * Prefab = new cPrefab(g_NetherFortPrefabs[i]);
|
|
||||||
m_AllPieces.push_back(Prefab);
|
|
||||||
if (Prefab->HasConnectorType(0))
|
|
||||||
{
|
|
||||||
m_OuterPieces.push_back(Prefab);
|
|
||||||
}
|
|
||||||
if (Prefab->HasConnectorType(1))
|
|
||||||
{
|
|
||||||
m_InnerPieces.push_back(Prefab);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize the starting piece prefabs:
|
|
||||||
for (size_t i = 0; i < g_NetherFortStartingPrefabsCount; i++)
|
|
||||||
{
|
|
||||||
m_StartingPieces.push_back(new cPrefab(g_NetherFortStartingPrefabs[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// DEBUG: Try one round of placement:
|
// DEBUG: Try one round of placement:
|
||||||
cPlacedPieces Pieces;
|
cPlacedPieces Pieces;
|
||||||
cBFSPieceGenerator pg(*this, a_Seed);
|
cBFSPieceGenerator pg(m_PiecePool, a_Seed);
|
||||||
pg.PlacePieces(0, 64, 0, a_MaxDepth, Pieces);
|
pg.PlacePieces(0, 64, 0, a_MaxDepth, Pieces);
|
||||||
*/
|
//*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cNetherFortGen::~cNetherFortGen()
|
cGridStructGen::cStructurePtr cNetherFortGen::CreateStructure(int a_OriginX, int a_OriginZ)
|
||||||
{
|
{
|
||||||
ClearCache();
|
return cStructurePtr(new cNetherFort(*this, a_OriginX, a_OriginZ, m_GridSizeX, m_MaxDepth, m_Seed));
|
||||||
for (cPieces::iterator itr = m_AllPieces.begin(), end = m_AllPieces.end(); itr != end; ++itr)
|
|
||||||
{
|
|
||||||
delete *itr;
|
|
||||||
} // for itr - m_AllPieces[]
|
|
||||||
m_AllPieces.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cNetherFortGen::ClearCache(void)
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cNetherFortGen::GetFortsForChunk(int a_ChunkX, int a_ChunkZ, cNetherForts & a_Forts)
|
|
||||||
{
|
|
||||||
int BaseX = a_ChunkX * cChunkDef::Width / m_GridSize;
|
|
||||||
int BaseZ = a_ChunkZ * cChunkDef::Width / m_GridSize;
|
|
||||||
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_Forts:
|
|
||||||
int StartX = BaseX * m_GridSize;
|
|
||||||
int EndX = (BaseX + NEIGHBORHOOD_SIZE + 1) * m_GridSize;
|
|
||||||
int StartZ = BaseZ * m_GridSize;
|
|
||||||
int EndZ = (BaseZ + NEIGHBORHOOD_SIZE + 1) * m_GridSize;
|
|
||||||
for (cNetherForts::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_Forts.push_back(*itr);
|
|
||||||
itr = m_Cache.erase(itr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// don't want
|
|
||||||
++itr;
|
|
||||||
}
|
|
||||||
} // for itr - m_Cache[]
|
|
||||||
|
|
||||||
// Create those forts that haven't been in the cache:
|
|
||||||
for (int x = 0; x < NEIGHBORHOOD_SIZE; x++)
|
|
||||||
{
|
|
||||||
int RealX = (BaseX + x) * m_GridSize;
|
|
||||||
for (int z = 0; z < NEIGHBORHOOD_SIZE; z++)
|
|
||||||
{
|
|
||||||
int RealZ = (BaseZ + z) * m_GridSize;
|
|
||||||
bool Found = false;
|
|
||||||
for (cNetherForts::const_iterator itr = a_Forts.begin(), end = a_Forts.end(); itr != end; ++itr)
|
|
||||||
{
|
|
||||||
if (((*itr)->m_BlockX == RealX) && ((*itr)->m_BlockZ == RealZ))
|
|
||||||
{
|
|
||||||
Found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} // for itr - a_Mineshafts
|
|
||||||
if (!Found)
|
|
||||||
{
|
|
||||||
a_Forts.push_back(new cNetherFort(*this, RealX, RealZ, m_GridSize, m_MaxDepth, m_Seed));
|
|
||||||
}
|
|
||||||
} // for z
|
|
||||||
} // for x
|
|
||||||
|
|
||||||
// Copy a_Forts into m_Cache to the beginning:
|
|
||||||
cNetherForts FortsCopy (a_Forts);
|
|
||||||
m_Cache.splice(m_Cache.begin(), FortsCopy, FortsCopy.begin(), FortsCopy.end());
|
|
||||||
|
|
||||||
// Trim the cache if it's too long:
|
|
||||||
if (m_Cache.size() > 100)
|
|
||||||
{
|
|
||||||
cNetherForts::iterator itr = m_Cache.begin();
|
|
||||||
std::advance(itr, 100);
|
|
||||||
for (cNetherForts::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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cNetherFortGen::GenFinish(cChunkDesc & a_ChunkDesc)
|
|
||||||
{
|
|
||||||
int ChunkX = a_ChunkDesc.GetChunkX();
|
|
||||||
int ChunkZ = a_ChunkDesc.GetChunkZ();
|
|
||||||
cNetherForts Forts;
|
|
||||||
GetFortsForChunk(ChunkX, ChunkZ, Forts);
|
|
||||||
for (cNetherForts::const_iterator itr = Forts.begin(); itr != Forts.end(); ++itr)
|
|
||||||
{
|
|
||||||
(*itr)->ProcessChunk(a_ChunkDesc);
|
|
||||||
} // for itr - Forts[]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cPieces cNetherFortGen::GetPiecesWithConnector(int a_ConnectorType)
|
|
||||||
{
|
|
||||||
switch (a_ConnectorType)
|
|
||||||
{
|
|
||||||
case 0: return m_OuterPieces;
|
|
||||||
case 1: return m_InnerPieces;
|
|
||||||
default: return cPieces();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cPieces cNetherFortGen::GetStartingPieces(void)
|
|
||||||
{
|
|
||||||
return m_StartingPieces;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int cNetherFortGen::GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece)
|
|
||||||
{
|
|
||||||
return ((const cPrefab &)a_NewPiece).GetPieceWeight(a_PlacedPiece, a_ExistingConnector);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cNetherFortGen::PiecePlaced(const cPiece & a_Piece)
|
|
||||||
{
|
|
||||||
UNUSED(a_Piece);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cNetherFortGen::Reset(void)
|
|
||||||
{
|
|
||||||
// Nothing needed
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,77 +10,34 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ComposableGenerator.h"
|
#include "ComposableGenerator.h"
|
||||||
#include "PieceGenerator.h"
|
#include "PrefabPiecePool.h"
|
||||||
|
#include "GridStructGen.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cNetherFortGen :
|
class cNetherFortGen :
|
||||||
public cFinishGen,
|
public cGridStructGen
|
||||||
public cPiecePool
|
|
||||||
{
|
{
|
||||||
|
typedef cGridStructGen super;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cNetherFortGen(int a_Seed, int a_GridSize, int a_MaxDepth);
|
cNetherFortGen(int a_Seed, int a_GridSize, int a_MaxDepth);
|
||||||
|
|
||||||
virtual ~cNetherFortGen();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class cNetherFortPerfTest; // fwd: NetherFortGen.cpp
|
friend class cNetherFortPerfTest; // fwd: NetherFortGen.cpp
|
||||||
class cNetherFort; // fwd: NetherFortGen.cpp
|
class cNetherFort; // fwd: NetherFortGen.cpp
|
||||||
typedef std::list<cNetherFort *> cNetherForts;
|
|
||||||
|
|
||||||
|
|
||||||
/** The seed used for generating*/
|
|
||||||
int m_Seed;
|
|
||||||
|
|
||||||
/** The noise used for generating */
|
|
||||||
cNoise m_Noise;
|
|
||||||
|
|
||||||
/** Average spacing between the fortresses*/
|
|
||||||
int m_GridSize;
|
|
||||||
|
|
||||||
/** Maximum depth of the piece-generator tree */
|
/** Maximum depth of the piece-generator tree */
|
||||||
int m_MaxDepth;
|
int m_MaxDepth;
|
||||||
|
|
||||||
/** Cache of the most recently used systems. MoveToFront used. */
|
/** The pool of pieces to use for generating. Static, so that it's shared by multiple generators. */
|
||||||
cNetherForts m_Cache;
|
static cPrefabPiecePool m_PiecePool;
|
||||||
|
|
||||||
/** All the pieces that are allowed for building.
|
|
||||||
This is the list that's used for memory allocation and deallocation for the pieces. */
|
|
||||||
cPieces m_AllPieces;
|
|
||||||
|
|
||||||
/** The pieces that are used as starting pieces.
|
|
||||||
This list is not shared and the pieces need deallocation. */
|
|
||||||
cPieces m_StartingPieces;
|
|
||||||
|
|
||||||
/** The pieces that have an "outer" connector.
|
|
||||||
The pieces are copies out of m_AllPieces and shouldn't be ever delete-d. */
|
|
||||||
cPieces m_OuterPieces;
|
|
||||||
|
|
||||||
/** The pieces that have an "inner" connector.
|
|
||||||
The pieces are copies out of m_AllPieces and shouldn't be ever delete-d. */
|
|
||||||
cPieces m_InnerPieces;
|
|
||||||
|
|
||||||
|
|
||||||
/** Clears everything from the cache.
|
// cGridStructGen overrides:
|
||||||
Also invalidates the forst returned by GetFortsForChunk(). */
|
virtual cStructurePtr CreateStructure(int a_OriginX, int a_OriginZ) override;
|
||||||
void ClearCache(void);
|
|
||||||
|
|
||||||
/** Returns all forts that *may* intersect the given chunk.
|
|
||||||
The returned forts live within m_Cache.They are valid until the next call
|
|
||||||
to this function (which may delete some of the pointers). */
|
|
||||||
void GetFortsForChunk(int a_ChunkX, int a_ChunkZ, cNetherForts & a_Forts);
|
|
||||||
|
|
||||||
// cFinishGen overrides:
|
|
||||||
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
|
|
||||||
|
|
||||||
// cPiecePool overrides:
|
|
||||||
virtual cPieces GetPiecesWithConnector(int a_ConnectorType) override;
|
|
||||||
virtual cPieces GetStartingPieces(void) override;
|
|
||||||
virtual int GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece) override;
|
|
||||||
virtual void PiecePlaced(const cPiece & a_Piece) override;
|
|
||||||
virtual void Reset(void) override;
|
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
121
src/Generating/PrefabPiecePool.cpp
Normal file
121
src/Generating/PrefabPiecePool.cpp
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
|
||||||
|
// PrefabPiecePool.cpp
|
||||||
|
|
||||||
|
// Implements the cPrefabPiecePool class that represents a cPiecePool descendant that uses cPrefab instances as the pieces
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "PrefabPiecePool.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cPrefabPiecePool::cPrefabPiecePool(
|
||||||
|
const cPrefab::sDef * a_PieceDefs, size_t a_NumPieceDefs,
|
||||||
|
const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs
|
||||||
|
)
|
||||||
|
{
|
||||||
|
AddPieceDefs(a_PieceDefs, a_NumPieceDefs);
|
||||||
|
if (a_StartingPieceDefs != NULL)
|
||||||
|
{
|
||||||
|
AddStartingPieceDefs(a_StartingPieceDefs, a_NumStartingPieceDefs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cPrefabPiecePool::AddPieceDefs(const cPrefab::sDef * a_PieceDefs, size_t a_NumPieceDefs)
|
||||||
|
{
|
||||||
|
ASSERT(a_PieceDefs != NULL);
|
||||||
|
for (size_t i = 0; i < a_NumPieceDefs; i++)
|
||||||
|
{
|
||||||
|
cPrefab * Prefab = new cPrefab(a_PieceDefs[i]);
|
||||||
|
m_AllPieces.push_back(Prefab);
|
||||||
|
AddToPerConnectorMap(Prefab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cPrefabPiecePool::AddStartingPieceDefs(const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs)
|
||||||
|
{
|
||||||
|
ASSERT(a_StartingPieceDefs != NULL);
|
||||||
|
for (size_t i = 0; i < a_NumStartingPieceDefs; i++)
|
||||||
|
{
|
||||||
|
cPrefab * Prefab = new cPrefab(a_StartingPieceDefs[i]);
|
||||||
|
m_StartingPieces.push_back(Prefab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cPrefabPiecePool::AddToPerConnectorMap(cPrefab * a_Prefab)
|
||||||
|
{
|
||||||
|
cPiece::cConnectors Connectors = ((const cPiece *)a_Prefab)->GetConnectors();
|
||||||
|
for (cPiece::cConnectors::const_iterator itr = Connectors.begin(), end = Connectors.end(); itr != end; ++itr)
|
||||||
|
{
|
||||||
|
m_PiecesByConnector[itr->m_Type].push_back(a_Prefab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cPieces cPrefabPiecePool::GetPiecesWithConnector(int a_ConnectorType)
|
||||||
|
{
|
||||||
|
return m_PiecesByConnector[a_ConnectorType];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cPieces cPrefabPiecePool::GetStartingPieces(void)
|
||||||
|
{
|
||||||
|
if (m_StartingPieces.empty())
|
||||||
|
{
|
||||||
|
return m_AllPieces;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return m_StartingPieces;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cPrefabPiecePool::GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece)
|
||||||
|
{
|
||||||
|
return ((const cPrefab &)a_NewPiece).GetPieceWeight(a_PlacedPiece, a_ExistingConnector);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cPrefabPiecePool::PiecePlaced(const cPiece & a_Piece)
|
||||||
|
{
|
||||||
|
// Do nothing
|
||||||
|
UNUSED(a_Piece);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cPrefabPiecePool::Reset(void)
|
||||||
|
{
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
79
src/Generating/PrefabPiecePool.h
Normal file
79
src/Generating/PrefabPiecePool.h
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
|
||||||
|
// PrefabPiecePool.h
|
||||||
|
|
||||||
|
// Declares the cPrefabPiecePool class that represents a cPiecePool descendant that uses cPrefab instances as the pieces
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "PieceGenerator.h"
|
||||||
|
#include "Prefab.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class cPrefabPiecePool :
|
||||||
|
public cPiecePool
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** Creates an empty instance. Prefabs can be added by calling AddPieceDefs() and AddStartingPieceDefs(). */
|
||||||
|
cPrefabPiecePool(void);
|
||||||
|
|
||||||
|
/** Creates a piece pool with prefabs from the specified definitions.
|
||||||
|
If both a_PieceDefs and a_StartingPieceDefs are given, only the a_StartingPieceDefs are used as starting
|
||||||
|
pieces for the pool, and they do not participate in the generation any further.
|
||||||
|
If only a_PieceDefs is given, any such piece can be chosen as a starting piece, and all the pieces are used
|
||||||
|
for generating.
|
||||||
|
More pieces can be added to the instance afterwards by calling AddPieceDefs() and AddStartingPieceDefs(). */
|
||||||
|
cPrefabPiecePool(
|
||||||
|
const cPrefab::sDef * a_PieceDefs, size_t a_NumPieceDefs,
|
||||||
|
const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Adds pieces from the specified definitions into m_AllPieces. Also adds the pieces into
|
||||||
|
the m_PiecesByConnector map.
|
||||||
|
May be called multiple times with different PieceDefs, will add all such pieces. */
|
||||||
|
void AddPieceDefs(const cPrefab::sDef * a_PieceDefs, size_t a_NumPieceDefs);
|
||||||
|
|
||||||
|
/** Adds pieces from the specified definitions into m_StartingPieces. Doesn't add them to
|
||||||
|
the m_PiecesByConnector map.
|
||||||
|
May be called multiple times with different PieceDefs, will add all such pieces. */
|
||||||
|
void AddStartingPieceDefs(const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs);
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/** The type used to map a connector type to the list of pieces with that connector */
|
||||||
|
typedef std::map<int, cPieces> cPiecesMap;
|
||||||
|
|
||||||
|
/** All the pieces that are allowed for building.
|
||||||
|
This is the list that's used for memory allocation and deallocation for the pieces. */
|
||||||
|
cPieces m_AllPieces;
|
||||||
|
|
||||||
|
/** The pieces that are used as starting pieces.
|
||||||
|
This list is not shared and the pieces need deallocation. */
|
||||||
|
cPieces m_StartingPieces;
|
||||||
|
|
||||||
|
/** The map that has all pieces by their connector types
|
||||||
|
The pieces are copies out of m_AllPieces and shouldn't be ever delete-d. */
|
||||||
|
cPiecesMap m_PiecesByConnector;
|
||||||
|
|
||||||
|
|
||||||
|
/** Adds the prefab to the m_PiecesByConnector map for all its connectors. */
|
||||||
|
void AddToPerConnectorMap(cPrefab * a_Prefab);
|
||||||
|
|
||||||
|
// cPiecePool overrides:
|
||||||
|
virtual cPieces GetPiecesWithConnector(int a_ConnectorType) override;
|
||||||
|
virtual cPieces GetStartingPieces(void) override;
|
||||||
|
virtual int GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece) override;
|
||||||
|
virtual void PiecePlaced(const cPiece & a_Piece) override;
|
||||||
|
virtual void Reset(void) override;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -9,9 +9,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// How many ravines in each direction are generated for a given chunk. Must be an even number
|
|
||||||
static const int NEIGHBORHOOD_SIZE = 8;
|
|
||||||
|
|
||||||
static const int NUM_RAVINE_POINTS = 4;
|
static const int NUM_RAVINE_POINTS = 4;
|
||||||
|
|
||||||
|
|
||||||
@ -42,40 +39,38 @@ typedef std::vector<cRavDefPoint> cRavDefPoints;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cStructGenRavines::cRavine
|
class cStructGenRavines::cRavine :
|
||||||
|
public cGridStructGen::cStructure
|
||||||
{
|
{
|
||||||
|
typedef cGridStructGen::cStructure super;
|
||||||
|
|
||||||
cRavDefPoints m_Points;
|
cRavDefPoints m_Points;
|
||||||
|
|
||||||
/// Generates the shaping defpoints for the ravine, based on the ravine block coords and noise
|
|
||||||
|
/** 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);
|
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
|
/** Refines (adds and smooths) defpoints from a_Src into a_Dst */
|
||||||
void RefineDefPoints(const cRavDefPoints & a_Src, cRavDefPoints & a_Dst);
|
void RefineDefPoints(const cRavDefPoints & a_Src, cRavDefPoints & a_Dst);
|
||||||
|
|
||||||
/// Does one round of smoothing, two passes of RefineDefPoints()
|
/** Does one round of smoothing, two passes of RefineDefPoints() */
|
||||||
void Smooth(void);
|
void Smooth(void);
|
||||||
|
|
||||||
/// Linearly interpolates the points so that the maximum distance between two neighbors is max 1 block
|
/** Linearly interpolates the points so that the maximum distance between two neighbors is max 1 block */
|
||||||
void FinishLinear(void);
|
void FinishLinear(void);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Coords for which the ravine was generated (not necessarily the center)
|
|
||||||
int m_BlockX;
|
|
||||||
int m_BlockZ;
|
|
||||||
|
|
||||||
cRavine(int a_BlockX, int a_BlockZ, int a_Size, cNoise & a_Noise);
|
cRavine(int a_BlockX, int a_BlockZ, int a_Size, cNoise & a_Noise);
|
||||||
|
|
||||||
/// Carves the ravine into the chunk specified
|
|
||||||
void ProcessChunk(
|
|
||||||
int a_ChunkX, int a_ChunkZ,
|
|
||||||
cChunkDef::BlockTypes & a_BlockTypes,
|
|
||||||
cChunkDef::HeightMap & a_HeightMap
|
|
||||||
);
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
/// Exports itself as a SVG line definition
|
/// Exports itself as a SVG line definition
|
||||||
AString ExportAsSVG(int a_Color, int a_OffsetX = 0, int a_OffsetZ = 0) const;
|
AString ExportAsSVG(int a_Color, int a_OffsetX = 0, int a_OffsetZ = 0) const;
|
||||||
#endif // _DEBUG
|
#endif // _DEBUG
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// cGridStructGen::cStructure overrides:
|
||||||
|
virtual void DrawIntoChunk(cChunkDesc & a_ChunkDesc) override;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
@ -86,6 +81,7 @@ public:
|
|||||||
// cStructGenRavines:
|
// cStructGenRavines:
|
||||||
|
|
||||||
cStructGenRavines::cStructGenRavines(int a_Seed, int a_Size) :
|
cStructGenRavines::cStructGenRavines(int a_Seed, int a_Size) :
|
||||||
|
super(a_Seed, a_Size, a_Size, a_Size * 2, a_Size * 2, 100),
|
||||||
m_Noise(a_Seed),
|
m_Noise(a_Seed),
|
||||||
m_Size(a_Size)
|
m_Size(a_Size)
|
||||||
{
|
{
|
||||||
@ -95,139 +91,9 @@ cStructGenRavines::cStructGenRavines(int a_Seed, int a_Size) :
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
cStructGenRavines::~cStructGenRavines()
|
cGridStructGen::cStructurePtr cStructGenRavines::CreateStructure(int a_OriginX, int a_OriginZ)
|
||||||
{
|
{
|
||||||
ClearCache();
|
return cStructurePtr(new cRavine(a_OriginX, a_OriginZ, m_Size, m_Noise));
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cStructGenRavines::ClearCache(void)
|
|
||||||
{
|
|
||||||
for (cRavines::const_iterator itr = m_Cache.begin(), end = m_Cache.end(); itr != end; ++itr)
|
|
||||||
{
|
|
||||||
delete *itr;
|
|
||||||
} // for itr - m_Cache[]
|
|
||||||
m_Cache.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cStructGenRavines::GenFinish(cChunkDesc & a_ChunkDesc)
|
|
||||||
{
|
|
||||||
int ChunkX = a_ChunkDesc.GetChunkX();
|
|
||||||
int ChunkZ = a_ChunkDesc.GetChunkZ();
|
|
||||||
cRavines Ravines;
|
|
||||||
GetRavinesForChunk(ChunkX, ChunkZ, Ravines);
|
|
||||||
for (cRavines::const_iterator itr = Ravines.begin(), end = Ravines.end(); itr != end; ++itr)
|
|
||||||
{
|
|
||||||
(*itr)->ProcessChunk(ChunkX, ChunkZ, a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap());
|
|
||||||
} // for itr - Ravines[]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cStructGenRavines::GetRavinesForChunk(int a_ChunkX, int a_ChunkZ, cStructGenRavines::cRavines & a_Ravines)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
// Walk the cache, move each ravine that we want into a_Ravines:
|
|
||||||
int StartX = BaseX * m_Size;
|
|
||||||
int EndX = (BaseX + NEIGHBORHOOD_SIZE + 1) * m_Size;
|
|
||||||
int StartZ = BaseZ * m_Size;
|
|
||||||
int EndZ = (BaseZ + NEIGHBORHOOD_SIZE + 1) * m_Size;
|
|
||||||
for (cRavines::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_Ravines.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_Size;
|
|
||||||
for (int z = 0; z < NEIGHBORHOOD_SIZE; z++)
|
|
||||||
{
|
|
||||||
int RealZ = (BaseZ + z) * m_Size;
|
|
||||||
bool Found = false;
|
|
||||||
for (cRavines::const_iterator itr = a_Ravines.begin(), end = a_Ravines.end(); itr != end; ++itr)
|
|
||||||
{
|
|
||||||
if (((*itr)->m_BlockX == RealX) && ((*itr)->m_BlockZ == RealZ))
|
|
||||||
{
|
|
||||||
Found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!Found)
|
|
||||||
{
|
|
||||||
a_Ravines.push_back(new cRavine(RealX, RealZ, m_Size, m_Noise));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy a_Ravines into m_Cache to the beginning:
|
|
||||||
cRavines RavinesCopy(a_Ravines);
|
|
||||||
m_Cache.splice(m_Cache.begin(), RavinesCopy, RavinesCopy.begin(), RavinesCopy.end());
|
|
||||||
|
|
||||||
// Trim the cache if it's too long:
|
|
||||||
if (m_Cache.size() > 100)
|
|
||||||
{
|
|
||||||
cRavines::iterator itr = m_Cache.begin();
|
|
||||||
std::advance(itr, 100);
|
|
||||||
for (cRavines::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());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
#ifdef _DEBUG
|
|
||||||
// DEBUG: Export as SVG into a file specific for the chunk, for visual verification:
|
|
||||||
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");
|
|
||||||
for (cRavines::const_iterator itr = a_Ravines.begin(), end = a_Ravines.end(); itr != end; ++itr)
|
|
||||||
{
|
|
||||||
SVG.append((*itr)->ExportAsSVG(0, 512, 512));
|
|
||||||
}
|
|
||||||
SVG.append("</svg>\n");
|
|
||||||
|
|
||||||
AString fnam;
|
|
||||||
Printf(fnam, "ravines\\%03d_%03d.svg", a_ChunkX, a_ChunkZ);
|
|
||||||
cFile File(fnam, cFile::fmWrite);
|
|
||||||
File.Write(SVG.c_str(), SVG.size());
|
|
||||||
#endif // _DEBUG
|
|
||||||
//*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -238,14 +104,13 @@ void cStructGenRavines::GetRavinesForChunk(int a_ChunkX, int a_ChunkZ, cStructGe
|
|||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// cStructGenRavines::cRavine
|
// cStructGenRavines::cRavine
|
||||||
|
|
||||||
cStructGenRavines::cRavine::cRavine(int a_BlockX, int a_BlockZ, int a_Size, cNoise & a_Noise) :
|
cStructGenRavines::cRavine::cRavine(int a_OriginX, int a_OriginZ, int a_Size, cNoise & a_Noise) :
|
||||||
m_BlockX(a_BlockX),
|
super(a_OriginX, a_OriginZ)
|
||||||
m_BlockZ(a_BlockZ)
|
|
||||||
{
|
{
|
||||||
// Calculate the ravine shape-defining points:
|
// Calculate the ravine shape-defining points:
|
||||||
GenerateBaseDefPoints(a_BlockX, a_BlockZ, a_Size, a_Noise);
|
GenerateBaseDefPoints(a_OriginX, a_OriginZ, a_Size, a_Noise);
|
||||||
|
|
||||||
// Smooth the ravine. A two passes are needed:
|
// Smooth the ravine. Two passes are needed:
|
||||||
Smooth();
|
Smooth();
|
||||||
Smooth();
|
Smooth();
|
||||||
|
|
||||||
@ -263,8 +128,8 @@ void cStructGenRavines::cRavine::GenerateBaseDefPoints(int a_BlockX, int a_Block
|
|||||||
a_Size = (512 + ((a_Noise.IntNoise3DInt(19 * a_BlockX, 11 * a_BlockZ, a_BlockX + a_BlockZ) / 17) % 512)) * a_Size / 1024;
|
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
|
// 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 * m_BlockZ, 1000) / 7) % (2 * a_Size)) - 2 * a_Size) / 2;
|
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 * m_BlockZ, 3000) / 9) % (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 CenterX = a_BlockX + OffsetX;
|
||||||
int CenterZ = a_BlockZ + OffsetZ;
|
int CenterZ = a_BlockZ + OffsetZ;
|
||||||
|
|
||||||
@ -429,15 +294,15 @@ AString cStructGenRavines::cRavine::ExportAsSVG(int a_Color, int a_OffsetX, int
|
|||||||
|
|
||||||
// Base point highlight:
|
// Base point highlight:
|
||||||
AppendPrintf(SVG, "<path style=\"fill:none;stroke:#ff0000;stroke-width:1px;\"\nd=\"M %d,%d L %d,%d\"/>\n",
|
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
|
a_OffsetX + m_OriginX - 5, a_OffsetZ + m_OriginZ, a_OffsetX + m_OriginX + 5, a_OffsetZ + m_OriginZ
|
||||||
);
|
);
|
||||||
AppendPrintf(SVG, "<path style=\"fill:none;stroke:#ff0000;stroke-width:1px;\"\nd=\"M %d,%d L %d,%d\"/>\n",
|
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_OffsetX + m_OriginX, a_OffsetZ + m_OriginZ - 5, a_OffsetX + m_OriginX, a_OffsetZ + m_OriginZ + 5
|
||||||
);
|
);
|
||||||
|
|
||||||
// A gray line from the base point to the first point of the ravine, for identification:
|
// 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",
|
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_Points.front().m_BlockX, a_OffsetZ + m_Points.front().m_BlockZ
|
a_OffsetX + m_OriginX, a_OffsetZ + m_OriginZ, a_OffsetX + m_Points.front().m_BlockX, a_OffsetZ + m_Points.front().m_BlockZ
|
||||||
);
|
);
|
||||||
|
|
||||||
// Offset guides:
|
// Offset guides:
|
||||||
@ -461,14 +326,10 @@ AString cStructGenRavines::cRavine::ExportAsSVG(int a_Color, int a_OffsetX, int
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cStructGenRavines::cRavine::ProcessChunk(
|
void cStructGenRavines::cRavine::DrawIntoChunk(cChunkDesc & a_ChunkDesc)
|
||||||
int a_ChunkX, int a_ChunkZ,
|
|
||||||
cChunkDef::BlockTypes & a_BlockTypes,
|
|
||||||
cChunkDef::HeightMap & a_HeightMap
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
int BlockStartX = a_ChunkX * cChunkDef::Width;
|
int BlockStartX = a_ChunkDesc.GetChunkX() * cChunkDef::Width;
|
||||||
int BlockStartZ = a_ChunkZ * cChunkDef::Width;
|
int BlockStartZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width;
|
||||||
int BlockEndX = BlockStartX + cChunkDef::Width;
|
int BlockEndX = BlockStartX + cChunkDef::Width;
|
||||||
int BlockEndZ = BlockStartZ + cChunkDef::Width;
|
int BlockEndZ = BlockStartZ + cChunkDef::Width;
|
||||||
for (cRavDefPoints::const_iterator itr = m_Points.begin(), end = m_Points.end(); itr != end; ++itr)
|
for (cRavDefPoints::const_iterator itr = m_Points.begin(), end = m_Points.end(); itr != end; ++itr)
|
||||||
@ -494,7 +355,7 @@ void cStructGenRavines::cRavine::ProcessChunk(
|
|||||||
// DEBUG: Make the ravine shapepoints visible on a single layer (so that we can see with Minutor what's going on)
|
// DEBUG: Make the ravine shapepoints visible on a single layer (so that we can see with Minutor what's going on)
|
||||||
if ((DifX + x == 0) && (DifZ + z == 0))
|
if ((DifX + x == 0) && (DifZ + z == 0))
|
||||||
{
|
{
|
||||||
cChunkDef::SetBlock(a_BlockTypes, x, 4, z, E_BLOCK_LAPIS_ORE);
|
a_ChunkDesc.SetBlockType(x, 4, z, E_BLOCK_LAPIS_ORE);
|
||||||
}
|
}
|
||||||
#endif // _DEBUG
|
#endif // _DEBUG
|
||||||
|
|
||||||
@ -504,7 +365,7 @@ void cStructGenRavines::cRavine::ProcessChunk(
|
|||||||
int Top = std::min(itr->m_Top, (int)(cChunkDef::Height)); // Stupid gcc needs int cast
|
int Top = std::min(itr->m_Top, (int)(cChunkDef::Height)); // Stupid gcc needs int cast
|
||||||
for (int y = std::max(itr->m_Bottom, 1); y <= Top; y++)
|
for (int y = std::max(itr->m_Bottom, 1); y <= Top; y++)
|
||||||
{
|
{
|
||||||
switch (cChunkDef::GetBlock(a_BlockTypes, x, y, z))
|
switch (a_ChunkDesc.GetBlockType(x, y, z))
|
||||||
{
|
{
|
||||||
// Only carve out these specific block types
|
// Only carve out these specific block types
|
||||||
case E_BLOCK_DIRT:
|
case E_BLOCK_DIRT:
|
||||||
@ -522,7 +383,7 @@ void cStructGenRavines::cRavine::ProcessChunk(
|
|||||||
case E_BLOCK_REDSTONE_ORE:
|
case E_BLOCK_REDSTONE_ORE:
|
||||||
case E_BLOCK_REDSTONE_ORE_GLOWING:
|
case E_BLOCK_REDSTONE_ORE_GLOWING:
|
||||||
{
|
{
|
||||||
cChunkDef::SetBlock(a_BlockTypes, x, y, z, E_BLOCK_AIR);
|
a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_AIR);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: break;
|
default: break;
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ComposableGenerator.h"
|
#include "GridStructGen.h"
|
||||||
#include "../Noise.h"
|
#include "../Noise.h"
|
||||||
|
|
||||||
|
|
||||||
@ -17,28 +17,22 @@
|
|||||||
|
|
||||||
|
|
||||||
class cStructGenRavines :
|
class cStructGenRavines :
|
||||||
public cFinishGen
|
public cGridStructGen
|
||||||
{
|
{
|
||||||
|
typedef cGridStructGen super;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cStructGenRavines(int a_Seed, int a_Size);
|
cStructGenRavines(int a_Seed, int a_Size);
|
||||||
~cStructGenRavines();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
class cRavine; // fwd: Ravines.cpp
|
class cRavine; // fwd: Ravines.cpp
|
||||||
typedef std::list<cRavine *> cRavines;
|
|
||||||
|
|
||||||
cNoise m_Noise;
|
cNoise m_Noise;
|
||||||
int m_Size; // Max size, in blocks, of the ravines generated
|
int m_Size; // Max size, in blocks, of the ravines generated
|
||||||
cRavines m_Cache;
|
|
||||||
|
|
||||||
/// Clears everything from the cache
|
|
||||||
void ClearCache(void);
|
|
||||||
|
|
||||||
/// Returns all ravines that *may* intersect the given chunk. All the ravines are valid until the next call to this function.
|
// cGridStructGen overrides:
|
||||||
void GetRavinesForChunk(int a_ChunkX, int a_ChunkZ, cRavines & a_Ravines);
|
virtual cStructurePtr CreateStructure(int a_OriginX, int a_OriginZ) override;
|
||||||
|
|
||||||
// cFinishGen override:
|
|
||||||
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
|
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user