载入中...
搜索中...
未找到
VolumeFluidMeshEmitter.cpp
浏览该文件的文档.
1#include <algorithm>
2#include <cmath>
3#include <glm/glm.hpp>
4#include <limits>
6
7namespace eve::fluids {
8namespace {
9bool finiteMeshVector(glm::vec3 p) { return std::isfinite(p.x) && std::isfinite(p.y) && std::isfinite(p.z); }
10bool intersects(glm::dvec3 a, glm::dvec3 b, glm::dvec3 c, glm::dvec3 center, double half) {
11 a -= center;
12 b -= center;
13 c -= center;
14 const glm::dvec3 edges[] = {b - a, c - b, a - c};
15 const glm::dvec3 basis[] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
16 const auto separated = [&](glm::dvec3 axis) {
17 const double radius = half * (std::abs(axis.x) + std::abs(axis.y) + std::abs(axis.z));
18 const double pa = glm::dot(a, axis), pb = glm::dot(b, axis), pc = glm::dot(c, axis);
19 return std::min({pa, pb, pc}) > radius + 1e-12 || std::max({pa, pb, pc}) < -radius - 1e-12;
20 };
21 for (const auto axis : basis)
22 if (separated(axis)) return false;
23 if (separated(glm::cross(edges[0], edges[1]))) return false;
24 for (const auto edge : edges)
25 for (const auto axis : basis)
26 if (separated(glm::cross(edge, axis))) return false;
27 return true;
28}
29} // namespace
31 std::span<const uint32_t> indices,
32 glm::vec3 scale, float spacing) {
34 const auto fail = [](const char* text) {
35 return Output::failure(
36 Diagnostic::error(DiagnosticCode::InvalidArgument, text, "fluids.volume.meshDistribution"));
37 };
38 if (vertices.empty() || vertices.size() > 1000000 || indices.empty() || indices.size() % 3 != 0 ||
39 indices.size() / 3 > 65536 || !finiteMeshVector(scale) || scale.x == 0 || scale.y == 0 || scale.z == 0 ||
40 !std::isfinite(spacing) || spacing < .001f || spacing > 10000.f)
41 return fail("Invalid mesh dimensions or spacing");
42 std::vector<glm::dvec3> points;
43 points.reserve(vertices.size());
44 glm::dvec3 minimum(std::numeric_limits<double>::max()), maximum(-std::numeric_limits<double>::max());
45 for (const auto vertex : vertices) {
46 if (!finiteMeshVector(vertex)) return fail("Nonfinite mesh vertex");
47 const auto p = glm::dvec3(vertex) * glm::dvec3(scale);
48 if (glm::any(glm::greaterThan(glm::abs(p), glm::dvec3(10000.0))))
49 return fail("Scaled mesh exceeds world-size limit");
50 minimum = glm::min(minimum, p);
51 maximum = glm::max(maximum, p);
52 points.push_back(p);
53 }
54 for (const auto index : indices)
55 if (index >= points.size()) return fail("Mesh index out of range");
56 const auto extent = maximum - minimum;
57 const double size = std::max(double(spacing), std::max({extent.x, extent.y, extent.z}) / 32.0);
58 const glm::ivec3 dimensions = glm::ivec3(glm::ceil(extent / size)) + glm::ivec3(4);
59 const auto origin = minimum - glm::dvec3(1.5 * size);
60 const auto index = [&](glm::ivec3 p) {
61 return size_t(p.x) + size_t(dimensions.x) * (size_t(p.y) + size_t(dimensions.y) * size_t(p.z));
62 };
63 std::vector<uint8_t> cells(size_t(dimensions.x) * size_t(dimensions.y) * size_t(dimensions.z), 0);
64 uint64_t work = 0;
65 for (size_t t = 0; t < indices.size(); t += 3) {
66 const auto a = points[indices[t]], b = points[indices[t + 1]], c = points[indices[t + 2]];
67 if (glm::length(glm::cross(b - a, c - a)) < 1e-12) return fail("Degenerate mesh triangle");
68 const auto lo = glm::ivec3(glm::floor((glm::min(a, glm::min(b, c)) - origin) / size));
69 const auto hi = glm::ivec3(glm::floor((glm::max(a, glm::max(b, c)) - origin) / size));
70 for (int z = lo.z; z <= hi.z; ++z)
71 for (int y = lo.y; y <= hi.y; ++y)
72 for (int x = lo.x; x <= hi.x; ++x) {
73 if (++work > 4000000) return fail("Mesh voxelization exceeds 4M intersection checks");
74 const glm::ivec3 p(x, y, z);
75 if (cells[index(p)] == 1) continue;
76 const auto center = origin + (glm::dvec3(p) + .5) * size;
77 if (intersects(a, b, c, center, size * .5)) cells[index(p)] = 1;
78 }
79 }
80 std::vector<glm::ivec3> queue;
81 queue.reserve(cells.size());
82 queue.emplace_back(0);
83 cells[0] = 2;
84 const glm::ivec3 directions[] = {{1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0}, {0, 0, 1}, {0, 0, -1}};
85 for (size_t i = 0; i < queue.size(); ++i)
86 for (const auto direction : directions) {
87 const auto p = queue[i] + direction;
88 if (glm::any(glm::lessThan(p, glm::ivec3(0))) || glm::any(glm::greaterThanEqual(p, dimensions))) continue;
89 if (cells[index(p)] == 0) {
90 cells[index(p)] = 2;
91 queue.push_back(p);
92 }
93 }
94 std::vector<VolumeFluidDistributionPoint> result;
95 for (int z = 0; z < dimensions.z; ++z)
96 for (int y = 0; y < dimensions.y; ++y)
97 for (int x = 0; x < dimensions.x; ++x) {
98 const glm::ivec3 p(x, y, z);
99 if (cells[index(p)] == 2) continue;
100 if (result.size() == 4096) return fail("Mesh distribution exceeds 4096 points; increase spacing");
101 result.push_back({glm::vec3(origin + (glm::dvec3(p) + .5) * size), glm::vec4(1.f)});
102 }
103 return Output::success(std::move(result));
104}
105} // namespace eve::fluids
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
glm::vec4 p[6]
float maximum[3]
float minimum[3]
std::vector< std::uint32_t > indices
std::int32_t c
std::string text
std::array< float, 3 > scale
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
size_t directions
Definition OnnxLstm.cpp:29
std::array< PixelCell, kPixelChunkSize *kPixelChunkSize > cells
std::vector< Point > vertices
float radius
std::shared_ptr< const std::vector< glm::vec2 > > points
float t
V3 origin
Definition RoadBake.cpp:138
RoadLaneDirection direction
const RoadEdge * edge
int spacing
float size
Definition TreeMesh.cpp:156
uint32_t index
std::vector< int > edges
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
Move-only operation result carrying either a value or Status.
Definition Result.h:155
GLSL compute kernels for the GPU surface-flow solver.
Definition FluidTarget.h:12
EVENGINE_API_DOMAINS Result< std::vector< VolumeFluidDistributionPoint > > buildVolumeFluidMeshDistribution(std::span< const glm::vec3 > vertices, std::span< const uint32_t > indices, glm::vec3 scale, float spacing)
Voxelizes indexed triangles, returning surface and enclosed interior cell centers.
double cross(const Vec2 &a, const Vec2 &b)
Cross.
Definition UrbanTypes.h:36
int axis(int64_t a, size_t rank)
Axis.