Skip to content

Commit

Permalink
Driving the interface for skeleton home
Browse files Browse the repository at this point in the history
  • Loading branch information
bartleyryan committed Mar 22, 2016
1 parent 80f08b3 commit e5875a8
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 61 deletions.
41 changes: 17 additions & 24 deletions src/Skeleton.cpp
Expand Up @@ -8,29 +8,22 @@

#include "Skeleton.h"

void Skeleton::resolveGlobalBindPose()
Skeleton::Skeleton( uint8_t numJoints )
: mJointArray( numJoints ), mJointNames( numJoints ),
mBindPose( this )
{
bindPose.globalPoses[0] = bindPose.localPoses[0].getTRS();
for( int i = 1; i < jointArray.size(); i++ ) {
bindPose.globalPoses[i] = getParentsWorldTransform( jointArray[i].parentId ) * bindPose.localPoses[i].getTRS();
}
}

const ci::mat4& Skeleton::getParentsWorldTransform( uint8_t parentId ) const
{
return bindPose.globalPoses[parentId];
}

bool Skeleton::hasJoint( const std::string &name ) const
{
auto endIt = end( jointNames );
return std::find( begin( jointNames ), endIt, name ) != endIt;
auto endIt = end( mJointNames );
return std::find( begin( mJointNames ), endIt, name ) != endIt;
}

