diff --git a/Runtime/Character/CAnimData.cpp b/Runtime/Character/CAnimData.cpp index f87c3f0b2..56992b443 100644 --- a/Runtime/Character/CAnimData.cpp +++ b/Runtime/Character/CAnimData.cpp @@ -41,7 +41,7 @@ void CAnimData::InitializeCache() {} CAnimData::CAnimData(CAssetId id, const CCharacterInfo& character, int defaultAnim, int charIdx, bool loop, TLockedToken layout, TToken model, - const std::optional>& iceModel, + const std::optional>& iceModel, const std::weak_ptr& ctx, std::shared_ptr animMgr, std::shared_ptr transMgr, TLockedToken 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::Render(CSkinnedModel& model, const CModelFlags& drawFlags, - const std::optional& morphEffect, TVectorRef morphMagnitudes) { - SetupRender(model, morphEffect, morphMagnitudes); +void CAnimData::Render(CSkinnedModel& model, const CModelFlags& drawFlags, CVertexMorphEffect* morphEffect, + TConstVectorRef averagedNormals) { + SetupRender(model, morphEffect, averagedNormals); DrawSkinnedModel(model, drawFlags); } -void CAnimData::SetupRender(CSkinnedModel& model, const std::optional& morphEffect, - TVectorRef morphMagnitudes) { +void CAnimData::SetupRender(CSkinnedModel& model, CVertexMorphEffect* morphEffect, TConstVectorRef averagedNormals) { OPTICK_EVENT(); if (!x220_30_poseBuilt) { x2fc_poseBuilder.BuildNoScale(x224_pose); x220_30_poseBuilt = true; } - PoseSkinnedModel(model, x224_pose, morphEffect, morphMagnitudes); + PoseSkinnedModel(model, x224_pose, morphEffect, averagedNormals); } void CAnimData::DrawSkinnedModel(CSkinnedModel& model, const CModelFlags& flags) { @@ -805,9 +804,9 @@ void CAnimData::SetInfraModel(const TLockedToken& model, const TLockedTo xf8_infraModel = std::make_shared(model, skinRules, xd8_modelData->GetLayoutInfo()); } -void CAnimData::PoseSkinnedModel(CSkinnedModel& model, const CPoseAsTransforms& pose, - const std::optional& morphEffect, TVectorRef morphMagnitudes) { - model.Calculate(pose, morphEffect, morphMagnitudes, nullptr); +void CAnimData::PoseSkinnedModel(CSkinnedModel& model, const CPoseAsTransforms& pose, CVertexMorphEffect* morphEffect, + TConstVectorRef averagedNormals) { + model.Calculate(pose, morphEffect, averagedNormals, nullptr); } void CAnimData::AdvanceParticles(const zeus::CTransform& xf, float dt, const zeus::CVector3f& vec, diff --git a/Runtime/Character/CAnimData.hpp b/Runtime/Character/CAnimData.hpp index 753acd178..9485adfd3 100644 --- a/Runtime/Character/CAnimData.hpp +++ b/Runtime/Character/CAnimData.hpp @@ -68,7 +68,7 @@ class CCharAnimTime; class CCharLayoutInfo; class CInt32POINode; class CModel; -class CMorphableSkinnedModel; +class CSkinnedModelWithAvgNormals; class CParticlePOINode; class CPrimitive; class CRandom16; @@ -102,7 +102,7 @@ private: CCharacterInfo xc_charInfo; TLockedToken xcc_layoutData; TLockedToken xd8_modelData; - TLockedToken xe4_iceModelData; + TLockedToken xe4_iceModelData; std::shared_ptr xf4_xrayModel; std::shared_ptr xf8_infraModel; std::shared_ptr xfc_animCtx; @@ -147,9 +147,9 @@ private: public: CAnimData(CAssetId, const CCharacterInfo& character, int defaultAnim, int charIdx, bool loop, TLockedToken layout, TToken model, - const std::optional>& iceModel, const std::weak_ptr& ctx, - std::shared_ptr animMgr, std::shared_ptr transMgr, - TLockedToken charFactory); + const std::optional>& iceModel, + const std::weak_ptr& ctx, std::shared_ptr animMgr, + std::shared_ptr transMgr, TLockedToken charFactory); void SetParticleEffectState(std::string_view effectName, bool active, CStateManager& mgr); void InitializeEffects(CStateManager& mgr, TAreaId aId, const zeus::CVector3f& scale); @@ -194,10 +194,9 @@ public: std::shared_ptr GetAnimationManager() const; void RecalcPoseBuilder(const CCharAnimTime* time); void RenderAuxiliary(const zeus::CFrustum& frustum) const; - void Render(CSkinnedModel& model, const CModelFlags& drawFlags, const std::optional& morphEffect, - TVectorRef morphMagnitudes); - void SetupRender(CSkinnedModel& model, const std::optional& morphEffect, - TVectorRef morphMagnitudes); + void Render(CSkinnedModel& model, const CModelFlags& drawFlags, CVertexMorphEffect* morphEffect, + TConstVectorRef averagedNormals); + void SetupRender(CSkinnedModel& model, CVertexMorphEffect* morphEffect, TConstVectorRef averagedNormals); static void DrawSkinnedModel(CSkinnedModel& model, const CModelFlags& flags); void PreRender(); void BuildPose(); @@ -218,8 +217,8 @@ public: TLockedToken& GetModelData() { return xd8_modelData; } const TLockedToken& GetModelData() const { return xd8_modelData; } - static void PoseSkinnedModel(CSkinnedModel& model, const CPoseAsTransforms& pose, - const std::optional& morphEffect, TVectorRef morphMagnitudes); + static void PoseSkinnedModel(CSkinnedModel& model, const CPoseAsTransforms& pose, CVertexMorphEffect* morphEffect, + TConstVectorRef averagedNormals); void AdvanceParticles(const zeus::CTransform& xf, float dt, const zeus::CVector3f&, CStateManager& stateMgr); float GetAverageVelocity(int animIn) const; void ResetPOILists(); @@ -243,8 +242,8 @@ public: s32 GetCharacterIndex() const { return x204_charIdx; } u16 GetDefaultAnimation() const { return x208_defaultAnim; } - TLockedToken& GetIceModel() { return xe4_iceModelData; } - const TLockedToken& GetIceModel() const { return xe4_iceModelData; } + TLockedToken& GetIceModel() { return xe4_iceModelData; } + const TLockedToken& GetIceModel() const { return xe4_iceModelData; } void SetParticleLightIdx(s32 idx) { x21c_particleLightIdx = idx; } void MarkPoseDirty() { x220_30_poseBuilt = false; } diff --git a/Runtime/Character/CCharacterFactory.cpp b/Runtime/Character/CCharacterFactory.cpp index f82e9ad92..fbaeb1bbe 100644 --- a/Runtime/Character/CCharacterFactory.cpp +++ b/Runtime/Character/CCharacterFactory.cpp @@ -27,7 +27,7 @@ CFactoryFnReturn CCharacterFactory::CDummyFactory::Build(const SObjectTag& tag, return TToken::GetIObjObjectFor(std::make_unique( *g_SimplePool, charInfo.GetModelId(), charInfo.GetSkinRulesId(), charInfo.GetCharLayoutInfoId())); case 1: - return TToken::GetIObjObjectFor(std::make_unique( + return TToken::GetIObjObjectFor(std::make_unique( *g_SimplePool, charInfo.GetIceModelId(), charInfo.GetIceSkinRulesId(), charInfo.GetCharLayoutInfoId())); default: break; @@ -82,7 +82,7 @@ std::unique_ptr CCharacterFactory::CreateCharacter(int charIdx, bool TToken skinnedModel = x70_cacheResPool.GetObj({FourCC(0u), charInfo.GetModelId()}, charParm); - std::optional> iceModel; + std::optional> iceModel; if (charInfo.GetIceModelId().IsValid() && charInfo.GetIceSkinRulesId().IsValid()) { iceModel.emplace(x70_cacheResPool.GetObj({FourCC(1u), charInfo.GetIceModelId()}, charParm)); } diff --git a/Runtime/Character/CModelData.cpp b/Runtime/Character/CModelData.cpp index 7ad119c99..310bbcb89 100644 --- a/Runtime/Character/CModelData.cpp +++ b/Runtime/Character/CModelData.cpp @@ -293,7 +293,7 @@ void CModelData::RenderThermal(const zeus::CTransform& xf, const zeus::CColor& m if (x10_animData) { CSkinnedModel& model = PickAnimatedModel(EWhichModel::ThermalHot); - x10_animData->SetupRender(model, {}, nullptr); + x10_animData->SetupRender(model, nullptr, nullptr); ThermalDraw(mulColor, addColor, flags); } else { auto& model = PickStaticModel(EWhichModel::ThermalHot); @@ -342,7 +342,7 @@ void CModelData::Render(EWhichModel which, const zeus::CTransform& xf, const CAc } if (x10_animData) { - x10_animData->Render(PickAnimatedModel(which), drawFlags, {}, nullptr); + x10_animData->Render(PickAnimatedModel(which), drawFlags, nullptr, nullptr); } else { // TODO supposed to be optional_object? if (x1c_normalModel) { @@ -387,7 +387,7 @@ void CModelData::MultiLightingDraw(EWhichModel which, const zeus::CTransform& xf CGraphics::SetModelMatrix(xf * zeus::CTransform::Scale(x0_scale)); if (x10_animData) { auto& skinnedModel = PickAnimatedModel(which); - x10_animData->SetupRender(skinnedModel, {}, nullptr); + x10_animData->SetupRender(skinnedModel, nullptr, nullptr); model = skinnedModel.GetModel().GetObj(); skinnedModel.DoDrawCallback(callback); } else { @@ -407,7 +407,7 @@ void CModelData::MultiPassDraw(EWhichModel which, const zeus::CTransform& xf, co } if (x10_animData) { auto& skinnedModel = PickAnimatedModel(which); - x10_animData->SetupRender(skinnedModel, {}, nullptr); + x10_animData->SetupRender(skinnedModel, nullptr, nullptr); auto& model = *skinnedModel.GetModel(); skinnedModel.DoDrawCallback([&](auto positions, auto normals) { for (int i = 0; i < count; ++i) { diff --git a/Runtime/Graphics/CSkinnedModel.cpp b/Runtime/Graphics/CSkinnedModel.cpp index 80abaa78b..99958a97b 100644 --- a/Runtime/Graphics/CSkinnedModel.cpp +++ b/Runtime/Graphics/CSkinnedModel.cpp @@ -36,8 +36,8 @@ void CSkinnedModel::AllocateStorage() { } } -void CSkinnedModel::Calculate(const CPoseAsTransforms& pose, const std::optional& morphEffect, - TConstVectorRef morphMagnitudes, SSkinningWorkspace* workspace) { +void CSkinnedModel::Calculate(const CPoseAsTransforms& pose, CVertexMorphEffect* morphEffect, + TConstVectorRef averagedNormals, SSkinningWorkspace* workspace) { if (workspace == nullptr) { if (x35_disableWorkspaces) { 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); if (morphEffect) { - morphEffect->MorphVertices(*workspace, morphMagnitudes, x10_skinRules, pose); + morphEffect->MorphVertices(*workspace, averagedNormals, x10_skinRules, pose, x10_skinRules->GetVertexCount()); } if (g_PointGenFunc != nullptr) { g_PointGenFunc(*workspace); @@ -93,13 +93,13 @@ void CSkinnedModel::DoDrawCallback(const FCustomDraw& func) const { } } -CMorphableSkinnedModel::CMorphableSkinnedModel(IObjectStore& store, CAssetId model, CAssetId skinRules, - CAssetId layoutInfo) +CSkinnedModelWithAvgNormals::CSkinnedModelWithAvgNormals(IObjectStore& store, CAssetId model, CAssetId skinRules, + CAssetId layoutInfo) : CSkinnedModel(store, model, skinRules, layoutInfo) { const auto vertexCount = GetSkinRules()->GetVertexCount(); const auto& modelPositions = *GetModel()->GetPositions(); - x40_morphMagnitudes.resize(vertexCount); + x40_averagedNormals.resize(vertexCount); std::vector>> vertMap; for (int vertIdx = 0; vertIdx < vertexCount; ++vertIdx) { const auto curPos = modelPositions[vertIdx]; @@ -123,7 +123,7 @@ CMorphableSkinnedModel::CMorphableSkinnedModel(IObjectStore& store, CAssetId mod } averagedNormal.normalize(); for (const auto idx : idxs) { - x40_morphMagnitudes[idx] = averagedNormal; + x40_averagedNormals[idx] = averagedNormal; } } } diff --git a/Runtime/Graphics/CSkinnedModel.hpp b/Runtime/Graphics/CSkinnedModel.hpp index d6a9839df..489a55855 100644 --- a/Runtime/Graphics/CSkinnedModel.hpp +++ b/Runtime/Graphics/CSkinnedModel.hpp @@ -60,8 +60,11 @@ public: const TLockedToken& GetLayoutInfo() const { return x1c_layoutInfo; } void AllocateStorage(); - void Calculate(const CPoseAsTransforms& pose, const std::optional& morphEffect, - TConstVectorRef averagedNormals, SSkinningWorkspace* workspace); + // Metaforce addition: Originally morphEffect is rstl::optional_object* + // 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(const CModelFlags& drawFlags); void DoDrawCallback(const FCustomDraw& func) const; @@ -71,13 +74,12 @@ public: static FPointGenerator g_PointGenFunc; }; -class CMorphableSkinnedModel : public CSkinnedModel { - std::vector x40_morphMagnitudes; // was rstl::auto_ptr +class CSkinnedModelWithAvgNormals : public CSkinnedModel { + std::vector x40_averagedNormals; // was rstl::auto_ptr public: - CMorphableSkinnedModel(IObjectStore& store, CAssetId model, CAssetId skinRules, CAssetId layoutInfo); - TConstVectorRef GetMorphMagnitudes() const { return &x40_morphMagnitudes; } - TVectorRef GetMorphMagnitudes() { return &x40_morphMagnitudes; } + CSkinnedModelWithAvgNormals(IObjectStore& store, CAssetId model, CAssetId skinRules, CAssetId layoutInfo); + TConstVectorRef GetAveragedNormals() const { return &x40_averagedNormals; } }; } // namespace metaforce diff --git a/Runtime/Graphics/CVertexMorphEffect.cpp b/Runtime/Graphics/CVertexMorphEffect.cpp index 668a38996..bf877cc29 100644 --- a/Runtime/Graphics/CVertexMorphEffect.cpp +++ b/Runtime/Graphics/CVertexMorphEffect.cpp @@ -1,15 +1,46 @@ #include "Runtime/Graphics/CVertexMorphEffect.hpp" #include "Runtime/Character/CSkinRules.hpp" +#include "Runtime/Graphics/CSkinnedModel.hpp" namespace metaforce { -CVertexMorphEffect::CVertexMorphEffect(const zeus::CUnitVector3f& v1, const zeus::CVector3f& v2, float diagExtent, - float f2, CRandom16& random) -: x0_(v1), x20_diagExtent(diagExtent), x24_random(random) {} +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 magnitudes, - const TLockedToken& skinRules, const CPoseAsTransforms& pose) const { +void CVertexMorphEffect::MorphVertices(SSkinningWorkspace& workspace, TConstVectorRef averagedNormals, + TLockedToken& skinRules, const CPoseAsTransforms& pose, + u32 vertexCount) { + if (x28_indices.empty()) { + std::vector 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 diff --git a/Runtime/Graphics/CVertexMorphEffect.hpp b/Runtime/Graphics/CVertexMorphEffect.hpp index 5589ee061..aeb91c906 100644 --- a/Runtime/Graphics/CVertexMorphEffect.hpp +++ b/Runtime/Graphics/CVertexMorphEffect.hpp @@ -16,24 +16,22 @@ class CSkinRules; struct SSkinningWorkspace; class CVertexMorphEffect { - zeus::CUnitVector3f x0_; - float xc_ = 0.f; - float x10_ = 0.f; - float x14_ = 0.f; - float x18_ = 0.f; - float x1c_ = 0.f; + zeus::CUnitVector3f x0_dir; + zeus::CVector3f xc_pos; + float x18_duration; + float x1c_elapsed = 0.f; float x20_diagExtent; CRandom16& x24_random; - std::vector x28_; - std::vector x38_; + std::vector x28_indices; + std::vector x38_floats; 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); - void MorphVertices(SSkinningWorkspace& workspace, TConstVectorRef magnitudes, - const TLockedToken& skinRules, const CPoseAsTransforms& pose) const; - void Reset(const zeus::CVector3f& dir, const zeus::CVector3f& pos, float duration) {} - void Update(float) {} + void MorphVertices(SSkinningWorkspace& workspace, TConstVectorRef averagedNormals, + TLockedToken& skinRules, const CPoseAsTransforms& pose, u32 vertexCount); + void Reset(const zeus::CVector3f& dir, const zeus::CVector3f& pos, float duration); + void Update(float dt); }; } // namespace metaforce diff --git a/Runtime/MP1/World/COmegaPirate.cpp b/Runtime/MP1/World/COmegaPirate.cpp index aa518969a..b6a7fd074 100644 --- a/Runtime/MP1/World/COmegaPirate.cpp +++ b/Runtime/MP1/World/COmegaPirate.cpp @@ -643,7 +643,7 @@ void COmegaPirate::Render(CStateManager& mgr) { if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::XRay && xa2c_skeletonAlpha > 0.f) { 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) { 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); const CModelFlags flags{5, 0, 1, zeus::CColor{1.f, 0.2f}}; auto& model = *animData->GetModelData().GetObj(); - animData->Render(model, flags, std::nullopt, nullptr); + animData->Render(model, flags, nullptr, nullptr); } CPatterned::Render(mgr); if (isXRay) { diff --git a/Runtime/World/CFishCloud.cpp b/Runtime/World/CFishCloud.cpp index 6011c7cd8..108d0cfad 100644 --- a/Runtime/World/CFishCloud.cpp +++ b/Runtime/World/CFishCloud.cpp @@ -586,7 +586,7 @@ void CFishCloud::RenderBoid(int idx, const CBoid& boid, u32& drawMask, bool ther constexpr CModelFlags thermFlags(0, 0, 3, zeus::skWhite); mData.RenderThermal(zeus::skWhite, zeus::CColor(0.f, 0.25f), thermFlags); } else { - mData.GetAnimationData()->Render(model, flags, std::nullopt, nullptr); + mData.GetAnimationData()->Render(model, flags, nullptr, nullptr); } } diff --git a/Runtime/World/CPatterned.cpp b/Runtime/World/CPatterned.cpp index fe6f030f0..f4cb4b48a 100644 --- a/Runtime/World/CPatterned.cpp +++ b/Runtime/World/CPatterned.cpp @@ -123,7 +123,7 @@ void CPatterned::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CState if (HasModelData() && GetModelData()->HasAnimData() && GetModelData()->GetAnimationData()->GetIceModel()) { const auto& baseAABB = GetBaseBoundingBox(); float diagExtent = (baseAABB.max - baseAABB.min).magnitude() * 0.5f; - x510_vertexMorph = std::make_shared(zeus::skRight, zeus::CVector3f{}, diagExtent, 0.f, + x510_vertexMorph = std::make_shared(zeus::skRight, zeus::CVector3f{}, 0.f, diagExtent, *mgr.GetActiveRandom()); } @@ -1697,8 +1697,8 @@ void CPatterned::RenderIceModelWithFlags(const CModelFlags& flags) const { CModelFlags useFlags = flags; useFlags.x1_matSetIdx = 0; CAnimData* animData = x64_modelData->GetAnimationData(); - if (CMorphableSkinnedModel* iceModel = animData->GetIceModel().GetObj()) { - animData->Render(*iceModel, useFlags, {*x510_vertexMorph}, iceModel->GetMorphMagnitudes()); + if (CSkinnedModelWithAvgNormals* iceModel = animData->GetIceModel().GetObj()) { + animData->Render(*iceModel, useFlags, x510_vertexMorph.get(), iceModel->GetAveragedNormals()); } } diff --git a/Runtime/World/CSnakeWeedSwarm.cpp b/Runtime/World/CSnakeWeedSwarm.cpp index 0c374e81c..50d6857a0 100644 --- a/Runtime/World/CSnakeWeedSwarm.cpp +++ b/Runtime/World/CSnakeWeedSwarm.cpp @@ -416,13 +416,13 @@ void CSnakeWeedSwarm::RenderBoid(u32 idx, const CBoid& boid, u32& posesToBuild) if (posesToBuild & 1 << modelIdx) { posesToBuild &= ~(1 << modelIdx); 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( zeus::CTransform::Translate(boid.GetPosition() - zeus::CVector3f(0.f, 0.f, boid.GetZOffset())) * zeus::CTransform::Scale(boid.GetScale())); 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) { diff --git a/Runtime/World/CWallCrawlerSwarm.cpp b/Runtime/World/CWallCrawlerSwarm.cpp index b83059ea5..1fe8cf94a 100644 --- a/Runtime/World/CWallCrawlerSwarm.cpp +++ b/Runtime/World/CWallCrawlerSwarm.cpp @@ -1057,7 +1057,7 @@ void CWallCrawlerSwarm::RenderBoid(const CBoid* boid, u32& drawMask, bool therma CGraphics::SetModelMatrix(boid->GetTransform()); if (boid->x48_timeToDie > 0.f && !thermalHot) { 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 (!iceModel->GetModelInst()->TryLockTextures()) { // return; @@ -1066,13 +1066,13 @@ void CWallCrawlerSwarm::RenderBoid(const CBoid* boid, u32& drawMask, bool therma const float alpha = 1.f - boid->x48_timeToDie; const zeus::CColor color(1.f, alpha > 0.f ? boid->x48_timeToDie : 1.f); 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) { constexpr CModelFlags thermFlags(5, 0, 3, zeus::skWhite); mData.RenderThermal(zeus::skWhite, zeus::CColor(0.f, 0.25f), thermFlags); } else { - mData.GetAnimationData()->Render(model, flags, std::nullopt, nullptr); + mData.GetAnimationData()->Render(model, flags, nullptr, nullptr); } }