| 441 | |
| 442 | |
| 443 | void cStructGenLakes::CreateLakeImage(int a_ChunkX, int a_ChunkZ, cBlockArea & a_Lake) |
| 444 | { |
| 445 | a_Lake.Create(16, 8, 16); |
| 446 | a_Lake.Fill(cBlockArea::baTypes, E_BLOCK_SPONGE); // Sponge is the NOP blocktype for lake merging strategy |
| 447 | |
| 448 | // Find the minimum height in this chunk: |
| 449 | cChunkDef::HeightMap HeightMap; |
| 450 | m_HeiGen.GenHeightMap(a_ChunkX, a_ChunkZ, HeightMap); |
| 451 | HEIGHTTYPE MinHeight = HeightMap[0]; |
| 452 | for (size_t i = 1; i < ARRAYCOUNT(HeightMap); i++) |
| 453 | { |
| 454 | if (HeightMap[i] < MinHeight) |
| 455 | { |
| 456 | MinHeight = HeightMap[i]; |
| 457 | } |
| 458 | } |
| 459 | |
| 460 | // Make a random position in the chunk by using a random 16 block XZ offset and random height up to chunk's max height minus 6 |
| 461 | MinHeight = std::max(MinHeight - 6, 2); |
| 462 | int Rnd = m_Noise.IntNoise3DInt(a_ChunkX, 128, a_ChunkZ) / 11; |
| 463 | // Random offset [-8 .. 8], with higher probability around 0; add up four three-bit-wide randoms [0 .. 28], divide and subtract to get range |
| 464 | int OffsetX = 4 * ((Rnd & 0x07) + ((Rnd & 0x38) >> 3) + ((Rnd & 0x1c0) >> 6) + ((Rnd & 0xe00) >> 9)) / 7 - 8; |
| 465 | Rnd >>= 12; |
| 466 | // Random offset [-8 .. 8], with higher probability around 0; add up four three-bit-wide randoms [0 .. 28], divide and subtract to get range |
| 467 | int OffsetZ = 4 * ((Rnd & 0x07) + ((Rnd & 0x38) >> 3) + ((Rnd & 0x1c0) >> 6) + ((Rnd & 0xe00) >> 9)) / 7 - 8; |
| 468 | Rnd = m_Noise.IntNoise3DInt(a_ChunkX, 512, a_ChunkZ) / 13; |
| 469 | // Random height [1 .. MinHeight] with preference to center heights |
| 470 | int HeightY = 1 + (((Rnd & 0x1ff) % MinHeight) + (((Rnd >> 9) & 0x1ff) % MinHeight)) / 2; |
| 471 | |
| 472 | a_Lake.SetOrigin(OffsetX, HeightY, OffsetZ); |
| 473 | |
| 474 | // Hollow out a few bubbles inside the blockarea: |
| 475 | int NumBubbles = 4 + ((Rnd >> 18) & 0x03); // 4 .. 7 bubbles |
| 476 | BLOCKTYPE * BlockTypes = a_Lake.GetBlockTypes(); |
| 477 | for (int i = 0; i < NumBubbles; i++) |
| 478 | { |
| 479 | int Rnd = m_Noise.IntNoise3DInt(a_ChunkX, i, a_ChunkZ) / 13; |
| 480 | const int BubbleR = 2 + (Rnd & 0x03); // 2 .. 5 |
| 481 | const int Range = 16 - 2 * BubbleR; |
| 482 | const int BubbleX = BubbleR + (Rnd % Range); |
| 483 | Rnd >>= 4; |
| 484 | const int BubbleY = 4 + (Rnd & 0x01); // 4 .. 5 |
| 485 | Rnd >>= 1; |
| 486 | const int BubbleZ = BubbleR + (Rnd % Range); |
| 487 | Rnd >>= 4; |
| 488 | const int HalfR = BubbleR / 2; // 1 .. 2 |
| 489 | const int RSquared = BubbleR * BubbleR; |
| 490 | for (int y = -HalfR; y <= HalfR; y++) |
| 491 | { |
| 492 | // BubbleY + y is in the [0, 7] bounds |
| 493 | int DistY = 4 * y * y / 3; |
| 494 | int IdxY = (BubbleY + y) * 16 * 16; |
| 495 | for (int z = -BubbleR; z <= BubbleR; z++) |
| 496 | { |
| 497 | int DistYZ = DistY + z * z; |
| 498 | if (DistYZ >= RSquared) |
| 499 | { |
| 500 | continue; |
nothing calls this directly
no test coverage detected