载入中...
搜索中...
未找到
CaveBreakdown.cpp
浏览该文件的文档.
2
3#include <algorithm>
4#include <cmath>
5#include <random>
6#include <utility>
7
8namespace eve::procgen {
9namespace {
10
11constexpr float Pi = 3.1415926535f;
12
13float ellipsoidDistance(float x, float y, float z, const CaveBreakdownEvent& event) {
14 const float c = std::cos(event.yaw);
15 const float s = std::sin(event.yaw);
16 const float dx = x - event.x;
17 const float dz = z - event.z;
18 const float u = dx * c + dz * s;
19 const float v = -dx * s + dz * c;
20 const float q = std::sqrt((u * u) / (event.scarX * event.scarX) +
21 ((y - event.ceilingY) * (y - event.ceilingY)) / (event.scarY * event.scarY) +
22 (v * v) / (event.scarZ * event.scarZ));
23 return (q - 1.f) * std::min({event.scarX, event.scarY, event.scarZ});
24}
25
26float roundedBoxDistance(float x, float y, float z, const CaveBreakdownBlock& block) {
27 const float c = std::cos(block.yaw);
28 const float s = std::sin(block.yaw);
29 const float dx = x - block.x;
30 const float dz = z - block.z;
31 const float u = std::fabs(dx * c + dz * s) - block.hx;
32 const float v = std::fabs(y - block.y) - block.hy;
33 const float w = std::fabs(-dx * s + dz * c) - block.hz;
34 const float outside = std::sqrt(std::max(u, 0.f) * std::max(u, 0.f) + std::max(v, 0.f) * std::max(v, 0.f) +
35 std::max(w, 0.f) * std::max(w, 0.f));
36 return outside + std::min(std::max({u, v, w}), 0.f) - 0.006f;
37}
38
39} // namespace
40
41CaveBreakdownSet createCaveBreakdown(const std::vector<CaveBreakdownChamber>& chambers, int eventCount, float strength,
42 uint32_t seed) {
43 CaveBreakdownSet result;
44 if (strength <= 0.f || eventCount <= 0 || chambers.empty()) return result;
45
46 std::mt19937 rng(seed ^ 0x91e10da5u);
47 std::uniform_real_distribution<float> unit(0.f, 1.f);
48 const float boundedStrength = std::clamp(strength, 0.f, 1.f);
49 result.events.reserve(size_t(eventCount));
50 for (int i = 0; i < eventCount; ++i) {
51 const CaveBreakdownChamber& chamber = chambers[size_t(rng() % uint32_t(chambers.size()))];
53 event.x = chamber.x + (unit(rng) * 2.f - 1.f) * chamber.rx * 0.38f;
54 event.z = chamber.z + (unit(rng) * 2.f - 1.f) * chamber.rz * 0.38f;
55 event.ceilingY = chamber.y + chamber.ry * (0.72f + unit(rng) * 0.1f);
56 event.scarX = (0.075f + unit(rng) * 0.065f) * (0.65f + 0.35f * boundedStrength);
57 event.scarY = (0.025f + unit(rng) * 0.025f) * (0.7f + 0.3f * boundedStrength);
58 event.scarZ = (0.075f + unit(rng) * 0.065f) * (0.65f + 0.35f * boundedStrength);
59 event.yaw = unit(rng) * Pi;
60
61 const int blockCount = 2 + int(rng() % 3u);
62 event.blocks.reserve(size_t(blockCount));
63 for (int blockIndex = 0; blockIndex < blockCount; ++blockIndex) {
65 const float slab = unit(rng);
66 block.hx = event.scarX * (0.22f + unit(rng) * 0.18f);
67 block.hz = event.scarZ * (0.22f + unit(rng) * 0.18f);
68 block.hy = (slab < 0.58f ? 0.28f : 0.55f) * std::min(block.hx, block.hz);
69 block.x = event.x + (unit(rng) * 2.f - 1.f) * event.scarX * 0.65f;
70 block.z = event.z + (unit(rng) * 2.f - 1.f) * event.scarZ * 0.65f;
71 const float floorY = chamber.y - chamber.ry * 0.92f;
72 block.y = floorY + block.hy * 0.55f;
73 block.yaw = event.yaw + (unit(rng) * 2.f - 1.f) * 0.42f;
74 event.blocks.push_back(block);
75 result.depositedVolume += 8.f * block.hx * block.hy * block.hz;
76 ++result.blockCount;
77 }
78 result.detachedVolume += 4.f / 3.f * Pi * event.scarX * event.scarY * event.scarZ;
79 result.events.push_back(std::move(event));
80 }
81 return result;
82}
83
84float carveCaveBreakdownScars(float x, float y, float z, float current, const CaveBreakdownSet& breakdown) {
85 for (const CaveBreakdownEvent& event : breakdown.events)
86 current = std::min(current, ellipsoidDistance(x, y, z, event));
87 return current;
88}
89
90float addCaveBreakdownBlocks(float x, float y, float z, float current, const CaveBreakdownSet& breakdown) {
91 for (const CaveBreakdownEvent& event : breakdown.events)
92 for (const CaveBreakdownBlock& block : event.blocks)
93 current = std::max(current, -roundedBoxDistance(x, y, z, block));
94 return current;
95}
96
97bool isCaveBreakdownBlockSurface(float x, float y, float z, float tolerance, const CaveBreakdownSet& breakdown) {
98 for (const CaveBreakdownEvent& event : breakdown.events)
99 for (const CaveBreakdownBlock& block : event.blocks)
100 if (std::fabs(roundedBoxDistance(x, y, z, block)) <= tolerance) return true;
101 return false;
102}
103
104} // namespace eve::procgen
float w
Definition AnimClip.cpp:738
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
const std::string & s
float u
Definition Grass.cpp:233
std::array< double, 10 > q
float v
std::int32_t c
std::uint32_t seed
Definition PointSet.cpp:807
double current
float dz
float dx
TacticalUnit * unit
float addCaveBreakdownBlocks(float x, float y, float z, float current, const CaveBreakdownSet &breakdown)
Union the event's landed breakdown blocks into a cave SDF.
bool isCaveBreakdownBlockSurface(float x, float y, float z, float tolerance, const CaveBreakdownSet &breakdown)
Test whether a point lies on a generated breakdown block surface.
CaveBreakdownSet createCaveBreakdown(const std::vector< CaveBreakdownChamber > &chambers, int eventCount, float strength, uint32_t seed)
Create paired ceiling-spall scars and floor blocks from host chambers.
float carveCaveBreakdownScars(float x, float y, float z, float current, const CaveBreakdownSet &breakdown)
Carve the event's shallow ceiling detachment scars from a cave SDF.
CaveBreakdownBlock public API.
CaveBreakdownChamber public API.
CaveBreakdownEvent public API.
CaveBreakdownSet public API.
std::vector< CaveBreakdownEvent > events