33 #include "../BlockInfo.h"
95 int a_BlockStartX,
int a_BlockStartY,
int a_BlockStartZ,
int a_StartRadius,
96 int a_BlockEndX,
int a_BlockEndY,
int a_BlockEndZ,
int a_EndRadius,
102 int a_ChunkX,
int a_ChunkZ,
131 cCaveSystem(
int a_GridX,
int a_GridZ,
int a_OriginX,
int a_OriginZ,
int a_MaxOffset,
int a_Size,
cNoise & a_Noise);
142 int a_OriginX,
int a_OriginY,
int a_OriginZ,
143 cNoise & a_Noise,
int a_Segments
147 int GetRadius(
cNoise & a_Noise,
int a_OriginX,
int a_OriginY,
int a_OriginZ);
161 int a_BlockStartX,
int a_BlockStartY,
int a_BlockStartZ,
int a_StartRadius,
162 int a_BlockEndX,
int a_BlockEndY,
int a_BlockEndZ,
int a_EndRadius,
166 m_Points.emplace_back(a_BlockStartX, a_BlockStartY, a_BlockStartZ, a_StartRadius);
167 m_Points.emplace_back(a_BlockEndX, a_BlockEndY, a_BlockEndZ, a_EndRadius);
169 if ((a_BlockStartY <= 0) && (a_BlockEndY <= 0))
194 for (
int i = 0; i < 4; i++)
203 Pts.reserve(
m_Points.size() * 2 + 1);
204 Pts.push_back(Point);
205 for (cCaveDefPoints::const_iterator itr =
m_Points.begin() + 1, end =
m_Points.end(); itr != end; ++itr)
207 int Random = a_Noise.
IntNoise3DInt(PrevX, PrevY, PrevZ + i) / 11;
208 int len = (PrevX - itr->m_BlockX) * (PrevX - itr->m_BlockX);
209 len += (PrevY - itr->m_BlockY) * (PrevY - itr->m_BlockY);
210 len += (PrevZ - itr->m_BlockZ) * (PrevZ - itr->m_BlockZ);
211 len = 3 *
static_cast<int>(sqrt(
static_cast<double>(len))) / 4;
212 int Rad = std::min(
MAX_RADIUS, std::max(
MIN_RADIUS, (PrevR + itr->m_Radius) / 2 + (Random % 3) - 1));
214 int x = (itr->m_BlockX + PrevX) / 2 + (Random % (len + 1) - len / 2);
216 int y = (itr->m_BlockY + PrevY) / 2 + (Random % (len / 2 + 1) - len / 4);
218 int z = (itr->m_BlockZ + PrevZ) / 2 + (Random % (len + 1) - len / 2);
219 Pts.emplace_back(x, y, z, Rad);
221 PrevX = itr->m_BlockX;
222 PrevY = itr->m_BlockY;
223 PrevZ = itr->m_BlockZ;
224 PrevR = itr->m_Radius;
236 if (a_Src.size() < 2)
244 size_t Num = a_Src.size() - 2;
246 a_Dst.reserve(Num * 2 + 2);
247 cCaveDefPoints::const_iterator itr = a_Src.begin() + 1;
249 a_Dst.push_back(Source);
254 for (
size_t i = 0; i <= Num; ++i, ++itr)
256 int dx = itr->m_BlockX - PrevX;
257 int dy = itr->m_BlockY - PrevY;
258 int dz = itr->m_BlockZ - PrevZ;
259 if (abs(dx) + abs(dz) + abs(dy) < 6)
262 PrevX = itr->m_BlockX;
263 PrevY = itr->m_BlockY;
264 PrevZ = itr->m_BlockZ;
265 PrevR = itr->m_Radius;
268 int dr = itr->m_Radius - PrevR;
269 int Rad1 = std::max(PrevR + 1 * dr / 4, 1);
270 int Rad2 = std::max(PrevR + 3 * dr / 4, 1);
271 a_Dst.emplace_back(PrevX + 1 * dx / 4, PrevY + 1 * dy / 4, PrevZ + 1 * dz / 4, Rad1);
272 a_Dst.emplace_back(PrevX + 3 * dx / 4, PrevY + 3 * dy / 4, PrevZ + 3 * dz / 4, Rad2);
273 PrevX = itr->m_BlockX;
274 PrevY = itr->m_BlockY;
275 PrevZ = itr->m_BlockZ;
276 PrevR = itr->m_Radius;
279 a_Dst.push_back(a_Src.back());
280 return res && (a_Src.size() < a_Dst.size());
319 for (cCaveDefPoints::const_iterator itr = Pts.begin() + 1, end = Pts.end(); itr != end; ++itr)
321 int x1 = itr->m_BlockX;
322 int y1 = itr->m_BlockY;
323 int z1 = itr->m_BlockZ;
324 int dx = abs(x1 - PrevX);
325 int dy = abs(y1 - PrevY);
326 int dz = abs(z1 - PrevZ);
327 int sx = (PrevX < x1) ? 1 : -1;
328 int sy = (PrevY < y1) ? 1 : -1;
329 int sz = (PrevZ < z1) ? 1 : -1;
330 int R = itr->m_Radius;
332 if (dx >= std::max(dy, dz))
334 int yd = dy - dx / 2;
335 int zd = dz - dx / 2;
339 m_Points.emplace_back(PrevX, PrevY, PrevZ, R);
364 else if (dy >= std::max(dx, dz))
366 int xd = dx - dy / 2;
367 int zd = dz - dy / 2;
371 m_Points.emplace_back(PrevX, PrevY, PrevZ, R);
399 ASSERT(dz >= std::max(dx, dy));
400 int xd = dx - dz / 2;
401 int yd = dy - dz / 2;
405 m_Points.emplace_back(PrevX, PrevY, PrevZ, R);
443 for (cCaveDefPoints::const_iterator itr =
m_Points.begin() + 1, end =
m_Points.end(); itr != end; ++itr)
459 int a_ChunkX,
int a_ChunkZ,
480 for (cCaveDefPoints::const_iterator itr =
m_Points.begin(), end =
m_Points.end(); itr != end; ++itr)
483 (itr->m_BlockX + itr->m_Radius < BlockStartX) ||
484 (itr->m_BlockX - itr->m_Radius > BlockEndX) ||
485 (itr->m_BlockZ + itr->m_Radius < BlockStartZ) ||
486 (itr->m_BlockZ - itr->m_Radius > BlockEndZ)
494 int DifX = itr->m_BlockX - BlockStartX;
495 int DifY = itr->m_BlockY;
496 int DifZ = itr->m_BlockZ - BlockStartZ;
497 int Bottom = std::max(itr->m_BlockY - 3 * itr->m_Radius / 7, 1);
498 int Top = std::min(itr->m_BlockY + 3 * itr->m_Radius / 7,
static_cast<int>(
cChunkDef::Height));
499 int SqRad = itr->m_Radius * itr->m_Radius;
502 for (
int y =
Bottom; y <= Top; y++)
504 int SqDist = (DifX - x) * (DifX - x) + (DifY - y) * (DifY - y) + (DifZ - z) * (DifZ - z);
505 if (4 * SqDist <= SqRad)
512 else if (SqDist <= SqRad * 2)
517 if (a_BlockMetas[Index] == 1)
519 a_BlockMetas[Index] = 0;
560 SVG.reserve(
m_Points.size() * 20 + 200);
561 SVG.append(fmt::format(FMT_STRING(
"<path style=\"fill:none;stroke:#{:06x};stroke-width:1px;\"\nd=\""), a_Color));
563 for (cCaveDefPoints::const_iterator itr =
m_Points.begin(); itr !=
m_Points.end(); ++itr)
565 SVG.append(fmt::format(FMT_STRING(
"{} {}, {} "), Prefix, a_OffsetX + itr->m_BlockX, a_OffsetZ + itr->m_BlockZ));
568 SVG.append(
"\"/>\n");
581 Super(a_GridX, a_GridZ, a_OriginX, a_OriginZ),
584 int Num = 1 + a_Noise.
IntNoise2DInt(a_OriginX, a_OriginZ) % 3;
585 for (
int i = 0; i < Num; i++)
587 int OriginX = a_OriginX + (a_Noise.
IntNoise3DInt(13 * a_OriginX, 17 * a_OriginZ, 11 * i) / 19) % a_MaxOffset;
588 int OriginZ = a_OriginZ + (a_Noise.
IntNoise3DInt(17 * a_OriginX, 13 * a_OriginZ, 11 * i) / 23) % a_MaxOffset;
589 int OriginY = 20 + (a_Noise.
IntNoise3DInt(19 * a_OriginX, 13 * a_OriginZ, 11 * i) / 17) % 20;
621 for (cCaveTunnels::const_iterator itr = m_Tunnels.begin(), end = m_Tunnels.end(); itr != end; ++itr)
623 (*itr)->ProcessChunk(ChunkX, ChunkZ, BlockTypes, BlockMetas, HeightMap);
633 for (cCaveTunnels::const_iterator itr = m_Tunnels.begin(), end = m_Tunnels.end(); itr != end; ++itr)
645 int a_OriginX,
int a_OriginY,
int a_OriginZ,
646 cNoise & a_Noise,
int a_NumSegments
649 int DoubleSize =
m_Size * 2;
650 int Radius = GetRadius(a_Noise, a_OriginX + a_OriginY, a_OriginY + a_OriginZ, a_OriginZ + a_OriginX);
651 for (
int i = a_NumSegments - 1; i >= 0; --i)
653 int EndX = a_OriginX + (((a_Noise.
IntNoise3DInt(a_OriginX, a_OriginY, a_OriginZ + 11 * a_NumSegments) / 7) % DoubleSize) -
m_Size) / 2;
654 int EndY = a_OriginY + (((a_Noise.
IntNoise3DInt(a_OriginY, 13 * a_NumSegments, a_OriginZ + a_OriginX) / 7) % DoubleSize) -
m_Size) / 4;
655 int EndZ = a_OriginZ + (((a_Noise.
IntNoise3DInt(a_OriginZ + 17 * a_NumSegments, a_OriginX, a_OriginY) / 7) % DoubleSize) -
m_Size) / 2;
656 int EndR = GetRadius(a_Noise, a_OriginX + 7 * i, a_OriginY + 11 * i, a_OriginZ + a_OriginX);
657 m_Tunnels.push_back(
new cCaveTunnel(a_OriginX, a_OriginY, a_OriginZ, Radius, EndX, EndY, EndZ, EndR, a_Noise));
658 GenerateTunnelsFromPoint(EndX, EndY, EndZ, a_Noise, i);
673 int rnd = a_Noise.
IntNoise3DInt(a_OriginX, a_OriginY, a_OriginZ) / 11;
710 static const float PI_2 = 1.57079633f;
711 float oct1 = (a_Noise.
CubicNoise3D(x * 0.1f, y * 0.1f, z * 0.1f)) * 4;
713 oct1 = oct1 * oct1 * oct1;
741 for (
int y = 1; y < Top; ++y)
748 const float yy =
static_cast<float>(y);
749 const float WaveNoise = 1;
750 if (cosf(
GetMarbleNoise(xx, yy * 0.5f, zz, Noise)) * fabs(cosf(yy * 0.2f + WaveNoise * 2) * 0.75f + WaveNoise) > 0.0005f)
776 for (
int y = 1; y <= Top; ++y)
778 const float yy =
static_cast<float>(y / 10);
779 float n1 = m_Noise1.CubicNoise3D(xx, yy, zz);
780 float n2 = m_Noise2.CubicNoise3D(xx, yy, zz);
781 float n3 = m_Noise1.CubicNoise3D(xx * 4, yy * 4, zz * 4) / 4;
782 float n4 = m_Noise2.CubicNoise3D(xx * 4, yy * 4, zz * 4) / 4;
783 if ((std::abs(n1 + n3) * std::abs(n2 + n4)) > m_Threshold)
std::vector< cCaveTunnel * > cCaveTunnels
static float GetMarbleNoise(float x, float y, float z, cNoise &a_Noise)
std::vector< cCaveDefPoint > cCaveDefPoints
bool Bottom(const BlockState Block)
static bool CanBeTerraformed(BLOCKTYPE Block)
Can a finisher change it?
BLOCKTYPE BlockTypes[NumBlocks]
The type used for block type operations and storage, AXIS_ORDER ordering.
HEIGHTTYPE HeightMap[Width *Width]
The type used for any heightmap operations and storage; idx = x + Width * z; Height points to the hig...
static BLOCKTYPE GetBlock(const BLOCKTYPE *a_BlockTypes, Vector3i a_RelPos)
static size_t MakeIndex(int x, int y, int z)
static void SetBlock(BLOCKTYPE *a_BlockTypes, int a_X, int a_Y, int a_Z, BLOCKTYPE a_Type)
cCaveDefPoint(int a_BlockX, int a_BlockY, int a_BlockZ, int a_Radius)
A single non-branching tunnel of a WormNestCave.
void FinishLinear(void)
Linearly interpolates the points so that the maximum distance between two neighbors is max 1 block.
void Randomize(cNoise &a_Noise)
Generates the shaping defpoints for the cave, based on the cave block coords and noise.
void Smooth(void)
Does rounds of smoothing, two passes of RefineDefPoints(), as long as they return true.
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.
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 (...
void CalcBoundingBox(void)
Calculates the bounding box of the points present.
AString ExportAsSVG(int a_Color, int a_OffsetX, int a_OffsetZ) const
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)
A collection of connected tunnels, possibly branching.
virtual ~cCaveSystem() override
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.
cCaveSystem(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ, int a_MaxOffset, int a_Size, cNoise &a_Noise)
int GetRadius(cNoise &a_Noise, int a_OriginX, int a_OriginY, int a_OriginZ)
Returns a radius based on the location provided.
virtual void DrawIntoChunk(cChunkDesc &a_ChunkDesc) override
Draws self into the specified chunk.
virtual void GenFinish(cChunkDesc &a_ChunkDesc) override
virtual void GenFinish(cChunkDesc &a_ChunkDesc) override
virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override
Create a new structure at the specified gridpoint.
HEIGHTTYPE GetHeight(int a_RelX, int a_RelZ) const
void SetBlockType(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType)
cChunkDef::BlockTypes & GetBlockTypes(void)
cChunkDef::HeightMap & GetHeightMap(void)
BlockNibbleBytes & GetBlockMetasUncompressed(void)
BLOCKTYPE GetBlockType(int a_RelX, int a_RelY, int a_RelZ) const
NIBBLETYPE BlockNibbleBytes[cChunkDef::NumBlocks]
Uncompressed block metas, 1 meta per byte.
std::shared_ptr< cStructure > cStructurePtr
int m_Seed
Seed for generating grid offsets and also available for descendants.
cNoise m_Noise
The noise used for generating grid offsets.
Represents a single structure that occupies the grid point.
NOISE_DATATYPE CubicNoise3D(NOISE_DATATYPE a_X, NOISE_DATATYPE a_Y, NOISE_DATATYPE a_Z) const
int IntNoise3DInt(int a_X, int a_Y, int a_Z) const
int IntNoise2DInt(int a_X, int a_Y) const