metaforce/Runtime/Graphics/CVertexMorphEffect.cpp

47 lines
1.8 KiB
C++

#include "Runtime/Graphics/CVertexMorphEffect.hpp"
#include "Runtime/Character/CSkinRules.hpp"
#include "Runtime/Graphics/CSkinnedModel.hpp"
namespace metaforce {
CVertexMorphEffect::CVertexMorphEffect(const zeus::CUnitVector3f& dir, const zeus::CVector3f& pos, float duration,
float diagExtent, CRandom16& random)
: x0_dir(dir), xc_pos(pos), x18_duration(duration), x20_diagExtent(diagExtent), x24_random(random) {}
void CVertexMorphEffect::MorphVertices(SSkinningWorkspace& workspace, TConstVectorRef averagedNormals,
TLockedToken<CSkinRules>& skinRules, const CPoseAsTransforms& pose,
u32 vertexCount) {
if (x28_indices.empty()) {
std::vector<zeus::CVector3f> normalsOut;
normalsOut.reserve(vertexCount);
skinRules->BuildNormals(averagedNormals, &normalsOut);
for (int i = 0; i < vertexCount; ++i) {
float dist = normalsOut[i].dot(x0_dir);
if (dist > 0.5f) {
x28_indices.emplace_back(i);
const auto vert = workspace.m_vertexWorkspace[i];
const auto length = vert.x() + vert.y() + vert.z();
x38_floats.emplace_back((length - std::trunc(length)) * (dist - 0.5f));
}
}
}
for (int i = 0; i < x28_indices.size(); ++i) {
const auto scale = x1c_elapsed / x18_duration;
workspace.m_vertexWorkspace[x28_indices[i]] += scale * x20_diagExtent * x38_floats[i] * x0_dir;
}
}
void CVertexMorphEffect::Reset(const zeus::CVector3f& dir, const zeus::CVector3f& pos, float duration) {
x0_dir = dir;
xc_pos = pos;
x18_duration = duration;
x1c_elapsed = 0.f;
x28_indices.clear();
x38_floats.clear();
}
void CVertexMorphEffect::Update(float dt) { x1c_elapsed = std::min(x1c_elapsed + dt, x18_duration); }
} // namespace metaforce