76 void Randomize(
cNoise & a_Noise);
85 void FinishLinear(
void);
88 void CalcBoundingBox(
void);
94 int a_BlockStartX,
int a_BlockStartY,
int a_BlockStartZ,
int a_StartRadius,
95 int a_BlockEndX,
int a_BlockEndY,
int a_BlockEndZ,
int a_EndRadius,
101 int a_ChunkX,
int a_ChunkZ,
108 AString ExportAsSVG(
int a_Color,
int a_OffsetX,
int a_OffsetZ)
const;
129 cCaveSystem(
int a_GridX,
int a_GridZ,
int a_OriginX,
int a_OriginZ,
int a_MaxOffset,
int a_Size,
cNoise & a_Noise);
139 void GenerateTunnelsFromPoint(
140 int a_OriginX,
int a_OriginY,
int a_OriginZ,
141 cNoise & a_Noise,
int a_Segments
145 int GetRadius(
cNoise & a_Noise,
int a_OriginX,
int a_OriginY,
int a_OriginZ);
148 virtual void DrawIntoChunk(
cChunkDesc & a_ChunkDesc)
override;
159 int a_BlockStartX,
int a_BlockStartY,
int a_BlockStartZ,
int a_StartRadius,
160 int a_BlockEndX,
int a_BlockEndY,
int a_BlockEndZ,
int a_EndRadius,
164 m_Points.push_back(
cCaveDefPoint(a_BlockStartX, a_BlockStartY, a_BlockStartZ, a_StartRadius));
165 m_Points.push_back(
cCaveDefPoint(a_BlockEndX, a_BlockEndY, a_BlockEndZ, a_EndRadius));
167 if ((a_BlockStartY <= 0) && (a_BlockEndY <= 0))
170 m_MinBlockX = m_MaxBlockX = 0;
171 m_MinBlockY = m_MaxBlockY = -1;
172 m_MinBlockZ = m_MaxBlockZ = 0;
192 for (
int i = 0; i < 4; i++)
201 Pts.reserve(m_Points.size() * 2 + 1);
202 Pts.push_back(Point);
203 for (cCaveDefPoints::const_iterator itr = m_Points.begin() + 1, end = m_Points.end(); itr != end; ++itr)
205 int Random = a_Noise.
IntNoise3DInt(PrevX, PrevY, PrevZ + i) / 11;
206 int len = (PrevX - itr->m_BlockX) * (PrevX - itr->m_BlockX);
207 len += (PrevY - itr->m_BlockY) * (PrevY - itr->m_BlockY);
208 len += (PrevZ - itr->m_BlockZ) * (PrevZ - itr->m_BlockZ);
209 len = 3 *
static_cast<int>(sqrt(static_cast<double>(len))) / 4;
210 int Rad = std::min(
MAX_RADIUS, std::max(
MIN_RADIUS, (PrevR + itr->m_Radius) / 2 + (Random % 3) - 1));
212 int x = (itr->m_BlockX + PrevX) / 2 + (Random % (len + 1) - len / 2);
214 int y = (itr->m_BlockY + PrevY) / 2 + (Random % (len / 2 + 1) - len / 4);
216 int z = (itr->m_BlockZ + PrevZ) / 2 + (Random % (len + 1) - len / 2);
219 PrevX = itr->m_BlockX;
220 PrevY = itr->m_BlockY;
221 PrevZ = itr->m_BlockZ;
222 PrevR = itr->m_Radius;
224 std::swap(Pts, m_Points);
234 if (a_Src.size() < 2)
242 size_t Num = a_Src.size() - 2;
244 a_Dst.reserve(Num * 2 + 2);
245 cCaveDefPoints::const_iterator itr = a_Src.begin() + 1;
247 a_Dst.push_back(Source);
252 for (
size_t i = 0; i <= Num; ++i, ++itr)
254 int dx = itr->m_BlockX - PrevX;
255 int dy = itr->m_BlockY - PrevY;
256 int dz = itr->m_BlockZ - PrevZ;
257 if (abs(dx) + abs(dz) + abs(dy) < 6)
260 PrevX = itr->m_BlockX;
261 PrevY = itr->m_BlockY;
262 PrevZ = itr->m_BlockZ;
263 PrevR = itr->m_Radius;
266 int dr = itr->m_Radius - PrevR;
267 int Rad1 = std::max(PrevR + 1 * dr / 4, 1);
268 int Rad2 = std::max(PrevR + 3 * dr / 4, 1);
269 a_Dst.push_back(
cCaveDefPoint(PrevX + 1 * dx / 4, PrevY + 1 * dy / 4, PrevZ + 1 * dz / 4, Rad1));
270 a_Dst.push_back(
cCaveDefPoint(PrevX + 3 * dx / 4, PrevY + 3 * dy / 4, PrevZ + 3 * dz / 4, Rad2));
271 PrevX = itr->m_BlockX;
272 PrevY = itr->m_BlockY;
273 PrevZ = itr->m_BlockZ;
274 PrevR = itr->m_Radius;
277 a_Dst.push_back(a_Src.back());
278 return res && (a_Src.size() < a_Dst.size());
290 if (!RefineDefPoints(m_Points, Pts))
292 std::swap(Pts, m_Points);
295 if (!RefineDefPoints(Pts, m_Points))
310 std::swap(Pts, m_Points);
312 m_Points.reserve(Pts.size() * 3);
317 for (cCaveDefPoints::const_iterator itr = Pts.begin() + 1, end = Pts.end(); itr != end; ++itr)
319 int x1 = itr->m_BlockX;
320 int y1 = itr->m_BlockY;
321 int z1 = itr->m_BlockZ;
322 int dx = abs(x1 - PrevX);
323 int dy = abs(y1 - PrevY);
324 int dz = abs(z1 - PrevZ);
325 int sx = (PrevX < x1) ? 1 : -1;
326 int sy = (PrevY < y1) ? 1 : -1;
327 int sz = (PrevZ < z1) ? 1 : -1;
328 int R = itr->m_Radius;
330 if (dx >= std::max(dy, dz))
332 int yd = dy - dx / 2;
333 int zd = dz - dx / 2;
362 else if (dy >= std::max(dx, dz))
364 int xd = dx - dy / 2;
365 int zd = dz - dy / 2;
397 ASSERT(dz >= std::max(dx, dy));
398 int xd = dx - dz / 2;
399 int yd = dy - dz / 2;
438 m_MinBlockX = m_MaxBlockX = Point.
m_BlockX;
439 m_MinBlockY = m_MaxBlockY = Point.
m_BlockY;
440 m_MinBlockZ = m_MaxBlockZ = Point.
m_BlockZ;
441 for (cCaveDefPoints::const_iterator itr = m_Points.begin() + 1, end = m_Points.end(); itr != end; ++itr)
443 m_MinBlockX = std::min(m_MinBlockX, itr->m_BlockX - itr->m_Radius);
444 m_MaxBlockX = std::max(m_MaxBlockX, itr->m_BlockX + itr->m_Radius);
445 m_MinBlockY = std::min(m_MinBlockY, itr->m_BlockY - itr->m_Radius);
446 m_MaxBlockY = std::max(m_MaxBlockY, itr->m_BlockY + itr->m_Radius);
447 m_MinBlockZ = std::min(m_MinBlockZ, itr->m_BlockZ - itr->m_Radius);
448 m_MaxBlockZ = std::max(m_MaxBlockZ, itr->m_BlockZ + itr->m_Radius);
457 int a_ChunkX,
int a_ChunkZ,
466 (BaseX > m_MaxBlockX) || (BaseX + cChunkDef::Width < m_MinBlockX) ||
467 (BaseZ > m_MaxBlockZ) || (BaseZ + cChunkDef::Width < m_MinBlockZ)
478 for (cCaveDefPoints::const_iterator itr = m_Points.begin(), end = m_Points.end(); itr != end; ++itr)
481 (itr->m_BlockX + itr->m_Radius < BlockStartX) ||
482 (itr->m_BlockX - itr->m_Radius > BlockEndX) ||
483 (itr->m_BlockZ + itr->m_Radius < BlockStartZ) ||
484 (itr->m_BlockZ - itr->m_Radius > BlockEndZ)
492 int DifX = itr->m_BlockX - BlockStartX;
493 int DifY = itr->m_BlockY;
494 int DifZ = itr->m_BlockZ - BlockStartZ;
495 int Bottom = std::max(itr->m_BlockY - 3 * itr->m_Radius / 7, 1);
496 int Top = std::min(itr->m_BlockY + 3 * itr->m_Radius / 7, static_cast<int>(
cChunkDef::Height));
497 int SqRad = itr->m_Radius * itr->m_Radius;
500 for (
int y = Bottom; y <= Top; y++)
502 int SqDist = (DifX - x) * (DifX - x) + (DifY - y) * (DifY - y) + (DifZ - z) * (DifZ - z);
503 if (4 * SqDist <= SqRad)
510 else if (SqDist <= SqRad * 2)
515 if (a_BlockMetas[Index] == 1)
517 a_BlockMetas[Index] = 0;
555 AString cCaveTunnel::ExportAsSVG(
int a_Color,
int a_OffsetX,
int a_OffsetZ)
const 558 SVG.reserve(m_Points.size() * 20 + 200);
559 AppendPrintf(SVG,
"<path style=\"fill:none;stroke:#%06x;stroke-width:1px;\"\nd=\"", a_Color);
561 for (cCaveDefPoints::const_iterator itr = m_Points.begin(); itr != m_Points.end(); ++itr)
563 AppendPrintf(SVG,
"%c %d, %d ", Prefix, a_OffsetX + itr->m_BlockX, a_OffsetZ + itr->m_BlockZ);
566 SVG.append(
"\"/>\n");
579 super(a_GridX, a_GridZ, a_OriginX, a_OriginZ),
582 int Num = 1 + a_Noise.
IntNoise2DInt(a_OriginX, a_OriginZ) % 3;
583 for (
int i = 0; i < Num; i++)
585 int OriginX = a_OriginX + (a_Noise.
IntNoise3DInt(13 * a_OriginX, 17 * a_OriginZ, 11 * i) / 19) % a_MaxOffset;
586 int OriginZ = a_OriginZ + (a_Noise.
IntNoise3DInt(17 * a_OriginX, 13 * a_OriginZ, 11 * i) / 23) % a_MaxOffset;
587 int OriginY = 20 + (a_Noise.
IntNoise3DInt(19 * a_OriginX, 13 * a_OriginZ, 11 * i) / 17) % 20;
619 for (cCaveTunnels::const_iterator itr =
m_Tunnels.begin(), end =
m_Tunnels.end(); itr != end; ++itr)
621 (*itr)->ProcessChunk(ChunkX, ChunkZ, BlockTypes, BlockMetas, HeightMap);
631 for (cCaveTunnels::const_iterator itr =
m_Tunnels.begin(), end =
m_Tunnels.end(); itr != end; ++itr)
643 int a_OriginX,
int a_OriginY,
int a_OriginZ,
644 cNoise & a_Noise,
int a_NumSegments
647 int DoubleSize =
m_Size * 2;
648 int Radius =
GetRadius(a_Noise, a_OriginX + a_OriginY, a_OriginY + a_OriginZ, a_OriginZ + a_OriginX);
649 for (
int i = a_NumSegments - 1; i >= 0; --i)
651 int EndX = a_OriginX + (((a_Noise.
IntNoise3DInt(a_OriginX, a_OriginY, a_OriginZ + 11 * a_NumSegments) / 7) % DoubleSize) -
m_Size) / 2;
652 int EndY = a_OriginY + (((a_Noise.
IntNoise3DInt(a_OriginY, 13 * a_NumSegments, a_OriginZ + a_OriginX) / 7) % DoubleSize) -
m_Size) / 4;
653 int EndZ = a_OriginZ + (((a_Noise.
IntNoise3DInt(a_OriginZ + 17 * a_NumSegments, a_OriginX, a_OriginY) / 7) % DoubleSize) -
m_Size) / 2;
654 int EndR =
GetRadius(a_Noise, a_OriginX + 7 * i, a_OriginY + 11 * i, a_OriginZ + a_OriginX);
655 m_Tunnels.push_back(
new cCaveTunnel(a_OriginX, a_OriginY, a_OriginZ, Radius, EndX, EndY, EndZ, EndR, a_Noise));
671 int rnd = a_Noise.
IntNoise3DInt(a_OriginX, a_OriginY, a_OriginZ) / 11;
708 static const float PI_2 = 1.57079633f;
709 float oct1 = (a_Noise.
CubicNoise3D(x * 0.1f, y * 0.1f, z * 0.1f)) * 4;
711 oct1 = oct1 * oct1 * oct1;
733 const float zz =
static_cast<float>(a_ChunkDesc.
GetChunkZ() * cChunkDef::Width + z);
736 const float xx =
static_cast<float>(a_ChunkDesc.
GetChunkX() * cChunkDef::Width + x);
739 for (
int y = 1; y < Top; ++y)
746 const float yy =
static_cast<float>(y);
747 const float WaveNoise = 1;
748 if (cosf(
GetMarbleNoise(xx, yy * 0.5f, zz, Noise)) * fabs(cosf(yy * 0.2f + WaveNoise * 2) * 0.75f + WaveNoise) > 0.0005f)
768 const float zz =
static_cast<float>(a_ChunkDesc.
GetChunkZ() * cChunkDef::Width + z) / 10;
771 const float xx =
static_cast<float>(a_ChunkDesc.
GetChunkX() * cChunkDef::Width + x) / 10;
774 for (
int y = 1; y <= Top; ++y)
776 const float yy =
static_cast<float>(y / 10);
777 float n1 = m_Noise1.CubicNoise3D(xx, yy, zz);
778 float n2 = m_Noise2.CubicNoise3D(xx, yy, zz);
779 float n3 = m_Noise1.CubicNoise3D(xx * 4, yy * 4, zz * 4) / 4;
780 float n4 = m_Noise2.CubicNoise3D(xx * 4, yy * 4, zz * 4) / 4;
781 if ((std::abs(n1 + n3) * std::abs(n2 + n4)) > m_Threshold)
void GenerateTunnelsFromPoint(int a_OriginX, int a_OriginY, int a_OriginZ, cNoise &a_Noise, int a_Segments)
Generates a_Segment successive tunnels, with possible branches.
BlockNibbleBytes & GetBlockMetasUncompressed(void)
NIBBLETYPE BlockNibbleBytes[cChunkDef::NumBlocks]
Uncompressed block metas, 1 meta per byte.
cGridStructGen::cStructure super
static bool CanBeTerraformed(BLOCKTYPE a_Type)
void SetBlockType(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType)
void Randomize(cNoise &a_Noise)
Generates the shaping defpoints for the cave, based on the cave block coords and noise.
void FinishLinear(void)
Linearly interpolates the points so that the maximum distance between two neighbors is max 1 block...
cChunkDef::BlockTypes & GetBlockTypes(void)
std::vector< cCaveDefPoint > cCaveDefPoints
BLOCKTYPE BlockTypes[NumBlocks]
The type used for block type operations and storage, AXIS_ORDER ordering.
virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override
Create a new structure at the specified gridpoint.
int IntNoise2DInt(int a_X, int a_Y) const
int GetRadius(cNoise &a_Noise, int a_OriginX, int a_OriginY, int a_OriginZ)
Returns a radius based on the location provided.
static void SetBlock(BLOCKTYPE *a_BlockTypes, int a_X, int a_Y, int a_Z, BLOCKTYPE a_Type)
void CalcBoundingBox(void)
Calculates the bounding box of the points present.
void ProcessChunk(int a_ChunkX, int a_ChunkZ, cChunkDef::BlockTypes &a_BlockTypes, cChunkDesc::BlockNibbleBytes &a_BlockMetas, cChunkDef::HeightMap &a_HeightMap)
Carves the tunnel into the chunk specified.
A collection of connected tunnels, possibly branching.
std::shared_ptr< cStructure > cStructurePtr
int IntNoise3DInt(int a_X, int a_Y, int a_Z) const
static BLOCKTYPE GetBlock(const BLOCKTYPE *a_BlockTypes, Vector3i a_RelPos)
static int MakeIndexNoCheck(int x, int y, int z)
BLOCKTYPE GetBlockType(int a_RelX, int a_RelY, int a_RelZ) const
cChunkDef::HeightMap & GetHeightMap(void)
void Smooth(void)
Does rounds of smoothing, two passes of RefineDefPoints(), as long as they return true...
bool RefineDefPoints(const cCaveDefPoints &a_Src, cCaveDefPoints &a_Dst)
Refines (adds and smooths) defpoints from a_Src into a_Dst; returns false if no refinement possible (...
std::vector< cCaveTunnel * > cCaveTunnels
virtual void DrawIntoChunk(cChunkDesc &a_ChunkDesc) override
Draws self into the specified chunk.
AString & AppendPrintf(AString &a_Dst, const char *format, const Args &...args)
Add the formated string to the existing data in the string.
static float GetMarbleNoise(float x, float y, float z, cNoise &a_Noise)
virtual void GenFinish(cChunkDesc &a_ChunkDesc) override
HEIGHTTYPE GetHeight(int a_RelX, int a_RelZ) const
cNoise m_Noise
The noise used for generating grid offsets.
int m_Seed
Seed for generating grid offsets and also available for descendants.
NOISE_DATATYPE CubicNoise3D(NOISE_DATATYPE a_X, NOISE_DATATYPE a_Y, NOISE_DATATYPE a_Z) const
cCaveSystem(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ, int a_MaxOffset, int a_Size, cNoise &a_Noise)
A single non-branching tunnel of a WormNestCave.
cCaveTunnel(int a_BlockStartX, int a_BlockStartY, int a_BlockStartZ, int a_StartRadius, int a_BlockEndX, int a_BlockEndY, int a_BlockEndZ, int a_EndRadius, cNoise &a_Noise)
Represents a single structure that occupies the grid point.
HEIGHTTYPE HeightMap[Width *Width]
The type used for any heightmap operations and storage; idx = x + Width * z; Height points to the hig...
virtual void GenFinish(cChunkDesc &a_ChunkDesc) override
virtual ~cCaveSystem() override
cCaveDefPoint(int a_BlockX, int a_BlockY, int a_BlockZ, int a_Radius)