FBX SDK を使って fbx からスキニングしているジョイントのローカル座標を取得する方法がヘルプ読まずにわからなかったので、メモ代わりにスキニングしているジョイントのローカル座標と変換行列をコンソール出力する関数を載せておきます。
ソースコード
void PrintLocalSrtAndTransformMatrixOfJoints(FbxNode* root_node)
{
FbxMesh* mesh = root_node->GetMesh();
int skin_count = mesh->GetDeformerCount(FbxDeformer::eSkin);
for (int skin_index = 0; skin_index < skin_count; ++skin_index)
{
FbxSkin* skin = static_cast<FbxSkin*>(mesh->GetDeformer(skin_index, FbxDeformer::eSkin));
int cluster_count = skin->GetClusterCount();
for (int cluster_index = 0; cluster_index < cluster_count; ++cluster_index)
{
FbxCluster* cluster = skin->GetCluster(cluster_index);
FbxNode* linked_node = cluster->GetLink();
printf("%s:\n", linked_node->GetName());
// ジョイントのローカル SRT を表示
fbxsdk::FbxDouble3 local_translate = linked_node->LclTranslation.Get();
fbxsdk::FbxDouble3 local_rotate = linked_node->LclRotation.Get();
fbxsdk::FbxDouble3 local_scale = linked_node->LclScaling.Get();
printf(" t = (%8.3f, %8.3f, %8.3f)\n r = (%8.3f, %8.3f, %8.3f)\n s = (%8.3f, %8.3f, %8.3f)\n",
local_translate[0],
local_translate[1],
local_translate[2],
local_rotate[0],
local_rotate[1],
local_rotate[2],
local_scale[0],
local_scale[1],
local_scale[2]);
// ジョイントの変換行列を表示
fbxsdk::FbxAMatrix init_matrix;
cluster->GetTransformLinkMatrix(init_matrix);
printf(" matrix =\n");
for (int row = 0; row < 4; ++row)
{
printf(" ");
for (int col = 0; col < 4; ++col)
{
printf("%8.3f, ", init_matrix.Get(row, col));
}
printf("\n");
}
}
}
}
コンソール出力結果例
joint1: t = ( 0.000, 0.000, 0.000) r = ( 0.000, 0.000, 0.000) s = ( 1.000, 1.000, 1.000) matrix = 1.000, 0.000, 0.000, 0.000, -0.000, 1.000, 0.000, 0.000, 0.000, -0.000, 1.000, 0.000, 0.000, 0.000, 0.000, 1.000, joint2: t = ( 0.000, 1.000, 0.000) r = ( 0.000, 0.000, 0.000) s = ( 1.000, 1.000, 1.000) matrix = 1.000, 0.000, 0.000, 0.000, -0.000, 1.000, 0.000, 0.000, 0.000, -0.000, 1.000, 0.000, 0.000, 1.000, 0.000, 1.000, joint3: t = ( 0.000, 1.000, -0.000) r = ( 0.000, 0.000, 0.000) s = ( 1.000, 1.000, 1.000) matrix = 1.000, 0.000, 0.000, 0.000, -0.000, 1.000, 0.000, 0.000, 0.000, -0.000, 1.000, 0.000, 0.000, 2.000, -0.000, 1.000, joint4: t = ( 1.000, 1.000, -0.000) r = ( 0.000, 0.000, 0.000) s = ( 1.000, 1.000, 1.000) matrix = 1.000, 0.000, 0.000, 0.000, -0.000, 1.000, 0.000, 0.000, 0.000, -0.000, 1.000, 0.000, 1.000, 3.000, -0.000, 1.000,
ついでにサンプルにあったバインドポーズのトンラスフォームの取得方法もメモ代わりに載せておきます。
バインドポーズのトランスフォームと行列(サンプルより)
void DisplayPose(FbxScene* pScene)
{
int i, j, k, lPoseCount;
FbxString lName;
lPoseCount = pScene->GetPoseCount();
for (i = 0; i < lPoseCount; i++)
{
FbxPose* lPose = pScene->GetPose(i);
lName = lPose->GetName();
printf("Pose Name: %s\n", lName.Buffer());
printf(" Is a bind pose: %s\n", lPose->IsBindPose()?"true":"false");
printf(" Number of items in the pose: %d\n", lPose->GetCount());
printf("\n");
for (j = 0; j<lPose->GetCount(); j++)
{
lName = lPose->GetNodeName(j).GetCurrentName();
printf(" Item name: %s\n", lName.Buffer());
if (!lPose->IsBindPose())
{
// Rest pose can have local matrix
printf(" Is local space matrix: %s\n", lPose->IsLocalMatrix(j)?"true":"false");
}
printf(" Matrix value: \n");
FbxString lMatrixValue;
FbxNode* node = lPose->GetNode(j);
for (k = 0; k<4; k++)
{
FbxMatrix lMatrix = lPose->GetMatrix(j);
FbxVector4 lRow = lMatrix.GetRow(k);
char lRowValue[1024];
FBXSDK_sprintf(lRowValue, 1024, "%9.4f %9.4f %9.4f %9.4f\n", lRow[0], lRow[1], lRow[2], lRow[3]);
lMatrixValue += FbxString(" ") + FbxString(lRowValue);
}
printf("%s\n", lMatrixValue.Buffer());
}
}
lPoseCount = pScene->GetCharacterPoseCount();
for (i = 0; i < lPoseCount; i++)
{
FbxCharacterPose* lPose = pScene->GetCharacterPose(i);
FbxCharacter* lCharacter = lPose->GetCharacter();
if (!lCharacter) break;
printf("Character Pose Name: %s\n", lCharacter->GetName());
FbxCharacterLink lCharacterLink;
FbxCharacter::ENodeId lNodeId = FbxCharacter::eHips;
while (lCharacter->GetCharacterLink(lNodeId, &lCharacterLink))
{
FbxAMatrix& lGlobalPosition = lCharacterLink.mNode->EvaluateGlobalTransform(FBXSDK_TIME_ZERO);
printf(" Matrix value: %s\n", "");
FbxString lMatrixValue;
for (k = 0; k<4; k++)
{
FbxVector4 lRow = lGlobalPosition.GetRow(k);
char lRowValue[1024];
FBXSDK_sprintf(lRowValue, 1024, "%9.4f %9.4f %9.4f %9.4f\n", lRow[0], lRow[1], lRow[2], lRow[3]);
lMatrixValue += FbxString(" ") + FbxString(lRowValue);
}
printf("%s\n", lMatrixValue.Buffer());
lNodeId = FbxCharacter::ENodeId(int(lNodeId) + 1);
}
}
}