mirror of https://github.com/AxioDL/metaforce.git
Implement CVertexMorphEffect & CSkinnedModelWithAvgNormals (prev. CMorphableSkinnedModel)
This commit is contained in:
parent
ddc34e3a0c
commit
d7dbec5be0
|
@ -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,
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue