Work on character animation

This commit is contained in:
Jack Andersen 2016-08-21 10:39:18 -10:00
parent d125b4769e
commit 670eb998d4
35 changed files with 460 additions and 102 deletions

View File

@ -1083,10 +1083,25 @@ bool ANCS::Cook(const hecl::ProjectPath& outPath,
Log.report(logvisor::Fatal, _S("'%s' not found as file"),
yamlPath.getRelativePath().c_str());
athena::io::FileReader yamlReader(yamlPath.getAbsolutePath());
if (!BigYAML::ValidateFromYAMLFile<ANCS>(yamlReader))
FILE* yamlFp = hecl::Fopen(yamlPath.getAbsolutePath().c_str(), _S("r"));
if (!yamlFp)
Log.report(logvisor::Fatal, _S("can't open '%s' for reading"),
yamlPath.getRelativePath().c_str());
if (!BigYAML::ValidateFromYAMLFile<ANCS>(yamlFp))
{
Log.report(logvisor::Fatal, _S("'%s' is not urde::DNAMP1::ANCS type"),
yamlPath.getRelativePath().c_str());
}
athena::io::YAMLDocReader yamlReader;
yaml_parser_set_input_file(yamlReader.getParser(), yamlFp);
if (!yamlReader.parse())
{
Log.report(logvisor::Fatal, _S("unable to parse '%s'"),
yamlPath.getRelativePath().c_str());
}
fclose(yamlFp);
ANCS ancs;
ancs.read(yamlReader);

View File

@ -26,7 +26,7 @@ namespace urde
void ViewManager::BuildTestPART(urde::IObjectStore& objStore)
{
#if 0
#if 1
SObjectTag samusCharSet = m_projManager.TagFromPath(_S("MP1/Shared/ANCS_77289A4A.blend"));
SObjectTag platModel = m_projManager.TagFromPath(_S("MP1/Shared/CMDL_6FA561D0.blend"));
SObjectTag bgModel = m_projManager.TagFromPath(_S("MP1/Shared/CMDL_BC34D54C.blend"));
@ -93,6 +93,7 @@ void ViewManager::ParticleView::draw(boo::IGraphicsCommandQueue *gfxQ)
if (m_vm.m_modelTest.IsLoaded())
{
#if 0
CModelFlags flags;
flags.m_extendedShaderIdx = 0;
@ -131,6 +132,8 @@ void ViewManager::ParticleView::draw(boo::IGraphicsCommandQueue *gfxQ)
//g_Renderer->DoThermalBlendHot();
//m_spaceWarpFilter.setStrength(std::sin(m_theta * 5.f) * 0.5f + 0.5f);
//m_spaceWarpFilter.draw(zeus::CVector2f{0.f, 0.f});
#endif
}
if (m_vm.m_partGen)
{
@ -167,6 +170,7 @@ void ViewManager::ParticleView::draw(boo::IGraphicsCommandQueue *gfxQ)
m_vm.m_moviePlayer->Update(1.f / 60.f);
m_vm.m_moviePlayer->DrawFrame();
}
g_GameState->GetWorldTransitionManager()->Draw();
}
specter::View* ViewManager::BuildSpaceViews()

View File

@ -275,7 +275,7 @@ public:
TUniqueId AllocateUniqueId();
const std::shared_ptr<CPlayerState>& GetPlayerState() const {return x8b8_playerState;}
CRandom16& GetActiveRandom() {return x8fc_random;}
CRandom16* GetActiveRandom() {return x900_activeRandom;}
CRumbleManager& GetRumbleManager() {return *x88c_rumbleManager;}
CCameraFilterPass& GetCameraFilterPass(int idx) {return xb84_camFilterPasses[idx];}

View File

@ -301,6 +301,9 @@ public:
T* operator->() {return GetObj();}
const T* operator->() const {return GetObj();}
void Unlock() {TToken<T>::Unlock(); m_obj = nullptr;}
TCachedToken& operator=(const TCachedToken& other) { CToken::operator=(other); m_obj = nullptr; return *this; }
TCachedToken& operator=(const CToken& other) { CToken::operator=(other); m_obj = nullptr; return *this; }
};
template <class T>
@ -309,9 +312,9 @@ class TLockedToken : public TCachedToken<T>
public:
TLockedToken() = default;
TLockedToken(const TLockedToken& other) : TCachedToken<T>(other) { CToken::Lock(); }
TLockedToken& operator=(const TLockedToken& other) { CToken::operator=(other); CToken::Lock(); return *this; }
TLockedToken& operator=(const TLockedToken& other) { TCachedToken<T>::operator=(other); CToken::Lock(); return *this; }
TLockedToken(const CToken& other) : TCachedToken<T>(other) { CToken::Lock(); }
TLockedToken& operator=(const CToken& other) { CToken::operator=(other); CToken::Lock(); return *this; }
TLockedToken& operator=(const CToken& other) { TCachedToken<T>::operator=(other); CToken::Lock(); return *this; }
TLockedToken(CToken&& other) : TCachedToken<T>(std::move(other)) { CToken::Lock(); }
};

View File

@ -78,7 +78,7 @@ void CCameraManager::Update(float dt, CStateManager& stateMgr)
it = x18_shakers.erase(it);
continue;
}
x30_shakeOffset += it->GeneratePoint(dt, stateMgr.GetActiveRandom());
x30_shakeOffset += it->GeneratePoint(dt, *stateMgr.GetActiveRandom());
++it;
}

View File

