mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-17 17:43:52 +00:00
refactor: name M2 renderer magic constants, add why-comments
- Name portal spin wrap value as kTwoPi constant - Name particle animTime wrap as kParticleWrapMs (3333ms) with why-comment: covers longest known emission cycle (~3s torch/campfire) while preventing float precision loss over hours of runtime - Add FBlock interpolation documentation: explain what FBlocks are (particle lifetime curves) and note that float/vec3 variants share identical logic and must be updated together
This commit is contained in:
parent
6dfac314ee
commit
4574d203b5
1 changed files with 14 additions and 6 deletions
|
|
@ -1974,12 +1974,13 @@ void M2Renderer::update(float deltaTime, const glm::vec3& cameraPos, const glm::
|
||||||
|
|
||||||
// --- Spin instance portals ---
|
// --- Spin instance portals ---
|
||||||
static constexpr float PORTAL_SPIN_SPEED = 1.2f; // radians/sec
|
static constexpr float PORTAL_SPIN_SPEED = 1.2f; // radians/sec
|
||||||
|
static constexpr float kTwoPi = 6.2831853f;
|
||||||
for (size_t idx : portalInstanceIndices_) {
|
for (size_t idx : portalInstanceIndices_) {
|
||||||
if (idx >= instances.size()) continue;
|
if (idx >= instances.size()) continue;
|
||||||
auto& inst = instances[idx];
|
auto& inst = instances[idx];
|
||||||
inst.portalSpinAngle += PORTAL_SPIN_SPEED * deltaTime;
|
inst.portalSpinAngle += PORTAL_SPIN_SPEED * deltaTime;
|
||||||
if (inst.portalSpinAngle > 6.2831853f)
|
if (inst.portalSpinAngle > kTwoPi)
|
||||||
inst.portalSpinAngle -= 6.2831853f;
|
inst.portalSpinAngle -= kTwoPi;
|
||||||
inst.rotation.z = inst.portalSpinAngle;
|
inst.rotation.z = inst.portalSpinAngle;
|
||||||
inst.updateModelMatrix();
|
inst.updateModelMatrix();
|
||||||
}
|
}
|
||||||
|
|
@ -1990,13 +1991,17 @@ void M2Renderer::update(float deltaTime, const glm::vec3& cameraPos, const glm::
|
||||||
for (auto& instance : instances) {
|
for (auto& instance : instances) {
|
||||||
instance.animTime += dtMs;
|
instance.animTime += dtMs;
|
||||||
}
|
}
|
||||||
// Wrap animTime for particle-only instances so emission rate tracks keep looping
|
// Wrap animTime for particle-only instances so emission rate tracks keep looping.
|
||||||
|
// 3333ms chosen as a safe wrap period: long enough to cover the longest known M2
|
||||||
|
// particle emission cycle (~3s for torch/campfire effects) while preventing float
|
||||||
|
// precision loss that accumulates over hours of runtime.
|
||||||
|
static constexpr float kParticleWrapMs = 3333.0f;
|
||||||
for (size_t idx : particleOnlyInstanceIndices_) {
|
for (size_t idx : particleOnlyInstanceIndices_) {
|
||||||
if (idx >= instances.size()) continue;
|
if (idx >= instances.size()) continue;
|
||||||
auto& instance = instances[idx];
|
auto& instance = instances[idx];
|
||||||
// Use iterative subtraction instead of fmod() to preserve precision
|
// Use iterative subtraction instead of fmod() to preserve precision
|
||||||
while (instance.animTime > 3333.0f) {
|
while (instance.animTime > kParticleWrapMs) {
|
||||||
instance.animTime -= 3333.0f;
|
instance.animTime -= kParticleWrapMs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3155,11 +3160,14 @@ float M2Renderer::interpFloat(const pipeline::M2AnimationTrack& track, float ani
|
||||||
return glm::mix(keys.floatValues[i0], keys.floatValues[i1], frac);
|
return glm::mix(keys.floatValues[i0], keys.floatValues[i1], frac);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Interpolate an M2 FBlock (particle lifetime curve) at a given life ratio [0..1].
|
||||||
|
// FBlocks store per-lifetime keyframes for particle color, alpha, and scale.
|
||||||
|
// NOTE: interpFBlockFloat and interpFBlockVec3 share identical interpolation logic —
|
||||||
|
// if you fix a bug in one, update the other to match.
|
||||||
float M2Renderer::interpFBlockFloat(const pipeline::M2FBlock& fb, float lifeRatio) {
|
float M2Renderer::interpFBlockFloat(const pipeline::M2FBlock& fb, float lifeRatio) {
|
||||||
if (fb.floatValues.empty()) return 1.0f;
|
if (fb.floatValues.empty()) return 1.0f;
|
||||||
if (fb.floatValues.size() == 1 || fb.timestamps.empty()) return fb.floatValues[0];
|
if (fb.floatValues.size() == 1 || fb.timestamps.empty()) return fb.floatValues[0];
|
||||||
lifeRatio = glm::clamp(lifeRatio, 0.0f, 1.0f);
|
lifeRatio = glm::clamp(lifeRatio, 0.0f, 1.0f);
|
||||||
// Find surrounding timestamps
|
|
||||||
for (size_t i = 0; i < fb.timestamps.size() - 1; i++) {
|
for (size_t i = 0; i < fb.timestamps.size() - 1; i++) {
|
||||||
if (lifeRatio <= fb.timestamps[i + 1]) {
|
if (lifeRatio <= fb.timestamps[i + 1]) {
|
||||||
float t0 = fb.timestamps[i];
|
float t0 = fb.timestamps[i];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue