3
\$\begingroup\$

This issue seems to arise with joint rotation animation.

Model in Maya

Model in Game

//------------------------------------------------------------------------------
// Fuction Name:
//      FbxConverter::ProcessJointsAndAnimations
// Arguments:
//      FbxNode *inMesh     // In Mesh
// Return Value:
//      void
// Description:
//      Processes Joint and Animation Data
// 説明:
//      スケルタルとアニメーションデータを処理する
//------------------------------------------------------------------------------
void FbxConverter::ProcessJointsAndAnimations( FbxMesh* inMesh )
{
    // Get Mesh Data
    // メッシュデータを習得
    FbxNode* currNode = inMesh->GetNode();

    // Node Geomtric Transformation
    // ノードのジオメトリー変換行列
    FbxAMatrix geometryTransform = GetGeometryTransformation( currNode );

    // Get Number of Deformers
    // Deformerの数を習得
    unsigned int numOfDeformers = inMesh->GetDeformerCount();

    // Loop through Node Deformers for Skins to get Cluster Data
    // スキンを探して、クラスタデータを習得
    for( unsigned int deformerIndex = 0; deformerIndex < numOfDeformers; ++deformerIndex )
    {
        // Check if Deformer is a Skin
        // スキンかどうかを確認する
        FbxSkin* currSkin = reinterpret_cast<FbxSkin*>( inMesh->GetDeformer( deformerIndex, FbxDeformer::eSkin ) );
        if( !currSkin )
        {
            continue;
        }

        // Get Number of Clusters in Skin
        // スキン内のクラスタ数を習得
        unsigned int numOfClusters = currSkin->GetClusterCount();

        // Process Cluster Data
        // クラスタデータを処理する
        for( unsigned int clusterIndex = 0; clusterIndex < numOfClusters; ++clusterIndex )
        {
            // Get Cluster from Skin
            // クラスタデータを習得
            FbxCluster* currCluster = currSkin->GetCluster( clusterIndex );

            // Get Joint Name
            // 関節の名前を習得
            std::string currJointName = currCluster->GetLink()->GetName();

            // Get Joint and Joint Index from Name
            // 名前で関節と関節インデックスを習得
            ModelObject::Joint* joint = nullptr;
            unsigned int jointIdx = FindJointIndexUsingName( currJointName, &joint );

            // Matrices
            // 行列
            FbxAMatrix transformMatrix;                 // Mesh Tranformation at Binding Time
            FbxAMatrix transformLinkMatrix;             // The Transformation of the Cluster(joint) at Binding Time from Joint Space to World Space
            FbxAMatrix globalBindposeInverseMatrix;     // Bindpose Inverse Matrix

            // Get Matrix Data
            // 行列を習得
            currCluster->GetTransformMatrix( transformMatrix );
            currCluster->GetTransformLinkMatrix( transformLinkMatrix );
            globalBindposeInverseMatrix = transformLinkMatrix.Inverse() * transformMatrix * geometryTransform;

            // Update Joint Matrix Data
            // 関節の行列データを更新する
            joint->globalBindposeInverse = FbxAMatrixToMatrix44( globalBindposeInverseMatrix );

            // Associate Each Joint with the Control Points it Affects
            // 関節と制御点データの関連を付ける
            unsigned int numOfIndices = currCluster->GetControlPointIndicesCount();
            for( unsigned int idxCount = 0; idxCount < numOfIndices; ++idxCount )
            {
                ModelObject::BlendingIndexWeightPair currBlendingIndexWeightPair;
                currBlendingIndexWeightPair.blendingIndex = jointIdx;
                currBlendingIndexWeightPair.blendingWeight = currCluster->GetControlPointWeights()[ idxCount ];

                // If Blending Weight is Above Minimum Value
                // ウェイトが十分大きかったら
                if( currBlendingIndexWeightPair.blendingWeight > 0.1f )
                {
                    // Get Control Index
                    // 制御のインデックスを習得
                    int ctrlIdx = currCluster->GetControlPointIndices()[ idxCount ];

                    // Get Model Blend Data Index
                    // モデルのブレンドのインデックスを習得
                    int blendIdx = 0;
                    for( blendIdx = 0; blendIdx < 4; blendIdx++ )
                    {
                        if( m_meshHold.ctrl.data[ ctrlIdx ].blendingInfo[ blendIdx ].blendingWeight == 0 )
                        {
                            // Add Blending Data to Control Point
                            // 制御点にブレンドのデータを追加する
                            m_meshHold.ctrl.data[ ctrlIdx ].blendingInfo[ blendIdx ] = currBlendingIndexWeightPair;
                            break;
                        }
                    }
                }
            }

            // Get Animation Data
            // アニメーションのデータを習得
            // ( Currently only Supports one Take )
            // ( 現在、一つのアニメーションしか対応していない )
            FbxAnimStack* currAnimStack = m_fbxScene->GetSrcObject<FbxAnimStack>( 0 );

            // Get Animation Name
            // アニメーションの名前を習得
            FbxString animStackName = currAnimStack->GetName();
            m_animationName = animStackName.Buffer();

            // Get Take Info using Animation Name
            // アニメーションの名前でテーク情報を習得
            FbxTakeInfo* takeInfo = m_fbxScene->GetTakeInfo( animStackName );

            // Get Animation Length
            // アニメーションの長さを習得
            FbxTime start = takeInfo->mLocalTimeSpan.GetStart();
            FbxTime end = takeInfo->mLocalTimeSpan.GetStop();
            m_animationLength = end.GetFrameCount( FbxTime::eFrames24 ) - start.GetFrameCount( FbxTime::eFrames24 ) + 1;

            // Create Frames Based on Animation Length
            // アニメーションの長さによってモデルのフレームを作成する
            joint->animation = new ModelObject::Frame[ ( int )m_animationLength ];

            // Process Animation Data
            // アニメーションのデータを処理する
            int animCount = 0;
            for( FbxLongLong frameCount = start.GetFrameCount( FbxTime::eFrames24 ); frameCount <= end.GetFrameCount( FbxTime::eFrames24 ); ++frameCount )
            {
                // Set Frame Time
                // フレームの時間設定
                FbxTime currTime;
                currTime.SetFrame( frameCount, FbxTime::eFrames24 );

                // Save Frame Number
                // フレーム番号を保存
                joint->animation[ animCount ].curFrameNum = ( int )frameCount;

                // Get Global Transform Matrix
                // グローバル変換行列を習得
                FbxAMatrix currentTransformOffset = currNode->EvaluateGlobalTransform( currTime ) * geometryTransform;
                FbxAMatrix globalMtx = currentTransformOffset.Inverse() * currCluster->GetLink()->EvaluateGlobalTransform( currTime );
                joint->animation[ animCount ].globalTransform = FbxAMatrixToMatrix44( globalMtx );

                // Increase Animation Array Count
                // アニメーションのカウントを増やす
                animCount++;
            }
        }
    }
}
\$\endgroup\$
0
\$\begingroup\$

I found one solution. The model's transformation were not frozen when made which caused the issue. Freezing the transformation will allow for correct animation in game. The next step would be to fix the above code to allow for unfrozen models

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.