@ -15,6 +15,7 @@
#include "CAnimTreeNode.hpp"
#include "CAnimPerSegmentData.hpp"
#include "CSegStatementSet.hpp"
#include "CStateManager.hpp"
namespace urde
{
@ -83,7 +84,7 @@ static void AdvanceAnimationTree(std::weak_ptr<CAnimTreeNode>& anim, const CChar
{
}
void CAnimData::AdvanceAdditiveAnims(float dt)
SAdvancementDeltas CAnimData::AdvanceAdditiveAnims(float dt)
{
CCharAnimTime time(dt);
@ -102,8 +103,11 @@ void CAnimData::AdvanceAdditiveAnims(float dt)
}
}
void CAnimData::UpdateAdditiveAnims(float)
SAdvancementDeltas CAnimData::UpdateAdditiveAnims(float dt)
{
return AdvanceAdditiveAnims(dt);
}
bool CAnimData::IsAdditiveAnimation(u32) const
@ -228,16 +232,30 @@ void CAnimData::RenderAuxiliary(const CFrustumPlanes& frustum) const
{
}
void CAnimData::Render(const CSkinnedModel& model, const CModelFlags& drawFlags,
void CAnimData::Render(CSkinnedModel& model, const CModelFlags& drawFlags,
const rstl::optional_object<CVertexMorphEffect>& morphEffect,
const float* morphMagnitudes) const
const float* morphMagnitudes)
{
SetupRender(model, drawFlags, morphEffect, morphMagnitudes);
DrawSkinnedModel(model, drawFlags);
}
void CAnimData::SetupRender(const CSkinnedModel& model,
void CAnimData::SetupRender(CSkinnedModel& model,
const CModelFlags& drawFlags,
const rstl::optional_object<CVertexMorphEffect>& morphEffect,
const float* morphMagnitudes) const
const float* morphMagnitudes)
{
if (!x220_30_poseBuilt)
{
x2fc_poseBuilder.BuildNoScale(x224_pose);
x220_30_poseBuilt = true;
}
PoseSkinnedModel(model, x224_pose, drawFlags, morphEffect, morphMagnitudes);
}
void CAnimData::DrawSkinnedModel(CSkinnedModel& model, const CModelFlags& flags)
{
model.Draw(flags);
}
void CAnimData::PreRender()
@ -246,7 +264,7 @@ void CAnimData::PreRender()
{
RecalcPoseBuilder(nullptr);
x220_31_poseCached = true;
x220_30_ = false;
x220_30_poseBuilt = false;
}
}
@ -266,22 +284,164 @@ void CAnimData::SetAnimation(const CAnimPlaybackParms& parms, bool)
{
}
void CAnimData::DoAdvance(float, bool&, CRandom16&, bool)
SAdvancementDeltas CAnimData::DoAdvance(float dt, bool& b1, CRandom16& random, bool b2)
{
b1 = false;
zeus::CVector3f offsetPre, offsetPost;
zeus::CQuaternion quatPre, quatPost;
ResetPOILists();
float scaleDt = dt * x200_speedScale;
if (x2fc_poseBuilder.HasRoot())
{
SAdvancementDeltas deltas = UpdateAdditiveAnims(scaleDt);
offsetPre = deltas.x0_posDelta;
quatPre = deltas.xc_rotDelta;
}
if (!x220_24_animating)
{
b1 = true;
return {};
}
if (x220_29_)
{
x220_29_ = false;
b1 = true;
}
if (b2)
{
SetRandomPlaybackRate(random);
CCharAnimTime time(scaleDt);
if (x220_25_loop)
{
while (time.GreaterThanZero() && !time.EpsilonZero())
{
x210_passedIntCount += x1f8_animRoot->GetInt32POIList(time, g_Int32POINodes.data(), 16, x210_passedIntCount, 0);
x20c_passedBoolCount += x1f8_animRoot->GetBoolPOIList(time, g_BoolPOINodes.data(), 16, x20c_passedBoolCount, 0);
x214_passedParticleCount += x1f8_animRoot->GetParticlePOIList(time, g_ParticlePOINodes.data(), 16, x214_passedParticleCount, 0);
x218_passedSoundCount += x1f8_animRoot->GetSoundPOIList(time, g_SoundPOINodes.data(), 16, x218_passedSoundCount, 0);
AdvanceAnim(time, offsetPost, quatPost);
}
}
else
{
CCharAnimTime remTime = x1f8_animRoot->VGetTimeRemaining();
while (remTime.GreaterThanZero() && !remTime.EpsilonZero())
{
x210_passedIntCount += x1f8_animRoot->GetInt32POIList(time, g_Int32POINodes.data(), 16, x210_passedIntCount, 0);
x20c_passedBoolCount += x1f8_animRoot->GetBoolPOIList(time, g_BoolPOINodes.data(), 16, x20c_passedBoolCount, 0);
x214_passedParticleCount += x1f8_animRoot->GetParticlePOIList(time, g_ParticlePOINodes.data(), 16, x214_passedParticleCount, 0);
x218_passedSoundCount += x1f8_animRoot->GetSoundPOIList(time, g_SoundPOINodes.data(), 16, x218_passedSoundCount, 0);
AdvanceAnim(time, offsetPost, quatPost);
remTime = x1f8_animRoot->VGetTimeRemaining();
time = std::max(0.f, std::min(float(remTime), float(time)));
if (remTime.EpsilonZero())
{
x220_24_animating = false;
x1dc_ = zeus::CVector3f::skZero;
x220_28_ = false;
x220_26_ = false;
}
}
}
x220_31_poseCached = false;
x220_30_poseBuilt = false;
}
return {offsetPost + offsetPre, quatPost * quatPre};
}
SAdvancementDeltas CAnimData::Advance(float, const zeus::CVector3f&, CStateManager& stateMgr, bool)
SAdvancementDeltas CAnimData::Advance(float dt, const zeus::CVector3f& scale,
CStateManager& stateMgr, TAreaId aid, bool b1)
{
return {};
bool b2;
return DoAdvance(dt, b2, *stateMgr.GetActiveRandom(), b1);
if (b2)
x120_particleDB.SuspendAllActiveEffects(stateMgr);
for (CParticlePOINode& node : g_ParticlePOINodes)
{
if (node.GetCharIdx() == -1 || node.GetCharIdx() == x204_charIdx)
{
x120_particleDB.StartEffect(node.GetName(), node.GetFlags(), node.GetParticleData(),
scale, stateMgr, aid, x21c_);
}
}
}
SAdvancementDeltas CAnimData::AdvanceIgnoreParticles(float, CRandom16&, bool)
SAdvancementDeltas CAnimData::AdvanceIgnoreParticles(float dt, CRandom16& random, bool b1)
{
return {};
bool b2;
return DoAdvance(dt, b2, random, b1);
}
void CAnimData::AdvanceAnim(CCharAnimTime& time, zeus::CVector3f&, zeus::CQuaternion&)
void CAnimData::AdvanceAnim(CCharAnimTime& time, zeus::CVector3f& offset, zeus::CQuaternion& quat)
{
SAdvancementResults results;
std::shared_ptr<IAnimReader> simplified;
if (x104_)
{
results = x1f8_animRoot->VAdvanceView(time);
simplified = x1f8_animRoot->VSimplified();
}
if (simplified)
{
if (simplified->IsCAnimTreeNode())
{
if (x1f8_animRoot != simplified)
x1f8_animRoot = std::move(simplified);
}
else
x1f8_animRoot.reset();
}
if ((x220_28_ || x220_27_) && x210_passedIntCount > 0)
{
for (CInt32POINode& node : g_Int32POINodes)
{
if (node.GetPoiType() == EPOIType::UserEvent)
{
switch (EUserEventType(node.GetValue()))
{
case EUserEventType::AlignTargetPosStart:
{
x220_26_ = true;
break;
}
case EUserEventType::AlignTargetPos:
{
x1dc_ = zeus::CVector3f::skZero;
x220_28_ = false;
x220_26_ = false;
break;
}
case EUserEventType::AlignTargetRot:
{
x1e8_ = zeus::CQuaternion::skNoRotation;
x220_27_ = false;
break;
}
default: break;
}
}
}
}
offset += results.x8_deltas.x0_posDelta;
if (x220_26_)
offset += x1dc_ * time;
zeus::CQuaternion rot = results.x8_deltas.xc_rotDelta * x1e8_;
quat = quat * rot;
x1dc_ = rot.transform(x1dc_);
time = results.x0_remTime;
}
void CAnimData::SetXRayModel(const TLockedToken<CModel>& model, const TLockedToken<CSkinRules>& skinRules)
@ -292,10 +452,12 @@ void CAnimData::SetInfraModel(const TLockedToken<CModel>& model, const TLockedTo
{
}
void CAnimData::PoseSkinnedModel(const CSkinnedModel& model, const CPoseAsTransforms& pose,
void CAnimData::PoseSkinnedModel(CSkinnedModel& model, const CPoseAsTransforms& pose,
const CModelFlags& drawFlags,
const rstl::optional_object<CVertexMorphEffect>& morphEffect,
const float* morphMagnitudes) const
const float* morphMagnitudes)
{
model.Calculate(pose, drawFlags, morphEffect, morphMagnitudes);
}
void CAnimData::AdvanceParticles(const zeus::CTransform& xf, float,

View File

@ -12,6 +12,41 @@
enum class EUserEventType
{
Projectile,
EggLay,
LoopedSoundStop,
AlignTargetPos,
AlignTargetRot,
ChangeMaterial,
Delete,
GenerateEnd,
DamageOn,
DamageOff,
AlignTargetPosStart,
DeGenerate,
Landing,
TakeOff,
FadeIn,
FadeOut,
ScreenShake,
BeginAction,
EndAction,
BecomeRagDoll,
IkLock,
IkRelease,
BreakLockOn,
BecomeShootThrough,
RemoveCollision,
ObjectPickUp,
ObjectDrop,
EventStart,
EventStop,
Activate,
Deactivate,
SoundPlay,
SoundStop,
EffectOn,
EffectOff
};
namespace urde
@ -41,6 +76,7 @@ class CBoolPOINode;
class CInt32POINode;
class CParticlePOINode;
class CSoundPOINode;
class IAnimReader;
struct SAdvancementDeltas;
class CAnimData
@ -61,16 +97,17 @@ class CAnimData
ResId x1d8_selfId;
zeus::CVector3f x1dc_;
zeus::CQuaternion x1e8_;
std::shared_ptr<CAnimTreeNode> x1f8_animRoot;
std::shared_ptr<IAnimReader> x1f8_animRoot;
std::shared_ptr<CTransitionManager> x1fc_transMgr;
float x200_ = 1.f;
float x200_speedScale = 1.f;
u32 x204_charIdx;
u16 x208_defaultAnim;
u32 x20c_passedBoolCount = 0;
u32 x210_passedIntCount = 0;
u32 x214_passedParticleCount = 0;
u32 x218_passedSoundCount = 0;
u32 x21c_ = 0;
union
{
@ -83,7 +120,7 @@ class CAnimData
bool x220_27_ : 1;
bool x220_28_ : 1;
bool x220_29_ : 1;
bool x220_30_ : 1;
bool x220_30_poseBuilt : 1;
bool x220_31_poseCached : 1;
};
};
@ -122,8 +159,8 @@ public:
ResId GetEventResourceIdForAnimResourceId(ResId) const;
void AddAdditiveSegData(const CSegIdList& list, CSegStatementSet& stSet);
void AdvanceAdditiveAnims(float);
void UpdateAdditiveAnims(float);
SAdvancementDeltas AdvanceAdditiveAnims(float);
SAdvancementDeltas UpdateAdditiveAnims(float);
bool IsAdditiveAnimation(u32) const;
std::shared_ptr<CAnimTreeNode> GetAdditiveAnimationTree(u32) const;
bool IsAdditiveAnimationActive(u32) const;
@ -152,27 +189,30 @@ public:
std::shared_ptr<CAnimationManager> GetAnimationManager() const;
void RecalcPoseBuilder(const CCharAnimTime*);
void RenderAuxiliary(const CFrustumPlanes& frustum) const;
void Render(const CSkinnedModel& model, const CModelFlags& drawFlags,
void Render(CSkinnedModel& model, const CModelFlags& drawFlags,
const std::experimental::optional<CVertexMorphEffect>& morphEffect,
const float* morphMagnitudes) const;
void SetupRender(const CSkinnedModel& model,
const float* morphMagnitudes);
void SetupRender(CSkinnedModel& model,
const CModelFlags& drawFlags,
const std::experimental::optional<CVertexMorphEffect>& morphEffect,
const float* morphMagnitudes) const;
const float* morphMagnitudes);
static void DrawSkinnedModel(CSkinnedModel& model, const CModelFlags& flags);
void PreRender();
void BuildPose();
void PrimitiveSetToTokenVector(const std::set<CPrimitive>& primSet, std::vector<CToken>& tokensOut);
void GetAnimationPrimitives(const CAnimPlaybackParms& parms, std::set<CPrimitive>& primsOut) const;
void SetAnimation(const CAnimPlaybackParms& parms, bool);
void DoAdvance(float, bool&, CRandom16&, bool);
SAdvancementDeltas Advance(float, const zeus::CVector3f&, CStateManager& stateMgr, bool);
SAdvancementDeltas DoAdvance(float, bool&, CRandom16&, bool);
SAdvancementDeltas Advance(float, const zeus::CVector3f&, CStateManager& stateMgr, TAreaId aid, bool);
SAdvancementDeltas AdvanceIgnoreParticles(float, CRandom16&, bool);
void AdvanceAnim(CCharAnimTime& time, zeus::CVector3f&, zeus::CQuaternion&);
void SetXRayModel(const TLockedToken<CModel>& model, const TLockedToken<CSkinRules>& skinRules);
void SetInfraModel(const TLockedToken<CModel>& model, const TLockedToken<CSkinRules>& skinRules);
void PoseSkinnedModel(const CSkinnedModel& model, const CPoseAsTransforms& pose,
const std::experimental::optional<CVertexMorphEffect>& morphEffect,
const float* morphMagnitudes) const;
static void PoseSkinnedModel(CSkinnedModel& model, const CPoseAsTransforms& pose,
const CModelFlags& drawFlags,
const std::experimental::optional<CVertexMorphEffect>& morphEffect,
const float* morphMagnitudes);
void AdvanceParticles(const zeus::CTransform& xf, float dt,
const zeus::CVector3f&, CStateManager& stateMgr);
void GetAverageVelocity(int) const;

View File

@ -5,7 +5,7 @@ namespace urde
{
CBoolPOINode::CBoolPOINode()
: CPOINode("root", 1, CCharAnimTime(), -1, false, 1.f, -1, 0) {}
: CPOINode("root", EPOIType::EmptyBool, CCharAnimTime(), -1, false, 1.f, -1, 0) {}
CBoolPOINode::CBoolPOINode(CInputStream& in)
: CPOINode(in), x38_val(in.readBool()) {}

View File

@ -1,5 +1,7 @@
#include "CCharAnimTime.hpp"
#include <algorithm>
#include <cmath>
#include <float.h>
namespace urde
{
@ -19,6 +21,11 @@ bool CCharAnimTime::EqualsZero() const
return (m_time == 0.f);
}
bool CCharAnimTime::EpsilonZero() const
{
return (std::fabs(m_time) < FLT_EPSILON);
}
bool CCharAnimTime::GreaterThanZero() const
{
if (EqualsZero())

View File

@ -30,6 +30,7 @@ public:
operator float() const {return m_time;}
bool EqualsZero() const;
bool EpsilonZero() const;
bool GreaterThanZero() const;
bool operator ==(const CCharAnimTime& other) const;
bool operator !=(const CCharAnimTime& other) const;

View File

@ -31,14 +31,14 @@ CFactoryFnReturn CCharacterFactory::CDummyFactory::Build(const SObjectTag& tag,
charInfo.GetModelId(),
charInfo.GetSkinRulesId(),
charInfo.GetCharLayoutInfoId(),
CSkinnedModel::EDataOwnership::One));
0));
case 1:
return TToken<CSkinnedModel>::GetIObjObjectFor(
std::make_unique<CMorphableSkinnedModel>(*g_SimplePool,
charInfo.GetIceModelId(),
charInfo.GetIceSkinRulesId(),
charInfo.GetCharLayoutInfoId(),
CSkinnedModel::EDataOwnership::One));
0));
default:
break;
}

