载入中...
搜索中...
未找到
GeometryCollectionRenderer.cpp
浏览该文件的文档.
2
3#include "graphics/Color.h"
4#include "graphics/Graphics.h"
5#include "graphics/Mesh.h"
7
8#include <glm/gtc/matrix_transform.hpp>
9#include <glm/gtc/quaternion.hpp>
10
11#include <algorithm>
12#include <cmath>
13#include <cstdint>
14#include <vector>
15
16namespace eve::physics {
17namespace {
18
19void appendBox(std::vector<float>& positions, std::vector<float>& normals, std::vector<float>& uv,
20 std::vector<std::uint32_t>& indices, const glm::mat4& model, float hx, float hy, float hz) {
21 struct Face {
22 glm::vec3 n;
23 glm::vec3 a, b, c, d;
24 };
25 const Face faces[] = {
26 {{0, 0, 1}, {-hx, -hy, hz}, {hx, -hy, hz}, {hx, hy, hz}, {-hx, hy, hz}},
27 {{0, 0, -1}, {hx, -hy, -hz}, {-hx, -hy, -hz}, {-hx, hy, -hz}, {hx, hy, -hz}},
28 {{0, 1, 0}, {-hx, hy, hz}, {hx, hy, hz}, {hx, hy, -hz}, {-hx, hy, -hz}},
29 {{0, -1, 0}, {-hx, -hy, -hz}, {hx, -hy, -hz}, {hx, -hy, hz}, {-hx, -hy, hz}},
30 {{1, 0, 0}, {hx, -hy, hz}, {hx, -hy, -hz}, {hx, hy, -hz}, {hx, hy, hz}},
31 {{-1, 0, 0}, {-hx, -hy, -hz}, {-hx, -hy, hz}, {-hx, hy, hz}, {-hx, hy, -hz}},
32 };
33 const float tex[8] = {0.f, 0.f, 1.f, 0.f, 1.f, 1.f, 0.f, 1.f};
34 for (const auto& face : faces) {
35 const std::uint32_t base = static_cast<std::uint32_t>(positions.size() / 3);
36 const glm::vec3 corners[4] = {face.a, face.b, face.c, face.d};
37 const glm::vec3 worldN = glm::normalize(glm::mat3(model) * face.n);
38 for (int i = 0; i < 4; ++i) {
39 const glm::vec4 world = model * glm::vec4(corners[i], 1.f);
40 positions.insert(positions.end(), {world.x, world.y, world.z});
41 normals.insert(normals.end(), {worldN.x, worldN.y, worldN.z});
42 uv.insert(uv.end(), {tex[i * 2], tex[i * 2 + 1]});
43 }
44 indices.insert(indices.end(), {base, base + 1, base + 2, base, base + 2, base + 3});
45 }
46}
47
48glm::mat4 boneModel(const BonePresentation& bone) {
49 const glm::quat rotation(bone.rotW, bone.rotX, bone.rotY, bone.rotZ);
50 glm::mat4 model = glm::translate(glm::mat4(1.f), glm::vec3(bone.worldX, bone.worldY, bone.worldZ));
51 model *= glm::mat4_cast(glm::normalize(rotation));
52 return model;
53}
54
55void clampColor(float& r, float& g, float& b, float& a) {
56 r = std::clamp(r, 0.f, 1.f);
57 g = std::clamp(g, 0.f, 1.f);
58 b = std::clamp(b, 0.f, 1.f);
59 a = std::clamp(a, 0.f, 1.f);
60}
61
62} // namespace
63
66
68
70 instance_ = instance;
71 invalidateSleepBatch(meshOwner_);
72}
73
74void GeometryCollectionRenderer::setExteriorColor(float r, float g, float b, float a) {
75 exteriorR_ = r;
76 exteriorG_ = g;
77 exteriorB_ = b;
78 exteriorA_ = a;
79 clampColor(exteriorR_, exteriorG_, exteriorB_, exteriorA_);
80}
81
82void GeometryCollectionRenderer::setInteriorColor(float r, float g, float b, float a) {
83 interiorR_ = r;
84 interiorG_ = g;
85 interiorB_ = b;
86 interiorA_ = a;
87 clampColor(interiorR_, interiorG_, interiorB_, interiorA_);
88}
89
90void GeometryCollectionRenderer::setSleepColor(float r, float g, float b, float a) {
91 sleepR_ = r;
92 sleepG_ = g;
93 sleepB_ = b;
94 sleepA_ = a;
95 clampColor(sleepR_, sleepG_, sleepB_, sleepA_);
96}
97
98void GeometryCollectionRenderer::releaseOwnedMeshes(graphics::Graphics* graphics) {
99 if (graphics) {
100 if (sleepBatch_) (void)graphics->releaseMesh(sleepBatch_);
101 if (unitBox_) (void)graphics->releaseMesh(unitBox_);
102 }
103 sleepBatch_ = nullptr;
104 unitBox_ = nullptr;
105 meshOwner_ = nullptr;
106 sleepBatchRevision_ = 0;
107 sleepBatchBoneCount_ = 0;
108}
109
110void GeometryCollectionRenderer::invalidateSleepBatch(graphics::Graphics* graphics) {
111 if (graphics && sleepBatch_) (void)graphics->releaseMesh(sleepBatch_);
112 sleepBatch_ = nullptr;
113 sleepBatchRevision_ = 0;
114 sleepBatchBoneCount_ = 0;
115}
116
117void GeometryCollectionRenderer::ensureUnitBox(graphics::Graphics& graphics) {
118 if (meshOwner_ != &graphics) {
119 releaseOwnedMeshes(meshOwner_);
120 meshOwner_ = &graphics;
121 }
122 if (unitBox_) return;
123 std::vector<float> positions;
124 std::vector<float> normals;
125 std::vector<float> uv;
126 std::vector<std::uint32_t> indices;
127 appendBox(positions, normals, uv, indices, glm::mat4(1.f), 1.f, 1.f, 1.f);
128 unitBox_ = graphics.newMeshFromArrays(positions.data(), normals.data(), uv.data(),
129 static_cast<int>(positions.size() / 3), indices.data(),
130 static_cast<int>(indices.size()));
131}
132
133eve::Result<void> GeometryCollectionRenderer::rebuildSleepBatch(graphics::Graphics& graphics) {
134 if (!instance_)
136 eve::DiagnosticCode::InvalidArgument, "geometry-collection renderer has no instance", "instance"));
137 if (meshOwner_ != &graphics) {
138 releaseOwnedMeshes(meshOwner_);
139 meshOwner_ = &graphics;
140 }
141 invalidateSleepBatch(&graphics);
142 std::vector<float> positions;
143 std::vector<float> normals;
144 std::vector<float> uv;
145 std::vector<std::uint32_t> indices;
146 int sleepCount = 0;
147 for (int i = 0; i < instance_->boneCount(); ++i) {
148 auto presentation = instance_->bonePresentation(i);
149 if (!presentation) return eve::Result<void>::failure(presentation.status());
150 if (presentation.value().state != BoneRuntimeState::Sleeping) continue;
151 appendBox(positions, normals, uv, indices, boneModel(presentation.value()),
152 presentation.value().halfExtentX, presentation.value().halfExtentY,
153 presentation.value().halfExtentZ);
154 ++sleepCount;
155 }
156 sleepBatchBoneCount_ = sleepCount;
157 sleepBatchRevision_ = instance_->sleepBatchRevision();
158 if (sleepCount == 0) return eve::Result<void>::success();
159 sleepBatch_ = graphics.newMeshFromArrays(positions.data(), normals.data(), uv.data(),
160 static_cast<int>(positions.size() / 3), indices.data(),
161 static_cast<int>(indices.size()));
162 if (!sleepBatch_)
164 eve::DiagnosticCode::Failed, "geometry-collection sleep batch mesh allocation failed", "mesh"));
166}
167
169 lastActiveDrawCount_ = 0;
170 lastSleepBatchCount_ = 0;
171 if (!graphics)
173 eve::DiagnosticCode::InvalidArgument, "geometry-collection draw requires Graphics", "graphics"));
174 if (!instance_)
176 eve::DiagnosticCode::InvalidArgument, "geometry-collection renderer has no instance", "instance"));
177 if (!instance_->hasLiveWorld())
179 eve::DiagnosticCode::StaleHandle, "geometry-collection world is gone", "world"));
180
181 ensureUnitBox(*graphics);
182 if (!unitBox_)
184 eve::DiagnosticCode::Failed, "geometry-collection unit box mesh allocation failed", "mesh"));
185
186 if (sleepBatchRevision_ != instance_->sleepBatchRevision() ||
187 (sleepBatch_ == nullptr && instance_->sleepBatchRevision() != 0)) {
188 auto rebuilt = rebuildSleepBatch(*graphics);
189 if (!rebuilt) return rebuilt;
190 }
191
192 for (int i = 0; i < instance_->boneCount(); ++i) {
193 auto presentation = instance_->bonePresentation(i);
194 if (!presentation) return eve::Result<void>::failure(presentation.status());
195 const auto& bone = presentation.value();
196 if (bone.state == BoneRuntimeState::Sleeping) continue;
197 glm::mat4 model = boneModel(bone);
198 model = glm::scale(model, glm::vec3(bone.halfExtentX, bone.halfExtentY, bone.halfExtentZ));
199 const bool detached = bone.state == BoneRuntimeState::Detached;
200 const graphics::Color tint(detached ? interiorR_ : exteriorR_, detached ? interiorG_ : exteriorG_,
201 detached ? interiorB_ : exteriorB_, detached ? interiorA_ : exteriorA_);
202 graphics->drawMesh(unitBox_, model, nullptr, tint);
203 ++lastActiveDrawCount_;
204 }
205
206 if (sleepBatch_) {
207 graphics->drawMesh(sleepBatch_, glm::mat4(1.f), nullptr,
208 graphics::Color(sleepR_, sleepG_, sleepB_, sleepA_));
209 lastSleepBatchCount_ = sleepBatchBoneCount_;
210 }
212}
213
214} // namespace eve::physics
float uv
tensor::Graph g
Definition GpuGraph.cpp:7
glm::vec4 tint
glm::vec3 n
Definition Grass.cpp:63
double r
std::vector< std::uint32_t > indices
std::vector< float > normals
std::vector< float > positions
std::int32_t c
std::array< float, 4 > rotation
std::uint32_t bone
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
World3D * world
float d
glm::mat4 model
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
static Result success(T value)
Construct a successful result owning value.
Definition Result.h:164
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
virtual bool releaseMesh(Mesh *mesh)
Eagerly releases a mesh created by this Graphics.
Definition Graphics.h:927
virtual void drawMesh(Mesh *mesh, const glm::mat4 &model, Texture *texture, const Color &tint)=0
Draw one mesh with model matrix. Requires begin3DFrame() (or an open swapchain pass).
Runtime owner of bone state, connection strain, and PhysicsLink bindings.
std::uint64_t sleepBatchRevision() const noexcept
Monotonic revision bumped when any bone enters Sleeping (for batch rebuild).
bool hasLiveWorld() const noexcept
Whether the owning world handle still resolves.
eve::Result< BonePresentation > bonePresentation(int boneIndex) const
Sample one bone's world pose and proxy extents for presentation.
void setInteriorColor(float r, float g, float b, float a)
Interior RGBA for Detached bones (broken-face stand-in).
void setExteriorColor(float r, float g, float b, float a)
Exterior RGBA for Attached bones.
eve::Result< void > draw(graphics::Graphics *graphics)
Synchronize caches and draw all bones into the current 3D frame.
GeometryCollectionRenderer(GeometryCollectionInstance *instance) noexcept
Construct a renderer that borrows an instance.
void setSleepColor(float r, float g, float b, float a)
Sleeping-batch RGBA.
void setInstance(GeometryCollectionInstance *instance)
Replace the borrowed instance; null disables drawing. @ownership Does not take ownership of instance....
~GeometryCollectionRenderer()
Geometry collection renderer.
eve::Color Color
RGBA color used by every graphics draw call. Lives inside eve::graphics so including a graphics heade...
Definition Color.h:13
Optional physics backend for vehicle mobility and body attach.
Definition Climbing.h:36