mirror of https://github.com/AxioDL/metaforce.git
Reimplement CSkinRules/CSkinnedModel; skinning kinda works!
This commit is contained in:
parent
8714fbf844
commit
cd963c4a5c
|
@ -455,7 +455,7 @@ zeus::CTransform CAnimData::GetLocatorTransform(CSegId id, const CCharAnimTime*
|
|||
if (!x220_30_poseBuilt) {
|
||||
x2fc_poseBuilder.BuildTransform(id, ret);
|
||||
} else {
|
||||
ret.setRotation(x224_pose.GetTransformMinusOffset(id));
|
||||
ret.setRotation(x224_pose.GetRotation(id));
|
||||
ret.origin = x224_pose.GetOffset(id);
|
||||
}
|
||||
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::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);
|
||||
DrawSkinnedModel(model, drawFlags);
|
||||
}
|
||||
|
||||
void CAnimData::SetupRender(CSkinnedModel& model, const std::optional<CVertexMorphEffect>& morphEffect,
|
||||
const float* morphMagnitudes) {
|
||||
TVectorRef morphMagnitudes) {
|
||||
OPTICK_EVENT();
|
||||
if (!x220_30_poseBuilt) {
|
||||
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) {
|
||||
// TODO: some GX light stuff?
|
||||
aurora::gfx::set_chan_mat_src(GX::COLOR0A0, GX::SRC_REG);
|
||||
model.Draw(flags);
|
||||
}
|
||||
|
||||
|
@ -806,8 +806,8 @@ void CAnimData::SetInfraModel(const TLockedToken<CModel>& model, const TLockedTo
|
|||
}
|
||||
|
||||
void CAnimData::PoseSkinnedModel(CSkinnedModel& model, const CPoseAsTransforms& pose,
|
||||
const std::optional<CVertexMorphEffect>& morphEffect, const float* morphMagnitudes) {
|
||||
model.Calculate(pose, morphEffect, morphMagnitudes);
|
||||
const std::optional<CVertexMorphEffect>& morphEffect, TVectorRef morphMagnitudes) {
|
||||
model.Calculate(pose, morphEffect, morphMagnitudes, nullptr);
|
||||
}
|
||||
|
||||
void CAnimData::AdvanceParticles(const zeus::CTransform& xf, float dt, const zeus::CVector3f& vec,
|
||||
|
|
|
@ -195,9 +195,9 @@ public:
|
|||
void RecalcPoseBuilder(const CCharAnimTime* time);
|
||||
void RenderAuxiliary(const zeus::CFrustum& frustum) const;
|
||||
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,
|
||||
const float* morphMagnitudes);
|
||||
TVectorRef morphMagnitudes);
|
||||
static void DrawSkinnedModel(CSkinnedModel& model, const CModelFlags& flags);
|
||||
void PreRender();
|
||||
void BuildPose();
|
||||
|
@ -219,7 +219,7 @@ public:
|
|||
const TLockedToken<CSkinnedModel>& GetModelData() const { return xd8_modelData; }
|
||||
|
||||
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);
|
||||
float GetAverageVelocity(int animIn) const;
|
||||
void ResetPOILists();
|
||||
|
|
|
@ -22,7 +22,7 @@ CFactoryFnReturn CCharacterFactory::CDummyFactory::Build(const SObjectTag& tag,
|
|||
|
||||
const CCharacterInfo& charInfo = *params.GetOwnedObj<const CCharacterInfo*>();
|
||||
|
||||
switch (tag.type.toUint32() & 0x1) {
|
||||
switch (tag.type.toUint32()) {
|
||||
case 0:
|
||||
return TToken<CSkinnedModel>::GetIObjObjectFor(std::make_unique<CSkinnedModel>(
|
||||
*g_SimplePool, charInfo.GetModelId(), charInfo.GetSkinRulesId(), charInfo.GetCharLayoutInfoId()));
|
||||
|
|
|
@ -33,17 +33,10 @@ void CHierarchyPoseBuilder::RecursivelyBuildNoScale(const CSegId& boneId, const
|
|||
CPoseAsTransforms& pose, const zeus::CQuaternion& parentRot,
|
||||
const zeus::CMatrix3f& parentXf,
|
||||
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::CMatrix3f xf = quat;
|
||||
zeus::CVector3f xfOffset = parentXf * node.x14_offset + parentOffset;
|
||||
pose.Insert(boneId, quat, xfOffset, bindOffset);
|
||||
pose.Insert(boneId, quat, xfOffset);
|
||||
|
||||
CSegId curBone = node.x0_child;
|
||||
while (curBone != 0) {
|
||||
|
@ -59,29 +52,25 @@ void CHierarchyPoseBuilder::RecursivelyBuild(const CSegId& boneId, const CTreeNo
|
|||
zeus::CQuaternion quat = parentRot * node.x4_rotation;
|
||||
|
||||
float scale;
|
||||
zeus::CVector3f bindOffset;
|
||||
if (x0_layoutDesc.GetScaledLayoutDescription()) {
|
||||
const CLayoutDescription::CScaledLayoutDescription& desc = *x0_layoutDesc.GetScaledLayoutDescription();
|
||||
scale = desc.GlobalScale();
|
||||
bindOffset = desc.ScaledLayout()->GetFromRootUnrotated(boneId);
|
||||
scale = x0_layoutDesc.GetScaledLayoutDescription()->GlobalScale();
|
||||
} else {
|
||||
scale = 1.f;
|
||||
bindOffset = x0_layoutDesc.GetCharLayoutInfo()->GetFromRootUnrotated(boneId);
|
||||
}
|
||||
|
||||
zeus::CMatrix3f mtxXf;
|
||||
zeus::CMatrix3f rotation;
|
||||
if (scale == 1.f)
|
||||
mtxXf = quat;
|
||||
rotation = quat;
|
||||
else
|
||||
mtxXf = parentXf * zeus::CMatrix3f(scale);
|
||||
rotation = parentXf * (zeus::CMatrix3f{node.x4_rotation} * zeus::CMatrix3f{scale});
|
||||
|
||||
zeus::CVector3f xfOffset = parentXf * node.x14_offset + parentOffset;
|
||||
pose.Insert(boneId, mtxXf, xfOffset, bindOffset);
|
||||
zeus::CVector3f offset = parentOffset + (parentXf * node.x14_offset);
|
||||
pose.Insert(boneId, rotation, offset);
|
||||
|
||||
CSegId curBone = node.x0_child;
|
||||
while (curBone != 0) {
|
||||
const CTreeNode& node = x38_treeMap[curBone];
|
||||
RecursivelyBuild(curBone, node, pose, quat, quat, xfOffset);
|
||||
RecursivelyBuild(curBone, node, pose, quat, quat, offset);
|
||||
curBone = node.x1_sibling;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ set(CHARACTER_SOURCES
|
|||
CTransitionDatabaseGame.hpp CTransitionDatabaseGame.cpp
|
||||
CHierarchyPoseBuilder.hpp CHierarchyPoseBuilder.cpp
|
||||
CPoseAsTransforms.hpp CPoseAsTransforms.cpp
|
||||
CSkinBank.hpp CSkinBank.cpp
|
||||
CCharLayoutInfo.hpp CCharLayoutInfo.cpp
|
||||
CLayoutDescription.hpp
|
||||
CSegIdList.hpp CSegIdList.cpp
|
||||
|
|
|
@ -99,7 +99,7 @@ void CParticleDatabase::UpdateParticleGenDB(float dt, const CPoseAsTransforms& p
|
|||
switch (info.GetParentedMode()) {
|
||||
case CParticleData::EParentedMode::Initial: {
|
||||
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);
|
||||
zeus::CTransform compXf = xf * segXf;
|
||||
info.SetCurTransform(compXf.getRotation());
|
||||
|
@ -125,7 +125,7 @@ void CParticleDatabase::UpdateParticleGenDB(float dt, const CPoseAsTransforms& p
|
|||
info.SetIsGrabInitialData(false);
|
||||
}
|
||||
|
||||
zeus::CTransform segXf(pose.GetTransformMinusOffset(segId), off * scale);
|
||||
zeus::CTransform segXf(pose.GetRotation(segId), off * scale);
|
||||
zeus::CTransform compXf = xf * segXf;
|
||||
|
||||
if (info.GetParentedMode() == CParticleData::EParentedMode::ContinuousEmitter) {
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
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 {
|
||||
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 std::pair<CSegId, CSegId>& link = x8_links[id];
|
||||
assert(link.second.IsValid());
|
||||
return xd0_transformArr[link.second].m_originToAccum;
|
||||
}
|
||||
|
||||
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;
|
||||
return xd0_transformArr[link.second];
|
||||
}
|
||||
|
||||
const zeus::CVector3f& CPoseAsTransforms::GetOffset(const CSegId& id) const {
|
||||
const std::pair<CSegId, CSegId>& link = x8_links[id];
|
||||
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 std::pair<CSegId, CSegId>& link = x8_links[id];
|
||||
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,
|
||||
const zeus::CVector3f& restOffset) {
|
||||
Transform& xfOut = xd0_transformArr[x0_nextId];
|
||||
xfOut.m_originToAccum = zeus::CTransform(rotation, offset);
|
||||
xfOut.m_restPoseToAccum = xfOut.m_originToAccum * zeus::CTransform::Translate(-restOffset);
|
||||
void CPoseAsTransforms::Insert(const CSegId& id, const zeus::CMatrix3f& rotation, const zeus::CVector3f& offset) {
|
||||
xd0_transformArr[x0_nextId] = zeus::CTransform(rotation, offset);
|
||||
|
||||
std::pair<CSegId, CSegId>& link = x8_links[id];
|
||||
link.first = xd4_lastInserted;
|
||||
|
@ -58,4 +50,10 @@ void CPoseAsTransforms::Insert(const CSegId& id, const zeus::CMatrix3f& rotation
|
|||
++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
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "Runtime/RetroTypes.hpp"
|
||||
#include "Runtime/Character/CCharLayoutInfo.hpp"
|
||||
#include "Runtime/Character/CSegId.hpp"
|
||||
#include "Runtime/RetroTypes.hpp"
|
||||
|
||||
#include <zeus/CMatrix3f.hpp>
|
||||
#include <zeus/CTransform.hpp>
|
||||
|
@ -16,31 +16,26 @@ namespace metaforce {
|
|||
class CPoseAsTransforms {
|
||||
friend class CAnimData;
|
||||
|
||||
public:
|
||||
struct Transform {
|
||||
zeus::CTransform m_originToAccum;
|
||||
zeus::CTransform m_restPoseToAccum;
|
||||
};
|
||||
|
||||
private:
|
||||
CSegId x0_nextId = 0;
|
||||
CSegId x1_count;
|
||||
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;
|
||||
|
||||
public:
|
||||
explicit CPoseAsTransforms(u8 boneCount);
|
||||
bool ContainsDataFor(const CSegId& id) const;
|
||||
|
||||
void Clear();
|
||||
void AccumulateScaledTransform(const CSegId& id, zeus::CMatrix3f& rotation, float scale) const;
|
||||
const zeus::CTransform& GetTransform(const CSegId& id) const;
|
||||
const zeus::CTransform& GetRestToAccumTransform(const CSegId& id) const;
|
||||
const zeus::CVector3f& GetOffset(const CSegId& id) const;
|
||||
const zeus::CMatrix3f& GetRotation(const CSegId& id) const;
|
||||
const zeus::CMatrix3f& GetTransformMinusOffset(const CSegId& id) const { return GetRotation(id); }
|
||||
void Insert(const CSegId& id, const zeus::CMatrix3f& rotation, const zeus::CVector3f& offset,
|
||||
const zeus::CVector3f& restOffset);
|
||||
void Insert(const CSegId& id, const zeus::CMatrix3f& rotation, const zeus::CVector3f& offset);
|
||||
|
||||
[[nodiscard]] bool ContainsDataFor(const CSegId& id) const;
|
||||
[[nodiscard]] const zeus::CTransform& GetTransform(const CSegId& id) const;
|
||||
[[nodiscard]] const zeus::CVector3f& GetOffset(const CSegId& id) const;
|
||||
[[nodiscard]] const zeus::CMatrix3f& GetRotation(const CSegId& id) const;
|
||||
[[nodiscard]] CSegId GetLastInserted() const { return xd4_lastInserted; }
|
||||
[[nodiscard]] CSegId GetParent(const CSegId& id) const;
|
||||
};
|
||||
|
||||
} // namespace metaforce
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -31,31 +31,47 @@ CSkinRules::CSkinRules(CInputStream& in) {
|
|||
x14_normalCount = ReadCount(in);
|
||||
}
|
||||
|
||||
// void CSkinRules::TransformVerticesCPU(std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vnOut,
|
||||
// const CPoseAsTransforms& pose, const CModel& model) const {
|
||||
// OPTICK_EVENT();
|
||||
// vnOut.resize(m_poolToSkinIdx.size());
|
||||
// for (size_t i = 0; i < m_poolToSkinIdx.size(); ++i) {
|
||||
// const CVirtualBone& vb = m_virtualBones[m_poolToSkinIdx[i]];
|
||||
// zeus::CVector3f origVertex = model.GetPoolVertex(i);
|
||||
// zeus::CVector3f vertex;
|
||||
// zeus::CVector3f origNormal = model.GetPoolNormal(i);
|
||||
// zeus::CVector3f normal;
|
||||
// for (const SSkinWeighting& w : vb.GetWeights()) {
|
||||
// const zeus::CTransform& xf = pose.GetRestToAccumTransform(w.m_id);
|
||||
// vertex += (xf * origVertex) * w.m_weight;
|
||||
// normal += (xf.basis.inverted().transposed() * origNormal) * w.m_weight;
|
||||
// }
|
||||
// vnOut[i] = std::make_pair(vertex, normal.normalized());
|
||||
// }
|
||||
// }
|
||||
void CSkinRules::BuildAccumulatedTransforms(const CPoseAsTransforms& pose, const CCharLayoutInfo& info) {
|
||||
std::array<zeus::CVector3f, 100> points;
|
||||
CSegId segId = pose.GetLastInserted();
|
||||
while (segId != 0) {
|
||||
zeus::CVector3f origin;
|
||||
if (segId != 3) { // root ID
|
||||
origin = info.GetFromRootUnrotated(segId);
|
||||
}
|
||||
const auto rotatedOrigin = pose.GetRotation(segId) * origin;
|
||||
points[segId] = pose.GetOffset(segId) - rotatedOrigin;
|
||||
segId = pose.GetParent(segId);
|
||||
}
|
||||
for (auto& bone : x0_bones) {
|
||||
bone.BuildAccumulatedTransform(pose, points.data());
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
CObjectReference* selfRef) {
|
||||
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;
|
||||
u32 weightCount = in.ReadLong();
|
||||
for (int i = 0; i < std::min(3u, weightCount); ++i) {
|
||||
|
@ -67,6 +83,58 @@ auto StreamInSkinWeighting(CInputStream& in) {
|
|||
return weights;
|
||||
}
|
||||
|
||||
CVirtualBone::CVirtualBone(CInputStream& in)
|
||||
: x0_weights(StreamInSkinWeighting(in)), x1c_vertexCount(in.ReadLong()) {}
|
||||
CVirtualBone::CVirtualBone(CInputStream& in) : 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
|
||||
|
|
|
@ -3,12 +3,14 @@
|
|||
#include <vector>
|
||||
|
||||
#include "Runtime/CFactoryMgr.hpp"
|
||||
#include "Runtime/Character/CSkinBank.hpp"
|
||||
#include "Runtime/Character/CSegId.hpp"
|
||||
#include "Runtime/Graphics/CCubeModel.hpp"
|
||||
#include "Runtime/RetroTypes.hpp"
|
||||
|
||||
#include <zeus/CVector3f.hpp>
|
||||
|
||||
namespace metaforce {
|
||||
class CCharLayoutInfo;
|
||||
class CPoseAsTransforms;
|
||||
class CModel;
|
||||
|
||||
|
@ -24,12 +26,20 @@ class CVirtualBone {
|
|||
rstl::reserved_vector<SSkinWeighting, 3> x0_weights;
|
||||
u32 x1c_vertexCount;
|
||||
zeus::CTransform x20_xf;
|
||||
zeus::CMatrix3f x50_mtx;
|
||||
zeus::CMatrix3f x50_rotation;
|
||||
|
||||
public:
|
||||
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 {
|
||||
|
@ -42,17 +52,12 @@ class CSkinRules {
|
|||
public:
|
||||
explicit CSkinRules(CInputStream& in);
|
||||
|
||||
// void GetBankTransforms(std::vector<const zeus::CTransform*>& out, const CPoseAsTransforms& pose,
|
||||
// int skinBankIdx) const {
|
||||
// // FIXME: This is definitely not proper behavior, this is here to fix the phazon suit crashing
|
||||
// if (x0_skinBanks.size() <= skinBankIdx) {
|
||||
// return;
|
||||
// }
|
||||
// x0_skinBanks[skinBankIdx].GetBankTransforms(out, pose);
|
||||
// }
|
||||
void BuildPoints(TConstVectorRef positions, TVectorRef out);
|
||||
void BuildNormals(TConstVectorRef normals, TVectorRef out);
|
||||
void BuildAccumulatedTransforms(const CPoseAsTransforms& pose, const CCharLayoutInfo& info);
|
||||
|
||||
// void TransformVerticesCPU(std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vnOut,
|
||||
// const CPoseAsTransforms& pose, const CModel& model) const;
|
||||
[[nodiscard]] u32 GetVertexCount() const { return x10_vertexCount; }
|
||||
[[nodiscard]] u32 GetNormalCount() const { return x14_normalCount; }
|
||||
};
|
||||
|
||||
CFactoryFnReturn FSkinRulesFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& params,
|
||||
|
|
|
@ -121,7 +121,7 @@ void CCubeModel::Draw(const CModelFlags& 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();
|
||||
SetSkinningArraysCurrent(positions, normals);
|
||||
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) {
|
||||
SetArraysCurrent();
|
||||
} 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::SetTevOp(ERglTevStage::Stage0, CTevCombiners::skPassZero);
|
||||
CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru);
|
||||
|
@ -277,7 +277,7 @@ void CCubeModel::SetRenderModelBlack(bool v) {
|
|||
// 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_normal_buffer(normals);
|
||||
// colors unused
|
||||
|
|
|
@ -21,18 +21,19 @@ enum class ESurfaceSelection {
|
|||
};
|
||||
|
||||
// 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 {
|
||||
friend class CModel;
|
||||
|
||||
private:
|
||||
class ModelInstance {
|
||||
std::vector<CCubeSurface>* x0_surfacePtrs; // was rstl::vector<void*>*
|
||||
u8* x4_materialData; //
|
||||
std::vector<zeus::CVector3f>* x8_positions; // was void*
|
||||
std::vector<zeus::CVector3f>* xc_normals; // was void*
|
||||
std::vector<zeus::CColor>* x10_colors; // was void*
|
||||
std::vector<CCubeSurface>* x0_surfacePtrs; // was rstl::vector<void*>*
|
||||
u8* x4_materialData; //
|
||||
std::vector<zeus::CVector3f>* x8_positions; // was void*
|
||||
std::vector<zeus::CVector3f>* xc_normals; // was void*
|
||||
std::vector<zeus::CColor>* x10_colors; // was void*
|
||||
std::vector<aurora::Vec2<float>>* x14_texCoords; // was void*
|
||||
std::vector<aurora::Vec2<float>>* x18_packedTexCoords; // was void*
|
||||
|
||||
|
@ -55,8 +56,10 @@ private:
|
|||
[[nodiscard]] std::vector<CCubeSurface>* Surfaces() const { return x0_surfacePtrs; }
|
||||
[[nodiscard]] u8* GetMaterialPointer() const { return x4_materialData; }
|
||||
void SetMaterialPointer(u8* mat) { x4_materialData = mat; }
|
||||
[[nodiscard]] TVectorRef GetVertexPointer() const { return x8_positions; }
|
||||
[[nodiscard]] TVectorRef GetNormalPointer() const { return xc_normals; }
|
||||
[[nodiscard]] TVectorRef GetVertexPointer() { return x8_positions; }
|
||||
[[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<aurora::Vec2<float>>* GetTCPointer() const { return x14_texCoords; }
|
||||
[[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 Draw(const CModelFlags& flags);
|
||||
void DrawAlpha(const CModelFlags& flags);
|
||||
void DrawFlat(TVectorRef positions, TVectorRef normals, ESurfaceSelection surfaces);
|
||||
void DrawNormal(TVectorRef positions, TVectorRef normals, ESurfaceSelection surfaces);
|
||||
void DrawFlat(TConstVectorRef positions, TConstVectorRef normals, ESurfaceSelection surfaces);
|
||||
void DrawNormal(TConstVectorRef positions, TConstVectorRef normals, ESurfaceSelection surfaces);
|
||||
void DrawNormal(const CModelFlags& flags);
|
||||
void DrawSurface(const CCubeSurface& surface, const CModelFlags& flags);
|
||||
void DrawSurfaceWireframe(const CCubeSurface& surface);
|
||||
|
@ -101,8 +104,10 @@ public:
|
|||
[[nodiscard]] CCubeSurface* GetFirstSortedSurface() { return x3c_firstSortedSurf; }
|
||||
[[nodiscard]] const CCubeSurface* GetFirstSortedSurface() const { return x3c_firstSortedSurf; }
|
||||
|
||||
[[nodiscard]] TVectorRef GetPositions() const { return x0_modelInstance.GetVertexPointer(); }
|
||||
[[nodiscard]] TVectorRef GetNormals() const { return x0_modelInstance.GetNormalPointer(); }
|
||||
[[nodiscard]] TVectorRef GetPositions() { return x0_modelInstance.GetVertexPointer(); }
|
||||
[[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); }
|
||||
|
||||
static void EnableShadowMaps(const CTexture& shadowTex, const zeus::CTransform& textureProjXf, u8 chan0DisableMask,
|
||||
|
@ -121,11 +126,11 @@ public:
|
|||
static const CTexture* sShadowTexture;
|
||||
|
||||
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 DrawNormalSurfaces(const CModelFlags& flags);
|
||||
void DrawSurfaces(const CModelFlags& flags);
|
||||
void SetSkinningArraysCurrent(TVectorRef positions, TVectorRef normals);
|
||||
void SetSkinningArraysCurrent(TConstVectorRef positions, TConstVectorRef normals);
|
||||
void SetStaticArraysCurrent();
|
||||
};
|
||||
} // namespace metaforce
|
||||
|
|
|
@ -634,9 +634,9 @@ u32 CCubeRenderer::GetFPS() { return CGraphics::GetFPS(); }
|
|||
void CCubeRenderer::CacheReflection(IRenderer::TReflectionCallback cb, void* ctx, bool clearAfter) {}
|
||||
void CCubeRenderer::DrawSpaceWarp(const zeus::CVector3f& pt, float strength) {}
|
||||
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,
|
||||
TVectorRef positions, TVectorRef normals) {}
|
||||
TConstVectorRef positions, TConstVectorRef normals) {}
|
||||
void CCubeRenderer::DrawModelFlat(const CModel& model, const CModelFlags& flags, bool unsortedOnly) {}
|
||||
void CCubeRenderer::SetWireframeFlags(s32 flags) {}
|
||||
void CCubeRenderer::SetWorldFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color) {}
|
||||
|
|
|
@ -180,9 +180,9 @@ public:
|
|||
void CacheReflection(TReflectionCallback cb, void* ctx, bool clearAfter) override;
|
||||
void DrawSpaceWarp(const zeus::CVector3f& pt, float strength) override;
|
||||
void DrawThermalModel(const CModel& model, const zeus::CColor& multCol, const zeus::CColor& addCol,
|
||||
TVectorRef positions, TVectorRef normals, const CModelFlags& flags) override;
|
||||
void DrawModelDisintegrate(const CModel& model, const CTexture& tex, const zeus::CColor& color, TVectorRef positions,
|
||||
TVectorRef normals) override;
|
||||
TConstVectorRef positions, TConstVectorRef normals, const CModelFlags& flags) override;
|
||||
void DrawModelDisintegrate(const CModel& model, const CTexture& tex, const zeus::CColor& color,
|
||||
TConstVectorRef positions, TConstVectorRef normals) override;
|
||||
void DrawModelFlat(const CModel& model, const CModelFlags& flags, bool unsortedOnly) override;
|
||||
void SetWireframeFlags(s32 flags) override;
|
||||
void SetWorldFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color) override;
|
||||
|
|
|
@ -37,8 +37,10 @@ public:
|
|||
[[nodiscard]] std::vector<CCubeSurface>* GetSurfaces() { return &x50_surfaces; }
|
||||
[[nodiscard]] const std::vector<CCubeSurface>* GetSurfaces() const { return &x50_surfaces; }
|
||||
[[nodiscard]] const u8* GetMaterialPointer() const { return x4c_materialData; }
|
||||
[[nodiscard]] TVectorRef GetVertexPointer() const { return &x60_positions; }
|
||||
[[nodiscard]] TVectorRef GetNormalPointer() const { return &x64_normals; }
|
||||
[[nodiscard]] TVectorRef GetVertexPointer() { return &x60_positions; }
|
||||
[[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<aurora::Vec2<float>>* GetTCPointer() const { return &x6c_texCoords; }
|
||||
[[nodiscard]] const std::vector<aurora::Vec2<float>>* GetPackedTCPointer() const { return &x70_packedTexCoords; }
|
||||
|
|
|
@ -201,9 +201,13 @@ void CModel::EnableTextureTimeout() { sIsTextureTimeoutEnabled = true; }
|
|||
|
||||
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) {
|
||||
if (matIdx > x18_matSets.size()) {
|
||||
|
@ -264,7 +268,7 @@ void CModel::Draw(CModelFlags 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) {
|
||||
x28_modelInst->DrawNormal(positions, normals, ESurfaceSelection::All);
|
||||
}
|
||||
|
|
|
@ -100,13 +100,15 @@ public:
|
|||
void VerifyCurrentShader(u32 matIdx);
|
||||
void Touch(u32 matIdx);
|
||||
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 DrawUnsortedParts(CModelFlags flags);
|
||||
bool IsLoaded(u32 matIdx);
|
||||
|
||||
TVectorRef GetPositions() const;
|
||||
TVectorRef GetNormals() const;
|
||||
TVectorRef GetPositions();
|
||||
TConstVectorRef GetPositions() const;
|
||||
TVectorRef GetNormals();
|
||||
TConstVectorRef GetNormals() const;
|
||||
u32 GetNumMaterialSets() const { return x18_matSets.size(); }
|
||||
bool IsOpaque() const { return x28_modelInst->x3c_firstSortedSurf == nullptr; }
|
||||
const zeus::CAABox& GetAABB() const { return x28_modelInst->x20_worldAABB; }
|
||||
|
|
|
@ -70,8 +70,7 @@ void CRainSplashGenerator::Draw(const zeus::CTransform& xf) {
|
|||
DoDraw(xf);
|
||||
}
|
||||
|
||||
CRainSplashGenerator::SSplashLine::SSplashLine()
|
||||
: m_renderer(CLineRenderer::EPrimitiveMode::LineStrip, 3, {}, false) {}
|
||||
CRainSplashGenerator::SSplashLine::SSplashLine() : m_renderer(CLineRenderer::EPrimitiveMode::LineStrip, 3, {}, false) {}
|
||||
|
||||
CRainSplashGenerator::SRainSplash::SRainSplash() {
|
||||
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,
|
||||
CRandom16& rand, float minZ) {
|
||||
const auto& refVert = vn[pt];
|
||||
u32 CRainSplashGenerator::GetNextBestPt(u32 pt, const SSkinningWorkspace& workspace, CRandom16& rand, float minZ) {
|
||||
const auto& refVert = workspace.m_vertexWorkspace[pt];
|
||||
float maxDist = 0.f;
|
||||
u32 nextPt = pt;
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
const auto idx = u32(rand.Range(0, int(vn.size() - 1)));
|
||||
const auto& vert = vn[idx];
|
||||
const float distSq = (refVert.first - vert.first).magSquared();
|
||||
if (distSq > maxDist && vert.second.dot(zeus::skUp) >= 0.f && (vert.first.z() <= 0.f || vert.first.z() > minZ)) {
|
||||
const auto idx = u32(rand.Range(0, int(workspace.m_vertexWorkspace.size() - 1)));
|
||||
const auto& vert = workspace.m_vertexWorkspace[idx];
|
||||
const auto& norm = workspace.m_normalWorkspace[idx];
|
||||
const float distSq = (refVert - vert).magSquared();
|
||||
if (distSq > maxDist && norm.dot(zeus::skUp) >= 0.f && (vert.z() <= 0.f || vert.z() > minZ)) {
|
||||
nextPt = idx;
|
||||
maxDist = distSq;
|
||||
}
|
||||
|
@ -177,7 +176,7 @@ void CRainSplashGenerator::AddPoint(const zeus::CVector3f& pos) {
|
|||
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)
|
||||
return;
|
||||
|
||||
|
@ -185,8 +184,8 @@ void CRainSplashGenerator::GeneratePoints(const std::vector<std::pair<zeus::CVec
|
|||
for (u32 i = 0; i < x44_genRate; ++i) {
|
||||
if (x40_queueSize >= x0_rainSplashes.size())
|
||||
break;
|
||||
x34_curPoint = GetNextBestPt(x34_curPoint, vn, x10_random, x2c_minZ);
|
||||
AddPoint(x14_scale * vn[x34_curPoint].first);
|
||||
x34_curPoint = GetNextBestPt(x34_curPoint, workspace, x10_random, x2c_minZ);
|
||||
AddPoint(x14_scale * workspace.m_vertexWorkspace[x34_curPoint]);
|
||||
}
|
||||
x20_generateTimer = 0.f;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "Runtime/RetroTypes.hpp"
|
||||
#include "Runtime/rstl.hpp"
|
||||
#include "Runtime/Graphics/CLineRenderer.hpp"
|
||||
#include "Runtime/Graphics/CSkinnedModel.hpp"
|
||||
|
||||
#include <zeus/CVector3f.hpp>
|
||||
|
||||
|
@ -61,14 +62,13 @@ class CRainSplashGenerator {
|
|||
void UpdateRainSplashRange(CStateManager& mgr, int start, int end, float dt);
|
||||
void UpdateRainSplashes(CStateManager& mgr, float magnitude, float dt);
|
||||
void DoDraw(const zeus::CTransform& xf);
|
||||
static u32 GetNextBestPt(u32 pt, const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn, CRandom16& rand,
|
||||
float minZ);
|
||||
static u32 GetNextBestPt(u32 pt, const SSkinningWorkspace& workspace, CRandom16& rand, float minZ);
|
||||
void AddPoint(const zeus::CVector3f& pos);
|
||||
|
||||
public:
|
||||
CRainSplashGenerator(const zeus::CVector3f& scale, u32 maxSplashes, u32 genRate, float minZ, float alpha);
|
||||
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);
|
||||
bool IsRaining() const { return x48_25_raining; }
|
||||
};
|
||||
|
|
|
@ -4,13 +4,17 @@
|
|||
#include "Runtime/Graphics/CVertexMorphEffect.hpp"
|
||||
|
||||
#include <logvisor/logvisor.hpp>
|
||||
#include <list>
|
||||
|
||||
namespace metaforce {
|
||||
static logvisor::Module Log("metaforce::CSkinnedModel");
|
||||
|
||||
CSkinnedModel::CSkinnedModel(const TLockedToken<CModel>& model, const TLockedToken<CSkinRules>& skinRules,
|
||||
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) {
|
||||
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}),
|
||||
store.GetObj(SObjectTag{FOURCC('CINF'), layoutInfo})) {}
|
||||
|
||||
void CSkinnedModel::Calculate(const CPoseAsTransforms& pose, const std::optional<CVertexMorphEffect>& morphEffect,
|
||||
const float* morphMagnitudes) {
|
||||
// TODO
|
||||
// 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::AllocateStorage() {
|
||||
if (x34_owned) {
|
||||
m_workspace.Reset(*x10_skinRules);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
x4_model->Draw(verts, norms, drawFlags);
|
||||
// PostDrawFunc();
|
||||
|
@ -63,10 +71,10 @@ void CSkinnedModel::Draw(const CModelFlags& drawFlags) {
|
|||
CGraphics::SetModelMatrix(mtx * x10_skinRules->x0_bones.front().x20_xf);
|
||||
x4_model->Draw(drawFlags);
|
||||
CGraphics::SetModelMatrix(mtx);
|
||||
} else if (x24_vertWorkspace.empty()) {
|
||||
} else if (m_workspace.IsEmpty()) {
|
||||
x4_model->Draw(drawFlags);
|
||||
} else {
|
||||
x4_model->Draw(&x24_vertWorkspace, &x2c_normalWorkspace, drawFlags);
|
||||
x4_model->Draw(&m_workspace.m_vertexWorkspace, &m_workspace.m_normalWorkspace, drawFlags);
|
||||
// PostDrawFunc();
|
||||
}
|
||||
}
|
||||
|
@ -77,19 +85,49 @@ void CSkinnedModel::DoDrawCallback(const FCustomDraw& func) const {
|
|||
CGraphics::SetModelMatrix(mtx * x10_skinRules->x0_bones.front().x20_xf);
|
||||
func(x4_model->GetPositions(), x4_model->GetNormals());
|
||||
CGraphics::SetModelMatrix(mtx);
|
||||
} else if (x24_vertWorkspace.empty()) {
|
||||
} else if (m_workspace.IsEmpty()) {
|
||||
func(x4_model->GetPositions(), x4_model->GetNormals());
|
||||
} else {
|
||||
func(&x24_vertWorkspace, &x2c_normalWorkspace);
|
||||
func(&m_workspace.m_vertexWorkspace, &m_workspace.m_normalWorkspace);
|
||||
// PostDrawFunc();
|
||||
}
|
||||
}
|
||||
|
||||
CMorphableSkinnedModel::CMorphableSkinnedModel(IObjectStore& store, CAssetId model, CAssetId skinRules,
|
||||
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;
|
||||
void* CSkinnedModel::g_PointGenCtx = nullptr;
|
||||
x40_morphMagnitudes.resize(vertexCount);
|
||||
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
|
||||
|
|
|
@ -18,15 +18,32 @@ class CPoseAsTransforms;
|
|||
class CVertexMorphEffect;
|
||||
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
|
||||
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 {
|
||||
TLockedToken<CModel> x4_model;
|
||||
TLockedToken<CSkinRules> x10_skinRules;
|
||||
TLockedToken<CCharLayoutInfo> x1c_layoutInfo;
|
||||
std::vector<zeus::CVector3f> x24_vertWorkspace; // was rstl::auto_ptr<float[]>
|
||||
std::vector<zeus::CVector3f> x2c_normalWorkspace; // was rstl::auto_ptr<float[]>
|
||||
// rstl::auto_ptr<float[]> x24_vertWorkspace;
|
||||
// rstl::auto_ptr<float[]> x2c_normalWorkspace;
|
||||
SSkinningWorkspace m_workspace;
|
||||
bool x34_owned = true;
|
||||
bool x35_disableWorkspaces = false;
|
||||
|
||||
|
@ -42,28 +59,25 @@ public:
|
|||
void SetLayoutInfo(const TLockedToken<CCharLayoutInfo>& inf) { x1c_layoutInfo = inf; }
|
||||
const TLockedToken<CCharLayoutInfo>& GetLayoutInfo() const { return x1c_layoutInfo; }
|
||||
|
||||
void AllocateStorage();
|
||||
void Calculate(const CPoseAsTransforms& pose, const std::optional<CVertexMorphEffect>& morphEffect,
|
||||
const float* morphMagnitudes);
|
||||
void Draw(TVectorRef verts, TVectorRef normals, const CModelFlags& drawFlags);
|
||||
TConstVectorRef averagedNormals, SSkinningWorkspace* workspace);
|
||||
void Draw(TConstVectorRef verts, TConstVectorRef normals, const CModelFlags& drawFlags);
|
||||
void Draw(const CModelFlags& drawFlags);
|
||||
void DoDrawCallback(const FCustomDraw& func) const;
|
||||
|
||||
using FPointGenerator = void (*)(void* item, const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn);
|
||||
static void SetPointGeneratorFunc(void* ctx, FPointGenerator func) {
|
||||
g_PointGenFunc = func;
|
||||
g_PointGenCtx = ctx;
|
||||
}
|
||||
static void SetPointGeneratorFunc(FPointGenerator func) { g_PointGenFunc = std::move(func); }
|
||||
static void ClearPointGeneratorFunc() { g_PointGenFunc = nullptr; }
|
||||
static FPointGenerator g_PointGenFunc;
|
||||
static void* g_PointGenCtx;
|
||||
};
|
||||
|
||||
class CMorphableSkinnedModel : public CSkinnedModel {
|
||||
std::unique_ptr<float[]> x40_morphMagnitudes;
|
||||
std::vector<zeus::CVector3f> x40_morphMagnitudes; // was rstl::auto_ptr<float[]>
|
||||
|
||||
public:
|
||||
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
|
||||
|
|
|
@ -8,8 +8,8 @@ CVertexMorphEffect::CVertexMorphEffect(const zeus::CUnitVector3f& v1, const zeus
|
|||
float f2, CRandom16& random)
|
||||
: x0_(v1), x20_diagExtent(diagExtent), x24_random(random) {}
|
||||
|
||||
void CVertexMorphEffect::MorphVertices(std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn,
|
||||
const float* magnitudes, const TLockedToken<CSkinRules>& skinRules,
|
||||
const CPoseAsTransforms& pose) const {}
|
||||
void CVertexMorphEffect::MorphVertices(SSkinningWorkspace& workspace, TConstVectorRef magnitudes,
|
||||
const TLockedToken<CSkinRules>& skinRules, const CPoseAsTransforms& pose) const {
|
||||
}
|
||||
|
||||
} // namespace metaforce
|
||||
} // namespace metaforce
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "Runtime/CToken.hpp"
|
||||
#include "Runtime/Character/CPoseAsTransforms.hpp"
|
||||
#include "Runtime/Graphics/CCubeModel.hpp"
|
||||
|
||||
#include <zeus/CUnitVector.hpp>
|
||||
#include <zeus/CVector3f.hpp>
|
||||
|
@ -12,6 +13,7 @@
|
|||
namespace metaforce {
|
||||
class CRandom16;
|
||||
class CSkinRules;
|
||||
struct SSkinningWorkspace;
|
||||
|
||||
class CVertexMorphEffect {
|
||||
zeus::CUnitVector3f x0_;
|
||||
|
@ -28,7 +30,7 @@ class CVertexMorphEffect {
|
|||
public:
|
||||
CVertexMorphEffect(const zeus::CUnitVector3f& v1, const zeus::CVector3f& v2, float diagExtent, float f2,
|
||||
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;
|
||||
void Reset(const zeus::CVector3f& dir, const zeus::CVector3f& pos, float duration) {}
|
||||
void Update(float) {}
|
||||
|
|
|
@ -93,9 +93,9 @@ public:
|
|||
virtual void CacheReflection(TReflectionCallback cb, void* ctx, bool clearAfter) = 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,
|
||||
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,
|
||||
TVectorRef positions, TVectorRef normals) = 0;
|
||||
TConstVectorRef positions, TConstVectorRef normals) = 0;
|
||||
virtual void DrawModelFlat(const CModel& model, const CModelFlags& flags, bool unsortedOnly) = 0;
|
||||
virtual void SetWireframeFlags(s32 flags) = 0;
|
||||
virtual void SetWorldFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color) = 0;
|
||||
|
|
|
@ -501,10 +501,6 @@ void CGrappleArm::RenderXRayModel(const CStateManager& mgr, const zeus::CTransfo
|
|||
// 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,
|
||||
const CActorLights* lights) {
|
||||
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()) {
|
||||
CSkinnedModel::SetPointGeneratorFunc(x3a4_rainSplashGenerator.get(), PointGenerator);
|
||||
CSkinnedModel::SetPointGeneratorFunc(
|
||||
[&](const auto& workspace) { x3a4_rainSplashGenerator->GeneratePoints(workspace); });
|
||||
}
|
||||
|
||||
x0_grappleArmModel->Render(mgr, modelXf, useLights, useFlags);
|
||||
|
|
|
@ -102,8 +102,6 @@ private:
|
|||
void UpdateSwingAction(float grappleSwingT, float dt, CStateManager& mgr);
|
||||
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:
|
||||
explicit CGrappleArm(const zeus::CVector3f& scale);
|
||||
void AsyncLoadSuit(CStateManager& mgr);
|
||||
|
|
|
@ -250,10 +250,6 @@ void CGunWeapon::TouchHolo(const CStateManager& mgr) {
|
|||
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,
|
||||
const CActorLights* lights) {
|
||||
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");
|
||||
|
||||
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) {
|
||||
/* Hot Draw */
|
||||
|
|
|
@ -102,8 +102,6 @@ protected:
|
|||
void LockTokens(CStateManager& mgr);
|
||||
void UnlockTokens();
|
||||
|
||||
static void PointGenerator(void* ctx, const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn);
|
||||
|
||||
public:
|
||||
CGunWeapon(CAssetId ancsId, EWeaponType type, TUniqueId playerId, EMaterialTypes playerMaterial,
|
||||
const zeus::CVector3f& scale);
|
||||
|
|
|
@ -30,14 +30,14 @@ CActorModelParticles::CItem::CItem(const CEntity& ent, CActorModelParticles& par
|
|||
x8_onFireGens.resize(8);
|
||||
}
|
||||
|
||||
static s32 GetNextBestPt(s32 start, const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn,
|
||||
CRandom16& rnd) {
|
||||
const zeus::CVector3f& startVec = vn[start].first;
|
||||
static s32 GetNextBestPt(s32 start, const SSkinningWorkspace& workspace, CRandom16& rnd) {
|
||||
const auto& verts = workspace.m_vertexWorkspace;
|
||||
const zeus::CVector3f& startVec = verts[start];
|
||||
s32 ret = start;
|
||||
float maxMag = 0.f;
|
||||
for (s32 i = 0; i < 10; ++i) {
|
||||
s32 idx = rnd.Range(0, s32(vn.size()) - 1);
|
||||
const zeus::CVector3f& rndVec = vn[idx].first;
|
||||
s32 idx = rnd.Range(0, s32(verts.size()) - 1);
|
||||
const zeus::CVector3f& rndVec = verts[idx];
|
||||
float mag = (startVec - rndVec).magSquared();
|
||||
if (mag > maxMag) {
|
||||
ret = idx;
|
||||
|
@ -46,11 +46,15 @@ static s32 GetNextBestPt(s32 start, const std::vector<std::pair<zeus::CVector3f,
|
|||
}
|
||||
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) {
|
||||
if (pair.first) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -60,9 +64,9 @@ void CActorModelParticles::CItem::GeneratePoints(const std::vector<std::pair<zeu
|
|||
s32 count = (x84_ashMaxParticles >= 16 ? 16 : x84_ashMaxParticles);
|
||||
s32 idx = x80_ashPointIterator;
|
||||
for (u32 i = 0; i < count; ++i) {
|
||||
idx = GetNextBestPt(idx, vn, rnd);
|
||||
x78_ashGen->SetTranslation(xec_particleOffsetScale * vn[idx].first);
|
||||
zeus::CVector3f v = vn[idx].second;
|
||||
idx = GetNextBestPt(idx, workspace, rnd);
|
||||
x78_ashGen->SetTranslation(xec_particleOffsetScale * verts[idx]);
|
||||
zeus::CVector3f v = norms[idx];
|
||||
if (v.canBeNormalized()) {
|
||||
v.normalize();
|
||||
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();
|
||||
iceGen->SetGlobalOrientAndTrans(xf8_iceXf);
|
||||
|
||||
s32 idx = GetNextBestPt(xb0_icePointIterator, vn, rnd);
|
||||
iceGen->SetTranslation(xec_particleOffsetScale * vn[idx].first);
|
||||
s32 idx = GetNextBestPt(xb0_icePointIterator, workspace, rnd);
|
||||
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));
|
||||
xb0_icePointIterator = (x8c_iceGens.size() == 4 ? -1 : idx);
|
||||
|
@ -98,9 +102,9 @@ void CActorModelParticles::CItem::GeneratePoints(const std::vector<std::pair<zeu
|
|||
#endif
|
||||
s32 idx = xc8_electricPointIterator;
|
||||
for (u32 i = 0; i < end; ++i) {
|
||||
xc0_electricGen->SetOverrideIPos(vn[rnd.Range(0, s32(vn.size()) - 1)].first * xec_particleOffsetScale);
|
||||
idx = rnd.Range(0, s32(vn.size()) - 1);
|
||||
xc0_electricGen->SetOverrideFPos(vn[idx].first * xec_particleOffsetScale);
|
||||
xc0_electricGen->SetOverrideIPos(verts[rnd.Range(0, s32(verts.size()) - 1)] * xec_particleOffsetScale);
|
||||
idx = rnd.Range(0, s32(verts.size()) - 1);
|
||||
xc0_electricGen->SetOverrideFPos(verts[idx] * xec_particleOffsetScale);
|
||||
xc0_electricGen->ForceParticleCreation(1);
|
||||
}
|
||||
|
||||
|
@ -109,7 +113,7 @@ void CActorModelParticles::CItem::GeneratePoints(const std::vector<std::pair<zeu
|
|||
}
|
||||
|
||||
if (xd4_rainSplashGen)
|
||||
xd4_rainSplashGen->GeneratePoints(vn);
|
||||
xd4_rainSplashGen->GeneratePoints(workspace);
|
||||
}
|
||||
|
||||
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) {
|
||||
const auto search = FindSystem(uid);
|
||||
|
||||
if (search == x0_items.cend()) {
|
||||
return;
|
||||
}
|
||||
|
||||
CSkinnedModel::SetPointGeneratorFunc(&*search, PointGenerator);
|
||||
CSkinnedModel::SetPointGeneratorFunc([=](const auto& workspace) { search->GeneratePoints(workspace); });
|
||||
}
|
||||
|
||||
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) {
|
||||
auto iter = FindSystem(act.GetUniqueId());
|
||||
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 nullptr;
|
||||
|
|
|
@ -71,7 +71,7 @@ public:
|
|||
|
||||
public:
|
||||
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);
|
||||
void Lock(EDependency i);
|
||||
void Unlock(EDependency i);
|
||||
|
@ -150,7 +150,6 @@ private:
|
|||
|
||||
public:
|
||||
CActorModelParticles();
|
||||
static void PointGenerator(void* item, const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn);
|
||||
void AddStragglersToRenderer(const CStateManager& mgr);
|
||||
void Update(float dt, CStateManager& mgr);
|
||||
void SetupHook(TUniqueId uid);
|
||||
|
|
|
@ -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 {
|
||||
SCOPED_GRAPHICS_DEBUG_GROUP("CPlayer::Render", zeus::skPurple);
|
||||
zeus::CTransform ballToWorld = GetBallToWorld();
|
||||
|
@ -1685,7 +1681,8 @@ void CMorphBall::Render(const CStateManager& mgr, const CActorLights* lights) co
|
|||
// flags.m_extendedShader = EExtendedShader::LightingCubeReflection;
|
||||
|
||||
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) {
|
||||
|
|
|
@ -170,7 +170,6 @@ private:
|
|||
static zeus::CVector3f TransformSpiderBallForcesXY(const zeus::CVector2f& forces, CStateManager& mgr);
|
||||
static zeus::CVector3f TransformSpiderBallForcesXZ(const zeus::CVector2f& forces, CStateManager& mgr);
|
||||
void ResetSpiderBallForces();
|
||||
static void PointGenerator(void* ctx, const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn);
|
||||
|
||||
public:
|
||||
CMorphBall(CPlayer& player, float radius);
|
||||
|
|
|
@ -416,7 +416,7 @@ void CSnakeWeedSwarm::RenderBoid(u32 idx, const CBoid& boid, u32& posesToBuild)
|
|||
if (posesToBuild & 1 << modelIdx) {
|
||||
posesToBuild &= ~(1 << modelIdx);
|
||||
animData.BuildPose();
|
||||
model.Calculate(animData.GetPose(), std::nullopt, nullptr);
|
||||
model.Calculate(animData.GetPose(), std::nullopt, nullptr, nullptr); // TODO x178_workspaces[modelIdx]
|
||||
}
|
||||
CGraphics::SetModelMatrix(
|
||||
zeus::CTransform::Translate(boid.GetPosition() - zeus::CVector3f(0.f, 0.f, boid.GetZOffset())) *
|
||||
|
|
Loading…
Reference in New Issue