View File

@ -43,6 +43,7 @@ class CHierarchyPoseBuilder
public:
CHierarchyPoseBuilder(const CLayoutDescription& layout);
bool HasRoot() const { return xcf0_hasRoot; }
void BuildTransform(const CSegId& boneId, zeus::CTransform& xfOut) const;
void BuildNoScale(CPoseAsTransforms& pose);
void Insert(const CSegId& boneId, const zeus::CQuaternion& quat);

View File

@ -5,7 +5,7 @@ namespace urde
{
CInt32POINode::CInt32POINode()
: CPOINode("root", 2, CCharAnimTime(), -1, false, 1.f, -1, 0), x38_val(0), x3c_locatorName("root") {}
: CPOINode("root", EPOIType::EmptyInt32, CCharAnimTime(), -1, false, 1.f, -1, 0), x38_val(0), x3c_locatorName("root") {}
CInt32POINode::CInt32POINode(CInputStream& in)
: CPOINode(in), x38_val(in.readUint32Big()), x3c_locatorName(in.readString()) {}

View File

@ -240,10 +240,10 @@ SAdvancementDeltas CModelData::AdvanceAnimationIgnoreParticles(float dt, CRandom
return {};
}
SAdvancementDeltas CModelData::AdvanceAnimation(float dt, CStateManager& stateMgr, bool flag)
SAdvancementDeltas CModelData::AdvanceAnimation(float dt, CStateManager& stateMgr, TAreaId aid, bool flag)
{
if (x10_animData)
return x10_animData->Advance(dt, x0_particleScale, stateMgr, flag);
return x10_animData->Advance(dt, x0_particleScale, stateMgr, aid, flag);
else
return {};
}
@ -292,13 +292,13 @@ void CModelData::RenderThermal(const zeus::CTransform& xf,
if (x10_animData)
{
const CSkinnedModel& model = PickAnimatedModel(EWhichModel::Thermal);
x10_animData->SetupRender(model, {}, nullptr);
CSkinnedModel& model = PickAnimatedModel(EWhichModel::Thermal);
x10_animData->SetupRender(model, drawFlags, {}, nullptr);
model.Draw(drawFlags);
}
else
{
const TLockedToken<CModel>& model = PickStaticModel(EWhichModel::Thermal);
TLockedToken<CModel>& model = PickStaticModel(EWhichModel::Thermal);
model->Draw(drawFlags);
}
}

View File

@ -119,7 +119,7 @@ public:
zeus::CTransform GetLocatorTransformDynamic(const std::string& name, const CCharAnimTime* time) const;
zeus::CTransform GetLocatorTransform(const std::string& name) const;
SAdvancementDeltas AdvanceAnimationIgnoreParticles(float dt, CRandom16&, bool);
SAdvancementDeltas AdvanceAnimation(float dt, CStateManager& stateMgr, bool);
SAdvancementDeltas AdvanceAnimation(float dt, CStateManager& stateMgr, TAreaId aid, bool);
bool IsAnimating() const;
bool IsInFrustum(const zeus::CTransform& xf, const CFrustumPlanes& frustum) const;
void RenderParticles(const CFrustumPlanes& frustum) const;

View File

@ -3,29 +3,29 @@
namespace urde
{
CPOINode::CPOINode(const std::string& name, u16 a, const CCharAnimTime& time,
CPOINode::CPOINode(const std::string& name, EPOIType type, const CCharAnimTime& time,
u32 index, bool c, float weight, u32 e, u32 f)
: x4_(1),
x8_name(name),
x18_(a),
x18_type(type),
x1c_time(time),
x24_index(index),
x28_(c),
x2c_weight(weight),
x30_(e),
x34_(f)
x30_charIdx(e),
x34_flags(f)
{}
CPOINode::CPOINode(CInputStream& in)
: x4_(in.readUint16Big()),
x8_name(in.readString()),
x18_(in.readUint16Big()),
x18_type(EPOIType(in.readUint16Big())),
x1c_time(in),
x24_index(in.readUint32Big()),
x28_(in.readBool()),
x2c_weight(in.readFloatBig()),
x30_(in.readUint32Big()),
x34_(in.readUint32Big())
x30_charIdx(in.readUint32Big()),
x34_flags(in.readUint32Big())
{}
}

View File

@ -7,27 +7,42 @@
namespace urde
{
enum class EPOIType : u16
{
Loop = 0,
EmptyBool = 1,
EmptyInt32 = 2,
Particle = 5,
UserEvent = 6,
RandRate = 7,
Sound = 8,
};
class CPOINode
{
protected:
u16 x4_ = 1;
std::string x8_name;
u16 x18_;
EPOIType x18_type;
CCharAnimTime x1c_time;
u32 x24_index;
bool x28_;
float x2c_weight;
u32 x30_;
u32 x34_;
u32 x30_charIdx = -1;
u32 x34_flags;
public:
CPOINode(const std::string& name, u16, const CCharAnimTime& time, u32 index, bool, float weight, u32, u32);
CPOINode(const std::string& name, EPOIType type, const CCharAnimTime& time,
u32 index, bool, float weight, u32 charIdx, u32 flags);
CPOINode(CInputStream& in);
virtual ~CPOINode() = default;
const std::string& GetName() const {return x8_name;}
const CCharAnimTime& GetTime() const {return x1c_time;}
EPOIType GetPoiType() const { return x18_type; }
u32 GetIndex() const {return x24_index;}
float GetWeight() const { return x2c_weight; }
u32 GetCharIdx() const { return x30_charIdx; }
u32 GetFlags() const { return x34_flags; }
};
}

View File

@ -7,4 +7,17 @@ void CParticleDatabase::CacheParticleDesc(const CCharacterInfo::CParticleResData
{
}
void CParticleDatabase::SetModulationColorAllActiveEffects(const zeus::CColor& color)
{
}
void CParticleDatabase::SuspendAllActiveEffects(CStateManager& stateMgr)
{
}
void CParticleDatabase::StartEffect(const std::string& name, u32 flags, const CParticleData& data,
const zeus::CVector3f& scale, CStateManager& stateMgr, TAreaId aid, u32 unk1)
{
}
}

View File

@ -14,6 +14,9 @@ class CParticleDatabase
public:
void CacheParticleDesc(const CCharacterInfo::CParticleResData& desc);
void SetModulationColorAllActiveEffects(const zeus::CColor& color);
void SuspendAllActiveEffects(CStateManager& stateMgr);
void StartEffect(const std::string& name, u32 flags, const CParticleData& data,
const zeus::CVector3f& scale, CStateManager& stateMgr, TAreaId aid, u32 unk1);
};
}

