CSkeleton: Make use of unique_ptr where applicable

Makes ownership semantics explicit.
This commit is contained in:
Lioncash 2020-06-14 16:22:55 -04:00
parent 4dcb539763
commit e49315a645
3 changed files with 61 additions and 70 deletions

View File

@ -5,12 +5,12 @@
#include <Common/Macros.h> #include <Common/Macros.h>
#include <Common/Math/MathUtil.h> #include <Common/Math/MathUtil.h>
#include <algorithm>
#include <cfloat> #include <cfloat>
// ************ CBone ************ // ************ CBone ************
CBone::CBone(CSkeleton *pSkel) CBone::CBone(CSkeleton *pSkel)
: mpSkeleton(pSkel) : mpSkeleton(pSkel)
, mSelected(false)
{ {
} }
@ -39,8 +39,8 @@ void CBone::UpdateTransform(CBoneTransformData& rData, const SBoneTransformInfo&
rTransform *= mInvBind; rTransform *= mInvBind;
// Calculate children // Calculate children
for (uint32 iChild = 0; iChild < mChildren.size(); iChild++) for (auto* child : mChildren)
mChildren[iChild]->UpdateTransform(rData, TransformInfo, pAnim, Time, AnchorRoot); child->UpdateTransform(rData, TransformInfo, pAnim, Time, AnchorRoot);
} }
CVector3f CBone::TransformedPosition(const CBoneTransformData& rkData) const CVector3f CBone::TransformedPosition(const CBoneTransformData& rkData) const
@ -58,57 +58,51 @@ bool CBone::IsRoot() const
// In Retro's engine most skeletons have another bone named Skeleton_Root parented directly under the // In Retro's engine most skeletons have another bone named Skeleton_Root parented directly under the
// actual root bone... that bone sometimes acts as the actual root (transforming the entire skeleton), // actual root bone... that bone sometimes acts as the actual root (transforming the entire skeleton),
// so we need to account for both // so we need to account for both
return (mpParent == nullptr || mpParent->Parent() == nullptr); return mpParent == nullptr || mpParent->Parent() == nullptr;
} }
// ************ CSkeleton ************ // ************ CSkeleton ************
const float CSkeleton::skSphereRadius = 0.025f;
CSkeleton::CSkeleton(CResourceEntry *pEntry /*= 0*/) CSkeleton::CSkeleton(CResourceEntry *pEntry)
: CResource(pEntry) : CResource(pEntry)
, mpRootBone(nullptr)
{ {
} }
CSkeleton::~CSkeleton() CSkeleton::~CSkeleton() = default;
{
for (uint32 iBone = 0; iBone < mBones.size(); iBone++)
delete mBones[iBone];
}
CBone* CSkeleton::BoneByID(uint32 BoneID) const CBone* CSkeleton::BoneByID(uint32 BoneID) const
{ {
for (uint32 iBone = 0; iBone < mBones.size(); iBone++) const auto iter = std::find_if(mBones.begin(), mBones.end(),
{ [BoneID](const auto& bone) { return bone->ID() == BoneID; });
if (mBones[iBone]->ID() == BoneID)
return mBones[iBone];
}
return nullptr; if (iter == mBones.cend())
return nullptr;
return iter->get();
} }
CBone* CSkeleton::BoneByName(const TString& rkBoneName) const CBone* CSkeleton::BoneByName(const TString& name) const
{ {
for (uint32 iBone = 0; iBone < mBones.size(); iBone++) const auto iter = std::find_if(mBones.begin(), mBones.end(),
{ [&name](const auto& bone) { return bone->Name() == name; });
if (mBones[iBone]->Name() == rkBoneName)
return mBones[iBone];
}
return nullptr; if (iter == mBones.cend())
return nullptr;
return iter->get();
} }
uint32 CSkeleton::MaxBoneID() const uint32 CSkeleton::MaxBoneID() const
{ {
uint32 ID = 0; const auto iter = std::max_element(mBones.cbegin(), mBones.cend(),
[](const auto& a, const auto& b) { return a->ID() < b->ID(); });
for (uint32 iBone = 0; iBone < mBones.size(); iBone++) if (iter == mBones.cend())
{ {
if (mBones[iBone]->ID() > ID) return 0;
ID = mBones[iBone]->ID();
} }
return ID; return (*iter)->ID();
} }
void CSkeleton::UpdateTransform(CBoneTransformData& rData, CAnimation *pAnim, float Time, bool AnchorRoot) void CSkeleton::UpdateTransform(CBoneTransformData& rData, CAnimation *pAnim, float Time, bool AnchorRoot)
@ -123,15 +117,14 @@ void CSkeleton::Draw(FRenderOptions /*Options*/, const CBoneTransformData *pkDat
glLineWidth(1.f); glLineWidth(1.f);
// Draw all child links first to minimize model matrix swaps. // Draw all child links first to minimize model matrix swaps.
for (uint32 iBone = 0; iBone < mBones.size(); iBone++) for (const auto& pBone : mBones)
{ {
CBone *pBone = mBones[iBone]; const CVector3f BonePos = pkData ? pBone->TransformedPosition(*pkData) : pBone->Position();
CVector3f BonePos = pkData ? pBone->TransformedPosition(*pkData) : pBone->Position();
// Draw the bone's local XYZ axes for selected bones // Draw the bone's local XYZ axes for selected bones
if (pBone->IsSelected()) if (pBone->IsSelected())
{ {
CQuaternion BoneRot = pkData ? pBone->TransformedRotation(*pkData) : pBone->Rotation(); const CQuaternion BoneRot = pkData ? pBone->TransformedRotation(*pkData) : pBone->Rotation();
CDrawUtil::DrawLine(BonePos, BonePos + BoneRot.XAxis(), CColor::skRed); CDrawUtil::DrawLine(BonePos, BonePos + BoneRot.XAxis(), CColor::skRed);
CDrawUtil::DrawLine(BonePos, BonePos + BoneRot.YAxis(), CColor::skGreen); CDrawUtil::DrawLine(BonePos, BonePos + BoneRot.YAxis(), CColor::skGreen);
CDrawUtil::DrawLine(BonePos, BonePos + BoneRot.ZAxis(), CColor::skBlue); CDrawUtil::DrawLine(BonePos, BonePos + BoneRot.ZAxis(), CColor::skBlue);
@ -140,19 +133,18 @@ void CSkeleton::Draw(FRenderOptions /*Options*/, const CBoneTransformData *pkDat
// Draw child links // Draw child links
for (uint32 iChild = 0; iChild < pBone->NumChildren(); iChild++) for (uint32 iChild = 0; iChild < pBone->NumChildren(); iChild++)
{ {
CBone *pChild = pBone->ChildByIndex(iChild); const CBone *pChild = pBone->ChildByIndex(iChild);
CVector3f ChildPos = pkData ? pChild->TransformedPosition(*pkData) : pChild->Position(); const CVector3f ChildPos = pkData ? pChild->TransformedPosition(*pkData) : pChild->Position();
CDrawUtil::DrawLine(BonePos, ChildPos); CDrawUtil::DrawLine(BonePos, ChildPos);
} }
} }
// Draw bone spheres // Draw bone spheres
CTransform4f BaseTransform = CGraphics::sMVPBlock.ModelMatrix; const CTransform4f BaseTransform = CGraphics::sMVPBlock.ModelMatrix;
for (uint32 iBone = 0; iBone < mBones.size(); iBone++) for (const auto& pBone : mBones)
{ {
CBone *pBone = mBones[iBone]; const CVector3f BonePos = pkData ? pBone->TransformedPosition(*pkData) : pBone->Position();
CVector3f BonePos = pkData ? pBone->TransformedPosition(*pkData) : pBone->Position();
CTransform4f Transform; CTransform4f Transform;
Transform.Scale(skSphereRadius); Transform.Scale(skSphereRadius);
@ -163,15 +155,14 @@ void CSkeleton::Draw(FRenderOptions /*Options*/, const CBoneTransformData *pkDat
} }
} }
std::pair<int32,float> CSkeleton::RayIntersect(const CRay& rkRay, const CBoneTransformData& rkData) std::pair<int32,float> CSkeleton::RayIntersect(const CRay& rkRay, const CBoneTransformData& rkData) const
{ {
std::pair<int32,float> Out(-1, FLT_MAX); std::pair<int32,float> Out(-1, FLT_MAX);
for (uint32 iBone = 0; iBone < mBones.size(); iBone++) for (const auto& pBone : mBones)
{ {
CBone *pBone = mBones[iBone]; const CVector3f BonePos = pBone->TransformedPosition(rkData);
CVector3f BonePos = pBone->TransformedPosition(rkData); const std::pair<bool, float> Intersect = Math::RaySphereIntersection(rkRay, BonePos, skSphereRadius);
std::pair<bool,float> Intersect = Math::RaySphereIntersection(rkRay, BonePos, skSphereRadius);
if (Intersect.first && Intersect.second < Out.second) if (Intersect.first && Intersect.second < Out.second)
{ {

View File

@ -8,6 +8,7 @@
#include <Common/TString.h> #include <Common/TString.h>
#include <Common/Math/CRay.h> #include <Common/Math/CRay.h>
#include <Common/Math/CVector3f.h> #include <Common/Math/CVector3f.h>
#include <memory>
class CBoneTransformData; class CBoneTransformData;
class CBone; class CBone;
@ -26,21 +27,21 @@ class CSkeleton : public CResource
DECLARE_RESOURCE_TYPE(Skeleton) DECLARE_RESOURCE_TYPE(Skeleton)
friend class CSkeletonLoader; friend class CSkeletonLoader;
CBone *mpRootBone; CBone *mpRootBone = nullptr;
std::vector<CBone*> mBones; std::vector<std::unique_ptr<CBone>> mBones;
static const float skSphereRadius; static constexpr float skSphereRadius = 0.025f;
public: public:
explicit CSkeleton(CResourceEntry *pEntry = nullptr); explicit CSkeleton(CResourceEntry *pEntry = nullptr);
~CSkeleton() override; ~CSkeleton() override;
void UpdateTransform(CBoneTransformData& rData, CAnimation *pAnim, float Time, bool AnchorRoot); void UpdateTransform(CBoneTransformData& rData, CAnimation *pAnim, float Time, bool AnchorRoot);
CBone* BoneByID(uint32 BoneID) const; CBone* BoneByID(uint32 BoneID) const;
CBone* BoneByName(const TString& rkBoneName) const; CBone* BoneByName(const TString& name) const;
uint32 MaxBoneID() const; uint32 MaxBoneID() const;
void Draw(FRenderOptions Options, const CBoneTransformData *pkData); void Draw(FRenderOptions Options, const CBoneTransformData *pkData);
std::pair<int32,float> RayIntersect(const CRay& rkRay, const CBoneTransformData& rkData); std::pair<int32, float> RayIntersect(const CRay& rkRay, const CBoneTransformData& rkData) const;
uint32 NumBones() const { return mBones.size(); } uint32 NumBones() const { return mBones.size(); }
CBone* RootBone() const { return mpRootBone; } CBone* RootBone() const { return mpRootBone; }
@ -51,38 +52,38 @@ class CBone
friend class CSkeletonLoader; friend class CSkeletonLoader;
CSkeleton *mpSkeleton; CSkeleton *mpSkeleton;
CBone *mpParent; CBone *mpParent = nullptr;
std::vector<CBone*> mChildren; std::vector<CBone*> mChildren;
uint32 mID; uint32 mID = 0;
CVector3f mPosition; CVector3f mPosition;
CVector3f mLocalPosition; CVector3f mLocalPosition;
CQuaternion mRotation; CQuaternion mRotation;
CQuaternion mLocalRotation; CQuaternion mLocalRotation;
TString mName; TString mName;
CTransform4f mInvBind; CTransform4f mInvBind;
bool mSelected; bool mSelected = false;
public: public:
CBone(CSkeleton *pSkel); explicit CBone(CSkeleton *pSkel);
void UpdateTransform(CBoneTransformData& rData, const SBoneTransformInfo& rkParentTransform, CAnimation *pAnim, float Time, bool AnchorRoot); void UpdateTransform(CBoneTransformData& rData, const SBoneTransformInfo& rkParentTransform, CAnimation *pAnim, float Time, bool AnchorRoot);
CVector3f TransformedPosition(const CBoneTransformData& rkData) const; CVector3f TransformedPosition(const CBoneTransformData& rkData) const;
CQuaternion TransformedRotation(const CBoneTransformData& rkData) const; CQuaternion TransformedRotation(const CBoneTransformData& rkData) const;
bool IsRoot() const; bool IsRoot() const;
// Accessors // Accessors
inline CSkeleton* Skeleton() const { return mpSkeleton; } CSkeleton* Skeleton() const { return mpSkeleton; }
inline CBone* Parent() const { return mpParent; } CBone* Parent() const { return mpParent; }
inline uint32 NumChildren() const { return mChildren.size(); } uint32 NumChildren() const { return mChildren.size(); }
inline CBone* ChildByIndex(uint32 Index) const { return mChildren[Index]; } CBone* ChildByIndex(uint32 Index) const { return mChildren[Index]; }
inline uint32 ID() const { return mID; } uint32 ID() const { return mID; }
inline CVector3f Position() const { return mPosition; } CVector3f Position() const { return mPosition; }
inline CVector3f LocalPosition() const { return mLocalPosition; } CVector3f LocalPosition() const { return mLocalPosition; }
inline CQuaternion Rotation() const { return mRotation; } CQuaternion Rotation() const { return mRotation; }
inline CQuaternion LocalRotation() const { return mLocalRotation; } CQuaternion LocalRotation() const { return mLocalRotation; }
inline TString Name() const { return mName; } TString Name() const { return mName; }
inline bool IsSelected() const { return mSelected; } bool IsSelected() const { return mSelected; }
inline void SetSelected(bool Selected) { mSelected = Selected; } void SetSelected(bool Selected) { mSelected = Selected; }
}; };
#endif // CSKELETON_H #endif // CSKELETON_H

View File

@ -17,7 +17,7 @@ void CSkeletonLoader::SetLocalBoneCoords(CBone *pBone)
void CSkeletonLoader::CalculateBoneInverseBindMatrices() void CSkeletonLoader::CalculateBoneInverseBindMatrices()
{ {
for (CBone* bone : mpSkeleton->mBones) for (auto& bone : mpSkeleton->mBones)
{ {
bone->mInvBind = CTransform4f::TranslationMatrix(-bone->Position()); bone->mInvBind = CTransform4f::TranslationMatrix(-bone->Position());
} }
@ -49,8 +49,7 @@ std::unique_ptr<CSkeleton> CSkeletonLoader::LoadCINF(IInputStream& rCINF, CResou
for (uint32 iBone = 0; iBone < NumBones; iBone++) for (uint32 iBone = 0; iBone < NumBones; iBone++)
{ {
CBone *pBone = new CBone(ptr.get()); auto& pBone = ptr->mBones.emplace_back(std::make_unique<CBone>(ptr.get()));
ptr->mBones.push_back(pBone);
pBone->mID = rCINF.ReadLong(); pBone->mID = rCINF.ReadLong();
BoneInfo[iBone].ParentID = rCINF.ReadLong(); BoneInfo[iBone].ParentID = rCINF.ReadLong();
@ -86,7 +85,7 @@ std::unique_ptr<CSkeleton> CSkeletonLoader::LoadCINF(IInputStream& rCINF, CResou
// Fill in bone info // Fill in bone info
for (uint32 iBone = 0; iBone < NumBones; iBone++) for (uint32 iBone = 0; iBone < NumBones; iBone++)
{ {
CBone *pBone = ptr->mBones[iBone]; CBone *pBone = ptr->mBones[iBone].get();
SBoneInfo& rInfo = BoneInfo[iBone]; SBoneInfo& rInfo = BoneInfo[iBone];
pBone->mpParent = ptr->BoneByID(rInfo.ParentID); pBone->mpParent = ptr->BoneByID(rInfo.ParentID);