载入中...
搜索中...
未找到
Renderable3D.cpp
浏览该文件的文档.
1#include <algorithm>
2#include <cmath>
3#include "common/Exception.h"
4#include "graphics/Material.h"
5#include "graphics/Mesh.h"
7
8namespace eve::graphics {
9void Renderable3D::setPosition(float x, float y, float z) {
10 auto t = transform();
11 t->x = x;
12 t->y = y;
13 t->z = z;
14}
15
16void Renderable3D::setRotation(float yaw, float pitch, float roll) {
17 auto t = transform();
18 t->yaw = yaw;
19 t->pitch = pitch;
20 t->roll = roll;
21}
22
23void Renderable3D::setYaw(float yaw) { transform()->yaw = yaw; }
24
25float Renderable3D::getYaw() { return transform()->yaw; }
26
27void Renderable3D::setScale(float sx, float sy, float sz) {
28 auto t = transform();
29 t->sx = sx;
30 t->sy = sy;
31 t->sz = sz;
32}
33
34void Renderable3D::setMesh(Mesh* mesh) { meshRenderer()->mesh = mesh; }
35
36Mesh* Renderable3D::getMesh() { return meshRenderer()->mesh; }
37
38void Renderable3D::setTexture(Texture* texture) { meshRenderer()->texture = texture; }
39
40void Renderable3D::setNormalTexture(Texture* texture) { meshRenderer()->normalTexture = texture; }
41
42void Renderable3D::setPackedNormalMask(bool enabled) { meshRenderer()->packedNormalMask = enabled; }
43
44void Renderable3D::setHeightTexture(Texture* texture) { meshRenderer()->heightTexture = texture; }
45
46void Renderable3D::setShader(Shader* shader) { meshRenderer()->shader = shader; }
47
48void Renderable3D::setMaterial(Material* material) { meshRenderer()->material = material; }
49
50Material* Renderable3D::getMaterial() { return meshRenderer()->material; }
51
52void Renderable3D::setXRayShader(Shader* shader) { meshRenderer()->xrayShader = shader; }
53
54Shader* Renderable3D::getXRayShader() { return meshRenderer()->xrayShader; }
55
56void Renderable3D::setXRayHighlight(bool on) { meshRenderer()->xrayHighlight = on; }
57
58bool Renderable3D::getXRayHighlight() { return meshRenderer()->xrayHighlight; }
59
60void Renderable3D::setPart(int index, const std::string& name, Mesh* mesh, Material* material) {
61 auto mr = meshRenderer();
62 if (index < 0 || index >= MeshRenderer::kMaxParts) return;
63 mr->parts[index].name = name;
64 mr->parts[index].mesh = mesh;
65 mr->parts[index].material = material;
66 if (mesh) {
67 if (mr->partCount < index + 1) mr->partCount = index + 1;
68 } else if (index + 1 == mr->partCount) {
69 while (mr->partCount > 0 && !mr->parts[mr->partCount - 1].mesh) --mr->partCount;
70 }
71}
72
74 auto mr = meshRenderer();
75 if (index < 0 || index >= MeshRenderer::kMaxParts) return;
76 mr->parts[index].sortPriority = priority;
77 mr->parts[index].hasSortPriority = true;
78}
79
81 auto mr = meshRenderer();
82 if (index < 0 || index >= MeshRenderer::kMaxParts) return;
83 mr->parts[index].sortPriority = 0;
84 mr->parts[index].hasSortPriority = false;
85}
86
88 auto mr = meshRenderer();
89 if (index < 0 || index >= mr->partCount) return 0;
90 const auto& part = mr->parts[index];
91 if (part.hasSortPriority) return part.sortPriority;
92 return part.material ? part.material->getSortPriority() : 0;
93}
94
96 auto mr = meshRenderer();
97 mr->partCount = 0;
98 for (int i = 0; i < MeshRenderer::kMaxParts; ++i) {
99 mr->parts[i] = ModelPart{};
100 }
101}
102
103int Renderable3D::getPartCount() { return meshRenderer()->partCount; }
104
106 auto mr = meshRenderer();
107 if (index < 0 || index >= mr->partCount) return {};
108 return mr->parts[index].name;
109}
110
112 auto mr = meshRenderer();
113 if (index < 0 || index >= mr->partCount) return nullptr;
114 return mr->parts[index].mesh;
115}
116
118 auto mr = meshRenderer();
119 if (index < 0 || index >= mr->partCount) return nullptr;
120 return mr->parts[index].material;
121}
122
123void Renderable3D::setHair(bool hair) { meshRenderer()->isHair = hair; }
124
125bool Renderable3D::getHair() { return meshRenderer()->isHair; }
126
127void Renderable3D::setTint(float r, float g, float b, float a) {
128 auto mr = meshRenderer();
129 mr->r = r;
130 mr->g = g;
131 mr->b = b;
132 mr->a = a;
133}
134
135void Renderable3D::setMetallic(float metallic) { meshRenderer()->metallic = metallic; }
136
137void Renderable3D::setRoughness(float roughness) { meshRenderer()->roughness = roughness; }
138
139void Renderable3D::setTexCellBomb(float cellScale, float strength, float rotAmount) {
140 auto mr = meshRenderer();
141 mr->texBombScale = cellScale > 1e-3f ? cellScale : 1e-3f;
142 mr->texBombStrength = strength < 0.f ? 0.f : (strength > 1.f ? 1.f : strength);
143 mr->texBombRot = rotAmount < 0.f ? 0.f : (rotAmount > 1.f ? 1.f : rotAmount);
144}
145
146float Renderable3D::getTexCellBombScale() { return meshRenderer()->texBombScale; }
147
148float Renderable3D::getTexCellBombStrength() { return meshRenderer()->texBombStrength; }
149
150float Renderable3D::getTexCellBombRotation() { return meshRenderer()->texBombRot; }
151
152void Renderable3D::setParallax(float scale, float minLayers, float maxLayers) {
153 auto mr = meshRenderer();
154 mr->parallaxScale = scale < 0.f ? 0.f : (scale > 0.25f ? 0.25f : scale);
155 float minL = minLayers < 1.f ? 1.f : minLayers;
156 float maxL = maxLayers < minL ? minL : maxLayers;
157 if (maxL > 64.f) maxL = 64.f;
158 mr->parallaxMinLayers = minL;
159 mr->parallaxMaxLayers = maxL;
160}
161
162float Renderable3D::getParallaxScale() { return meshRenderer()->parallaxScale; }
163
164float Renderable3D::getParallaxMinLayers() { return meshRenderer()->parallaxMinLayers; }
165
166float Renderable3D::getParallaxMaxLayers() { return meshRenderer()->parallaxMaxLayers; }
167
168void Renderable3D::setVisible(bool visible) { meshRenderer()->visible = visible; }
169
171 meshRenderer()->reflectionCaptureMask = static_cast<uint32_t>(mask);
172}
173
174int Renderable3D::getReflectionCaptureMask() { return static_cast<int>(meshRenderer()->reflectionCaptureMask); }
175
176void Renderable3D::setReceiveLight(bool receive) { meshRenderer()->receiveLight = receive; }
177
178void Renderable3D::setCastShadow(bool cast) { meshRenderer()->castShadow = cast; }
179
180void Renderable3D::setReceiveShadow(bool receive) { meshRenderer()->receiveShadow = receive; }
181
182void Renderable3D::setCastOcclusion(bool cast) { meshRenderer()->castOcclusion = cast; }
183
184bool Renderable3D::getCastOcclusion() { return meshRenderer()->castOcclusion; }
185
186void Renderable3D::setCamera(Camera3D* camera) { meshRenderer()->camera = camera; }
187
188void Renderable3D::setMeshLod(int index, Mesh* mesh, float switchDistance) {
189 auto mr = meshRenderer();
190 if (index < 0 || index >= MeshRenderer::kMaxLodLevels) return;
191 mr->lodMeshes[index] = mesh;
192 if (index > 0) mr->lodDistances[index - 1] = switchDistance;
193 if (mesh) {
194 if (mr->lodCount < index + 1) mr->lodCount = index + 1;
195 } else if (index + 1 == mr->lodCount) {
196 while (mr->lodCount > 0 && !mr->lodMeshes[mr->lodCount - 1]) --mr->lodCount;
197 }
198 // Keep primary mesh in sync with LOD0 when set.
199 if (index == 0 && mesh) mr->mesh = mesh;
200}
201
203 float& secondaryWeight) const {
204 primary = lodLevelForDistance(distance);
205 secondary = -1;
206 secondaryWeight = 0.f;
207 if (lodFadeMode == 0 || lodCount <= 0) return;
211 secondaryWeight = std::clamp(lodAnimatedProgress, 0.f, 1.f);
212 if (primary == secondary || secondaryWeight >= 1.f) {
213 primary = secondary;
214 secondary = -1;
215 secondaryWeight = 0.f;
216 }
217 return;
218 }
219 for (int level = 0; level < lodCount; ++level) {
220 const float boundary = level + 1 < lodCount ? lodDistances[level] : lodCullDistance;
221 if (!(boundary > 0.f)) continue;
222 const float start = level == 0 ? 0.f : lodDistances[level - 1];
223 const float width = (boundary - start) * std::clamp(lodFadeWidths[level], 0.f, 1.f);
224 if (width > 0.f && distance >= boundary - width && distance < boundary) {
225 primary = level;
226 secondary = level + 1 < lodCount ? level + 1 : -1;
227 secondaryWeight = std::clamp((distance - (boundary - width)) / width, 0.f, 1.f);
228 return;
229 }
230 }
231}
232
234 meshRenderer()->lodCullDistance = std::isfinite(distance) && distance > 0.f ? distance : 0.f;
235}
236
238 auto mr = meshRenderer();
239 mr->lodCount = 0;
240 for (int i = 0; i < MeshRenderer::kMaxLodLevels; ++i) mr->lodMeshes[i] = nullptr;
241}
242
243int Renderable3D::getMeshLodCount() { return meshRenderer()->lodCount; }
244
245int Renderable3D::getMeshLodLevelAtDistance(float distance) { return meshRenderer()->lodLevelForDistance(distance); }
246
247
248Result<void> Renderable3D::setMeshLodRendererState(int index, int skinQuality, int shadowCastingMode,
249 bool receiveShadows, int motionVectorMode,
250 bool skinnedMotionVectors, int lightProbeUsage,
251 int reflectionProbeUsage) {
252 const bool validSkin = skinQuality == 0 || skinQuality == 1 || skinQuality == 2 || skinQuality == 4;
253 const bool validLight = lightProbeUsage == 0 || lightProbeUsage == 1 || lightProbeUsage == 2 ||
254 lightProbeUsage == 4;
255 if (index < 0 || index >= MeshRenderer::kMaxLodLevels || !validSkin || shadowCastingMode < 0 ||
256 shadowCastingMode > 3 || motionVectorMode < 0 || motionVectorMode > 2 || !validLight ||
257 reflectionProbeUsage < 0 || reflectionProbeUsage > 2)
259 "mesh LOD renderer state is invalid", "graphics.renderable3d.lod"));
260 auto& state = meshRenderer()->lodRendererStates[index];
261 state.configured = true;
262 state.skinQuality = skinQuality;
263 state.shadowCastingMode = shadowCastingMode;
264 state.receiveShadows = receiveShadows;
265 state.motionVectorMode = motionVectorMode;
266 state.skinnedMotionVectors = skinnedMotionVectors;
267 state.lightProbeUsage = lightProbeUsage;
268 state.reflectionProbeUsage = reflectionProbeUsage;
269 return Result<void>::success();
270}
271
273 if (index < 0 || index >= MeshRenderer::kMaxLodLevels || !std::isfinite(width) || width < 0.f || width > 1.f)
275 "mesh LOD fade width is invalid", "graphics.renderable3d.lod"));
276 meshRenderer()->lodFadeWidths[index] = width;
277 return Result<void>::success();
278}
279
281 if (mode < 0 || mode > 2 || !std::isfinite(duration) || duration <= 0.f || (animate && mode == 0))
283 "mesh LOD fade policy is invalid", "graphics.renderable3d.lod"));
284 auto mr = meshRenderer();
285 mr->lodFadeMode = mode;mr->lodAnimateCrossFading = animate;mr->lodCrossFadeDuration = duration;
286 mr->lodAnimatedCurrent = -2;mr->lodAnimatedPrevious = -2;mr->lodAnimatedProgress = 1.f;
287 return Result<void>::success();
288}
289
291 auto mr = meshRenderer();
292 if (index < 0 || index >= mr->lodCount || field < 0 || field > 6) return -1;
293 const auto& state = mr->lodRendererStates[index];
294 switch (field) {
295 case 0: return state.skinQuality;
296 case 1: return state.shadowCastingMode;
297 case 2: return state.receiveShadows ? 1 : 0;
298 case 3: return state.motionVectorMode;
299 case 4: return state.skinnedMotionVectors ? 1 : 0;
300 case 5: return state.lightProbeUsage;
301 case 6: return state.reflectionProbeUsage;
302 default: return -1;
303 }
304}
305
307 if (!std::isfinite(distance) || distance < 0.f || !std::isfinite(dt) || dt < 0.f)
309 "mesh LOD transition inputs are invalid", "graphics.renderable3d.lod"));
310 auto mr = meshRenderer();const int target = mr->lodLevelForDistance(distance);
311 if (mr->lodAnimatedCurrent == -2) {mr->lodAnimatedCurrent=target;mr->lodAnimatedProgress=1.f;return Result<void>::success();}
312 if (target != mr->lodAnimatedCurrent) {
313 mr->lodAnimatedPrevious=mr->lodAnimatedCurrent;mr->lodAnimatedCurrent=target;mr->lodAnimatedProgress=0.f;
314 }
315 if (mr->lodAnimatedPrevious != -2 && mr->lodAnimatedPrevious != mr->lodAnimatedCurrent) {
316 mr->lodAnimatedProgress=std::min(1.f,mr->lodAnimatedProgress+dt/mr->lodCrossFadeDuration);
317 if (mr->lodAnimatedProgress>=1.f)mr->lodAnimatedPrevious=-2;
318 }
319 return Result<void>::success();
320}
321
323 int primary=-1,secondary=-1;float weight=0.f;meshRenderer()->lodBlendForDistance(distance,primary,secondary,weight);
324 return secondary;
325}
326
328 int primary=-1,secondary=-1;float weight=0.f;meshRenderer()->lodBlendForDistance(distance,primary,secondary,weight);
329 return weight;
330}
331
332float Renderable3D::getMeshLodCullDistance() { return meshRenderer()->lodCullDistance; }
333
335 EV_PARAM_CHECK(layer >= 0, "layer must be in [0,31]");
336 EV_PARAM_CHECK(layer < 32, "layer must be in [0,31]");
337 meshRenderer()->layer = layer;
338}
339
340int Renderable3D::getLayer() { return meshRenderer()->layer; }
341
343 if (!std::isfinite(r) || !std::isfinite(g) || !std::isfinite(b) || r < 0.f || g < 0.f || b < 0.f)
345 "custom light probe irradiance must be finite and nonnegative", "graphics.renderable3d.lightProbe"));
346 meshRenderer()->customLightProbe = true;
347 meshRenderer()->customLightProbeSh = {};
348 constexpr float kY00 = 0.2820947918f;
349 meshRenderer()->customLightProbeSh[0] = glm::vec4(r / kY00, g / kY00, b / kY00, 0.f);
350 return Result<void>::success();
351}
352
353Result<void> Renderable3D::setCustomLightProbeCoefficient(int coefficient, float r, float g, float b) {
354 if (coefficient < 0 || coefficient >= 9 || !std::isfinite(r) || !std::isfinite(g) || !std::isfinite(b))
356 "custom light probe coefficient requires index 0..8 and finite RGB", "graphics.renderable3d.lightProbe"));
357 meshRenderer()->customLightProbe = true;
358 meshRenderer()->customLightProbeSh[static_cast<size_t>(coefficient)] = glm::vec4(r, g, b, 0.f);
359 return Result<void>::success();
360}
361
363 meshRenderer()->customLightProbe = false;
364 meshRenderer()->customLightProbeSh = {};
365}
366
367} // namespace eve::graphics
LogicalId target
Duration start
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
float duration
#define EV_PARAM_CHECK(cond,...)
Validate a function parameter / public API precondition.
Definition Assert.h:30
int mask
int priority
tensor::Graph g
Definition GpuGraph.cpp:7
float camera[2]
double r
int secondary
std::uint32_t width
std::array< float, 3 > scale
std::string name
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
float distance
float roughness
float metallic
int level
TileLayer * layer
float t
Renderable3D::MeshRenderer * mr
Mesh * mesh
int lightProbeUsage
Shader * shader
bool hair
Material * material
CommandLogBoundary boundary
Anchor rule, see above.
bool visible
uint32_t index
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
EVENGINE_API_BACKENDS public API.
Packages shading method + surface parameters into one attachable asset.
Definition Material.h:35
GPU mesh handle (+ optional CPU morph targets).
Definition Mesh.h:25
void setNormalTexture(Texture *texture)
void setCamera(Camera3D *camera)
void setReflectionCaptureMask(int mask)
Set the bit mask used to include this object in reflection-probe captures.
int getMeshLodLevelAtDistance(float distance)
void setPartSortPriority(int index, int priority)
Override transparent sorting for one part without mutating its shared Material.
std::string getPartName(int index)
Material * getPartMaterial(int index)
Result< void > advanceMeshLodTransition(float distance, float dt)
Advance an animated transition using caller-injected distance and dt.
void setRotation(float yaw, float pitch, float roll)
void setLayer(int layer)
Assign this renderable to a camera-culling layer in [0,31].
void setHeightTexture(Texture *texture)
Height map for parallax (R channel; white = raised). nullptr disables sampling.
void setPart(int index, const std::string &name, Mesh *mesh, Material *material)
Bind a named mesh+material part (e.g. Assimp submesh / body region). index 0..kMaxParts-1....
void setTexCellBomb(float cellScale, float strength, float rotAmount=1.f)
Texture cell bombing — random per-cell UV offset/rotation blended across a 2×2 neighborhood to hide t...
Mesh * getMesh()
Main (non-part) mesh attached via setMesh; nullptr when unset.
void setTint(float r, float g, float b, float a=1.f)
void clearCustomLightProbe()
Clear the custom diffuse probe and restore the camera ambient value.
void setMetallic(float metallic)
void setTexture(Texture *texture)
void setMeshLodCullDistance(float distance)
Set the distance that culls the whole mesh LOD chain; zero disables culling.
void setReceiveLight(bool receive)
float getMeshLodSecondaryWeightAtDistance(float distance)
Return secondary LOD weight in [0,1].
void setShader(Shader *shader)
int getReflectionCaptureMask()
Return the reflection-probe capture bit mask.
Result< void > setMeshLodFadePolicy(int mode, bool animate, float duration)
Configure Unity LODFadeMode and deterministic time-driven transitions.
void setMaterial(Material *material)
Attach a Material that packages shading method + surface params.
void setPackedNormalMask(bool enabled)
Enable RG normal XY, B AO and A smoothness interpretation for the normal texture.
void setParallax(float scale, float minLayers=8.f, float maxLayers=32.f)
Parallax occlusion mapping. scale 0 disables (default). Typical scale 0.02..0.08. Requires a height t...
void setPosition(float x, float y, float z)
void clearPartSortPriority(int index)
Clear a part's per-instance sort override and use its Material priority.
void setXRayShader(Shader *shader)
Attach an X-ray mesh shader (see Shader::setXray) for occluded silhouettes.
Result< void > setCustomLightProbe(float r, float g, float b)
Supply baked diffuse irradiance for LOD levels using CustomProvided light probes.
int getMeshLodRendererState(int index, int field)
Return one LOD renderer policy field, or -1 for an invalid level/field.
float getMeshLodCullDistance()
Return the mesh LOD culling distance; zero means disabled.
void setXRayHighlight(bool on)
When true, this entity is an X-ray target: its G-buffer pixels are replaced by occluders and it is re...
int getPartSortPriority(int index)
Return the effective per-part or Material transparent sort priority.
int getMeshLodSecondaryLevelAtDistance(float distance)
Return secondary LOD selected for a fade, or -1 for cull/no secondary.
Mesh * getPartMesh(int index)
Result< void > setMeshLodRendererState(int index, int skinQuality, int shadowCastingMode, bool receiveShadows, int motionVectorMode, bool skinnedMotionVectors, int lightProbeUsage, int reflectionProbeUsage)
Set one LOD's Pcg-compatible renderer policy using Unity enum numeric values.
int getLayer()
Return this renderable's camera-culling layer.
void setMeshLod(int index, Mesh *mesh, float switchDistance=0.f)
Configure geometric LOD. index 0 = highest detail. For index > 0, switchDistance is the camera distan...
void setRoughness(float roughness)
Result< void > setMeshLodFadeWidth(int index, float width)
Configure per-level distance fade width.
void setScale(float sx, float sy, float sz)
void setReceiveShadow(bool receive)
void setVisible(bool visible)
Result< void > setCustomLightProbeCoefficient(int coefficient, float r, float g, float b)
Set one L0..L2 RGB spherical-harmonic coefficient for CustomProvided mode.
Custom GPU program.
Definition Shader.h:39
GPU texture created via Graphics::newTexture. Owns GPU resources through an opaque backend handle.
Definition Texture.h:18
卡牌游戏 UI 工具模块:工厂 + 脚本绑定入口。 功能参考 ycarowr/UiCard:扇形手牌布局、抽牌/洗牌、悬浮放大、拖拽到落牌区、 敌方手牌(背面/偷看)、费用不足置灰,以及可实时调节的布局...
Definition Animation.h:25
bool enabled
One mesh + material slot on a multi-part model (Assimp mesh / body region). When Material* is null,...
Definition Material.h:330
void lodBlendForDistance(float distance, int &primary, int &secondary, float &secondaryWeight) const
Select primary/secondary levels and secondary weight for the active fade policy.
int lodLevelForDistance(float distance) const
Lod level for distance.
int lodCount
Optional geometric LOD. When lodCount > 0, lodMeshes[0..lodCount) are used instead of mesh based on c...
float lodCullDistance
Distance beyond which the complete LOD chain is culled; zero disables.