View File

@ -5,7 +5,7 @@ namespace urde
{
CParticlePOINode::CParticlePOINode()
: CPOINode("root", 5, CCharAnimTime(), -1, false, 1.f, -1, 0) {}
: CPOINode("root", EPOIType::Particle, CCharAnimTime(), -1, false, 1.f, -1, 0) {}
CParticlePOINode::CParticlePOINode(CInputStream& in)
: CPOINode(in), x38_data(in) {}

View File

@ -1,4 +1,5 @@
#include "CSkinBank.hpp"
#include "CPoseAsTransforms.hpp"
namespace urde
{
@ -11,4 +12,11 @@ CSkinBank::CSkinBank(CInputStream& in)
x0_segments.emplace_back(in);
}
void CSkinBank::GetBankTransforms(std::vector<const zeus::CTransform*>& out,
const CPoseAsTransforms& pose) const
{
for (CSegId id : x0_segments)
out.push_back(&pose.GetTransform(id));
}
}

View File

@ -6,12 +6,15 @@
namespace urde
{
class CPoseAsTransforms;
class CSkinBank
{
std::vector<CSegId> x0_segments;
public:
CSkinBank(CInputStream& in);
void GetBankTransforms(std::vector<const zeus::CTransform*>& out,
const CPoseAsTransforms& pose) const;
};
}

