예제 #1
0
void MeshLoaderSPM::readChunkAnimationSkeletal()
{
    /* Read skeletal animation basics */
    const io::stringc AnimName(File_->readStringData());
    
    /* Add new skeletal animation */
    SkeletalAnimation* Anim = gSharedObjects.SceneMngr->createAnimation<SkeletalAnimation>("SPM Animation");
    AnimationSkeleton* Skeleton = Anim->createSkeleton();
    
    /* Read animation joints */
    const u32 JointCount = File_->readValue<u32>();
    
    Joints_.resize(JointCount);
    
    for (u32 i = 0; i < JointCount; ++i)
        readChunkAnimationJoint(Joints_[i]);
    
    /* Build joint construction */
    foreach (SJointSPM &Joint, Joints_)
    {
        /* Create joint object */
        Joint.JointObject = Skeleton->createJoint(
            Transformation(Joint.Position, Joint.Rotation, Joint.Scale), Joint.Name
        );
        
        /* Setup vertex weights */
        std::vector<SVertexGroup> VertexGroups;
        VertexGroups.resize(Joint.VertexWeights.size());
        
        u32 i = 0;
        foreach (const SVertexWeightSPM &Vertex, Joint.VertexWeights)
        {
            VertexGroups[i++] = SVertexGroup(
                CurMesh_, Vertex.Surface, Vertex.Index, Vertex.Weight
            );
        }
        
        Joint.JointObject->setVertexGroups(VertexGroups);
        
        /* Setup keyframes */
        foreach (const SKeyframeSPM &Keyframe, Joint.Keyframes)
        {
            Anim->addKeyframe(
                Joint.JointObject,
                Keyframe.Frame,
                Transformation(Keyframe.Position, Keyframe.Rotation, Keyframe.Scale)
            );
        }
    }
예제 #2
0
bool GameLib::loadSkeletalAnimation(std::string filename, SkeletalAnimation& outAnimation)
{
    Assimp::Importer importer;
    const aiScene* scene = importer.ReadFile(filename, aiProcess_ValidateDataStructure);

    if(scene == nullptr || scene->mNumAnimations == 0)
        return false;

    aiAnimation* animation = scene->mAnimations[0];
    
    std::unordered_map<double, SkeletalPose> poses;
    
    std::hash<std::string> hash;
    
    for(unsigned int i = 0; i < animation->mNumChannels; i++)
    {
        aiNodeAnim* node = animation->mChannels[i];
        std::string nodeName(node->mNodeName.C_Str());
        unsigned int boneId = hash(nodeName);

        // load positions
        for(unsigned int j = 0; j < node->mNumPositionKeys; j++)
        {
            aiVectorKey key = node->mPositionKeys[j];
            SkeletalPose::BonePosition existingPosition = poses[key.mTime].getBonePosition(boneId);
            existingPosition.position.x = key.mValue.x;
            existingPosition.position.y = key.mValue.y;
            existingPosition.position.z = key.mValue.z;
            poses[key.mTime].setBonePosition(boneId, existingPosition);
        }

        // load rotations     
        for(unsigned int j = 0; j < node->mNumRotationKeys; j++)
        {
            aiQuatKey key = node->mRotationKeys[j];
            SkeletalPose::BonePosition existingPosition = poses[key.mTime].getBonePosition(boneId);

            // calculate the angle from the quaternion
            float rad = std::acos(key.mValue.w);
            float sinRad = std::sin(rad);

            existingPosition.rotationAxis.x = key.mValue.x / sinRad;
            existingPosition.rotationAxis.y = key.mValue.y / sinRad;
            existingPosition.rotationAxis.z = key.mValue.z / sinRad;
            existingPosition.rotation = rad;
            poses[key.mTime].setBonePosition(boneId, existingPosition);
        }

        // load scalings     
        for(unsigned int j = 0; j < node->mNumScalingKeys; j++)
        {
            aiVectorKey key = node->mScalingKeys[j];
            SkeletalPose::BonePosition existingPosition = poses[key.mTime].getBonePosition(boneId);
            existingPosition.scale.x = key.mValue.x;
            existingPosition.scale.y = key.mValue.y;
            existingPosition.scale.z = key.mValue.z;
            poses[key.mTime].setBonePosition(boneId, existingPosition);
        }
    }

    // add poses to animation
    for(auto posePair : poses)
    {
        outAnimation.addPose((float)posePair.first, posePair.second);
    }

    return true;
}
예제 #3
0
UNNAMESPACE_BEGIN

/*==============================================================================
   Procedural API/functions.
==============================================================================*/

//------------------------------------------------------------------------------
//!
int animationVM( VMState* vm )
{
   ProceduralAnimation* userData = (ProceduralAnimation*)VM::userData( vm );
   SkeletalAnimation* anim       = userData->animation();

   // Only accept a table as argument.
   if( !VM::isTable( vm, 1 ) )
   {
      StdErr << "Missing arguments to animation()." << nl;
      return 0;
   }

   // Read parameters.
   float rate;
   if( VM::get( vm, 1, "rate", rate ) ) anim->rate( rate );

   Vec3f vel;
   if( VM::get( vm, 1, "velocity", vel ) ) anim->velocity( vel );

   Vec3f offset;
   if( VM::get( vm, 1, "offset", offset ) ) anim->offset( offset );

   bool cyclic;
   if( VM::get( vm, 1, "cyclic", cyclic ) ) anim->cyclic( cyclic );

   uint type;
   if( VM::get( vm, 1, "type", type ) ) anim->type( type );

   if( VM::get( vm, 1, "poses" ) )
   {
      anim->reservePoses( VM::getTableSize( vm, -1 ) );

      // Read all poses.
      for( int p = 1; VM::geti( vm, -1, p ); ++p )
      {
         Reff ref = Reff::identity();
         if( !VM::get( vm, -1, "p", ref.position() ) )
         {
            ref.position( Vec3f::zero() );
         }
         if( !VM::get( vm, -1, "q", ref.orientation() ) )
         {
            ref.orientation( Quatf::identity() );
         }

         RCP<SkeletalPose> pose = anim->addPose( ref );
         pose->reserveBones( VM::getTableSize( vm, -1 ) );
         // Read all bones positions in pose.
         for( int i = 1; VM::geti( vm, -1, i ); ++i )
         {
            pose->addBone( VM::toQuatf( vm, -1 ) );
            VM::pop( vm, 1 );
         }
         VM::pop( vm, 1 );
      }
      VM::pop( vm, 1 );
   }
   anim->prepare();  // Fix some corner cases.
   anim->makeRelative();
   return 0;
}
예제 #4
0
void SkeletalMeshNode::Play(SkeletalAnimation& anim, bool loop)
{
	assert(anim.CheckJoints(*m_jointList));
	m_anim = &anim;
	m_anim->Play(loop);
}