Cuberite
A lightweight, fast and extensible game server for Minecraft
RoughRavines.cpp
Go to the documentation of this file.
1 
2 // RoughRavines.cpp
3 
4 // Implements the cRoughRavines class representing the rough ravine generator
5 
6 #include "Globals.h"
7 
8 #include "RoughRavines.h"
9 #include "../BlockInfo.h"
10 
11 
12 
13 
14 
16 // cRoughRavine:
17 
20 {
22 
23 public:
24 
26  int a_Seed, size_t a_Size,
27  float a_CenterWidth, float a_Roughness,
28  float a_FloorHeightEdge1, float a_FloorHeightEdge2, float a_FloorHeightCenter,
29  float a_CeilingHeightEdge1, float a_CeilingHeightEdge2, float a_CeilingHeightCenter,
30  int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ
31  ):
32  Super(a_GridX, a_GridZ, a_OriginX, a_OriginZ),
33  m_Seed(a_Seed + 100),
34  m_Noise(a_Seed + 100),
35  m_Roughness(a_Roughness)
36  {
37  // Create the basic structure - 2 lines meeting at the centerpoint:
38  size_t Max = 2 * a_Size;
39  size_t Half = a_Size; // m_DefPoints[Half] will be the centerpoint
40  m_DefPoints.resize(Max + 1);
41  int rnd = m_Noise.IntNoise2DInt(a_OriginX, a_OriginZ) / 7;
42  float Len = static_cast<float>(a_Size);
43  float Angle = static_cast<float>(rnd); // Angle is in radians, will be wrapped in the "sin" and "cos" operations
44  float OfsX = sinf(Angle) * Len;
45  float OfsZ = cosf(Angle) * Len;
46  m_DefPoints[0].Set (a_OriginX - OfsX, a_OriginZ - OfsZ, 1, a_CeilingHeightEdge1, a_FloorHeightEdge1);
47  m_DefPoints[Half].Set(static_cast<float>(a_OriginX), static_cast<float>(a_OriginZ), a_CenterWidth, a_CeilingHeightCenter, a_FloorHeightCenter);
48  m_DefPoints[Max].Set (a_OriginX + OfsX, a_OriginZ + OfsZ, 1, a_CeilingHeightEdge2, a_FloorHeightEdge2);
49 
50  // Calculate the points in between, recursively:
51  SubdivideLine(0, Half);
52  SubdivideLine(Half, Max);
53 
54  // Initialize the per-height radius modifiers:
55  InitPerHeightRadius(a_GridX, a_GridZ);
56  }
57 
58 protected:
60  {
61  float m_X;
62  float m_Z;
63  float m_Radius;
64  float m_Top;
65  float m_Bottom;
66 
67  void Set(float a_X, float a_Z, float a_Radius, float a_Top, float a_Bottom)
68  {
69  m_X = a_X;
70  m_Z = a_Z;
71  m_Radius = a_Radius;
72  m_Top = a_Top;
73  m_Bottom = a_Bottom;
74  }
75  };
76  using sRavineDefPoints = std::vector<sRavineDefPoint>;
77 
78  int m_Seed;
79 
81 
82  int m_MaxSize;
83 
85 
86  float m_Roughness;
87 
90 
91 
95  void SubdivideLine(size_t a_Idx1, size_t a_Idx2)
96  {
97  // Calculate the midpoint:
98  const sRavineDefPoint & p1 = m_DefPoints[a_Idx1];
99  const sRavineDefPoint & p2 = m_DefPoints[a_Idx2];
100  float MidX = (p1.m_X + p2.m_X) / 2;
101  float MidZ = (p1.m_Z + p2.m_Z) / 2;
102  float MidR = (p1.m_Radius + p2.m_Radius) / 2 + 0.1f;
103  float MidT = (p1.m_Top + p2.m_Top) / 2;
104  float MidB = (p1.m_Bottom + p2.m_Bottom) / 2;
105 
106  // Adjust the midpoint by a small amount of perpendicular vector in a random one of its two directions:
107  float dx = p2.m_X - p1.m_X;
108  float dz = p2.m_Z - p1.m_Z;
109  if ((m_Noise.IntNoise2DInt(static_cast<int>(MidX), static_cast<int>(MidZ)) / 11) % 2 == 0)
110  {
111  MidX += dz * m_Roughness;
112  MidZ -= dx * m_Roughness;
113  }
114  else
115  {
116  MidX -= dz * m_Roughness;
117  MidZ += dx * m_Roughness;
118  }
119  size_t MidIdx = (a_Idx1 + a_Idx2) / 2;
120  m_DefPoints[MidIdx].Set(MidX, MidZ, MidR, MidT, MidB);
121 
122  // Recurse the two halves, if they are worth recursing:
123  if (MidIdx - a_Idx1 > 1)
124  {
125  SubdivideLine(a_Idx1, MidIdx);
126  }
127  if (a_Idx2 - MidIdx > 1)
128  {
129  SubdivideLine(MidIdx, a_Idx2);
130  }
131  }
132 
133 
134  void InitPerHeightRadius(int a_GridX, int a_GridZ)
135  {
136  int h = 0;
137  while (h < cChunkDef::Height)
138  {
139  m_Noise.SetSeed(m_Seed + h);
140  int rnd = m_Noise.IntNoise2DInt(a_GridX, a_GridZ) / 13;
141  int NumBlocks = (rnd % 3) + 2;
142  rnd = rnd / 4;
143  float Val = static_cast<float>(rnd % 256) / 128.0f - 1.0f; // Random float in range [-1, +1]
144  if (h + NumBlocks > cChunkDef::Height)
145  {
146  NumBlocks = cChunkDef::Height - h;
147  }
148  for (int i = 0; i < NumBlocks; i++)
149  {
150  m_PerHeightRadius[h + i] = Val;
151  }
152  h += NumBlocks;
153  }
154  }
155 
156 
157  virtual void DrawIntoChunk(cChunkDesc & a_ChunkDesc) override
158  {
159  int BlockStartX = a_ChunkDesc.GetChunkX() * cChunkDef::Width;
160  int BlockStartZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width;
161  int BlockEndX = BlockStartX + cChunkDef::Width;
162  int BlockEndZ = BlockStartZ + cChunkDef::Width;
163  for (sRavineDefPoints::const_iterator itr = m_DefPoints.begin(), end = m_DefPoints.end(); itr != end; ++itr)
164  {
165  if (
166  (ceilf (itr->m_X + itr->m_Radius + 2) < BlockStartX) ||
167  (floorf(itr->m_X - itr->m_Radius - 2) > BlockEndX) ||
168  (ceilf (itr->m_Z + itr->m_Radius + 2) < BlockStartZ) ||
169  (floorf(itr->m_Z - itr->m_Radius - 2) > BlockEndZ)
170  )
171  {
172  // Cannot intersect, bail out early
173  continue;
174  }
175 
176  // Carve out a cylinder around the xz point, up to (m_Radius + 2) in diameter, from Bottom to Top:
177  // On each height level, use m_PerHeightRadius[] to modify the actual radius used
178  // EnlargedRadiusSq is the square of the radius enlarged by the maximum m_PerHeightRadius offset - anything outside it will never be touched.
179  float RadiusSq = (itr->m_Radius + 2) * (itr->m_Radius + 2);
180  float DifX = BlockStartX - itr->m_X; // substitution for faster calc
181  float DifZ = BlockStartZ - itr->m_Z; // substitution for faster calc
182  for (int x = 0; x < cChunkDef::Width; x++) for (int z = 0; z < cChunkDef::Width; z++)
183  {
184  #ifndef NDEBUG
185  // DEBUG: Make the roughravine shapepoints visible on a single layer (so that we can see with Minutor what's going on)
186  if ((FloorC(DifX + x) == 0) && (FloorC(DifZ + z) == 0))
187  {
188  a_ChunkDesc.SetBlockType(x, 4, z, E_BLOCK_LAPIS_ORE);
189  }
190  #endif // !NDEBUG
191 
192  // If the column is outside the enlarged radius, bail out completely
193  float DistSq = (DifX + x) * (DifX + x) + (DifZ + z) * (DifZ + z);
194  if (DistSq > RadiusSq)
195  {
196  continue;
197  }
198 
199  int Top = std::min(CeilC(itr->m_Top), +cChunkDef::Height);
200  for (int y = std::max(FloorC(itr->m_Bottom), 1); y <= Top; y++)
201  {
202  if ((itr->m_Radius + m_PerHeightRadius[y]) * (itr->m_Radius + m_PerHeightRadius[y]) < DistSq)
203  {
204  continue;
205  }
206 
207  if (cBlockInfo::CanBeTerraformed(a_ChunkDesc.GetBlockType(x, y, z)))
208  {
209  a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_AIR);
210  }
211  } // for y
212  } // for x, z - a_BlockTypes
213  } // for itr - m_Points[]
214  }
215 };
216 
217 
218 
219 
220 
222 // cRoughRavines:
223 
225  int a_Seed,
226  int a_MaxSize, int a_MinSize,
227  float a_MaxCenterWidth, float a_MinCenterWidth,
228  float a_MaxRoughness, float a_MinRoughness,
229  float a_MaxFloorHeightEdge, float a_MinFloorHeightEdge,
230  float a_MaxFloorHeightCenter, float a_MinFloorHeightCenter,
231  float a_MaxCeilingHeightEdge, float a_MinCeilingHeightEdge,
232  float a_MaxCeilingHeightCenter, float a_MinCeilingHeightCenter,
233  int a_GridSize, int a_MaxOffset
234 ) :
235  Super(a_Seed, a_GridSize, a_GridSize, a_MaxOffset, a_MaxOffset, a_MaxSize, a_MaxSize, 64),
236  m_MaxSize(a_MaxSize),
237  m_MinSize(a_MinSize),
238  m_MaxCenterWidth(a_MaxCenterWidth),
239  m_MinCenterWidth(a_MinCenterWidth),
240  m_MaxRoughness(a_MaxRoughness),
241  m_MinRoughness(a_MinRoughness),
242  m_MaxFloorHeightEdge(a_MaxFloorHeightEdge),
243  m_MinFloorHeightEdge(a_MinFloorHeightEdge),
244  m_MaxFloorHeightCenter(a_MaxFloorHeightCenter),
245  m_MinFloorHeightCenter(a_MinFloorHeightCenter),
246  m_MaxCeilingHeightEdge(a_MaxCeilingHeightEdge),
247  m_MinCeilingHeightEdge(a_MinCeilingHeightEdge),
248  m_MaxCeilingHeightCenter(a_MaxCeilingHeightCenter),
249  m_MinCeilingHeightCenter(a_MinCeilingHeightCenter)
250 {
251  if (m_MinSize > m_MaxSize)
252  {
253  std::swap(m_MinSize, m_MaxSize);
254  std::swap(a_MinSize, a_MaxSize);
255  }
256  if (m_MaxSize < 16)
257  {
258  m_MaxSize = 16;
259  LOGWARNING("RoughRavines: MaxSize too small, adjusting request from %d to %d", a_MaxSize, m_MaxSize);
260  }
261  if (m_MinSize < 16)
262  {
263  m_MinSize = 16;
264  LOGWARNING("RoughRavines: MinSize too small, adjusting request from %d to %d", a_MinSize, m_MinSize);
265  }
266  if (m_MinSize == m_MaxSize)
267  {
268  m_MaxSize = m_MinSize + 1;
269  }
270 }
271 
272 
273 
274 
275 
276 cGridStructGen::cStructurePtr cRoughRavines::CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ)
277 {
278  // Pick a random value for each of the ravine's parameters:
279  size_t Size = static_cast<size_t>(m_MinSize + (m_Noise.IntNoise2DInt(a_GridX, a_GridZ) / 7) % (m_MaxSize - m_MinSize)); // Random int from m_MinSize to m_MaxSize
280  float CenterWidth = m_Noise.IntNoise2DInRange(a_GridX + 10, a_GridZ, m_MinCenterWidth, m_MaxCenterWidth);
281  float Roughness = m_Noise.IntNoise2DInRange(a_GridX + 20, a_GridZ, m_MinRoughness, m_MaxRoughness);
282  float FloorHeightEdge1 = m_Noise.IntNoise2DInRange(a_GridX + 30, a_GridZ, m_MinFloorHeightEdge, m_MaxFloorHeightEdge);
283  float FloorHeightEdge2 = m_Noise.IntNoise2DInRange(a_GridX + 40, a_GridZ, m_MinFloorHeightEdge, m_MaxFloorHeightEdge);
284  float FloorHeightCenter = m_Noise.IntNoise2DInRange(a_GridX + 50, a_GridZ, m_MinFloorHeightCenter, m_MaxFloorHeightCenter);
285  float CeilingHeightEdge1 = m_Noise.IntNoise2DInRange(a_GridX + 60, a_GridZ, m_MinCeilingHeightEdge, m_MaxCeilingHeightEdge);
286  float CeilingHeightEdge2 = m_Noise.IntNoise2DInRange(a_GridX + 70, a_GridZ, m_MinCeilingHeightEdge, m_MaxCeilingHeightEdge);
287  float CeilingHeightCenter = m_Noise.IntNoise2DInRange(a_GridX + 80, a_GridZ, m_MinCeilingHeightCenter, m_MaxCeilingHeightCenter);
288 
289  // Create a ravine:
290  return cStructurePtr(new cRoughRavine(
291  m_Seed,
292  Size, CenterWidth, Roughness,
293  FloorHeightEdge1, FloorHeightEdge2, FloorHeightCenter,
294  CeilingHeightEdge1, CeilingHeightEdge2, CeilingHeightCenter,
295  a_GridX, a_GridZ, a_OriginX, a_OriginZ
296  ));
297 }
298 
299 
300 
301 
@ E_BLOCK_AIR
Definition: BlockType.h:10
@ E_BLOCK_LAPIS_ORE
Definition: BlockType.h:31
std::enable_if< std::is_arithmetic< T >::value, C >::type CeilC(T a_Value)
Ceils a value, then casts it to C (an int by default).
Definition: Globals.h:354
std::enable_if< std::is_arithmetic< T >::value, C >::type FloorC(T a_Value)
Floors a value, then casts it to C (an int by default).
Definition: Globals.h:347
void LOGWARNING(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:67
static bool CanBeTerraformed(BLOCKTYPE Block)
Can a finisher change it?
Definition: BlockInfo.cpp:575
static const int Width
Definition: ChunkDef.h:124
static const int Height
Definition: ChunkDef.h:125
void SetBlockType(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType)
Definition: ChunkDesc.cpp:81
int GetChunkX() const
Definition: ChunkDesc.h:49
BLOCKTYPE GetBlockType(int a_RelX, int a_RelY, int a_RelZ) const
Definition: ChunkDesc.cpp:90
int GetChunkZ() const
Definition: ChunkDesc.h:50
Generates structures in a semi-random grid.
Definition: GridStructGen.h:46
std::shared_ptr< cStructure > cStructurePtr
Definition: GridStructGen.h:77
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.
Definition: GridStructGen.h:50
float m_PerHeightRadius[cChunkDef::Height]
Number to add to the radius based on the height.
sRavineDefPoints m_DefPoints
void InitPerHeightRadius(int a_GridX, int a_GridZ)
void SubdivideLine(size_t a_Idx1, size_t a_Idx2)
Recursively subdivides the line between the points of the specified index.
cRoughRavine(int a_Seed, size_t a_Size, float a_CenterWidth, float a_Roughness, float a_FloorHeightEdge1, float a_FloorHeightEdge2, float a_FloorHeightCenter, float a_CeilingHeightEdge1, float a_CeilingHeightEdge2, float a_CeilingHeightCenter, int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ)
virtual void DrawIntoChunk(cChunkDesc &a_ChunkDesc) override
Draws self into the specified chunk.
std::vector< sRavineDefPoint > sRavineDefPoints
void Set(float a_X, float a_Z, float a_Radius, float a_Top, float a_Bottom)
float m_MaxCeilingHeightCenter
Maximum ceiling height at the ravine's center.
Definition: RoughRavines.h:74
cRoughRavines(int a_Seed, int a_MaxSize, int a_MinSize, float a_MaxCenterWidth, float a_MinCenterWidth, float a_MaxRoughness, float a_MinRoughness, float a_MaxFloorHeightEdge, float a_MinFloorHeightEdge, float a_MaxFloorHeightCenter, float a_MinFloorHeightCenter, float a_MaxCeilingHeightEdge, float a_MinCeilingHeightEdge, float a_MaxCeilingHeightCenter, float a_MinCeilingHeightCenter, int a_GridSize, int a_MaxOffset)
float m_MaxFloorHeightEdge
Maximum floor height at the ravine's edge.
Definition: RoughRavines.h:56
virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override
Create a new structure at the specified gridpoint.
float m_MinCeilingHeightEdge
Minimum ceiling height at the ravine's edge.
Definition: RoughRavines.h:71
float m_MinCeilingHeightCenter
Minimum ceiling height at the ravine's center.
Definition: RoughRavines.h:77
float m_MaxCenterWidth
Maximum width of the ravine's center, in blocks.
Definition: RoughRavines.h:44
float m_MinFloorHeightEdge
Minimum floor height at the ravine's edge.
Definition: RoughRavines.h:59
float m_MaxFloorHeightCenter
Maximum floor height at the ravine's center.
Definition: RoughRavines.h:62
int m_MaxSize
Maximum size of the ravine, in each of the X / Z axis.
Definition: RoughRavines.h:38
int m_MinSize
Minimum size of the ravine.
Definition: RoughRavines.h:41
float m_MaxRoughness
Maximum roughness of the ravine.
Definition: RoughRavines.h:50
float m_MinRoughness
Minimum roughness of the ravine.
Definition: RoughRavines.h:53
float m_MinFloorHeightCenter
Minimum floor height at the ravine's center.
Definition: RoughRavines.h:65
float m_MaxCeilingHeightEdge
Maximum ceiling height at the ravine's edge.
Definition: RoughRavines.h:68
float m_MinCenterWidth
Minimum width of the ravine's center, in blocks.
Definition: RoughRavines.h:47
Definition: Noise.h:20
void SetSeed(int a_Seed)
Definition: Noise.h:52
int IntNoise2DInt(int a_X, int a_Y) const
Definition: Noise.h:243
NOISE_DATATYPE IntNoise2DInRange(int a_X, int a_Y, float a_Min, float a_Max) const
Definition: Noise.h:32