CSkeleton: Make use of unique_ptr where applicable
Makes ownership semantics explicit.
This commit is contained in:
parent
4dcb539763
commit
e49315a645
|
@ -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; });
|
||||
|
||||
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; });
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue