Reimplement CSkinRules/CSkinnedModel; skinning kinda works!

This commit is contained in:
Luke Street 2022-03-10 01:33:17 -05:00
parent 8714fbf844
commit cd963c4a5c
35 changed files with 346 additions and 284 deletions

View File

@ -455,7 +455,7 @@ zeus::CTransform CAnimData::GetLocatorTransform(CSegId id, const CCharAnimTime*
if (!x220_30_poseBuilt) { if (!x220_30_poseBuilt) {
x2fc_poseBuilder.BuildTransform(id, ret); x2fc_poseBuilder.BuildTransform(id, ret);
} else { } else {
ret.setRotation(x224_pose.GetTransformMinusOffset(id)); ret.setRotation(x224_pose.GetRotation(id));
ret.origin = x224_pose.GetOffset(id); ret.origin = x224_pose.GetOffset(id);
} }
return ret; return ret;
@ -544,13 +544,13 @@ 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,
const std::optional<CVertexMorphEffect>& morphEffect, const float* morphMagnitudes) { const std::optional<CVertexMorphEffect>& morphEffect, TVectorRef morphMagnitudes) {
SetupRender(model, morphEffect, morphMagnitudes); SetupRender(model, morphEffect, morphMagnitudes);
DrawSkinnedModel(model, drawFlags); DrawSkinnedModel(model, drawFlags);
} }
void CAnimData::SetupRender(CSkinnedModel& model, const std::optional<CVertexMorphEffect>& morphEffect, void CAnimData::SetupRender(CSkinnedModel& model, const std::optional<CVertexMorphEffect>& morphEffect,
const float* morphMagnitudes) { TVectorRef morphMagnitudes) {
OPTICK_EVENT(); OPTICK_EVENT();
if (!x220_30_poseBuilt) { if (!x220_30_poseBuilt) {
x2fc_poseBuilder.BuildNoScale(x224_pose); x2fc_poseBuilder.BuildNoScale(x224_pose);
@ -560,7 +560,7 @@ void CAnimData::SetupRender(CSkinnedModel& model, const std::optional<CVertexMor
} }
void CAnimData::DrawSkinnedModel(CSkinnedModel& model, const CModelFlags& flags) { void CAnimData::DrawSkinnedModel(CSkinnedModel& model, const CModelFlags& flags) {
// TODO: some GX light stuff? aurora::gfx::set_chan_mat_src(GX::COLOR0A0, GX::SRC_REG);
model.Draw(flags); model.Draw(flags);
} }
@ -806,8 +806,8 @@ void CAnimData::SetInfraModel(const TLockedToken<CModel>& model, const TLockedTo
} }
void CAnimData::PoseSkinnedModel(CSkinnedModel& model, const CPoseAsTransforms& pose, void CAnimData::PoseSkinnedModel(CSkinnedModel& model, const CPoseAsTransforms& pose,
const std::optional<CVertexMorphEffect>& morphEffect, const float* morphMagnitudes) { const std::optional<CVertexMorphEffect>& morphEffect, TVectorRef morphMagnitudes) {
model.Calculate(pose, morphEffect, morphMagnitudes); model.Calculate(pose, morphEffect, morphMagnitudes, 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

@ -195,9 +195,9 @@ public:
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, const std::optional<CVertexMorphEffect>& morphEffect,
const float* morphMagnitudes); TVectorRef morphMagnitudes);
void SetupRender(CSkinnedModel& model, const std::optional<CVertexMorphEffect>& morphEffect, void SetupRender(CSkinnedModel& model, const std::optional<CVertexMorphEffect>& morphEffect,
const float* morphMagnitudes); 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();
@ -219,7 +219,7 @@ public:
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,
const std::optional<CVertexMorphEffect>& morphEffect, const float* morphMagnitudes); const std::optional<CVertexMorphEffect>& morphEffect, TVectorRef morphMagnitudes);
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();

View File

@ -22,7 +22,7 @@ CFactoryFnReturn CCharacterFactory::CDummyFactory::Build(const SObjectTag& tag,
const CCharacterInfo& charInfo = *params.GetOwnedObj<const CCharacterInfo*>(); const CCharacterInfo& charInfo = *params.GetOwnedObj<const CCharacterInfo*>();
switch (tag.type.toUint32() & 0x1) { switch (tag.type.toUint32()) {
case 0: case 0:
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()));

View File

@ -33,17 +33,10 @@ void CHierarchyPoseBuilder::RecursivelyBuildNoScale(const CSegId& boneId, const
CPoseAsTransforms& pose, const zeus::CQuaternion& parentRot, CPoseAsTransforms& pose, const zeus::CQuaternion& parentRot,
const zeus::CMatrix3f& parentXf, const zeus::CMatrix3f& parentXf,
const zeus::CVector3f& parentOffset) const { const zeus::CVector3f& parentOffset) const {
zeus::CVector3f bindOffset;
if (x0_layoutDesc.GetScaledLayoutDescription()) {
const CLayoutDescription::CScaledLayoutDescription& desc = *x0_layoutDesc.GetScaledLayoutDescription();
bindOffset = desc.ScaledLayout()->GetFromRootUnrotated(boneId);
} else
bindOffset = x0_layoutDesc.GetCharLayoutInfo()->GetFromRootUnrotated(boneId);
zeus::CQuaternion quat = parentRot * node.x4_rotation; zeus::CQuaternion quat = parentRot * node.x4_rotation;
zeus::CMatrix3f xf = quat; zeus::CMatrix3f xf = quat;
zeus::CVector3f xfOffset = parentXf * node.x14_offset + parentOffset; zeus::CVector3f xfOffset = parentXf * node.x14_offset + parentOffset;
pose.Insert(boneId, quat, xfOffset, bindOffset); pose.Insert(boneId, quat, xfOffset);
CSegId curBone = node.x0_child; CSegId curBone = node.x0_child;
while (curBone != 0) { while (curBone != 0) {
@ -59,29 +52,25 @@ void CHierarchyPoseBuilder::RecursivelyBuild(const CSegId& boneId, const CTreeNo
zeus::CQuaternion quat = parentRot * node.x4_rotation; zeus::CQuaternion quat = parentRot * node.x4_rotation;
float scale; float scale;
zeus::CVector3f bindOffset;
if (x0_layoutDesc.GetScaledLayoutDescription()) { if (x0_layoutDesc.GetScaledLayoutDescription()) {
const CLayoutDescription::CScaledLayoutDescription& desc = *x0_layoutDesc.GetScaledLayoutDescription(); scale = x0_layoutDesc.GetScaledLayoutDescription()->GlobalScale();
scale = desc.GlobalScale();
bindOffset = desc.ScaledLayout()->GetFromRootUnrotated(boneId);
} else { } else {
scale = 1.f; scale = 1.f;
bindOffset = x0_layoutDesc.GetCharLayoutInfo()->GetFromRootUnrotated(boneId);
} }
zeus::CMatrix3f mtxXf; zeus::CMatrix3f rotation;
if (scale == 1.f) if (scale == 1.f)
mtxXf = quat; rotation = quat;
else else
mtxXf = parentXf * zeus::CMatrix3f(scale); rotation = parentXf * (zeus::CMatrix3f{node.x4_rotation} * zeus::CMatrix3f{scale});
zeus::CVector3f xfOffset = parentXf * node.x14_offset + parentOffset; zeus::CVector3f offset = parentOffset + (parentXf * node.x14_offset);
pose.Insert(boneId, mtxXf, xfOffset, bindOffset); pose.Insert(boneId, rotation, offset);
CSegId curBone = node.x0_child; CSegId curBone = node.x0_child;
while (curBone != 0) { while (curBone != 0) {
const CTreeNode& node = x38_treeMap[curBone]; const CTreeNode& node = x38_treeMap[curBone];
RecursivelyBuild(curBone, node, pose, quat, quat, xfOffset); RecursivelyBuild(curBone, node, pose, quat, quat, offset);
curBone = node.x1_sibling; curBone = node.x1_sibling;
} }
} }

View File

@ -14,7 +14,6 @@ set(CHARACTER_SOURCES
CTransitionDatabaseGame.hpp CTransitionDatabaseGame.cpp CTransitionDatabaseGame.hpp CTransitionDatabaseGame.cpp
CHierarchyPoseBuilder.hpp CHierarchyPoseBuilder.cpp CHierarchyPoseBuilder.hpp CHierarchyPoseBuilder.cpp
CPoseAsTransforms.hpp CPoseAsTransforms.cpp CPoseAsTransforms.hpp CPoseAsTransforms.cpp
CSkinBank.hpp CSkinBank.cpp
CCharLayoutInfo.hpp CCharLayoutInfo.cpp CCharLayoutInfo.hpp CCharLayoutInfo.cpp
CLayoutDescription.hpp CLayoutDescription.hpp
CSegIdList.hpp CSegIdList.cpp CSegIdList.hpp CSegIdList.cpp

View File

@ -99,7 +99,7 @@ void CParticleDatabase::UpdateParticleGenDB(float dt, const CPoseAsTransforms& p
switch (info.GetParentedMode()) { switch (info.GetParentedMode()) {
case CParticleData::EParentedMode::Initial: { case CParticleData::EParentedMode::Initial: {
if (info.GetIsGrabInitialData()) { if (info.GetIsGrabInitialData()) {
zeus::CTransform segXf((info.GetFlags() & 0x10) ? zeus::CMatrix3f() : pose.GetTransformMinusOffset(segId), zeus::CTransform segXf((info.GetFlags() & 0x10) ? zeus::CMatrix3f() : pose.GetRotation(segId),
off * scale); off * scale);
zeus::CTransform compXf = xf * segXf; zeus::CTransform compXf = xf * segXf;
info.SetCurTransform(compXf.getRotation()); info.SetCurTransform(compXf.getRotation());
@ -125,7 +125,7 @@ void CParticleDatabase::UpdateParticleGenDB(float dt, const CPoseAsTransforms& p
info.SetIsGrabInitialData(false); info.SetIsGrabInitialData(false);
} }
zeus::CTransform segXf(pose.GetTransformMinusOffset(segId), off * scale); zeus::CTransform segXf(pose.GetRotation(segId), off * scale);
zeus::CTransform compXf = xf * segXf; zeus::CTransform compXf = xf * segXf;
if (info.GetParentedMode() == CParticleData::EParentedMode::ContinuousEmitter) { if (info.GetParentedMode() == CParticleData::EParentedMode::ContinuousEmitter) {

View File

@ -4,7 +4,8 @@
namespace metaforce { namespace metaforce {
CPoseAsTransforms::CPoseAsTransforms(u8 boneCount) : x1_count(boneCount), xd0_transformArr(new Transform[boneCount]) {} CPoseAsTransforms::CPoseAsTransforms(u8 boneCount)
: x1_count(boneCount), xd0_transformArr(std::make_unique<zeus::CTransform[]>(boneCount)) {}
bool CPoseAsTransforms::ContainsDataFor(const CSegId& id) const { bool CPoseAsTransforms::ContainsDataFor(const CSegId& id) const {
const std::pair<CSegId, CSegId>& link = x8_links[id]; const std::pair<CSegId, CSegId>& link = x8_links[id];
@ -24,32 +25,23 @@ void CPoseAsTransforms::AccumulateScaledTransform(const CSegId& id, zeus::CMatri
const zeus::CTransform& CPoseAsTransforms::GetTransform(const CSegId& id) const { const zeus::CTransform& CPoseAsTransforms::GetTransform(const CSegId& id) const {
const std::pair<CSegId, CSegId>& link = x8_links[id]; const std::pair<CSegId, CSegId>& link = x8_links[id];
assert(link.second.IsValid()); assert(link.second.IsValid());
return xd0_transformArr[link.second].m_originToAccum; return xd0_transformArr[link.second];
}
const zeus::CTransform& CPoseAsTransforms::GetRestToAccumTransform(const CSegId& id) const {
const std::pair<CSegId, CSegId>& link = x8_links[id];
assert(link.second.IsValid());
return xd0_transformArr[link.second].m_restPoseToAccum;
} }
const zeus::CVector3f& CPoseAsTransforms::GetOffset(const CSegId& id) const { const zeus::CVector3f& CPoseAsTransforms::GetOffset(const CSegId& id) const {
const std::pair<CSegId, CSegId>& link = x8_links[id]; const std::pair<CSegId, CSegId>& link = x8_links[id];
assert(link.second.IsValid()); assert(link.second.IsValid());
return xd0_transformArr[link.second].m_originToAccum.origin; return xd0_transformArr[link.second].origin;
} }
const zeus::CMatrix3f& CPoseAsTransforms::GetRotation(const CSegId& id) const { const zeus::CMatrix3f& CPoseAsTransforms::GetRotation(const CSegId& id) const {
const std::pair<CSegId, CSegId>& link = x8_links[id]; const std::pair<CSegId, CSegId>& link = x8_links[id];
assert(link.second.IsValid()); assert(link.second.IsValid());
return xd0_transformArr[link.second].m_originToAccum.basis; return xd0_transformArr[link.second].basis;
} }
void CPoseAsTransforms::Insert(const CSegId& id, const zeus::CMatrix3f& rotation, const zeus::CVector3f& offset, void CPoseAsTransforms::Insert(const CSegId& id, const zeus::CMatrix3f& rotation, const zeus::CVector3f& offset) {
const zeus::CVector3f& restOffset) { xd0_transformArr[x0_nextId] = zeus::CTransform(rotation, offset);
Transform& xfOut = xd0_transformArr[x0_nextId];
xfOut.m_originToAccum = zeus::CTransform(rotation, offset);
xfOut.m_restPoseToAccum = xfOut.m_originToAccum * zeus::CTransform::Translate(-restOffset);
std::pair<CSegId, CSegId>& link = x8_links[id]; std::pair<CSegId, CSegId>& link = x8_links[id];
link.first = xd4_lastInserted; link.first = xd4_lastInserted;
@ -58,4 +50,10 @@ void CPoseAsTransforms::Insert(const CSegId& id, const zeus::CMatrix3f& rotation
++x0_nextId; ++x0_nextId;
} }
CSegId CPoseAsTransforms::GetParent(const CSegId& id) const {
const std::pair<CSegId, CSegId>& link = x8_links[id];
assert(link.first.IsValid());
return link.first;
}
} // namespace metaforce } // namespace metaforce

View File

@ -4,9 +4,9 @@
#include <memory> #include <memory>
#include <utility> #include <utility>
#include "Runtime/RetroTypes.hpp"
#include "Runtime/Character/CCharLayoutInfo.hpp" #include "Runtime/Character/CCharLayoutInfo.hpp"
#include "Runtime/Character/CSegId.hpp" #include "Runtime/Character/CSegId.hpp"
#include "Runtime/RetroTypes.hpp"
#include <zeus/CMatrix3f.hpp> #include <zeus/CMatrix3f.hpp>
#include <zeus/CTransform.hpp> #include <zeus/CTransform.hpp>
@ -16,31 +16,26 @@ namespace metaforce {
class CPoseAsTransforms { class CPoseAsTransforms {
friend class CAnimData; friend class CAnimData;
public:
struct Transform {
zeus::CTransform m_originToAccum;
zeus::CTransform m_restPoseToAccum;
};
private: private:
CSegId x0_nextId = 0; CSegId x0_nextId = 0;
CSegId x1_count; CSegId x1_count;
std::array<std::pair<CSegId, CSegId>, 100> x8_links; std::array<std::pair<CSegId, CSegId>, 100> x8_links;
std::unique_ptr<Transform[]> xd0_transformArr; std::unique_ptr<zeus::CTransform[]> xd0_transformArr;
CSegId xd4_lastInserted = 0; CSegId xd4_lastInserted = 0;
public: public:
explicit CPoseAsTransforms(u8 boneCount); explicit CPoseAsTransforms(u8 boneCount);
bool ContainsDataFor(const CSegId& id) const;
void Clear(); void Clear();
void AccumulateScaledTransform(const CSegId& id, zeus::CMatrix3f& rotation, float scale) const; void AccumulateScaledTransform(const CSegId& id, zeus::CMatrix3f& rotation, float scale) const;
const zeus::CTransform& GetTransform(const CSegId& id) const; void Insert(const CSegId& id, const zeus::CMatrix3f& rotation, const zeus::CVector3f& offset);
const zeus::CTransform& GetRestToAccumTransform(const CSegId& id) const;
const zeus::CVector3f& GetOffset(const CSegId& id) const; [[nodiscard]] bool ContainsDataFor(const CSegId& id) const;
const zeus::CMatrix3f& GetRotation(const CSegId& id) const; [[nodiscard]] const zeus::CTransform& GetTransform(const CSegId& id) const;
const zeus::CMatrix3f& GetTransformMinusOffset(const CSegId& id) const { return GetRotation(id); } [[nodiscard]] const zeus::CVector3f& GetOffset(const CSegId& id) const;
void Insert(const CSegId& id, const zeus::CMatrix3f& rotation, const zeus::CVector3f& offset, [[nodiscard]] const zeus::CMatrix3f& GetRotation(const CSegId& id) const;
const zeus::CVector3f& restOffset); [[nodiscard]] CSegId GetLastInserted() const { return xd4_lastInserted; }
[[nodiscard]] CSegId GetParent(const CSegId& id) const;
}; };
} // namespace metaforce } // namespace metaforce

View File

@ -1,21 +0,0 @@
#include "Runtime/Character/CSkinBank.hpp"
#include "Runtime/Character/CPoseAsTransforms.hpp"
namespace metaforce {
CSkinBank::CSkinBank(CInputStream& in) {
u32 boneCount = in.ReadLong();
x0_segments.reserve(boneCount);
for (u32 i = 0; i < boneCount; ++i)
x0_segments.emplace_back(in);
}
void CSkinBank::GetBankTransforms(std::vector<const zeus::CTransform*>& out, const CPoseAsTransforms& pose) const {
for (CSegId id : x0_segments) {
const zeus::CTransform& xf = pose.GetRestToAccumTransform(id);
out.push_back(&xf);
}
}
} // namespace metaforce

View File

@ -1,19 +0,0 @@
#pragma once
#include <vector>
#include "Runtime/Streams/IOStreams.hpp"
#include "Runtime/Character/CSegId.hpp"
namespace metaforce {
class CPoseAsTransforms;
class CSkinBank {
std::vector<CSegId> x0_segments;
public:
explicit CSkinBank(CInputStream& in);
void GetBankTransforms(std::vector<const zeus::CTransform*>& out, const CPoseAsTransforms& pose) const;
};
} // namespace metaforce

View File

@ -31,31 +31,47 @@ CSkinRules::CSkinRules(CInputStream& in) {
x14_normalCount = ReadCount(in); x14_normalCount = ReadCount(in);
} }
// void CSkinRules::TransformVerticesCPU(std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vnOut, void CSkinRules::BuildAccumulatedTransforms(const CPoseAsTransforms& pose, const CCharLayoutInfo& info) {
// const CPoseAsTransforms& pose, const CModel& model) const { std::array<zeus::CVector3f, 100> points;
// OPTICK_EVENT(); CSegId segId = pose.GetLastInserted();
// vnOut.resize(m_poolToSkinIdx.size()); while (segId != 0) {
// for (size_t i = 0; i < m_poolToSkinIdx.size(); ++i) { zeus::CVector3f origin;
// const CVirtualBone& vb = m_virtualBones[m_poolToSkinIdx[i]]; if (segId != 3) { // root ID
// zeus::CVector3f origVertex = model.GetPoolVertex(i); origin = info.GetFromRootUnrotated(segId);
// zeus::CVector3f vertex; }
// zeus::CVector3f origNormal = model.GetPoolNormal(i); const auto rotatedOrigin = pose.GetRotation(segId) * origin;
// zeus::CVector3f normal; points[segId] = pose.GetOffset(segId) - rotatedOrigin;
// for (const SSkinWeighting& w : vb.GetWeights()) { segId = pose.GetParent(segId);
// const zeus::CTransform& xf = pose.GetRestToAccumTransform(w.m_id); }
// vertex += (xf * origVertex) * w.m_weight; for (auto& bone : x0_bones) {
// normal += (xf.basis.inverted().transposed() * origNormal) * w.m_weight; bone.BuildAccumulatedTransform(pose, points.data());
// } }
// vnOut[i] = std::make_pair(vertex, normal.normalized()); }
// }
// } void CSkinRules::BuildPoints(TConstVectorRef positions, TVectorRef out) {
size_t offset = 0;
for (auto& bone : x0_bones) {
u32 vertexCount = bone.GetVertexCount();
bone.BuildPoints(positions->data() + offset, out, vertexCount);
offset += vertexCount;
}
}
void CSkinRules::BuildNormals(TConstVectorRef normals, TVectorRef out) {
size_t offset = 0;
for (auto& bone : x0_bones) {
u32 vertexCount = bone.GetVertexCount();
bone.BuildNormals(normals->data() + offset, out, vertexCount);
offset += vertexCount;
}
}
CFactoryFnReturn FSkinRulesFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& params, CFactoryFnReturn FSkinRulesFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& params,
CObjectReference* selfRef) { CObjectReference* selfRef) {
return TToken<CSkinRules>::GetIObjObjectFor(std::make_unique<CSkinRules>(in)); return TToken<CSkinRules>::GetIObjObjectFor(std::make_unique<CSkinRules>(in));
} }
auto StreamInSkinWeighting(CInputStream& in) { static inline auto StreamInSkinWeighting(CInputStream& in) {
rstl::reserved_vector<SSkinWeighting, 3> weights; rstl::reserved_vector<SSkinWeighting, 3> weights;
u32 weightCount = in.ReadLong(); u32 weightCount = in.ReadLong();
for (int i = 0; i < std::min(3u, weightCount); ++i) { for (int i = 0; i < std::min(3u, weightCount); ++i) {
@ -67,6 +83,58 @@ auto StreamInSkinWeighting(CInputStream& in) {
return weights; return weights;
} }
CVirtualBone::CVirtualBone(CInputStream& in) CVirtualBone::CVirtualBone(CInputStream& in) : x0_weights(StreamInSkinWeighting(in)), x1c_vertexCount(in.ReadLong()) {}
: x0_weights(StreamInSkinWeighting(in)), x1c_vertexCount(in.ReadLong()) {}
void CVirtualBone::BuildPoints(const zeus::CVector3f* in, TVectorRef out, u32 count) const {
for (u32 i = 0; i < count; ++i) {
out->emplace_back(x20_xf * in[i]);
}
}
void CVirtualBone::BuildNormals(const zeus::CVector3f* in, TVectorRef out, u32 count) const {
for (u32 i = 0; i < count; ++i) {
out->emplace_back(x50_rotation * in[i]);
}
}
void CVirtualBone::BuildAccumulatedTransform(const CPoseAsTransforms& pose, const zeus::CVector3f* points) {
BuildFinalPosMatrix(pose, points);
x50_rotation = pose.GetRotation(x0_weights[0].x0_id);
}
static constexpr zeus::CMatrix3f WeightedMatrix(const zeus::CMatrix3f& m1, float w1, const zeus::CMatrix3f& m2, float w2) {
return {
m1[0] * w1 + m2[0] * w2,
m1[1] * w1 + m2[1] * w2,
m1[2] * w1 + m2[2] * w2,
};
}
static constexpr zeus::CVector3f WeightedVector(const zeus::CVector3f& v1, float w1, const zeus::CVector3f& v2, float w2) {
return v1 * w1 + v2 * w2;
}
void CVirtualBone::BuildFinalPosMatrix(const CPoseAsTransforms& pose, const zeus::CVector3f* points) {
if (x0_weights.size() == 1) {
const auto id = x0_weights[0].x0_id;
x20_xf = {pose.GetRotation(id), points[id]};
} else if (x0_weights.size() == 2) {
const auto w0 = x0_weights[0];
const auto w1 = x0_weights[1];
x20_xf = {
WeightedMatrix(pose.GetRotation(w0.x0_id), w0.x4_weight, pose.GetRotation(w1.x0_id), w1.x4_weight),
WeightedVector(points[w0.x0_id], w0.x4_weight, points[w1.x0_id], w1.x4_weight),
};
} else if (x0_weights.size() == 3) {
const auto w0 = x0_weights[0];
const auto w1 = x0_weights[1];
const auto w2 = x0_weights[2];
auto rot = WeightedMatrix(pose.GetRotation(w0.x0_id), w0.x4_weight, pose.GetRotation(w1.x0_id), w1.x4_weight);
auto pos = WeightedVector(points[w0.x0_id], w0.x4_weight, points[w1.x0_id], w1.x4_weight);
pose.AccumulateScaledTransform(w2.x0_id, rot, w2.x4_weight);
x20_xf = {rot, pos + points[w2.x0_id] * w2.x4_weight};
} else {
x20_xf = {};
}
}
} // namespace metaforce } // namespace metaforce

View File

@ -3,12 +3,14 @@
#include <vector> #include <vector>
#include "Runtime/CFactoryMgr.hpp" #include "Runtime/CFactoryMgr.hpp"
#include "Runtime/Character/CSkinBank.hpp" #include "Runtime/Character/CSegId.hpp"
#include "Runtime/Graphics/CCubeModel.hpp"
#include "Runtime/RetroTypes.hpp" #include "Runtime/RetroTypes.hpp"
#include <zeus/CVector3f.hpp> #include <zeus/CVector3f.hpp>
namespace metaforce { namespace metaforce {
class CCharLayoutInfo;
class CPoseAsTransforms; class CPoseAsTransforms;
class CModel; class CModel;
@ -24,12 +26,20 @@ class CVirtualBone {
rstl::reserved_vector<SSkinWeighting, 3> x0_weights; rstl::reserved_vector<SSkinWeighting, 3> x0_weights;
u32 x1c_vertexCount; u32 x1c_vertexCount;
zeus::CTransform x20_xf; zeus::CTransform x20_xf;
zeus::CMatrix3f x50_mtx; zeus::CMatrix3f x50_rotation;
public: public:
explicit CVirtualBone(CInputStream& in); explicit CVirtualBone(CInputStream& in);
[[nodiscard]] const rstl::reserved_vector<SSkinWeighting, 3>& GetWeights() const { return x0_weights; } void BuildPoints(const zeus::CVector3f* in, TVectorRef out, u32 count) const;
void BuildNormals(const zeus::CVector3f* in, TVectorRef out, u32 count) const;
void BuildAccumulatedTransform(const CPoseAsTransforms& pose, const zeus::CVector3f* points);
[[nodiscard]] const auto& GetWeights() const { return x0_weights; }
[[nodiscard]] u32 GetVertexCount() const { return x1c_vertexCount; }
private:
void BuildFinalPosMatrix(const CPoseAsTransforms& pose, const zeus::CVector3f* points);
}; };
class CSkinRules { class CSkinRules {
@ -42,17 +52,12 @@ class CSkinRules {
public: public:
explicit CSkinRules(CInputStream& in); explicit CSkinRules(CInputStream& in);
// void GetBankTransforms(std::vector<const zeus::CTransform*>& out, const CPoseAsTransforms& pose, void BuildPoints(TConstVectorRef positions, TVectorRef out);
// int skinBankIdx) const { void BuildNormals(TConstVectorRef normals, TVectorRef out);
// // FIXME: This is definitely not proper behavior, this is here to fix the phazon suit crashing void BuildAccumulatedTransforms(const CPoseAsTransforms& pose, const CCharLayoutInfo& info);
// if (x0_skinBanks.size() <= skinBankIdx) {
// return;
// }
// x0_skinBanks[skinBankIdx].GetBankTransforms(out, pose);
// }
// void TransformVerticesCPU(std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vnOut, [[nodiscard]] u32 GetVertexCount() const { return x10_vertexCount; }
// const CPoseAsTransforms& pose, const CModel& model) const; [[nodiscard]] u32 GetNormalCount() const { return x14_normalCount; }
}; };
CFactoryFnReturn FSkinRulesFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& params, CFactoryFnReturn FSkinRulesFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& params,

View File

@ -121,7 +121,7 @@ void CCubeModel::Draw(const CModelFlags& flags) {
DrawSurfaces(flags); DrawSurfaces(flags);
} }
void CCubeModel::Draw(TVectorRef positions, TVectorRef normals, const CModelFlags& flags) { void CCubeModel::Draw(TConstVectorRef positions, TConstVectorRef normals, const CModelFlags& flags) {
CCubeMaterial::KillCachedViewDepState(); CCubeMaterial::KillCachedViewDepState();
SetSkinningArraysCurrent(positions, normals); SetSkinningArraysCurrent(positions, normals);
DrawSurfaces(flags); DrawSurfaces(flags);
@ -149,7 +149,7 @@ void CCubeModel::DrawAlphaSurfaces(const CModelFlags& flags) {
} }
} }
void CCubeModel::DrawFlat(TVectorRef positions, TVectorRef normals, ESurfaceSelection surfaces) { void CCubeModel::DrawFlat(TConstVectorRef positions, TConstVectorRef normals, ESurfaceSelection surfaces) {
if (positions == nullptr) { if (positions == nullptr) {
SetArraysCurrent(); SetArraysCurrent();
} else { } else {
@ -175,7 +175,7 @@ void CCubeModel::DrawFlat(TVectorRef positions, TVectorRef normals, ESurfaceSele
} }
} }
void CCubeModel::DrawNormal(TVectorRef positions, TVectorRef normals, ESurfaceSelection surfaces) { void CCubeModel::DrawNormal(TConstVectorRef positions, TConstVectorRef normals, ESurfaceSelection surfaces) {
CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, true); CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, true);
CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::skPassZero); CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::skPassZero);
CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru); CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru);
@ -277,7 +277,7 @@ void CCubeModel::SetRenderModelBlack(bool v) {
// TODO another value is set here, but always 0? // TODO another value is set here, but always 0?
} }
void CCubeModel::SetSkinningArraysCurrent(TVectorRef positions, TVectorRef normals) { void CCubeModel::SetSkinningArraysCurrent(TConstVectorRef positions, TConstVectorRef normals) {
aurora::gfx::model::set_vertex_buffer(positions); aurora::gfx::model::set_vertex_buffer(positions);
aurora::gfx::model::set_normal_buffer(normals); aurora::gfx::model::set_normal_buffer(normals);
// colors unused // colors unused

View File

@ -21,7 +21,8 @@ enum class ESurfaceSelection {
}; };
// These parameters were originally float* // These parameters were originally float*
using TVectorRef = const std::vector<zeus::CVector3f>*; using TVectorRef = std::vector<zeus::CVector3f>*;
using TConstVectorRef = const std::vector<zeus::CVector3f>*;
class CCubeModel { class CCubeModel {
friend class CModel; friend class CModel;
@ -55,8 +56,10 @@ private:
[[nodiscard]] std::vector<CCubeSurface>* Surfaces() const { return x0_surfacePtrs; } [[nodiscard]] std::vector<CCubeSurface>* Surfaces() const { return x0_surfacePtrs; }
[[nodiscard]] u8* GetMaterialPointer() const { return x4_materialData; } [[nodiscard]] u8* GetMaterialPointer() const { return x4_materialData; }
void SetMaterialPointer(u8* mat) { x4_materialData = mat; } void SetMaterialPointer(u8* mat) { x4_materialData = mat; }
[[nodiscard]] TVectorRef GetVertexPointer() const { return x8_positions; } [[nodiscard]] TVectorRef GetVertexPointer() { return x8_positions; }
[[nodiscard]] TVectorRef GetNormalPointer() const { return xc_normals; } [[nodiscard]] TConstVectorRef GetVertexPointer() const { return x8_positions; }
[[nodiscard]] TVectorRef GetNormalPointer() { return xc_normals; }
[[nodiscard]] TConstVectorRef GetNormalPointer() const { return xc_normals; }
[[nodiscard]] std::vector<zeus::CColor>* GetColorPointer() const { return x10_colors; } [[nodiscard]] std::vector<zeus::CColor>* GetColorPointer() const { return x10_colors; }
[[nodiscard]] std::vector<aurora::Vec2<float>>* GetTCPointer() const { return x14_texCoords; } [[nodiscard]] std::vector<aurora::Vec2<float>>* GetTCPointer() const { return x14_texCoords; }
[[nodiscard]] std::vector<aurora::Vec2<float>>* GetPackedTCPointer() const { return x18_packedTexCoords; } [[nodiscard]] std::vector<aurora::Vec2<float>>* GetPackedTCPointer() const { return x18_packedTexCoords; }
@ -84,8 +87,8 @@ public:
void RemapMaterialData(u8* data, std::vector<TCachedToken<CTexture>>& textures); void RemapMaterialData(u8* data, std::vector<TCachedToken<CTexture>>& textures);
void Draw(const CModelFlags& flags); void Draw(const CModelFlags& flags);
void DrawAlpha(const CModelFlags& flags); void DrawAlpha(const CModelFlags& flags);
void DrawFlat(TVectorRef positions, TVectorRef normals, ESurfaceSelection surfaces); void DrawFlat(TConstVectorRef positions, TConstVectorRef normals, ESurfaceSelection surfaces);
void DrawNormal(TVectorRef positions, TVectorRef normals, ESurfaceSelection surfaces); void DrawNormal(TConstVectorRef positions, TConstVectorRef normals, ESurfaceSelection surfaces);
void DrawNormal(const CModelFlags& flags); void DrawNormal(const CModelFlags& flags);
void DrawSurface(const CCubeSurface& surface, const CModelFlags& flags); void DrawSurface(const CCubeSurface& surface, const CModelFlags& flags);
void DrawSurfaceWireframe(const CCubeSurface& surface); void DrawSurfaceWireframe(const CCubeSurface& surface);
@ -101,8 +104,10 @@ public:
[[nodiscard]] CCubeSurface* GetFirstSortedSurface() { return x3c_firstSortedSurf; } [[nodiscard]] CCubeSurface* GetFirstSortedSurface() { return x3c_firstSortedSurf; }
[[nodiscard]] const CCubeSurface* GetFirstSortedSurface() const { return x3c_firstSortedSurf; } [[nodiscard]] const CCubeSurface* GetFirstSortedSurface() const { return x3c_firstSortedSurf; }
[[nodiscard]] TVectorRef GetPositions() const { return x0_modelInstance.GetVertexPointer(); } [[nodiscard]] TVectorRef GetPositions() { return x0_modelInstance.GetVertexPointer(); }
[[nodiscard]] TVectorRef GetNormals() const { return x0_modelInstance.GetNormalPointer(); } [[nodiscard]] TConstVectorRef GetPositions() const { return x0_modelInstance.GetVertexPointer(); }
[[nodiscard]] TVectorRef GetNormals() { return x0_modelInstance.GetNormalPointer(); }
[[nodiscard]] TConstVectorRef GetNormals() const { return x0_modelInstance.GetNormalPointer(); }
[[nodiscard]] TCachedToken<CTexture>& GetTexture(u32 idx) const { return x1c_textures->at(idx); } [[nodiscard]] TCachedToken<CTexture>& GetTexture(u32 idx) const { return x1c_textures->at(idx); }
static void EnableShadowMaps(const CTexture& shadowTex, const zeus::CTransform& textureProjXf, u8 chan0DisableMask, static void EnableShadowMaps(const CTexture& shadowTex, const zeus::CTransform& textureProjXf, u8 chan0DisableMask,
@ -121,11 +126,11 @@ public:
static const CTexture* sShadowTexture; static const CTexture* sShadowTexture;
private: private:
void Draw(TVectorRef positions, TVectorRef normals, const CModelFlags& flags); void Draw(TConstVectorRef positions, TConstVectorRef normals, const CModelFlags& flags);
void DrawAlphaSurfaces(const CModelFlags& flags); void DrawAlphaSurfaces(const CModelFlags& flags);
void DrawNormalSurfaces(const CModelFlags& flags); void DrawNormalSurfaces(const CModelFlags& flags);
void DrawSurfaces(const CModelFlags& flags); void DrawSurfaces(const CModelFlags& flags);
void SetSkinningArraysCurrent(TVectorRef positions, TVectorRef normals); void SetSkinningArraysCurrent(TConstVectorRef positions, TConstVectorRef normals);
void SetStaticArraysCurrent(); void SetStaticArraysCurrent();
}; };
} // namespace metaforce } // namespace metaforce

View File

@ -634,9 +634,9 @@ u32 CCubeRenderer::GetFPS() { return CGraphics::GetFPS(); }
void CCubeRenderer::CacheReflection(IRenderer::TReflectionCallback cb, void* ctx, bool clearAfter) {} void CCubeRenderer::CacheReflection(IRenderer::TReflectionCallback cb, void* ctx, bool clearAfter) {}
void CCubeRenderer::DrawSpaceWarp(const zeus::CVector3f& pt, float strength) {} void CCubeRenderer::DrawSpaceWarp(const zeus::CVector3f& pt, float strength) {}
void CCubeRenderer::DrawThermalModel(const CModel& model, const zeus::CColor& multCol, const zeus::CColor& addCol, void CCubeRenderer::DrawThermalModel(const CModel& model, const zeus::CColor& multCol, const zeus::CColor& addCol,
TVectorRef positions, TVectorRef normals, const CModelFlags& flags) {} TConstVectorRef positions, TConstVectorRef normals, const CModelFlags& flags) {}
void CCubeRenderer::DrawModelDisintegrate(const CModel& model, const CTexture& tex, const zeus::CColor& color, void CCubeRenderer::DrawModelDisintegrate(const CModel& model, const CTexture& tex, const zeus::CColor& color,
TVectorRef positions, TVectorRef normals) {} TConstVectorRef positions, TConstVectorRef normals) {}
void CCubeRenderer::DrawModelFlat(const CModel& model, const CModelFlags& flags, bool unsortedOnly) {} void CCubeRenderer::DrawModelFlat(const CModel& model, const CModelFlags& flags, bool unsortedOnly) {}
void CCubeRenderer::SetWireframeFlags(s32 flags) {} void CCubeRenderer::SetWireframeFlags(s32 flags) {}
void CCubeRenderer::SetWorldFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color) {} void CCubeRenderer::SetWorldFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color) {}

View File

@ -180,9 +180,9 @@ public:
void CacheReflection(TReflectionCallback cb, void* ctx, bool clearAfter) override; void CacheReflection(TReflectionCallback cb, void* ctx, bool clearAfter) override;
void DrawSpaceWarp(const zeus::CVector3f& pt, float strength) override; void DrawSpaceWarp(const zeus::CVector3f& pt, float strength) override;
void DrawThermalModel(const CModel& model, const zeus::CColor& multCol, const zeus::CColor& addCol, void DrawThermalModel(const CModel& model, const zeus::CColor& multCol, const zeus::CColor& addCol,
TVectorRef positions, TVectorRef normals, const CModelFlags& flags) override; TConstVectorRef positions, TConstVectorRef normals, const CModelFlags& flags) override;
void DrawModelDisintegrate(const CModel& model, const CTexture& tex, const zeus::CColor& color, TVectorRef positions, void DrawModelDisintegrate(const CModel& model, const CTexture& tex, const zeus::CColor& color,
TVectorRef normals) override; TConstVectorRef positions, TConstVectorRef normals) override;
void DrawModelFlat(const CModel& model, const CModelFlags& flags, bool unsortedOnly) override; void DrawModelFlat(const CModel& model, const CModelFlags& flags, bool unsortedOnly) override;
void SetWireframeFlags(s32 flags) override; void SetWireframeFlags(s32 flags) override;
void SetWorldFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color) override; void SetWorldFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color) override;

View File

@ -37,8 +37,10 @@ public:
[[nodiscard]] std::vector<CCubeSurface>* GetSurfaces() { return &x50_surfaces; } [[nodiscard]] std::vector<CCubeSurface>* GetSurfaces() { return &x50_surfaces; }
[[nodiscard]] const std::vector<CCubeSurface>* GetSurfaces() const { return &x50_surfaces; } [[nodiscard]] const std::vector<CCubeSurface>* GetSurfaces() const { return &x50_surfaces; }
[[nodiscard]] const u8* GetMaterialPointer() const { return x4c_materialData; } [[nodiscard]] const u8* GetMaterialPointer() const { return x4c_materialData; }
[[nodiscard]] TVectorRef GetVertexPointer() const { return &x60_positions; } [[nodiscard]] TVectorRef GetVertexPointer() { return &x60_positions; }
[[nodiscard]] TVectorRef GetNormalPointer() const { return &x64_normals; } [[nodiscard]] TConstVectorRef GetVertexPointer() const { return &x60_positions; }
[[nodiscard]] TVectorRef GetNormalPointer() { return &x64_normals; }
[[nodiscard]] TConstVectorRef GetNormalPointer() const { return &x64_normals; }
[[nodiscard]] const std::vector<zeus::CColor>* GetColorPointer() const { return &x68_colors; } [[nodiscard]] const std::vector<zeus::CColor>* GetColorPointer() const { return &x68_colors; }
[[nodiscard]] const std::vector<aurora::Vec2<float>>* GetTCPointer() const { return &x6c_texCoords; } [[nodiscard]] const std::vector<aurora::Vec2<float>>* GetTCPointer() const { return &x6c_texCoords; }
[[nodiscard]] const std::vector<aurora::Vec2<float>>* GetPackedTCPointer() const { return &x70_packedTexCoords; } [[nodiscard]] const std::vector<aurora::Vec2<float>>* GetPackedTCPointer() const { return &x70_packedTexCoords; }

View File

@ -201,9 +201,13 @@ void CModel::EnableTextureTimeout() { sIsTextureTimeoutEnabled = true; }
void CModel::DisableTextureTimeout() { sIsTextureTimeoutEnabled = false; } void CModel::DisableTextureTimeout() { sIsTextureTimeoutEnabled = false; }
TVectorRef CModel::GetPositions() const { return x28_modelInst->GetPositions(); } TVectorRef CModel::GetPositions() { return x28_modelInst->GetPositions(); }
TVectorRef CModel::GetNormals() const { return x28_modelInst->GetNormals(); } TConstVectorRef CModel::GetPositions() const { return x28_modelInst->GetPositions(); }
TVectorRef CModel::GetNormals() { return x28_modelInst->GetNormals(); }
TConstVectorRef CModel::GetNormals() const { return x28_modelInst->GetNormals(); }
void CModel::VerifyCurrentShader(u32 matIdx) { void CModel::VerifyCurrentShader(u32 matIdx) {
if (matIdx > x18_matSets.size()) { if (matIdx > x18_matSets.size()) {
@ -264,7 +268,7 @@ void CModel::Draw(CModelFlags flags) {
x28_modelInst->Draw(flags); x28_modelInst->Draw(flags);
} }
void CModel::Draw(TVectorRef positions, TVectorRef normals, const CModelFlags& flags) { void CModel::Draw(TConstVectorRef positions, TConstVectorRef normals, const CModelFlags& flags) {
if (flags.x2_flags & CModelFlagBits::DrawNormal) { if (flags.x2_flags & CModelFlagBits::DrawNormal) {
x28_modelInst->DrawNormal(positions, normals, ESurfaceSelection::All); x28_modelInst->DrawNormal(positions, normals, ESurfaceSelection::All);
} }

View File

@ -100,13 +100,15 @@ public:
void VerifyCurrentShader(u32 matIdx); void VerifyCurrentShader(u32 matIdx);
void Touch(u32 matIdx); void Touch(u32 matIdx);
void Draw(CModelFlags flags); void Draw(CModelFlags flags);
void Draw(TVectorRef positions, TVectorRef normals, const CModelFlags& flags); void Draw(TConstVectorRef positions, TConstVectorRef normals, const CModelFlags& flags);
void DrawSortedParts(CModelFlags flags); void DrawSortedParts(CModelFlags flags);
void DrawUnsortedParts(CModelFlags flags); void DrawUnsortedParts(CModelFlags flags);
bool IsLoaded(u32 matIdx); bool IsLoaded(u32 matIdx);
TVectorRef GetPositions() const; TVectorRef GetPositions();
TVectorRef GetNormals() const; TConstVectorRef GetPositions() const;
TVectorRef GetNormals();
TConstVectorRef GetNormals() const;
u32 GetNumMaterialSets() const { return x18_matSets.size(); } u32 GetNumMaterialSets() const { return x18_matSets.size(); }
bool IsOpaque() const { return x28_modelInst->x3c_firstSortedSurf == nullptr; } bool IsOpaque() const { return x28_modelInst->x3c_firstSortedSurf == nullptr; }
const zeus::CAABox& GetAABB() const { return x28_modelInst->x20_worldAABB; } const zeus::CAABox& GetAABB() const { return x28_modelInst->x20_worldAABB; }

View File

@ -70,8 +70,7 @@ void CRainSplashGenerator::Draw(const zeus::CTransform& xf) {
DoDraw(xf); DoDraw(xf);
} }
CRainSplashGenerator::SSplashLine::SSplashLine() CRainSplashGenerator::SSplashLine::SSplashLine() : m_renderer(CLineRenderer::EPrimitiveMode::LineStrip, 3, {}, false) {}
: m_renderer(CLineRenderer::EPrimitiveMode::LineStrip, 3, {}, false) {}
CRainSplashGenerator::SRainSplash::SRainSplash() { CRainSplashGenerator::SRainSplash::SRainSplash() {
for (size_t i = 0; i < x0_lines.capacity(); ++i) { for (size_t i = 0; i < x0_lines.capacity(); ++i) {
@ -146,16 +145,16 @@ void CRainSplashGenerator::Update(float dt, CStateManager& mgr) {
} }
} }
u32 CRainSplashGenerator::GetNextBestPt(u32 pt, const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn, u32 CRainSplashGenerator::GetNextBestPt(u32 pt, const SSkinningWorkspace& workspace, CRandom16& rand, float minZ) {
CRandom16& rand, float minZ) { const auto& refVert = workspace.m_vertexWorkspace[pt];
const auto& refVert = vn[pt];
float maxDist = 0.f; float maxDist = 0.f;
u32 nextPt = pt; u32 nextPt = pt;
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
const auto idx = u32(rand.Range(0, int(vn.size() - 1))); const auto idx = u32(rand.Range(0, int(workspace.m_vertexWorkspace.size() - 1)));
const auto& vert = vn[idx]; const auto& vert = workspace.m_vertexWorkspace[idx];
const float distSq = (refVert.first - vert.first).magSquared(); const auto& norm = workspace.m_normalWorkspace[idx];
if (distSq > maxDist && vert.second.dot(zeus::skUp) >= 0.f && (vert.first.z() <= 0.f || vert.first.z() > minZ)) { const float distSq = (refVert - vert).magSquared();
if (distSq > maxDist && norm.dot(zeus::skUp) >= 0.f && (vert.z() <= 0.f || vert.z() > minZ)) {
nextPt = idx; nextPt = idx;
maxDist = distSq; maxDist = distSq;
} }
@ -177,7 +176,7 @@ void CRainSplashGenerator::AddPoint(const zeus::CVector3f& pos) {
x38_queueTail += 1; x38_queueTail += 1;
} }
void CRainSplashGenerator::GeneratePoints(const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn) { void CRainSplashGenerator::GeneratePoints(const SSkinningWorkspace& workspace) {
if (!x48_25_raining) if (!x48_25_raining)
return; return;
@ -185,8 +184,8 @@ void CRainSplashGenerator::GeneratePoints(const std::vector<std::pair<zeus::CVec
for (u32 i = 0; i < x44_genRate; ++i) { for (u32 i = 0; i < x44_genRate; ++i) {
if (x40_queueSize >= x0_rainSplashes.size()) if (x40_queueSize >= x0_rainSplashes.size())
break; break;
x34_curPoint = GetNextBestPt(x34_curPoint, vn, x10_random, x2c_minZ); x34_curPoint = GetNextBestPt(x34_curPoint, workspace, x10_random, x2c_minZ);
AddPoint(x14_scale * vn[x34_curPoint].first); AddPoint(x14_scale * workspace.m_vertexWorkspace[x34_curPoint]);
} }
x20_generateTimer = 0.f; x20_generateTimer = 0.f;
} }

View File

@ -7,6 +7,7 @@
#include "Runtime/RetroTypes.hpp" #include "Runtime/RetroTypes.hpp"
#include "Runtime/rstl.hpp" #include "Runtime/rstl.hpp"
#include "Runtime/Graphics/CLineRenderer.hpp" #include "Runtime/Graphics/CLineRenderer.hpp"
#include "Runtime/Graphics/CSkinnedModel.hpp"
#include <zeus/CVector3f.hpp> #include <zeus/CVector3f.hpp>
@ -61,14 +62,13 @@ class CRainSplashGenerator {
void UpdateRainSplashRange(CStateManager& mgr, int start, int end, float dt); void UpdateRainSplashRange(CStateManager& mgr, int start, int end, float dt);
void UpdateRainSplashes(CStateManager& mgr, float magnitude, float dt); void UpdateRainSplashes(CStateManager& mgr, float magnitude, float dt);
void DoDraw(const zeus::CTransform& xf); void DoDraw(const zeus::CTransform& xf);
static u32 GetNextBestPt(u32 pt, const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn, CRandom16& rand, static u32 GetNextBestPt(u32 pt, const SSkinningWorkspace& workspace, CRandom16& rand, float minZ);
float minZ);
void AddPoint(const zeus::CVector3f& pos); void AddPoint(const zeus::CVector3f& pos);
public: public:
CRainSplashGenerator(const zeus::CVector3f& scale, u32 maxSplashes, u32 genRate, float minZ, float alpha); CRainSplashGenerator(const zeus::CVector3f& scale, u32 maxSplashes, u32 genRate, float minZ, float alpha);
void Update(float dt, CStateManager& mgr); void Update(float dt, CStateManager& mgr);
void GeneratePoints(const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn); void GeneratePoints(const SSkinningWorkspace& workspace);
void Draw(const zeus::CTransform& xf); void Draw(const zeus::CTransform& xf);
bool IsRaining() const { return x48_25_raining; } bool IsRaining() const { return x48_25_raining; }
}; };

View File

@ -4,13 +4,17 @@
#include "Runtime/Graphics/CVertexMorphEffect.hpp" #include "Runtime/Graphics/CVertexMorphEffect.hpp"
#include <logvisor/logvisor.hpp> #include <logvisor/logvisor.hpp>
#include <list>
namespace metaforce { namespace metaforce {
static logvisor::Module Log("metaforce::CSkinnedModel"); static logvisor::Module Log("metaforce::CSkinnedModel");
CSkinnedModel::CSkinnedModel(const TLockedToken<CModel>& model, const TLockedToken<CSkinRules>& skinRules, CSkinnedModel::CSkinnedModel(const TLockedToken<CModel>& model, const TLockedToken<CSkinRules>& skinRules,
const TLockedToken<CCharLayoutInfo>& layoutInfo) const TLockedToken<CCharLayoutInfo>& layoutInfo)
: x4_model(std::move(model)), x10_skinRules(std::move(skinRules)), x1c_layoutInfo(std::move(layoutInfo)) { : x4_model(std::move(model))
, x10_skinRules(std::move(skinRules))
, x1c_layoutInfo(std::move(layoutInfo))
, m_workspace(*x10_skinRules) {
if (!x4_model) { if (!x4_model) {
Log.report(logvisor::Fatal, FMT_STRING("bad model token provided to CSkinnedModel")); Log.report(logvisor::Fatal, FMT_STRING("bad model token provided to CSkinnedModel"));
} }
@ -26,32 +30,36 @@ CSkinnedModel::CSkinnedModel(IObjectStore& store, CAssetId model, CAssetId skinR
: CSkinnedModel(store.GetObj(SObjectTag{FOURCC('CMDL'), model}), store.GetObj(SObjectTag{FOURCC('CSKR'), skinRules}), : CSkinnedModel(store.GetObj(SObjectTag{FOURCC('CMDL'), model}), store.GetObj(SObjectTag{FOURCC('CSKR'), skinRules}),
store.GetObj(SObjectTag{FOURCC('CINF'), layoutInfo})) {} store.GetObj(SObjectTag{FOURCC('CINF'), layoutInfo})) {}
void CSkinnedModel::Calculate(const CPoseAsTransforms& pose, const std::optional<CVertexMorphEffect>& morphEffect, void CSkinnedModel::AllocateStorage() {
const float* morphMagnitudes) { if (x34_owned) {
// TODO m_workspace.Reset(*x10_skinRules);
// if (morphEffect || g_PointGenFunc) { }
// if (boo::ObjToken<boo::IGraphicsBufferD> vertBuf = m_modelInst->UpdateUniformData(drawFlags, nullptr, nullptr))
// {
// x10_skinRules->TransformVerticesCPU(m_vertWorkspace, pose, *x4_model);
// if (morphEffect)
// morphEffect->MorphVertices(m_vertWorkspace, morphMagnitudes, x10_skinRules, pose);
// if (g_PointGenFunc)
// g_PointGenFunc(g_PointGenCtx, m_vertWorkspace);
// x4_model->ApplyVerticesCPU(vertBuf, m_vertWorkspace);
// m_modifiedVBO = true;
// }
// } else {
// if (boo::ObjToken<boo::IGraphicsBufferD> vertBuf =
// m_modelInst->UpdateUniformData(drawFlags, x10_skinRules.GetObj(), &pose)) {
// if (m_modifiedVBO) {
// x4_model->RestoreVerticesCPU(vertBuf);
// m_modifiedVBO = false;
// }
// }
// }
} }
void CSkinnedModel::Draw(TVectorRef verts, TVectorRef norms, const CModelFlags& drawFlags) { void CSkinnedModel::Calculate(const CPoseAsTransforms& pose, const std::optional<CVertexMorphEffect>& morphEffect,
TConstVectorRef morphMagnitudes, SSkinningWorkspace* workspace) {
if (workspace == nullptr) {
if (x35_disableWorkspaces) {
x10_skinRules->BuildAccumulatedTransforms(pose, *x1c_layoutInfo);
return;
}
AllocateStorage();
workspace = &m_workspace;
}
x10_skinRules->BuildAccumulatedTransforms(pose, *x1c_layoutInfo);
x10_skinRules->BuildPoints(x4_model->GetPositions(), &workspace->m_vertexWorkspace);
x10_skinRules->BuildNormals(x4_model->GetNormals(), &workspace->m_normalWorkspace);
if (morphEffect) {
morphEffect->MorphVertices(*workspace, morphMagnitudes, x10_skinRules, pose);
}
if (g_PointGenFunc != nullptr) {
g_PointGenFunc(*workspace);
}
}
void CSkinnedModel::Draw(TConstVectorRef verts, TConstVectorRef norms, const CModelFlags& drawFlags) {
OPTICK_EVENT(); OPTICK_EVENT();
x4_model->Draw(verts, norms, drawFlags); x4_model->Draw(verts, norms, drawFlags);
// PostDrawFunc(); // PostDrawFunc();
@ -63,10 +71,10 @@ void CSkinnedModel::Draw(const CModelFlags& drawFlags) {
CGraphics::SetModelMatrix(mtx * x10_skinRules->x0_bones.front().x20_xf); CGraphics::SetModelMatrix(mtx * x10_skinRules->x0_bones.front().x20_xf);
x4_model->Draw(drawFlags); x4_model->Draw(drawFlags);
CGraphics::SetModelMatrix(mtx); CGraphics::SetModelMatrix(mtx);
} else if (x24_vertWorkspace.empty()) { } else if (m_workspace.IsEmpty()) {
x4_model->Draw(drawFlags); x4_model->Draw(drawFlags);
} else { } else {
x4_model->Draw(&x24_vertWorkspace, &x2c_normalWorkspace, drawFlags); x4_model->Draw(&m_workspace.m_vertexWorkspace, &m_workspace.m_normalWorkspace, drawFlags);
// PostDrawFunc(); // PostDrawFunc();
} }
} }
@ -77,19 +85,49 @@ void CSkinnedModel::DoDrawCallback(const FCustomDraw& func) const {
CGraphics::SetModelMatrix(mtx * x10_skinRules->x0_bones.front().x20_xf); CGraphics::SetModelMatrix(mtx * x10_skinRules->x0_bones.front().x20_xf);
func(x4_model->GetPositions(), x4_model->GetNormals()); func(x4_model->GetPositions(), x4_model->GetNormals());
CGraphics::SetModelMatrix(mtx); CGraphics::SetModelMatrix(mtx);
} else if (x24_vertWorkspace.empty()) { } else if (m_workspace.IsEmpty()) {
func(x4_model->GetPositions(), x4_model->GetNormals()); func(x4_model->GetPositions(), x4_model->GetNormals());
} else { } else {
func(&x24_vertWorkspace, &x2c_normalWorkspace); func(&m_workspace.m_vertexWorkspace, &m_workspace.m_normalWorkspace);
// PostDrawFunc(); // PostDrawFunc();
} }
} }
CMorphableSkinnedModel::CMorphableSkinnedModel(IObjectStore& store, CAssetId model, CAssetId skinRules, CMorphableSkinnedModel::CMorphableSkinnedModel(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& modelPositions = *GetModel()->GetPositions();
CSkinnedModel::FPointGenerator CSkinnedModel::g_PointGenFunc = nullptr; x40_morphMagnitudes.resize(vertexCount);
void* CSkinnedModel::g_PointGenCtx = nullptr; std::vector<std::pair<zeus::CVector3f, std::list<u32>>> vertMap;
for (int vertIdx = 0; vertIdx < vertexCount; ++vertIdx) {
const auto curPos = modelPositions[vertIdx];
if (std::find_if(vertMap.cbegin(), vertMap.cend(), [=](const auto& pair) { return pair.first.isEqu(curPos); }) ==
vertMap.cend()) {
auto& [_, list] = vertMap.emplace_back(curPos, std::list<u32>{});
for (int idx = vertIdx; idx < vertexCount; ++idx) {
// Originally uses ==, but adjusted to match above
if (modelPositions[idx].isEqu(curPos)) {
list.emplace_back(idx);
}
}
}
}
const auto& modelNormals = *GetModel()->GetNormals();
for (const auto& [_, idxs] : vertMap) {
zeus::CVector3f averagedNormal;
for (const auto idx : idxs) {
averagedNormal += modelNormals[idx];
}
averagedNormal.normalize();
for (const auto idx : idxs) {
x40_morphMagnitudes[idx] = averagedNormal;
}
}
}
FPointGenerator CSkinnedModel::g_PointGenFunc;
} // namespace metaforce } // namespace metaforce

View File

@ -18,15 +18,32 @@ class CPoseAsTransforms;
class CVertexMorphEffect; class CVertexMorphEffect;
class IObjectStore; class IObjectStore;
// Originally vert + normal workspaces were allocated together, but here separated for ease of use
struct SSkinningWorkspace {
std::vector<zeus::CVector3f> m_vertexWorkspace;
std::vector<zeus::CVector3f> m_normalWorkspace;
SSkinningWorkspace(const CSkinRules& rules) { Reset(rules); }
void Reset(const CSkinRules& rules) {
m_vertexWorkspace.clear();
m_normalWorkspace.clear();
m_vertexWorkspace.reserve(rules.GetVertexCount());
m_normalWorkspace.reserve(rules.GetNormalCount());
}
[[nodiscard]] bool IsEmpty() const { return m_vertexWorkspace.empty() || m_normalWorkspace.empty(); }
};
// Lambda instead of userdata pointer // Lambda instead of userdata pointer
using FCustomDraw = std::function<void(TVectorRef positions, TVectorRef normals)>; using FCustomDraw = std::function<void(TConstVectorRef positions, TConstVectorRef normals)>;
using FPointGenerator = std::function<void(const SSkinningWorkspace& workspace)>;
class CSkinnedModel { class CSkinnedModel {
TLockedToken<CModel> x4_model; TLockedToken<CModel> x4_model;
TLockedToken<CSkinRules> x10_skinRules; TLockedToken<CSkinRules> x10_skinRules;
TLockedToken<CCharLayoutInfo> x1c_layoutInfo; TLockedToken<CCharLayoutInfo> x1c_layoutInfo;
std::vector<zeus::CVector3f> x24_vertWorkspace; // was rstl::auto_ptr<float[]> // rstl::auto_ptr<float[]> x24_vertWorkspace;
std::vector<zeus::CVector3f> x2c_normalWorkspace; // was rstl::auto_ptr<float[]> // rstl::auto_ptr<float[]> x2c_normalWorkspace;
SSkinningWorkspace m_workspace;
bool x34_owned = true; bool x34_owned = true;
bool x35_disableWorkspaces = false; bool x35_disableWorkspaces = false;
@ -42,28 +59,25 @@ public:
void SetLayoutInfo(const TLockedToken<CCharLayoutInfo>& inf) { x1c_layoutInfo = inf; } void SetLayoutInfo(const TLockedToken<CCharLayoutInfo>& inf) { x1c_layoutInfo = inf; }
const TLockedToken<CCharLayoutInfo>& GetLayoutInfo() const { return x1c_layoutInfo; } const TLockedToken<CCharLayoutInfo>& GetLayoutInfo() const { return x1c_layoutInfo; }
void AllocateStorage();
void Calculate(const CPoseAsTransforms& pose, const std::optional<CVertexMorphEffect>& morphEffect, void Calculate(const CPoseAsTransforms& pose, const std::optional<CVertexMorphEffect>& morphEffect,
const float* morphMagnitudes); TConstVectorRef averagedNormals, SSkinningWorkspace* workspace);
void Draw(TVectorRef verts, TVectorRef 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;
using FPointGenerator = void (*)(void* item, const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn); static void SetPointGeneratorFunc(FPointGenerator func) { g_PointGenFunc = std::move(func); }
static void SetPointGeneratorFunc(void* ctx, FPointGenerator func) {
g_PointGenFunc = func;
g_PointGenCtx = ctx;
}
static void ClearPointGeneratorFunc() { g_PointGenFunc = nullptr; } static void ClearPointGeneratorFunc() { g_PointGenFunc = nullptr; }
static FPointGenerator g_PointGenFunc; static FPointGenerator g_PointGenFunc;
static void* g_PointGenCtx;
}; };
class CMorphableSkinnedModel : public CSkinnedModel { class CMorphableSkinnedModel : public CSkinnedModel {
std::unique_ptr<float[]> x40_morphMagnitudes; std::vector<zeus::CVector3f> x40_morphMagnitudes; // was rstl::auto_ptr<float[]>
public: public:
CMorphableSkinnedModel(IObjectStore& store, CAssetId model, CAssetId skinRules, CAssetId layoutInfo); CMorphableSkinnedModel(IObjectStore& store, CAssetId model, CAssetId skinRules, CAssetId layoutInfo);
const float* GetMorphMagnitudes() const { return x40_morphMagnitudes.get(); } TConstVectorRef GetMorphMagnitudes() const { return &x40_morphMagnitudes; }
TVectorRef GetMorphMagnitudes() { return &x40_morphMagnitudes; }
}; };
} // namespace metaforce } // namespace metaforce

View File

@ -8,8 +8,8 @@ CVertexMorphEffect::CVertexMorphEffect(const zeus::CUnitVector3f& v1, const zeus
float f2, CRandom16& random) float f2, CRandom16& random)
: x0_(v1), x20_diagExtent(diagExtent), x24_random(random) {} : x0_(v1), x20_diagExtent(diagExtent), x24_random(random) {}
void CVertexMorphEffect::MorphVertices(std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn, void CVertexMorphEffect::MorphVertices(SSkinningWorkspace& workspace, TConstVectorRef magnitudes,
const float* magnitudes, const TLockedToken<CSkinRules>& skinRules, const TLockedToken<CSkinRules>& skinRules, const CPoseAsTransforms& pose) const {
const CPoseAsTransforms& pose) const {} }
} // namespace metaforce } // namespace metaforce

View File

@ -5,6 +5,7 @@
#include "Runtime/CToken.hpp" #include "Runtime/CToken.hpp"
#include "Runtime/Character/CPoseAsTransforms.hpp" #include "Runtime/Character/CPoseAsTransforms.hpp"
#include "Runtime/Graphics/CCubeModel.hpp"
#include <zeus/CUnitVector.hpp> #include <zeus/CUnitVector.hpp>
#include <zeus/CVector3f.hpp> #include <zeus/CVector3f.hpp>
@ -12,6 +13,7 @@
namespace metaforce { namespace metaforce {
class CRandom16; class CRandom16;
class CSkinRules; class CSkinRules;
struct SSkinningWorkspace;
class CVertexMorphEffect { class CVertexMorphEffect {
zeus::CUnitVector3f x0_; zeus::CUnitVector3f x0_;
@ -28,7 +30,7 @@ class CVertexMorphEffect {
public: public:
CVertexMorphEffect(const zeus::CUnitVector3f& v1, const zeus::CVector3f& v2, float diagExtent, float f2, CVertexMorphEffect(const zeus::CUnitVector3f& v1, const zeus::CVector3f& v2, float diagExtent, float f2,
CRandom16& random); CRandom16& random);
void MorphVertices(std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn, const float* magnitudes, void MorphVertices(SSkinningWorkspace& workspace, TConstVectorRef magnitudes,
const TLockedToken<CSkinRules>& skinRules, const CPoseAsTransforms& pose) const; const TLockedToken<CSkinRules>& skinRules, const CPoseAsTransforms& pose) const;
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) {}

View File

@ -93,9 +93,9 @@ public:
virtual void CacheReflection(TReflectionCallback cb, void* ctx, bool clearAfter) = 0; virtual void CacheReflection(TReflectionCallback cb, void* ctx, bool clearAfter) = 0;
virtual void DrawSpaceWarp(const zeus::CVector3f& pt, float strength) = 0; virtual void DrawSpaceWarp(const zeus::CVector3f& pt, float strength) = 0;
virtual void DrawThermalModel(const CModel& model, const zeus::CColor& multCol, const zeus::CColor& addCol, virtual void DrawThermalModel(const CModel& model, const zeus::CColor& multCol, const zeus::CColor& addCol,
TVectorRef positions, TVectorRef normals, const CModelFlags& flags) = 0; TConstVectorRef positions, TConstVectorRef normals, const CModelFlags& flags) = 0;
virtual void DrawModelDisintegrate(const CModel& model, const CTexture& tex, const zeus::CColor& color, virtual void DrawModelDisintegrate(const CModel& model, const CTexture& tex, const zeus::CColor& color,
TVectorRef positions, TVectorRef normals) = 0; TConstVectorRef positions, TConstVectorRef normals) = 0;
virtual void DrawModelFlat(const CModel& model, const CModelFlags& flags, bool unsortedOnly) = 0; virtual void DrawModelFlat(const CModel& model, const CModelFlags& flags, bool unsortedOnly) = 0;
virtual void SetWireframeFlags(s32 flags) = 0; virtual void SetWireframeFlags(s32 flags) = 0;
virtual void SetWorldFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color) = 0; virtual void SetWorldFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color) = 0;

View File

@ -501,10 +501,6 @@ void CGrappleArm::RenderXRayModel(const CStateManager& mgr, const zeus::CTransfo
// CGraphics::DisableAllLights(); // CGraphics::DisableAllLights();
} }
void CGrappleArm::PointGenerator(void* ctx, const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn) {
static_cast<CRainSplashGenerator*>(ctx)->GeneratePoints(vn);
}
void CGrappleArm::Render(const CStateManager& mgr, const zeus::CVector3f& pos, const CModelFlags& flags, void CGrappleArm::Render(const CStateManager& mgr, const zeus::CVector3f& pos, const CModelFlags& flags,
const CActorLights* lights) { const CActorLights* lights) {
if (!x3b2_24_active || x3b2_29_suitLoading) { if (!x3b2_24_active || x3b2_29_suitLoading) {
@ -528,7 +524,8 @@ void CGrappleArm::Render(const CStateManager& mgr, const zeus::CVector3f& pos, c
} }
if (x3a4_rainSplashGenerator && x3a4_rainSplashGenerator->IsRaining()) { if (x3a4_rainSplashGenerator && x3a4_rainSplashGenerator->IsRaining()) {
CSkinnedModel::SetPointGeneratorFunc(x3a4_rainSplashGenerator.get(), PointGenerator); CSkinnedModel::SetPointGeneratorFunc(
[&](const auto& workspace) { x3a4_rainSplashGenerator->GeneratePoints(workspace); });
} }
x0_grappleArmModel->Render(mgr, modelXf, useLights, useFlags); x0_grappleArmModel->Render(mgr, modelXf, useLights, useFlags);

View File

@ -102,8 +102,6 @@ private:
void UpdateSwingAction(float grappleSwingT, float dt, CStateManager& mgr); void UpdateSwingAction(float grappleSwingT, float dt, CStateManager& mgr);
void RenderXRayModel(const CStateManager& mgr, const zeus::CTransform& modelXf, const CModelFlags& flags); void RenderXRayModel(const CStateManager& mgr, const zeus::CTransform& modelXf, const CModelFlags& flags);
static void PointGenerator(void* ctx, const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn);
public: public:
explicit CGrappleArm(const zeus::CVector3f& scale); explicit CGrappleArm(const zeus::CVector3f& scale);
void AsyncLoadSuit(CStateManager& mgr); void AsyncLoadSuit(CStateManager& mgr);

View File

@ -250,10 +250,6 @@ void CGunWeapon::TouchHolo(const CStateManager& mgr) {
x60_holoModelData->Touch(mgr, 0); x60_holoModelData->Touch(mgr, 0);
} }
void CGunWeapon::PointGenerator(void* ctx, const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn) {
static_cast<CRainSplashGenerator*>(ctx)->GeneratePoints(vn);
}
void CGunWeapon::Draw(bool drawSuitArm, const CStateManager& mgr, const zeus::CTransform& xf, const CModelFlags& flags, void CGunWeapon::Draw(bool drawSuitArm, const CStateManager& mgr, const zeus::CTransform& xf, const CModelFlags& flags,
const CActorLights* lights) { const CActorLights* lights) {
if (!x218_26_loaded) if (!x218_26_loaded)
@ -262,7 +258,8 @@ void CGunWeapon::Draw(bool drawSuitArm, const CStateManager& mgr, const zeus::CT
zeus::CTransform armXf = xf * x10_solidModelData->GetScaledLocatorTransform("elbow"); zeus::CTransform armXf = xf * x10_solidModelData->GetScaledLocatorTransform("elbow");
if (x1bc_rainSplashGenerator && x1bc_rainSplashGenerator->IsRaining()) if (x1bc_rainSplashGenerator && x1bc_rainSplashGenerator->IsRaining())
CSkinnedModel::SetPointGeneratorFunc(x1bc_rainSplashGenerator, PointGenerator); CSkinnedModel::SetPointGeneratorFunc(
[&](const auto& workspace) { x1bc_rainSplashGenerator->GeneratePoints(workspace); });
if (mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot && x200_beamId != CPlayerState::EBeamId::Ice) { if (mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot && x200_beamId != CPlayerState::EBeamId::Ice) {
/* Hot Draw */ /* Hot Draw */

View File

@ -102,8 +102,6 @@ protected:
void LockTokens(CStateManager& mgr); void LockTokens(CStateManager& mgr);
void UnlockTokens(); void UnlockTokens();
static void PointGenerator(void* ctx, const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn);
public: public:
CGunWeapon(CAssetId ancsId, EWeaponType type, TUniqueId playerId, EMaterialTypes playerMaterial, CGunWeapon(CAssetId ancsId, EWeaponType type, TUniqueId playerId, EMaterialTypes playerMaterial,
const zeus::CVector3f& scale); const zeus::CVector3f& scale);

View File

@ -30,14 +30,14 @@ CActorModelParticles::CItem::CItem(const CEntity& ent, CActorModelParticles& par
x8_onFireGens.resize(8); x8_onFireGens.resize(8);
} }
static s32 GetNextBestPt(s32 start, const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn, static s32 GetNextBestPt(s32 start, const SSkinningWorkspace& workspace, CRandom16& rnd) {
CRandom16& rnd) { const auto& verts = workspace.m_vertexWorkspace;
const zeus::CVector3f& startVec = vn[start].first; const zeus::CVector3f& startVec = verts[start];
s32 ret = start; s32 ret = start;
float maxMag = 0.f; float maxMag = 0.f;
for (s32 i = 0; i < 10; ++i) { for (s32 i = 0; i < 10; ++i) {
s32 idx = rnd.Range(0, s32(vn.size()) - 1); s32 idx = rnd.Range(0, s32(verts.size()) - 1);
const zeus::CVector3f& rndVec = vn[idx].first; const zeus::CVector3f& rndVec = verts[idx];
float mag = (startVec - rndVec).magSquared(); float mag = (startVec - rndVec).magSquared();
if (mag > maxMag) { if (mag > maxMag) {
ret = idx; ret = idx;
@ -46,11 +46,15 @@ static s32 GetNextBestPt(s32 start, const std::vector<std::pair<zeus::CVector3f,
} }
return ret; return ret;
} }
void CActorModelParticles::CItem::GeneratePoints(const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn) {
void CActorModelParticles::CItem::GeneratePoints(const SSkinningWorkspace& workspace) {
const auto& verts = workspace.m_vertexWorkspace;
const auto& norms = workspace.m_normalWorkspace;
for (std::pair<std::unique_ptr<CElementGen>, u32>& pair : x8_onFireGens) { for (std::pair<std::unique_ptr<CElementGen>, u32>& pair : x8_onFireGens) {
if (pair.first) { if (pair.first) {
CRandom16 rnd(pair.second); CRandom16 rnd(pair.second);
const zeus::CVector3f& vec = vn[rnd.Float() * (vn.size() - 1)].first; const zeus::CVector3f& vec = verts[rnd.Float() * (verts.size() - 1)];
pair.first->SetTranslation(xec_particleOffsetScale * vec); pair.first->SetTranslation(xec_particleOffsetScale * vec);
} }
} }
@ -60,9 +64,9 @@ void CActorModelParticles::CItem::GeneratePoints(const std::vector<std::pair<zeu
s32 count = (x84_ashMaxParticles >= 16 ? 16 : x84_ashMaxParticles); s32 count = (x84_ashMaxParticles >= 16 ? 16 : x84_ashMaxParticles);
s32 idx = x80_ashPointIterator; s32 idx = x80_ashPointIterator;
for (u32 i = 0; i < count; ++i) { for (u32 i = 0; i < count; ++i) {
idx = GetNextBestPt(idx, vn, rnd); idx = GetNextBestPt(idx, workspace, rnd);
x78_ashGen->SetTranslation(xec_particleOffsetScale * vn[idx].first); x78_ashGen->SetTranslation(xec_particleOffsetScale * verts[idx]);
zeus::CVector3f v = vn[idx].second; zeus::CVector3f v = norms[idx];
if (v.canBeNormalized()) { if (v.canBeNormalized()) {
v.normalize(); v.normalize();
x78_ashGen->SetOrientation(zeus::CTransform{v.cross(zeus::skUp), v, zeus::skUp, zeus::skZero3f}); x78_ashGen->SetOrientation(zeus::CTransform{v.cross(zeus::skUp), v, zeus::skUp, zeus::skZero3f});
@ -80,10 +84,10 @@ void CActorModelParticles::CItem::GeneratePoints(const std::vector<std::pair<zeu
std::unique_ptr<CElementGen> iceGen = x128_parent.MakeIceGen(); std::unique_ptr<CElementGen> iceGen = x128_parent.MakeIceGen();
iceGen->SetGlobalOrientAndTrans(xf8_iceXf); iceGen->SetGlobalOrientAndTrans(xf8_iceXf);
s32 idx = GetNextBestPt(xb0_icePointIterator, vn, rnd); s32 idx = GetNextBestPt(xb0_icePointIterator, workspace, rnd);
iceGen->SetTranslation(xec_particleOffsetScale * vn[idx].first); iceGen->SetTranslation(xec_particleOffsetScale * verts[idx]);
iceGen->SetOrientation(zeus::CTransform::MakeRotationsBasedOnY(zeus::CUnitVector3f(vn[idx].second))); iceGen->SetOrientation(zeus::CTransform::MakeRotationsBasedOnY(zeus::CUnitVector3f(norms[idx])));
x8c_iceGens.push_back(std::move(iceGen)); x8c_iceGens.push_back(std::move(iceGen));
xb0_icePointIterator = (x8c_iceGens.size() == 4 ? -1 : idx); xb0_icePointIterator = (x8c_iceGens.size() == 4 ? -1 : idx);
@ -98,9 +102,9 @@ void CActorModelParticles::CItem::GeneratePoints(const std::vector<std::pair<zeu
#endif #endif
s32 idx = xc8_electricPointIterator; s32 idx = xc8_electricPointIterator;
for (u32 i = 0; i < end; ++i) { for (u32 i = 0; i < end; ++i) {
xc0_electricGen->SetOverrideIPos(vn[rnd.Range(0, s32(vn.size()) - 1)].first * xec_particleOffsetScale); xc0_electricGen->SetOverrideIPos(verts[rnd.Range(0, s32(verts.size()) - 1)] * xec_particleOffsetScale);
idx = rnd.Range(0, s32(vn.size()) - 1); idx = rnd.Range(0, s32(verts.size()) - 1);
xc0_electricGen->SetOverrideFPos(vn[idx].first * xec_particleOffsetScale); xc0_electricGen->SetOverrideFPos(verts[idx] * xec_particleOffsetScale);
xc0_electricGen->ForceParticleCreation(1); xc0_electricGen->ForceParticleCreation(1);
} }
@ -109,7 +113,7 @@ void CActorModelParticles::CItem::GeneratePoints(const std::vector<std::pair<zeu
} }
if (xd4_rainSplashGen) if (xd4_rainSplashGen)
xd4_rainSplashGen->GeneratePoints(vn); xd4_rainSplashGen->GeneratePoints(workspace);
} }
bool CActorModelParticles::CItem::UpdateOnFire(float dt, CActor* actor, CStateManager& mgr) { bool CActorModelParticles::CItem::UpdateOnFire(float dt, CActor* actor, CStateManager& mgr) {
@ -516,19 +520,12 @@ void CActorModelParticles::Update(float dt, CStateManager& mgr) {
} }
} }
void CActorModelParticles::PointGenerator(void* ctx,
const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn) {
static_cast<CItem*>(ctx)->GeneratePoints(vn);
}
void CActorModelParticles::SetupHook(TUniqueId uid) { void CActorModelParticles::SetupHook(TUniqueId uid) {
const auto search = FindSystem(uid); const auto search = FindSystem(uid);
if (search == x0_items.cend()) { if (search == x0_items.cend()) {
return; return;
} }
CSkinnedModel::SetPointGeneratorFunc([=](const auto& workspace) { search->GeneratePoints(workspace); });
CSkinnedModel::SetPointGeneratorFunc(&*search, PointGenerator);
} }
std::list<CActorModelParticles::CItem>::iterator CActorModelParticles::FindSystem(TUniqueId uid) { std::list<CActorModelParticles::CItem>::iterator CActorModelParticles::FindSystem(TUniqueId uid) {
@ -622,7 +619,7 @@ void CActorModelParticles::LightDudeOnFire(CActor& act) {
const CTexture* CActorModelParticles::GetAshyTexture(const CActor& act) { const CTexture* CActorModelParticles::GetAshyTexture(const CActor& act) {
auto iter = FindSystem(act.GetUniqueId()); auto iter = FindSystem(act.GetUniqueId());
if (iter != x0_items.cend() && iter->xdc_ashy && iter->xdc_ashy.IsLoaded()) { if (iter != x0_items.cend() && iter->xdc_ashy && iter->xdc_ashy.IsLoaded()) {
// iter->xdc_ashy->GetBooTexture()->setClampMode(boo::TextureClampMode::ClampToEdge); // iter->xdc_ashy->GetBooTexture()->setClampMode(boo::TextureClampMode::ClampToEdge);
return iter->xdc_ashy.GetObj(); return iter->xdc_ashy.GetObj();
} }
return nullptr; return nullptr;

View File

@ -71,7 +71,7 @@ public:
public: public:
CItem(const CEntity& ent, CActorModelParticles& parent); CItem(const CEntity& ent, CActorModelParticles& parent);
void GeneratePoints(const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn); void GeneratePoints(const SSkinningWorkspace& workspace);
bool Update(float dt, CStateManager& mgr); bool Update(float dt, CStateManager& mgr);
void Lock(EDependency i); void Lock(EDependency i);
void Unlock(EDependency i); void Unlock(EDependency i);
@ -150,7 +150,6 @@ private:
public: public:
CActorModelParticles(); CActorModelParticles();
static void PointGenerator(void* item, const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn);
void AddStragglersToRenderer(const CStateManager& mgr); void AddStragglersToRenderer(const CStateManager& mgr);
void Update(float dt, CStateManager& mgr); void Update(float dt, CStateManager& mgr);
void SetupHook(TUniqueId uid); void SetupHook(TUniqueId uid);

View File

@ -1657,10 +1657,6 @@ void CMorphBall::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) {
} }
} }
void CMorphBall::PointGenerator(void* ctx, const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn) {
static_cast<CRainSplashGenerator*>(ctx)->GeneratePoints(vn);
}
void CMorphBall::Render(const CStateManager& mgr, const CActorLights* lights) const { void CMorphBall::Render(const CStateManager& mgr, const CActorLights* lights) const {
SCOPED_GRAPHICS_DEBUG_GROUP("CPlayer::Render", zeus::skPurple); SCOPED_GRAPHICS_DEBUG_GROUP("CPlayer::Render", zeus::skPurple);
zeus::CTransform ballToWorld = GetBallToWorld(); zeus::CTransform ballToWorld = GetBallToWorld();
@ -1685,7 +1681,8 @@ void CMorphBall::Render(const CStateManager& mgr, const CActorLights* lights) co
// flags.m_extendedShader = EExtendedShader::LightingCubeReflection; // flags.m_extendedShader = EExtendedShader::LightingCubeReflection;
if (x1c1c_rainSplashGen && x1c1c_rainSplashGen->IsRaining()) { if (x1c1c_rainSplashGen && x1c1c_rainSplashGen->IsRaining()) {
CSkinnedModel::SetPointGeneratorFunc(x1c1c_rainSplashGen.get(), PointGenerator); CSkinnedModel::SetPointGeneratorFunc(
[&](const auto& workspace) { x1c1c_rainSplashGen->GeneratePoints(workspace); });
} }
if (x1c34_boostLightFactor != 1.f) { if (x1c34_boostLightFactor != 1.f) {

View File

@ -170,7 +170,6 @@ private:
static zeus::CVector3f TransformSpiderBallForcesXY(const zeus::CVector2f& forces, CStateManager& mgr); static zeus::CVector3f TransformSpiderBallForcesXY(const zeus::CVector2f& forces, CStateManager& mgr);
static zeus::CVector3f TransformSpiderBallForcesXZ(const zeus::CVector2f& forces, CStateManager& mgr); static zeus::CVector3f TransformSpiderBallForcesXZ(const zeus::CVector2f& forces, CStateManager& mgr);
void ResetSpiderBallForces(); void ResetSpiderBallForces();
static void PointGenerator(void* ctx, const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn);
public: public:
CMorphBall(CPlayer& player, float radius); CMorphBall(CPlayer& player, float radius);

View File

@ -416,7 +416,7 @@ 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); model.Calculate(animData.GetPose(), std::nullopt, 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())) *