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/Math/MathUtil.h>
#include <algorithm>
#include <cfloat>
// ************ CBone ************
CBone::CBone(CSkeleton *pSkel)
: mpSkeleton(pSkel)
, mSelected(false)
{
}
@ -39,8 +39,8 @@ void CBone::UpdateTransform(CBoneTransformData& rData, const SBoneTransformInfo&
rTransform *= mInvBind;
// Calculate children
for (uint32 iChild = 0; iChild < mChildren.size(); iChild++)
mChildren[iChild]->UpdateTransform(rData, TransformInfo, pAnim, Time, AnchorRoot);
for (auto* child : mChildren)
child->UpdateTransform(rData, TransformInfo, pAnim, Time, AnchorRoot);
}
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
// actual root bone... that bone sometimes acts as the actual root (transforming the entire skeleton),
// so we need to account for both
return (mpParent == nullptr || mpParent->Parent() == nullptr);
return mpParent == nullptr || mpParent->Parent() == nullptr;
}
// ************ CSkeleton ************
const float CSkeleton::skSphereRadius = 0.025f;
CSkeleton::CSkeleton(CResourceEntry *pEntry /*= 0*/)
CSkeleton::CSkeleton(CResourceEntry *pEntry)
: CResource(pEntry)
, mpRootBone(nullptr)
{
}
CSkeleton::~CSkeleton()
{
for (uint32 iBone = 0; iBone < mBones.size(); iBone++)
delete mBones[iBone];
}
CSkeleton::~CSkeleton() = default;
CBone* CSkeleton::BoneByID(uint32 BoneID) const
{
for (uint32 iBone = 0; iBone < mBones.size(); iBone++)
{
if (mBones[iBone]->ID() == BoneID)
return mBones[iBone];
}
const auto iter = std::find_if(mBones.begin(), mBones.end(),
[BoneID](const auto& bone) { return bone->ID() == BoneID; });
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++)
{
if (mBones[iBone]->Name() == rkBoneName)
return mBones[iBone];
}
const auto iter = std::find_if(mBones.begin(), mBones.end(),
[&name](const auto& bone) { return bone->Name() == name; });
return nullptr;
if (iter == mBones.cend())
return nullptr;
return iter->get();
}
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)
ID = mBones[iBone]->ID();
return 0;
}
return ID;
return (*iter)->ID();
}
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);
// 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];
CVector3f BonePos = pkData ? pBone->TransformedPosition(*pkData) : pBone->Position();
const CVector3f BonePos = pkData ? pBone->TransformedPosition(*pkData) : pBone->Position();
// Draw the bone's local XYZ axes for selected bones
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.YAxis(), CColor::skGreen);
CDrawUtil::DrawLine(BonePos, BonePos + BoneRot.ZAxis(), CColor::skBlue);
@ -140,19 +133,18 @@ void CSkeleton::Draw(FRenderOptions /*Options*/, const CBoneTransformData *pkDat
// Draw child links
for (uint32 iChild = 0; iChild < pBone->NumChildren(); iChild++)
{
CBone *pChild = pBone->ChildByIndex(iChild);
CVector3f ChildPos = pkData ? pChild->TransformedPosition(*pkData) : pChild->Position();
const CBone *pChild = pBone->ChildByIndex(iChild);
const CVector3f ChildPos = pkData ? pChild->TransformedPosition(*pkData) : pChild->Position();
CDrawUtil::DrawLine(BonePos, ChildPos);
}
}
// 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];
CVector3f BonePos = pkData ? pBone->TransformedPosition(*pkData) : pBone->Position();
const CVector3f BonePos = pkData ? pBone->TransformedPosition(*pkData) : pBone->Position();
CTransform4f Transform;
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);
for (uint32 iBone = 0; iBone < mBones.size(); iBone++)
for (const auto& pBone : mBones)
{
CBone *pBone = mBones[iBone];
CVector3f BonePos = pBone->TransformedPosition(rkData);
std::pair<bool,float> Intersect = Math::RaySphereIntersection(rkRay, BonePos, skSphereRadius);
const CVector3f BonePos = pBone->TransformedPosition(rkData);
const std::pair<bool, float> Intersect = Math::RaySphereIntersection(rkRay, BonePos, skSphereRadius);
if (Intersect.first && Intersect.second < Out.second)
{

View File

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

View File

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