1
0

Ravines rewritten using cGridStructGen.

Ref.: #987.
This commit is contained in:
Mattes D 2014-05-09 18:30:39 +02:00
parent 95ead1128f
commit ea593dcaad
2 changed files with 40 additions and 182 deletions

View File

@ -42,40 +42,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 +84,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 +94,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 +107,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 +131,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 +297,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 +329,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 +358,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 +368,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 +386,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;

View File

@ -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); // cGridStructGen overrides:
virtual cStructurePtr CreateStructure(int a_OriginX, int a_OriginZ) override;
/// Returns all ravines that *may* intersect the given chunk. All the ravines are valid until the next call to this function.
void GetRavinesForChunk(int a_ChunkX, int a_ChunkZ, cRavines & a_Ravines);
// cFinishGen override:
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
} ; } ;