FbxSDK 사용 요약
인터넷상에서 나의 아픔을 해결할 방법을 찾지 못했다.
같은 고민을 한 사람은 나뿐만이 아니었다. Tianyu Lang이라는 비뚤어진 과인도 불평을 하며 화를 냈다.
I have searched almost all the corners on the Internet to clarify things so that I can have a clear
mapping from FBX SDK's data to what I need in a game engine. Since I don't think anyone has ever
posted a clear and thorough tutorial on how to convert FBX files to custom formats, I will do it.
I hope this will help people.
그의 노호는 내 마음을 깊이 사로잡았다.같은 목적에 근거하여 나는 이 문장을 쓸 것이다.(그의 글은 여기 있다. 전송문)이 글은 FbxSDK의 입문 문장이 아니라 진급 문장이다.
이 글을 쓰기 전에 저는 FbxSDK를 한동안 연구했고 다음과 같은 두 편의 박문을 썼습니다. 여러분들은 그대로 읽으세요.
1,, 내가 수집한 읽을 만한 문장, 전송문
2., 사방에서 벽에 부딪힌 후에 저는 홈페이지 문서를 읽고 문을 전송하려고 합니다.
1, ControlPoint 및 PolygonVertex
FbxMesh 객체에는 다음과 같은 4개의 함수가 있습니다.
FbxMesh::GetControlPointsCount() FbxMesh::GetControlPointAt() FbxMesh::GetPolygonCount() FbxMesh::GetPolygonVertex()
ControlPoint와 PolygonVertex는 각각 무엇입니까?
밤(예)을 들면 알 수 있듯이 사각형은 4개의 정점이 있고 2개의 삼각형으로 구성되어 있다. 그러면 FbxMesh::GetControlPointsCount()는 4로 되돌아간다.
FbxMesh::GetPolygonCount()가 2로 돌아갑니다.
ControlPoint 컨테이너에 4개의 정점의 좌표값을 저장했는데 저장 구조는 {[x, y,z], [x, y,z], [x, y,z], [x, y,z]}
PolygonVertex 용기에 6개의 인덱스 값을 저장했는데 저장 구조는 다음과 같다. {0,1,2,0,2,3}
따라서 ControlPoint는'제어점'으로 이해할 수 있다. 사각형에 4개의 제어점이 있고 각 제어점의 좌표 변화는 사각형의 모양을 변화시킨다.
PolygonVertex는 삼각형을 기초로 하는 도형학의 개념으로 삼각형마다 3개의 정점이 있다.
만약 당신이 Fbx의 Layer의 개념(예를 들어 법선 Layer, UV Layer 등)을 이해했다면, 여기서 비교를 할 수 있다. ControlPoint 용기는 다음과 같다.
Layer의 DirectArray, PolygonVertex 용기는 IndexArray와 같습니다.
2,FbxLayerElement::MappingMode()
정점 데이터를 추출할 때 (예를 들어 법선, UV 등), 우리는 Fbx Layer Element::Mapping Mode () 라는 함수를 자주 만난다.
우리는 Fbx Geometry Element::eBy ControlPoint와 Fbx Geometry Element:::eBy PolygonVertex 두 가지 값에만 관심을 가진다.
밤을 예로 들면 입방체에 8개의 ControlPoint, 24개의 PolygonVertex가 있는데 우리는 법선 Layer를 예로 들자.
만약 모든 ControlPoint가 하나의 법선에만 대응한다면, 이런 MappingMode가 바로 eBy ControlPoint이다.
그러나 실제 상황은 법선은 면(삼각형)과 일일이 대응해야 하며 각 ControlPoint는 3개의 삼각형을 구축하는 데 참여하면 각 ControlPoint는
세 개의 법선이 대응해야 한다. 즉, 법선과 Polygon Vertex는 일일이 대응한다. 그러면 이런 Mapping Mode는 바로 eBy Polygon Vertex이다.
MappingMode는 법선을 결정하고 저장 방식을 결정합니다.
3,FbxLayerElement::ReferenceMode()
Layer에는 Mapping Mode 외에도 Reference Mode가 있습니다.
우리는 FbxGeometryElement::eDirect와 FbxGeometryElement::eIndexToDirect 두 가지 수치에만 관심을 가진다.
밤을 예로 들면 입방체에 8개의 ControlPoint, 24개의 PolygonVertex가 있는데 우리는 법선 Layer의 MappingMode 값을
eByControlPoint, 법선 Layer에 8개의 법선 값이 있음,
이 8개의 법선 값이 각각 다르다고 가정하면 저장 방식은 다음과 같다. DirectArray = {법선 1, 법선 2, 법선 3, 법선 4, 법선 5, 법선 6, 법선 7, 법선 8}
그러면 Reference Mode의 값은 eDirect입니다.
만약에 법선 3, 법선 4, 법선 5의 값이 같다고 가정하면 Fbx는 최적화를 했고 세 개의 값을 하나의 값으로 최적화한 다음에 색인을 추가했다. 저장 방식은 다음과 같다.
DirectArray = {법선 1, 법선 2, 법선 3, 법선 6, 법선 7, 법선 8}
IndexArray = {0, 1, 2, 2, 2, 3, 4, 5}
그러면 Reference Mode의 값은 eIndexToDirect입니다.
4, 애니메이션 데이터(매트릭스 데이터)를 얻는 방법은 두 가지가 있다.
FbxSDK 홈페이지 문서에서 FbxTakeInfo라는 종류를 언급한 다음에 애니메이션 매트릭스 데이터를 얻는 데는 두 가지 방법이 있다고 지적했다.
첫 번째는 새로운 방법을 사용하여 돌아가는 방식으로 FbxScene를 훑어보고 순서대로 FbxAnimStack, FbxAnimLayer, FbxAnimCurve를 얻는 것이다.
두 번째는 이전 방법을 사용하여 FbxTakeInfo 객체를 가져오는 것입니다.
새 메서드의 예제 코드:
//----------------------------------------------------------------
void SoFBXManager::ParseAnimation(FbxScene* pSDKScene)
{
FbxNode* pNode = pSDKScene->GetRootNode();
const int nStackCount = pSDKScene->GetSrcObjectCount();
for (int i = 0; i < nStackCount; ++i)
{
FbxAnimStack* pStack = pSDKScene->GetSrcObject(i);
const char* szStackName = pStack->GetName();
const int nLayerCount = pStack->GetMemberCount();
for (int j = 0; j < nLayerCount; ++j)
{
FbxAnimLayer* pLayer = pStack->GetMember(j);
const char* szLayerName = pLayer->GetName();
ParseLayer(pNode, pLayer);
}
}
}
//----------------------------------------------------------------
void SoFBXManager::ParseLayer(FbxNode* pNode, FbxAnimLayer* pLayer)
{
ParseChannel(pNode, pLayer);
const int nChildCount = pNode->GetChildCount();
for (int k = 0; k < nChildCount; ++k)
{
ParseLayer(pNode->GetChild(k), pLayer);
}
}
//----------------------------------------------------------------
void SoFBXManager::ParseChannel(FbxNode* pNode, FbxAnimLayer* pLayer)
{
FbxAnimCurve* pCurve = pNode->LclTranslation.GetCurve(pLayer, FBXSDK_CURVENODE_COMPONENT_X);
if (pCurve == 0)
{
return;
}
FbxTime kTime;
char lTimeString[256];
const int nKeyCount = pCurve->KeyGetCount();
for (int i = 0; i < nKeyCount; ++i)
{
kTime = pCurve->KeyGetTime(i);
const FbxAMatrix& kMatLocal = pNode->EvaluateLocalTransform(kTime);
const FbxAMatrix& kMatGlobal = pNode->EvaluateGlobalTransform(kTime);
//
kTime.GetTimeString(lTimeString, FbxUShort(256));
SoLogDebug("FBXTime : %s", lTimeString);
}
}
이전 메서드의 예제 코드:
FbxAnimStack* currAnimStack = mFBXScene->GetSrcObject(0);
FbxString animStackName = currAnimStack->GetName();
mAnimationName = animStackName.Buffer();
FbxTakeInfo* takeInfo = mFBXScene->GetTakeInfo(animStackName);
FbxTime start = takeInfo->mLocalTimeSpan.GetStart();
FbxTime end = takeInfo->mLocalTimeSpan.GetStop();
mAnimationLength = end.GetFrameCount(FbxTime::eFrames24) - start.GetFrameCount(FbxTime::eFrames24) + 1;
Keyframe** currAnim = &mSkeleton.mJoints[currJointIndex].mAnimation;
for (FbxLongLong i = start.GetFrameCount(FbxTime::eFrames24); i <= end.GetFrameCount(FbxTime::eFrames24); ++i)
{
FbxTime currTime;
currTime.SetFrame(i, FbxTime::eFrames24);
*currAnim = new Keyframe();
(*currAnim)->mFrameNum = i;
FbxAMatrix currentTransformOffset = inNode->EvaluateGlobalTransform(currTime) * geometryTransform;
(*currAnim)->mGlobalTransform = currentTransformOffset.Inverse() * currCluster->GetLink()->EvaluateGlobalTransform(currTime);
currAnim = &((*currAnim)->mNext);
}
나는 두 편의 블로그가 모두 낡은 방법을 사용하는 것을 보았다.
이 게시물은 새로운 방법과 낡은 방법에 대해 약간의 차이를 보였다.http://gamedev.stackexchange.com/questions/59419/c-fbx-animation-importer-using-the-fbx-sdk
새로운 방법의 결함은 이 애니메이션의 지속 시간을 모른다는 것이다.낡은 방법을 사용하면 애니메이션의 지속 시간을 얻을 수 있고, 그 다음에 당신에 따라
필요에 따라 이 애니메이션을 몇 개의 프레임으로 잘라서 각 프레임의 행렬을 저장합니다.
모든 Fbx 파일에는 하나의 FbxTakeInfo만 저장할 수 있고 하나의 애니메이션만 저장할 수 있다. 예를 들어 하나의 걷기 애니메이션이나 달리기 애니메이션만 저장할 수 있다.
한 외국 팀은 FBX Multi Take(3DS Max)라는 플러그인을 만들었는데 여러 개의 애니메이션을 하나의 애니메이션으로 연결하여 fbx 파일로 연결된 애니메이션을 저장할 수 있다.
이 플러그인은 유료입니다. 홈페이지는 여기에 있습니다.
Fbx 파일에는 mesh 정점 데이터만 포함하거나 뼈 애니메이션 데이터만 포함할 수 있습니다.메시 정점 데이터를 fbx 파일로 저장할 수 있는 캐릭터 모델
모든 골격 애니메이션을 각각 fbx 파일로 저장합니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.