const Skeleton::Joint* Skeleton::getJoint( const std::string &name ) const
{
auto begIt = begin( jointNames );
auto endIt = end( jointNames );
auto begIt = begin( mJointNames );
auto endIt = end( mJointNames );
auto jointIt = std::find( begIt, endIt, name );
if( jointIt != endIt ) {
auto dist = std::distance( begIt, jointIt );
Expand All @@ -42,19 +35,19 @@ const Skeleton::Joint* Skeleton::getJoint( const std::string &name ) const

const Skeleton::Joint* Skeleton::getJoint( uint8_t id ) const
{
CI_ASSERT( id < jointArray.size() );
return &jointArray[id];
CI_ASSERT( id < mJointArray.size() );
return &mJointArray[id];
}

const std::string* Skeleton::getJointName( const Skeleton::Joint &joint ) const
{
return getJointName( joint.nameId );
return getJointName( joint.getNameId() );
}

const std::string* Skeleton::getJointName( uint8_t nameId ) const
{
CI_ASSERT( nameId < jointNames.size() );
return &jointNames[nameId];
CI_ASSERT( nameId < mJointNames.size() );
return &mJointNames[nameId];
}

void SkeletonAnim::get( double time, std::vector<ci::mat4> &offsetMatrices ) const
Expand Down Expand Up @@ -86,24 +79,24 @@ void SkeletonAnim::getLooped( double time, std::vector<ci::mat4> &offsetMatrices
void SkeletonAnim::calcGlobalStack( const std::vector<Transform> &preInverseTransforms,
std::vector<ci::mat4> &globalCache ) const
{
auto &joints = mSkeleton->jointArray;
auto &joints = mSkeleton->getJoints();
// Derive root
globalCache[0] = preInverseTransforms[0].getTRS();
// Derive children
for( int i = 1; i < numJoints; i++ ) {
globalCache[i] = globalCache[joints[i].parentId] * preInverseTransforms[i].getTRS();
globalCache[i] = globalCache[joints[i].getParentId()] * preInverseTransforms[i].getTRS();
}
}

void SkeletonAnim::calcMatrixPalette( const std::vector<ci::mat4> &globalCache,
std::vector<ci::mat4> &offsetMatrices ) const
{
auto &joints = mSkeleton->jointArray;
auto &joints = mSkeleton->getJoints();
// Derive root
offsetMatrices[0] = joints[0].inverseGlobalBindPose * globalCache[0];
offsetMatrices[0] = joints[0].getInverseBindMatrix() * globalCache[0];
// Derive children
for( int i = 1; i < numJoints; i++ ) {
offsetMatrices[i] = joints[i].inverseGlobalBindPose * globalCache[i];
offsetMatrices[i] = joints[i].getInverseBindMatrix() * globalCache[i];
}
}

Expand Down
102 changes: 68 additions & 34 deletions src/Skeleton.h
Expand Up @@ -13,56 +13,87 @@

using SkeletonRef = std::shared_ptr<class Skeleton>;

struct Skeleton {
Skeleton( uint32_t numJoints )
: jointNames( numJoints ), jointArray( jointNames.size() )
{
bindPose.skeleton = this;
bindPose.localPoses.resize( numJoints );
bindPose.globalPoses.resize( numJoints );
}
class Skeleton {
public:
Skeleton( uint8_t numJoints );

struct Joint {
glm::mat4 inverseGlobalBindPose;
uint8_t nameId;
uint8_t parentId;
Joint();
Joint( uint8_t parentId, uint8_t nameId );

void setInverseBindMatrix( const glm::mat4 &inverseBind ) { mInverseBindMatrix = inverseBind; }
glm::mat4& getInverseBindMatrix() { return mInverseBindMatrix; }
const glm::mat4& getInverseBindMatrix() const { return mInverseBindMatrix; }

uint8_t getNameId() const { return mNameId; }
uint8_t getParentId() const { return mParentId; }

private:
void setNameId( uint8_t nameId ) { mNameId = nameId; }
void setParentId( uint8_t parentId ) { mParentId = parentId; }

glm::mat4 mInverseBindMatrix;
uint8_t mNameId;
uint8_t mParentId;

friend class Skeleton;
};

struct TreeJoint {
Joint* parent;
std::vector<Joint*> children;
std::string *name;
class Pose {
public:
Pose( Skeleton *skeleton );

void calcMatrixPalette( std::vector<ci::mat4> &offsetMatrices );
void calcGlobalStack();

const std::vector<Transform>& getLocalPoses() const { return mLocalPoseTransforms; }
std::vector<Transform>& getLocalPoses() { return mLocalPoseTransforms; }
const std::vector<ci::mat4>& getGlobalMatrices() const { return mGlobalPose; }
std::vector<ci::mat4>& getGlobalMatrices() { return mGlobalPose; }
bool needsGlobalCache() const { return mNeedsGlobalCache; }

private:
Skeleton *mSkeleton = nullptr;
std::vector<Transform> mLocalPoseTransforms;
std::vector<ci::mat4> mGlobalPose;
bool mNeedsGlobalCache;
};

const Joint* getRoot() const { return &jointArray[0]; }

void traverse( std::function<void( const Joint& )> visit ) const;
static void traverse( const Joint& node, std::function<void( const Joint& )> visit );
struct Anim {
Anim( const std::vector<Clip<Transform>> &jointClips );

void get( double time, Pose &localJointTransforms ) const;
void getLooped( double time, Pose &localJointTransforms ) const;

public:
std::vector<Clip<Transform>> mJointClips;
};

bool hasJoint( const std::string& name ) const;
const Joint* getRoot() const { return &mJointArray[0]; }
const Joint* getJoint( const std::string& name ) const;
const Joint* getJoint( uint8_t jointId ) const;
bool hasJoint( const std::string& name ) const;
size_t getNumJoints() { return mJointArray.size(); }

const std::string* getJointName( const Joint &joint ) const;
const std::string* getJointName( uint8_t nameId ) const;
const std::string* getJointName( const Joint &joint ) const;
const std::string* getJointName( uint8_t nameId ) const;

size_t getNumJoints() { return jointArray.size(); }
const std::vector<Joint>& getJoints() const { return jointArray; }
const std::vector<Joint>& getJoints() const { return mJointArray; }
const std::vector<std::string>& getJointNames() const { return mJointNames; }

ci::AxisAlignedBox calcBoundingBox() const;

struct Pose {
Skeleton *skeleton = nullptr;
std::vector<Transform> localPoses;
std::vector<ci::mat4> globalPoses;
};
void calcGlobalStack( const Pose &jointLocalTransforms,
std::vector<ci::mat4> &globalStack );
void calcMatrixPalette( const std::vector<ci::mat4> &globalCache,
std::vector<ci::mat4> &offsetMatrices ) const;

void resolveGlobalBindPose();
const ci::mat4& getParentsWorldTransform( uint8_t parentId ) const;
const Pose& getBindPose() { return mBindPose; }

std::vector<std::string> jointNames;
std::vector<Joint> jointArray;
Pose bindPose;
private:
std::vector<Joint> mJointArray;
Pose mBindPose;
std::vector<std::string> mJointNames;
};

using SkeletonAnimRef = std::shared_ptr<class SkeletonAnim>;
Expand All @@ -76,6 +107,9 @@ class SkeletonAnim {
void getLooped( double time, std::vector<ci::mat4> &offsetMatrices ) const;
void getPreInverse( double time, std::vector<Transform> &preInverseBakedTransforms ) const;
void getLoopedPreInverse( double time, std::vector<Transform> &preInverseBakedTransforms ) const;

void traverse( std::function<void( const Skeleton::Joint& )> visit ) const;
static void traverse( const Skeleton::Joint& node, std::function<void( const Skeleton::Joint& )> visit );

private:
void calcGlobalStack( const std::vector<Transform> &preInverseTransforms,
Expand Down
5 changes: 2 additions & 3 deletions src/gltf.cpp
Expand Up @@ -1303,11 +1303,11 @@ SkeletonRef Skin::createSkeleton() const
int i = 0;
for( auto jointNode : joints ) {
auto &joint = skeleton->jointArray[i];
auto &jointBindPose = skeleton->bindPose.localPoses[i];
auto &jointBindPose = skeleton->bindPose.getLocalPoses()[i];
auto &jointName = joints[i]->jointName;
CI_ASSERT( ! jointName.empty() );
skeleton->jointNames[i] = jointName;
joint.inverseGlobalBindPose = *matricesPtr++;
joint.setInverseBindMatrix( *matricesPtr++ );
jointBindPose.rot = jointNode->getRotation();
jointBindPose.scale = jointNode->getScale();
jointBindPose.trans = jointNode->getTranslation();
Expand All @@ -1322,7 +1322,6 @@ SkeletonRef Skin::createSkeleton() const
// if this joint is the root.
i++;
}
skeleton->resolveGlobalBindPose();

return skeleton;
}
Expand Down

0 comments on commit e5875a8

Please sign in to comment.