Implement CVertexMorphEffect & CSkinnedModelWithAvgNormals (prev. CMorphableSkinnedModel)

This commit is contained in:
Luke Street 2022-03-10 18:56:50 -05:00
parent ddc34e3a0c
commit d7dbec5be0
13 changed files with 101 additions and 72 deletions

View File

@ -41,7 +41,7 @@ void CAnimData::InitializeCache() {}
CAnimData::CAnimData(CAssetId id, const CCharacterInfo& character, int defaultAnim, int charIdx, bool loop, CAnimData::CAnimData(CAssetId id, const CCharacterInfo& character, int defaultAnim, int charIdx, bool loop,
TLockedToken<CCharLayoutInfo> layout, TToken<CSkinnedModel> model, TLockedToken<CCharLayoutInfo> layout, TToken<CSkinnedModel> model,
const std::optional<TToken<CMorphableSkinnedModel>>& iceModel, const std::optional<TToken<CSkinnedModelWithAvgNormals>>& iceModel,
const std::weak_ptr<CAnimSysContext>& ctx, std::shared_ptr<CAnimationManager> animMgr, const std::weak_ptr<CAnimSysContext>& ctx, std::shared_ptr<CAnimationManager> animMgr,
std::shared_ptr<CTransitionManager> transMgr, TLockedToken<CCharacterFactory> charFactory) std::shared_ptr<CTransitionManager> transMgr, TLockedToken<CCharacterFactory> charFactory)
: x0_charFactory(charFactory) : x0_charFactory(charFactory)
@ -543,20 +543,19 @@ void CAnimData::RecalcPoseBuilder(const CCharAnimTime* time) {
void CAnimData::RenderAuxiliary(const zeus::CFrustum& frustum) const { x120_particleDB.AddToRendererClipped(frustum); } void CAnimData::RenderAuxiliary(const zeus::CFrustum& frustum) const { x120_particleDB.AddToRendererClipped(frustum); }
void CAnimData::Render(CSkinnedModel& model, const CModelFlags& drawFlags, void CAnimData::Render(CSkinnedModel& model, const CModelFlags& drawFlags, CVertexMorphEffect* morphEffect,
const std::optional<CVertexMorphEffect>& morphEffect, TVectorRef morphMagnitudes) { TConstVectorRef averagedNormals) {
SetupRender(model, morphEffect, morphMagnitudes); SetupRender(model, morphEffect, averagedNormals);
DrawSkinnedModel(model, drawFlags); DrawSkinnedModel(model, drawFlags);
} }
void CAnimData::SetupRender(CSkinnedModel& model, const std::optional<CVertexMorphEffect>& morphEffect, void CAnimData::SetupRender(CSkinnedModel& model, CVertexMorphEffect* morphEffect, TConstVectorRef averagedNormals) {
TVectorRef morphMagnitudes) {
OPTICK_EVENT(); OPTICK_EVENT();
if (!x220_30_poseBuilt) { if (!x220_30_poseBuilt) {
x2fc_poseBuilder.BuildNoScale(x224_pose); x2fc_poseBuilder.BuildNoScale(x224_pose);
x220_30_poseBuilt = true; x220_30_poseBuilt = true;
} }
PoseSkinnedModel(model, x224_pose, morphEffect, morphMagnitudes); PoseSkinnedModel(model, x224_pose, morphEffect, averagedNormals);
} }
void CAnimData::DrawSkinnedModel(CSkinnedModel& model, const CModelFlags& flags) { void CAnimData::DrawSkinnedModel(CSkinnedModel& model, const CModelFlags& flags) {
@ -805,9 +804,9 @@ void CAnimData::SetInfraModel(const TLockedToken<CModel>& model, const TLockedTo
xf8_infraModel = std::make_shared<CSkinnedModel>(model, skinRules, xd8_modelData->GetLayoutInfo()); xf8_infraModel = std::make_shared<CSkinnedModel>(model, skinRules, xd8_modelData->GetLayoutInfo());
} }
void CAnimData::PoseSkinnedModel(CSkinnedModel& model, const CPoseAsTransforms& pose, void CAnimData::PoseSkinnedModel(CSkinnedModel& model, const CPoseAsTransforms& pose, CVertexMorphEffect* morphEffect,
const std::optional<CVertexMorphEffect>& morphEffect, TVectorRef morphMagnitudes) { TConstVectorRef averagedNormals) {
model.Calculate(pose, morphEffect, morphMagnitudes, nullptr); model.Calculate(pose, morphEffect, averagedNormals, nullptr);
} }
void CAnimData::AdvanceParticles(const zeus::CTransform& xf, float dt, const zeus::CVector3f& vec, void CAnimData::AdvanceParticles(const zeus::CTransform& xf, float dt, const zeus::CVector3f& vec,

View File

@ -68,7 +68,7 @@ class CCharAnimTime;
class CCharLayoutInfo; class CCharLayoutInfo;
class CInt32POINode; class CInt32POINode;
class CModel; class CModel;
class CMorphableSkinnedModel; class CSkinnedModelWithAvgNormals;
class CParticlePOINode; class CParticlePOINode;
class CPrimitive; class CPrimitive;
class CRandom16; class CRandom16;
@ -102,7 +102,7 @@ private:
CCharacterInfo xc_charInfo; CCharacterInfo xc_charInfo;
TLockedToken<CCharLayoutInfo> xcc_layoutData; TLockedToken<CCharLayoutInfo> xcc_layoutData;
TLockedToken<CSkinnedModel> xd8_modelData; TLockedToken<CSkinnedModel> xd8_modelData;
TLockedToken<CMorphableSkinnedModel> xe4_iceModelData; TLockedToken<CSkinnedModelWithAvgNormals> xe4_iceModelData;
std::shared_ptr<CSkinnedModel> xf4_xrayModel; std::shared_ptr<CSkinnedModel> xf4_xrayModel;
std::shared_ptr<CSkinnedModel> xf8_infraModel; std::shared_ptr<CSkinnedModel> xf8_infraModel;
std::shared_ptr<CAnimSysContext> xfc_animCtx; std::shared_ptr<CAnimSysContext> xfc_animCtx;
@ -147,9 +147,9 @@ private:
public: public:
CAnimData(CAssetId, const CCharacterInfo& character, int defaultAnim, int charIdx, bool loop, CAnimData(CAssetId, const CCharacterInfo& character, int defaultAnim, int charIdx, bool loop,
TLockedToken<CCharLayoutInfo> layout, TToken<CSkinnedModel> model, TLockedToken<CCharLayoutInfo> layout, TToken<CSkinnedModel> model,
const std::optional<TToken<CMorphableSkinnedModel>>& iceModel, const std::weak_ptr<CAnimSysContext>& ctx, const std::optional<TToken<CSkinnedModelWithAvgNormals>>& iceModel,
std::shared_ptr<CAnimationManager> animMgr, std::shared_ptr<CTransitionManager> transMgr, const std::weak_ptr<CAnimSysContext>& ctx, std::shared_ptr<CAnimationManager> animMgr,
TLockedToken<CCharacterFactory> charFactory); std::shared_ptr<CTransitionManager> transMgr, TLockedToken<CCharacterFactory> charFactory);
void SetParticleEffectState(std::string_view effectName, bool active, CStateManager& mgr); void SetParticleEffectState(std::string_view effectName, bool active, CStateManager& mgr);
void InitializeEffects(CStateManager& mgr, TAreaId aId, const zeus::CVector3f& scale); void InitializeEffects(CStateManager& mgr, TAreaId aId, const zeus::CVector3f& scale);
@ -194,10 +194,9 @@ public:
std::shared_ptr<CAnimationManager> GetAnimationManager() const; std::shared_ptr<CAnimationManager> GetAnimationManager() const;
void RecalcPoseBuilder(const CCharAnimTime* time); void RecalcPoseBuilder(const CCharAnimTime* time);
void RenderAuxiliary(const zeus::CFrustum& frustum) const; void RenderAuxiliary(const zeus::CFrustum& frustum) const;
void Render(CSkinnedModel& model, const CModelFlags& drawFlags, const std::optional<CVertexMorphEffect>& morphEffect, void Render(CSkinnedModel& model, const CModelFlags& drawFlags, CVertexMorphEffect* morphEffect,
TVectorRef morphMagnitudes); TConstVectorRef averagedNormals);
void SetupRender(CSkinnedModel& model, const std::optional<CVertexMorphEffect>& morphEffect, void SetupRender(CSkinnedModel& model, CVertexMorphEffect* morphEffect, TConstVectorRef averagedNormals);
TVectorRef morphMagnitudes);
static void DrawSkinnedModel(CSkinnedModel& model, const CModelFlags& flags); static void DrawSkinnedModel(CSkinnedModel& model, const CModelFlags& flags);
void PreRender(); void PreRender();
void BuildPose(); void BuildPose();
@ -218,8 +217,8 @@ public:
TLockedToken<CSkinnedModel>& GetModelData() { return xd8_modelData; } TLockedToken<CSkinnedModel>& GetModelData() { return xd8_modelData; }
const TLockedToken<CSkinnedModel>& GetModelData() const { return xd8_modelData; } const TLockedToken<CSkinnedModel>& GetModelData() const { return xd8_modelData; }
static void PoseSkinnedModel(CSkinnedModel& model, const CPoseAsTransforms& pose, static void PoseSkinnedModel(CSkinnedModel& model, const CPoseAsTransforms& pose, CVertexMorphEffect* morphEffect,
const std::optional<CVertexMorphEffect>& morphEffect, TVectorRef morphMagnitudes); TConstVectorRef averagedNormals);
void AdvanceParticles(const zeus::CTransform& xf, float dt, const zeus::CVector3f&, CStateManager& stateMgr); void AdvanceParticles(const zeus::CTransform& xf, float dt, const zeus::CVector3f&, CStateManager& stateMgr);
float GetAverageVelocity(int animIn) const; float GetAverageVelocity(int animIn) const;
void ResetPOILists(); void ResetPOILists();
@ -243,8 +242,8 @@ public:
s32 GetCharacterIndex() const { return x204_charIdx; } s32 GetCharacterIndex() const { return x204_charIdx; }
u16 GetDefaultAnimation() const { return x208_defaultAnim; } u16 GetDefaultAnimation() const { return x208_defaultAnim; }
TLockedToken<CMorphableSkinnedModel>& GetIceModel() { return xe4_iceModelData; } TLockedToken<CSkinnedModelWithAvgNormals>& GetIceModel() { return xe4_iceModelData; }
const TLockedToken<CMorphableSkinnedModel>& GetIceModel() const { return xe4_iceModelData; } const TLockedToken<CSkinnedModelWithAvgNormals>& GetIceModel() const { return xe4_iceModelData; }
void SetParticleLightIdx(s32 idx) { x21c_particleLightIdx = idx; } void SetParticleLightIdx(s32 idx) { x21c_particleLightIdx = idx; }
void MarkPoseDirty() { x220_30_poseBuilt = false; } void MarkPoseDirty() { x220_30_poseBuilt = false; }

View File

@ -27,7 +27,7 @@ CFactoryFnReturn CCharacterFactory::CDummyFactory::Build(const SObjectTag& tag,
return TToken<CSkinnedModel>::GetIObjObjectFor(std::make_unique<CSkinnedModel>( return TToken<CSkinnedModel>::GetIObjObjectFor(std::make_unique<CSkinnedModel>(
*g_SimplePool, charInfo.GetModelId(), charInfo.GetSkinRulesId(), charInfo.GetCharLayoutInfoId())); *g_SimplePool, charInfo.GetModelId(), charInfo.GetSkinRulesId(), charInfo.GetCharLayoutInfoId()));
case 1: case 1:
return TToken<CSkinnedModel>::GetIObjObjectFor(std::make_unique<CMorphableSkinnedModel>( return TToken<CSkinnedModel>::GetIObjObjectFor(std::make_unique<CSkinnedModelWithAvgNormals>(
*g_SimplePool, charInfo.GetIceModelId(), charInfo.GetIceSkinRulesId(), charInfo.GetCharLayoutInfoId())); *g_SimplePool, charInfo.GetIceModelId(), charInfo.GetIceSkinRulesId(), charInfo.GetCharLayoutInfoId()));
default: default:
break; break;
@ -82,7 +82,7 @@ std::unique_ptr<CAnimData> CCharacterFactory::CreateCharacter(int charIdx, bool
TToken<CSkinnedModel> skinnedModel = x70_cacheResPool.GetObj({FourCC(0u), charInfo.GetModelId()}, charParm); TToken<CSkinnedModel> skinnedModel = x70_cacheResPool.GetObj({FourCC(0u), charInfo.GetModelId()}, charParm);
std::optional<TToken<CMorphableSkinnedModel>> iceModel; std::optional<TToken<CSkinnedModelWithAvgNormals>> iceModel;
if (charInfo.GetIceModelId().IsValid() && charInfo.GetIceSkinRulesId().IsValid()) { if (charInfo.GetIceModelId().IsValid() && charInfo.GetIceSkinRulesId().IsValid()) {
iceModel.emplace(x70_cacheResPool.GetObj({FourCC(1u), charInfo.GetIceModelId()}, charParm)); iceModel.emplace(x70_cacheResPool.GetObj({FourCC(1u), charInfo.GetIceModelId()}, charParm));
} }

View File

@ -293,7 +293,7 @@ void CModelData::RenderThermal(const zeus::CTransform& xf, const zeus::CColor& m
if (x10_animData) { if (x10_animData) {
CSkinnedModel& model = PickAnimatedModel(EWhichModel::ThermalHot); CSkinnedModel& model = PickAnimatedModel(EWhichModel::ThermalHot);
x10_animData->SetupRender(model, {}, nullptr); x10_animData->SetupRender(model, nullptr, nullptr);
ThermalDraw(mulColor, addColor, flags); ThermalDraw(mulColor, addColor, flags);
} else { } else {
auto& model = PickStaticModel(EWhichModel::ThermalHot); auto& model = PickStaticModel(EWhichModel::ThermalHot);
@ -342,7 +342,7 @@ void CModelData::Render(EWhichModel which, const zeus::CTransform& xf, const CAc
} }
if (x10_animData) { if (x10_animData) {
x10_animData->Render(PickAnimatedModel(which), drawFlags, {}, nullptr); x10_animData->Render(PickAnimatedModel(which), drawFlags, nullptr, nullptr);
} else { } else {
// TODO supposed to be optional_object? // TODO supposed to be optional_object?
if (x1c_normalModel) { if (x1c_normalModel) {
@ -387,7 +387,7 @@ void CModelData::MultiLightingDraw(EWhichModel which, const zeus::CTransform& xf
CGraphics::SetModelMatrix(xf * zeus::CTransform::Scale(x0_scale)); CGraphics::SetModelMatrix(xf * zeus::CTransform::Scale(x0_scale));
if (x10_animData) { if (x10_animData) {
auto& skinnedModel = PickAnimatedModel(which); auto& skinnedModel = PickAnimatedModel(which);
x10_animData->SetupRender(skinnedModel, {}, nullptr); x10_animData->SetupRender(skinnedModel, nullptr, nullptr);
model = skinnedModel.GetModel().GetObj(); model = skinnedModel.GetModel().GetObj();
skinnedModel.DoDrawCallback(callback); skinnedModel.DoDrawCallback(callback);
} else { } else {
@ -407,7 +407,7 @@ void CModelData::MultiPassDraw(EWhichModel which, const zeus::CTransform& xf, co
} }
if (x10_animData) { if (x10_animData) {
auto& skinnedModel = PickAnimatedModel(which); auto& skinnedModel = PickAnimatedModel(which);
x10_animData->SetupRender(skinnedModel, {}, nullptr); x10_animData->SetupRender(skinnedModel, nullptr, nullptr);
auto& model = *skinnedModel.GetModel(); auto& model = *skinnedModel.GetModel();
skinnedModel.DoDrawCallback([&](auto positions, auto normals) { skinnedModel.DoDrawCallback([&](auto positions, auto normals) {
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {

View File

@ -36,8 +36,8 @@ void CSkinnedModel::AllocateStorage() {
} }
} }
void CSkinnedModel::Calculate(const CPoseAsTransforms& pose, const std::optional<CVertexMorphEffect>& morphEffect, void CSkinnedModel::Calculate(const CPoseAsTransforms& pose, CVertexMorphEffect* morphEffect,
TConstVectorRef morphMagnitudes, SSkinningWorkspace* workspace) { TConstVectorRef averagedNormals, SSkinningWorkspace* workspace) {
if (workspace == nullptr) { if (workspace == nullptr) {
if (x35_disableWorkspaces) { if (x35_disableWorkspaces) {
x10_skinRules->BuildAccumulatedTransforms(pose, *x1c_layoutInfo); x10_skinRules->BuildAccumulatedTransforms(pose, *x1c_layoutInfo);
@ -52,7 +52,7 @@ void CSkinnedModel::Calculate(const CPoseAsTransforms& pose, const std::optional
x10_skinRules->BuildNormals(x4_model->GetNormals(), &workspace->m_normalWorkspace); x10_skinRules->BuildNormals(x4_model->GetNormals(), &workspace->m_normalWorkspace);
if (morphEffect) { if (morphEffect) {
morphEffect->MorphVertices(*workspace, morphMagnitudes, x10_skinRules, pose); morphEffect->MorphVertices(*workspace, averagedNormals, x10_skinRules, pose, x10_skinRules->GetVertexCount());
} }
if (g_PointGenFunc != nullptr) { if (g_PointGenFunc != nullptr) {
g_PointGenFunc(*workspace); g_PointGenFunc(*workspace);
@ -93,13 +93,13 @@ void CSkinnedModel::DoDrawCallback(const FCustomDraw& func) const {
} }
} }
CMorphableSkinnedModel::CMorphableSkinnedModel(IObjectStore& store, CAssetId model, CAssetId skinRules, CSkinnedModelWithAvgNormals::CSkinnedModelWithAvgNormals(IObjectStore& store, CAssetId model, CAssetId skinRules,
CAssetId layoutInfo) CAssetId layoutInfo)
: CSkinnedModel(store, model, skinRules, layoutInfo) { : CSkinnedModel(store, model, skinRules, layoutInfo) {
const auto vertexCount = GetSkinRules()->GetVertexCount(); const auto vertexCount = GetSkinRules()->GetVertexCount();
const auto& modelPositions = *GetModel()->GetPositions(); const auto& modelPositions = *GetModel()->GetPositions();
x40_morphMagnitudes.resize(vertexCount); x40_averagedNormals.resize(vertexCount);
std::vector<std::pair<zeus::CVector3f, std::list<u32>>> vertMap; std::vector<std::pair<zeus::CVector3f, std::list<u32>>> vertMap;
for (int vertIdx = 0; vertIdx < vertexCount; ++vertIdx) { for (int vertIdx = 0; vertIdx < vertexCount; ++vertIdx) {
const auto curPos = modelPositions[vertIdx]; const auto curPos = modelPositions[vertIdx];
@ -123,7 +123,7 @@ CMorphableSkinnedModel::CMorphableSkinnedModel(IObjectStore& store, CAssetId mod
} }
averagedNormal.normalize(); averagedNormal.normalize();
for (const auto idx : idxs) { for (const auto idx : idxs) {
x40_morphMagnitudes[idx] = averagedNormal; x40_averagedNormals[idx] = averagedNormal;
} }
} }
} }

View File

@ -60,8 +60,11 @@ public:
const TLockedToken<CCharLayoutInfo>& GetLayoutInfo() const { return x1c_layoutInfo; } const TLockedToken<CCharLayoutInfo>& GetLayoutInfo() const { return x1c_layoutInfo; }
void AllocateStorage(); void AllocateStorage();
void Calculate(const CPoseAsTransforms& pose, const std::optional<CVertexMorphEffect>& morphEffect, // Metaforce addition: Originally morphEffect is rstl::optional_object<CVertexMorphEffect>*
TConstVectorRef averagedNormals, SSkinningWorkspace* workspace); // This prevents constructing it as a reference to the held pointer in CPatterned, thus in
// retail it's copied in every invocation of RenderIceModelWithFlags.
void Calculate(const CPoseAsTransforms& pose, CVertexMorphEffect* morphEffect, TConstVectorRef averagedNormals,
SSkinningWorkspace* workspace);
void Draw(TConstVectorRef verts, TConstVectorRef normals, const CModelFlags& drawFlags); void Draw(TConstVectorRef verts, TConstVectorRef normals, const CModelFlags& drawFlags);
void Draw(const CModelFlags& drawFlags); void Draw(const CModelFlags& drawFlags);
void DoDrawCallback(const FCustomDraw& func) const; void DoDrawCallback(const FCustomDraw& func) const;
@ -71,13 +74,12 @@ public:
static FPointGenerator g_PointGenFunc; static FPointGenerator g_PointGenFunc;
}; };
class CMorphableSkinnedModel : public CSkinnedModel { class CSkinnedModelWithAvgNormals : public CSkinnedModel {
std::vector<zeus::CVector3f> x40_morphMagnitudes; // was rstl::auto_ptr<float[]> std::vector<zeus::CVector3f> x40_averagedNormals; // was rstl::auto_ptr<float[]>
public: public:
CMorphableSkinnedModel(IObjectStore& store, CAssetId model, CAssetId skinRules, CAssetId layoutInfo); CSkinnedModelWithAvgNormals(IObjectStore& store, CAssetId model, CAssetId skinRules, CAssetId layoutInfo);
TConstVectorRef GetMorphMagnitudes() const { return &x40_morphMagnitudes; } TConstVectorRef GetAveragedNormals() const { return &x40_averagedNormals; }
TVectorRef GetMorphMagnitudes() { return &x40_morphMagnitudes; }
}; };
} // namespace metaforce } // namespace metaforce

View File

@ -1,15 +1,46 @@
#include "Runtime/Graphics/CVertexMorphEffect.hpp" #include "Runtime/Graphics/CVertexMorphEffect.hpp"
#include "Runtime/Character/CSkinRules.hpp" #include "Runtime/Character/CSkinRules.hpp"
#include "Runtime/Graphics/CSkinnedModel.hpp"
namespace metaforce { namespace metaforce {
CVertexMorphEffect::CVertexMorphEffect(const zeus::CUnitVector3f& v1, const zeus::CVector3f& v2, float diagExtent, CVertexMorphEffect::CVertexMorphEffect(const zeus::CUnitVector3f& dir, const zeus::CVector3f& pos, float duration,
float f2, CRandom16& random) float diagExtent, CRandom16& random)
: x0_(v1), x20_diagExtent(diagExtent), x24_random(random) {} : x0_dir(dir), xc_pos(pos), x18_duration(duration), x20_diagExtent(diagExtent), x24_random(random) {}
void CVertexMorphEffect::MorphVertices(SSkinningWorkspace& workspace, TConstVectorRef magnitudes, void CVertexMorphEffect::MorphVertices(SSkinningWorkspace& workspace, TConstVectorRef averagedNormals,
const TLockedToken<CSkinRules>& skinRules, const CPoseAsTransforms& pose) const { 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 } // namespace metaforce

View File

@ -16,24 +16,22 @@ class CSkinRules;
struct SSkinningWorkspace; struct SSkinningWorkspace;
class CVertexMorphEffect { class CVertexMorphEffect {
zeus::CUnitVector3f x0_; zeus::CUnitVector3f x0_dir;
float xc_ = 0.f; zeus::CVector3f xc_pos;
float x10_ = 0.f; float x18_duration;
float x14_ = 0.f; float x1c_elapsed = 0.f;
float x18_ = 0.f;
float x1c_ = 0.f;
float x20_diagExtent; float x20_diagExtent;
CRandom16& x24_random; CRandom16& x24_random;
std::vector<u32> x28_; std::vector<u32> x28_indices;
std::vector<u32> x38_; std::vector<float> x38_floats;
public: public:
CVertexMorphEffect(const zeus::CUnitVector3f& v1, const zeus::CVector3f& v2, float diagExtent, float f2, CVertexMorphEffect(const zeus::CUnitVector3f& dir, const zeus::CVector3f& pos, float duration, float diagExtent,
CRandom16& random); CRandom16& random);
void MorphVertices(SSkinningWorkspace& workspace, TConstVectorRef magnitudes, void MorphVertices(SSkinningWorkspace& workspace, TConstVectorRef averagedNormals,
const TLockedToken<CSkinRules>& skinRules, const CPoseAsTransforms& pose) const; TLockedToken<CSkinRules>& skinRules, const CPoseAsTransforms& pose, u32 vertexCount);
void Reset(const zeus::CVector3f& dir, const zeus::CVector3f& pos, float duration) {} void Reset(const zeus::CVector3f& dir, const zeus::CVector3f& pos, float duration);
void Update(float) {} void Update(float dt);
}; };
} // namespace metaforce } // namespace metaforce

View File

@ -643,7 +643,7 @@ void COmegaPirate::Render(CStateManager& mgr) {
if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::XRay && xa2c_skeletonAlpha > 0.f) { if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::XRay && xa2c_skeletonAlpha > 0.f) {
const CModelFlags flags{5, 0, 3, zeus::CColor{1.f, xa2c_skeletonAlpha}}; const CModelFlags flags{5, 0, 3, zeus::CColor{1.f, xa2c_skeletonAlpha}};
animData->Render(x9f0_skeletonModel, flags, std::nullopt, nullptr); animData->Render(x9f0_skeletonModel, flags, nullptr, nullptr);
} }
if (x9a0_visible) { if (x9a0_visible) {
bool isXRay = mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay; bool isXRay = mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay;
@ -651,7 +651,7 @@ void COmegaPirate::Render(CStateManager& mgr) {
g_Renderer->SetWorldFog(ERglFogMode::None, 0.f, 1.f, zeus::skBlack); g_Renderer->SetWorldFog(ERglFogMode::None, 0.f, 1.f, zeus::skBlack);
const CModelFlags flags{5, 0, 1, zeus::CColor{1.f, 0.2f}}; const CModelFlags flags{5, 0, 1, zeus::CColor{1.f, 0.2f}};
auto& model = *animData->GetModelData().GetObj(); auto& model = *animData->GetModelData().GetObj();
animData->Render(model, flags, std::nullopt, nullptr); animData->Render(model, flags, nullptr, nullptr);
} }
CPatterned::Render(mgr); CPatterned::Render(mgr);
if (isXRay) { if (isXRay) {

View File

@ -586,7 +586,7 @@ void CFishCloud::RenderBoid(int idx, const CBoid& boid, u32& drawMask, bool ther
constexpr CModelFlags thermFlags(0, 0, 3, zeus::skWhite); constexpr CModelFlags thermFlags(0, 0, 3, zeus::skWhite);
mData.RenderThermal(zeus::skWhite, zeus::CColor(0.f, 0.25f), thermFlags); mData.RenderThermal(zeus::skWhite, zeus::CColor(0.f, 0.25f), thermFlags);
} else { } else {
mData.GetAnimationData()->Render(model, flags, std::nullopt, nullptr); mData.GetAnimationData()->Render(model, flags, nullptr, nullptr);
} }
} }

View File

@ -123,7 +123,7 @@ void CPatterned::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CState
if (HasModelData() && GetModelData()->HasAnimData() && GetModelData()->GetAnimationData()->GetIceModel()) { if (HasModelData() && GetModelData()->HasAnimData() && GetModelData()->GetAnimationData()->GetIceModel()) {
const auto& baseAABB = GetBaseBoundingBox(); const auto& baseAABB = GetBaseBoundingBox();
float diagExtent = (baseAABB.max - baseAABB.min).magnitude() * 0.5f; float diagExtent = (baseAABB.max - baseAABB.min).magnitude() * 0.5f;
x510_vertexMorph = std::make_shared<CVertexMorphEffect>(zeus::skRight, zeus::CVector3f{}, diagExtent, 0.f, x510_vertexMorph = std::make_shared<CVertexMorphEffect>(zeus::skRight, zeus::CVector3f{}, 0.f, diagExtent,
*mgr.GetActiveRandom()); *mgr.GetActiveRandom());
} }
@ -1697,8 +1697,8 @@ void CPatterned::RenderIceModelWithFlags(const CModelFlags& flags) const {
CModelFlags useFlags = flags; CModelFlags useFlags = flags;
useFlags.x1_matSetIdx = 0; useFlags.x1_matSetIdx = 0;
CAnimData* animData = x64_modelData->GetAnimationData(); CAnimData* animData = x64_modelData->GetAnimationData();
if (CMorphableSkinnedModel* iceModel = animData->GetIceModel().GetObj()) { if (CSkinnedModelWithAvgNormals* iceModel = animData->GetIceModel().GetObj()) {
animData->Render(*iceModel, useFlags, {*x510_vertexMorph}, iceModel->GetMorphMagnitudes()); animData->Render(*iceModel, useFlags, x510_vertexMorph.get(), iceModel->GetAveragedNormals());
} }
} }

View File

@ -416,13 +416,13 @@ void CSnakeWeedSwarm::RenderBoid(u32 idx, const CBoid& boid, u32& posesToBuild)
if (posesToBuild & 1 << modelIdx) { if (posesToBuild & 1 << modelIdx) {
posesToBuild &= ~(1 << modelIdx); posesToBuild &= ~(1 << modelIdx);
animData.BuildPose(); animData.BuildPose();
model.Calculate(animData.GetPose(), std::nullopt, nullptr, nullptr); // TODO x178_workspaces[modelIdx] model.Calculate(animData.GetPose(), nullptr, nullptr, nullptr); // TODO x178_workspaces[modelIdx]
} }
CGraphics::SetModelMatrix( CGraphics::SetModelMatrix(
zeus::CTransform::Translate(boid.GetPosition() - zeus::CVector3f(0.f, 0.f, boid.GetZOffset())) * zeus::CTransform::Translate(boid.GetPosition() - zeus::CVector3f(0.f, 0.f, boid.GetZOffset())) *
zeus::CTransform::Scale(boid.GetScale())); zeus::CTransform::Scale(boid.GetScale()));
constexpr CModelFlags useFlags{0, 0, 3, zeus::skWhite}; constexpr CModelFlags useFlags{0, 0, 3, zeus::skWhite};
animData.Render(model, useFlags, std::nullopt, nullptr); animData.Render(model, useFlags, nullptr, nullptr);
} }
void CSnakeWeedSwarm::ApplyRadiusDamage(const zeus::CVector3f& pos, const CDamageInfo& info, CStateManager& mgr) { void CSnakeWeedSwarm::ApplyRadiusDamage(const zeus::CVector3f& pos, const CDamageInfo& info, CStateManager& mgr) {

View File

@ -1057,7 +1057,7 @@ void CWallCrawlerSwarm::RenderBoid(const CBoid* boid, u32& drawMask, bool therma
CGraphics::SetModelMatrix(boid->GetTransform()); CGraphics::SetModelMatrix(boid->GetTransform());
if (boid->x48_timeToDie > 0.f && !thermalHot) { if (boid->x48_timeToDie > 0.f && !thermalHot) {
constexpr CModelFlags useFlags(0, 0, 3, zeus::skWhite); constexpr CModelFlags useFlags(0, 0, 3, zeus::skWhite);
mData.GetAnimationData()->Render(model, useFlags, std::nullopt, nullptr); mData.GetAnimationData()->Render(model, useFlags, nullptr, nullptr);
if (auto iceModel = mData.GetAnimationData()->GetIceModel()) { if (auto iceModel = mData.GetAnimationData()->GetIceModel()) {
// if (!iceModel->GetModelInst()->TryLockTextures()) { // if (!iceModel->GetModelInst()->TryLockTextures()) {
// return; // return;
@ -1066,13 +1066,13 @@ void CWallCrawlerSwarm::RenderBoid(const CBoid* boid, u32& drawMask, bool therma
const float alpha = 1.f - boid->x48_timeToDie; const float alpha = 1.f - boid->x48_timeToDie;
const zeus::CColor color(1.f, alpha > 0.f ? boid->x48_timeToDie : 1.f); const zeus::CColor color(1.f, alpha > 0.f ? boid->x48_timeToDie : 1.f);
const CModelFlags iceFlags(5, 0, 3, color); const CModelFlags iceFlags(5, 0, 3, color);
mData.GetAnimationData()->Render(*iceModel, iceFlags, std::nullopt, nullptr); mData.GetAnimationData()->Render(*iceModel, iceFlags, nullptr, nullptr);
} }
} else if (thermalHot) { } else if (thermalHot) {
constexpr CModelFlags thermFlags(5, 0, 3, zeus::skWhite); constexpr CModelFlags thermFlags(5, 0, 3, zeus::skWhite);
mData.RenderThermal(zeus::skWhite, zeus::CColor(0.f, 0.25f), thermFlags); mData.RenderThermal(zeus::skWhite, zeus::CColor(0.f, 0.25f), thermFlags);
} else { } else {
mData.GetAnimationData()->Render(model, flags, std::nullopt, nullptr); mData.GetAnimationData()->Render(model, flags, nullptr, nullptr);
} }
} }