View File

@ -7,6 +7,7 @@
namespace urde
{
class CPoseAsTransforms;
class CSkinRules
{
@ -14,6 +15,11 @@ class CSkinRules
public:
CSkinRules(CInputStream& in);
void BuildAccumulatedTransforms();
void GetBankTransforms(std::vector<const zeus::CTransform*>& out,
const CPoseAsTransforms& pose, int skinBankIdx) const
{
x0_skinBanks[skinBankIdx].GetBankTransforms(out, pose);
}
};
CFactoryFnReturn FSkinRulesFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& params);

View File

@ -5,7 +5,7 @@ namespace urde
{
CSoundPOINode::CSoundPOINode()
: CPOINode("root", 8, CCharAnimTime(), -1, false, 1.f, -1, 0),
: CPOINode("root", EPOIType::Sound, CCharAnimTime(), -1, false, 1.f, -1, 0),
x38_sfxId(0),
x3c_falloff(0.f),
x40_maxDist(0.f)
@ -18,7 +18,7 @@ CSoundPOINode::CSoundPOINode(CInputStream& in)
x40_maxDist(in.readFloatBig())
{}
CSoundPOINode::CSoundPOINode(const std::string& name, u16 a,
CSoundPOINode::CSoundPOINode(const std::string& name, EPOIType a,
const CCharAnimTime& time, u32 b, bool c,
float d, u32 e, u32 f, u32 sfxId, float falloff, float maxDist)
: CPOINode(name, a, time, b, c, d, e, f),

View File

@ -16,7 +16,7 @@ class CSoundPOINode : public CPOINode
public:
CSoundPOINode();
CSoundPOINode(CInputStream& in);
CSoundPOINode(const std::string& name, u16 a,
CSoundPOINode(const std::string& name, EPOIType type,
const CCharAnimTime& time, u32 b, bool c,
float d, u32 e, u32 f, u32 sfxId, float falloff, float maxDist);

View File

@ -615,7 +615,7 @@ void CBooRenderer::DrawXRayOutline(const zeus::CAABox& aabb)
if (bitmap[c] & (1 << b))
{
CBooModel* model = item.x10_models[c * 32 + b];
model->UpdateUniformData(flags);
model->UpdateUniformData(flags, nullptr, nullptr);
const CBooSurface* surf = model->x38_firstUnsortedSurface;
while (surf)
{

View File

@ -17,6 +17,8 @@ namespace urde
class IObjectStore;
class CTexture;
class CLight;
class CSkinRules;
class CPoseAsTransforms;
struct CModelFlags
{
@ -62,6 +64,7 @@ class CBooModel
friend class CModel;
friend class CBooRenderer;
friend class CMetroidModelInstance;
friend class CSkinnedModel;
public:
using MaterialSet = DataSpec::DNAMP1::HMDLMaterialSet;
using UVAnimation = DataSpec::DNAMP1::MaterialSet::Material::UVAnimation;
@ -125,10 +128,18 @@ public:
void RemapMaterialData(SShader& shader);
bool TryLockTextures() const;
void UnlockTextures() const;
void UpdateUniformData(const CModelFlags& flags) const;
void DrawAlpha(const CModelFlags& flags) const;
void DrawNormal(const CModelFlags& flags) const;
void Draw(const CModelFlags& flags) const;
void UpdateUniformData(const CModelFlags& flags,
const CSkinRules* cskr,
const CPoseAsTransforms* pose) const;
void DrawAlpha(const CModelFlags& flags,
const CSkinRules* cskr,
const CPoseAsTransforms* pose) const;
void DrawNormal(const CModelFlags& flags,
const CSkinRules* cskr,
const CPoseAsTransforms* pose) const;
void Draw(const CModelFlags& flags,
const CSkinRules* cskr,
const CPoseAsTransforms* pose) const;
const MaterialSet::Material& GetMaterialByIndex(int idx) const
{

View File

@ -7,6 +7,7 @@
#include "boo/graphicsdev/Metal.hpp"
#include "Shaders/CModelShaders.hpp"
#include "Graphics/CBooRenderer.hpp"
#include "Character/CSkinRules.hpp"
#include "GameGlobalObjects.hpp"
#include <array>
@ -456,7 +457,9 @@ void CBooModel::UVAnimationBuffer::Update(u8*& bufOut, const MaterialSet* matSet
}
}
void CBooModel::UpdateUniformData(const CModelFlags& flags) const
void CBooModel::UpdateUniformData(const CModelFlags& flags,
const CSkinRules* cskr,
const CPoseAsTransforms* pose) const
{
u8* dataOut = reinterpret_cast<u8*>(m_uniformBuffer->map(m_uniformDataSize));
u8* dataCur = dataOut;
@ -464,19 +467,54 @@ void CBooModel::UpdateUniformData(const CModelFlags& flags) const
if (m_skinBankCount)
{
/* Skinned */
std::vector<const zeus::CTransform*> bankTransforms;
bankTransforms.reserve(m_weightVecCount*4);
for (size_t i=0 ; i<m_skinBankCount ; ++i)
{
for (size_t w=0 ; w<m_weightVecCount*4 ; ++w)
if (cskr && pose)
{
zeus::CMatrix4f& mv = reinterpret_cast<zeus::CMatrix4f&>(*dataCur);
mv = CGraphics::g_GXModelView.toMatrix4f();
dataCur += sizeof(zeus::CMatrix4f);
cskr->GetBankTransforms(bankTransforms, *pose, i);
for (size_t w=0 ; w<m_weightVecCount*4 ; ++w)
{
zeus::CMatrix4f& mv = reinterpret_cast<zeus::CMatrix4f&>(*dataCur);
if (w >= bankTransforms.size())
mv = CGraphics::g_GXModelView.toMatrix4f();
else
mv = (CGraphics::g_GXModelView * *bankTransforms[w]).toMatrix4f();
dataCur += sizeof(zeus::CMatrix4f);
}
for (size_t w=0 ; w<m_weightVecCount*4 ; ++w)
{
zeus::CMatrix4f& mvinv = reinterpret_cast<zeus::CMatrix4f&>(*dataCur);
if (w >= bankTransforms.size())
mvinv = CGraphics::g_GXModelViewInvXpose.toMatrix4f();
else
{
zeus::CTransform xf = (CGraphics::g_GXModelView * *bankTransforms[w]).inverse();
xf.origin.zeroOut();
xf.basis.transpose();
mvinv = xf.toMatrix4f();
}
dataCur += sizeof(zeus::CMatrix4f);
}
bankTransforms.clear();
}
for (size_t w=0 ; w<m_weightVecCount*4 ; ++w)
else
{
zeus::CMatrix4f& mvinv = reinterpret_cast<zeus::CMatrix4f&>(*dataCur);
mvinv = CGraphics::g_GXModelViewInvXpose.toMatrix4f();
dataCur += sizeof(zeus::CMatrix4f);
for (size_t w=0 ; w<m_weightVecCount*4 ; ++w)
{
zeus::CMatrix4f& mv = reinterpret_cast<zeus::CMatrix4f&>(*dataCur);
mv = CGraphics::g_GXModelView.toMatrix4f();
dataCur += sizeof(zeus::CMatrix4f);
}
for (size_t w=0 ; w<m_weightVecCount*4 ; ++w)
{
zeus::CMatrix4f& mvinv = reinterpret_cast<zeus::CMatrix4f&>(*dataCur);
mvinv = CGraphics::g_GXModelViewInvXpose.toMatrix4f();
dataCur += sizeof(zeus::CMatrix4f);
}
}
zeus::CMatrix4f& proj = reinterpret_cast<zeus::CMatrix4f&>(*dataCur);
proj = CGraphics::GetPerspectiveProjectionMatrix(true);
@ -524,29 +562,35 @@ void CBooModel::UpdateUniformData(const CModelFlags& flags) const
m_uniformBuffer->unmap();
}
void CBooModel::DrawAlpha(const CModelFlags& flags) const
void CBooModel::DrawAlpha(const CModelFlags& flags,
const CSkinRules* cskr,
const CPoseAsTransforms* pose) const
{
if (TryLockTextures())
{
UpdateUniformData(flags);
UpdateUniformData(flags, cskr, pose);
DrawAlphaSurfaces(flags);
}
}
void CBooModel::DrawNormal(const CModelFlags& flags) const
void CBooModel::DrawNormal(const CModelFlags& flags,
const CSkinRules* cskr,
const CPoseAsTransforms* pose) const
{
if (TryLockTextures())
{
UpdateUniformData(flags);
UpdateUniformData(flags, cskr, pose);
DrawNormalSurfaces(flags);
}
}
void CBooModel::Draw(const CModelFlags& flags) const
void CBooModel::Draw(const CModelFlags& flags,
const CSkinRules* cskr,
const CPoseAsTransforms* pose) const
{
if (TryLockTextures())
{
UpdateUniformData(flags);
UpdateUniformData(flags, cskr, pose);
DrawSurfaces(flags);
}
}
@ -667,19 +711,19 @@ void CModel::VerifyCurrentShader(int shaderIdx) const
void CModel::DrawSortedParts(const CModelFlags& flags) const
{
VerifyCurrentShader(flags.m_matSetIdx);
x28_modelInst->DrawAlpha(flags);
x28_modelInst->DrawAlpha(flags, nullptr, nullptr);
}
void CModel::DrawUnsortedParts(const CModelFlags& flags) const
{
VerifyCurrentShader(flags.m_matSetIdx);
x28_modelInst->DrawNormal(flags);
x28_modelInst->DrawNormal(flags, nullptr, nullptr);
}
void CModel::Draw(const CModelFlags& flags) const
{
VerifyCurrentShader(flags.m_matSetIdx);
x28_modelInst->Draw(flags);
x28_modelInst->Draw(flags, nullptr, nullptr);
}
void CModel::Touch(int shaderIdx) const

View File

@ -3,29 +3,43 @@
namespace urde
{
CSkinnedModel::CSkinnedModel(const TLockedToken<CModel>& model,
const TLockedToken<CSkinRules>& skinRules,
const TLockedToken<CCharLayoutInfo>& layoutInfo)
CSkinnedModel::CSkinnedModel(TLockedToken<CModel> model,
TLockedToken<CSkinRules> skinRules,
TLockedToken<CCharLayoutInfo> layoutInfo,
int shaderIdx)
: x4_model(model), x10_skinRules(skinRules), x1c_layoutInfo(layoutInfo)
{
m_modelInst = model->MakeNewInstance(shaderIdx);
}
CSkinnedModel::CSkinnedModel(IObjectStore& store, ResId model,
ResId skinRules, ResId layoutInfo,
EDataOwnership ownership)
int shaderIdx)
: CSkinnedModel(store.GetObj(SObjectTag{FOURCC('CMDL'), model}),
store.GetObj(SObjectTag{FOURCC('CSKR'), skinRules}),
store.GetObj(SObjectTag{FOURCC('CINF'), layoutInfo}),
shaderIdx)
{
}
void CSkinnedModel::Calculate(const CPoseAsTransforms& pose,
const rstl::optional_object<CVertexMorphEffect>&)
const CModelFlags& drawFlags,
const rstl::optional_object<CVertexMorphEffect>& morphEffect,
const float* morphMagnitudes)
{
m_modelInst->UpdateUniformData(drawFlags, x10_skinRules.GetObj(), &pose);
}
void CSkinnedModel::Draw(const CModelFlags& drawFlags) const
{
if (m_modelInst->TryLockTextures())
m_modelInst->DrawSurfaces(drawFlags);
}
CMorphableSkinnedModel::CMorphableSkinnedModel(IObjectStore& store, ResId model,
ResId skinRules, ResId layoutInfo,
EDataOwnership ownership)
: CSkinnedModel(store, model, skinRules, layoutInfo, ownership)
int shaderIdx)
: CSkinnedModel(store, model, skinRules, layoutInfo, shaderIdx)
{
}

View File

@ -16,6 +16,7 @@ class IObjectStore;
class CSkinnedModel
{
friend class CBooModel;
std::unique_ptr<CBooModel> m_modelInst;
TLockedToken<CModel> x4_model;
TLockedToken<CSkinRules> x10_skinRules;
@ -26,25 +27,29 @@ public:
Zero,
One
};
CSkinnedModel(const TLockedToken<CModel>& model,
const TLockedToken<CSkinRules>& skinRules,
const TLockedToken<CCharLayoutInfo>& layoutInfo);
CSkinnedModel(TLockedToken<CModel> model,
TLockedToken<CSkinRules> skinRules,
TLockedToken<CCharLayoutInfo> layoutInfo,
int shaderIdx);
CSkinnedModel(IObjectStore& store, ResId model, ResId skinRules,
ResId layoutInfo, EDataOwnership ownership);
ResId layoutInfo, int shaderIdx);
TLockedToken<CModel>& GetModel() {return x4_model;}
TLockedToken<CSkinRules>& GetSkinRules() {return x10_skinRules;}
TLockedToken<CCharLayoutInfo>& GetLayoutInfo() {return x1c_layoutInfo;}
void Calculate(const CPoseAsTransforms& pose, const std::experimental::optional<CVertexMorphEffect>&);
void Draw(const CModelFlags& drawFlags) const {}
void Calculate(const CPoseAsTransforms& pose,
const CModelFlags& drawFlags,
const std::experimental::optional<CVertexMorphEffect>& morphEffect,
const float* morphMagnitudes);
void Draw(const CModelFlags& drawFlags) const;
};
class CMorphableSkinnedModel : public CSkinnedModel
{
public:
CMorphableSkinnedModel(IObjectStore& store, ResId model, ResId skinRules,
ResId layoutInfo, EDataOwnership ownership);
ResId layoutInfo, int shaderIdx);
};
}

View File

@ -28,7 +28,7 @@ CCameraBlurFilter::CCameraBlurFilter()
void CCameraBlurFilter::draw(float amount)
{
if (amount == 0.f)
if (amount <= 0.f)
return;
SClipScreenRect clipRect = {};

View File

@ -197,6 +197,7 @@ void CWorldTransManager::DrawFirstPass()
360.f + 180.f - 90.f));
CGraphics::SetViewPointMatrix(rotateXf * translateXf);
DrawAllModels();
m_camblur.draw(x4_modelData->x1c8_blurResult);
}
void CWorldTransManager::DrawSecondPass()

View File

@ -8,6 +8,7 @@
#include "Graphics/CLight.hpp"
#include "Graphics/Shaders/CColoredQuadFilter.hpp"
#include "Graphics/Shaders/CTexturedQuadFilter.hpp"
#include "Graphics/Shaders/CCameraBlurFilter.hpp"
namespace urde
{
@ -83,6 +84,7 @@ private:
CTexturedQuadFilter m_dissolve = { CCameraFilterPass::EFilterType::Blend,
CGraphics::g_SpareTexture };
CWideScreenFilter m_widescreen = { CCameraFilterPass::EFilterType::Blend };
CCameraBlurFilter m_camblur;
static int GetSuitCharIdx();
void DrawFirstPass();

2
hecl

@ -1 +1 @@
Subproject commit 53ae402b2b130e6d0e1742d0a9d864223149c8ac
Subproject commit 667c476f2e78ac6aedef9faba4783ade01dfbd47

@ -1 +1 @@
Subproject commit d8186d24b70a8ca885b4bd3e19e1f5402c076191
Subproject commit 4260ea58f19648d6548b0c25488bfb8b47d0263b