8.2 KiB
Raw Blame History

title, date, excerpt, tags, rating
title date excerpt tags rating
FBX相关笔记 2023-11-06 11:45:14

FBX SDK setup for Qt

https://help.autodesk.com/view/FBX/2020/ENU/?guid=FBX_Developer_Help_welcome_to_the_fbx_sdk_html

使用之前建议仔细查看文档。FBX Sdk有三种库分别为动态链接库(dll + lib)、静态链接库(/MD)、静态链接库(/MT)。

  • 动态链接库使用Qt的导入库功能导入动态库之后只需要再添加一行DEFINES += FBXSDK_SHARED即可。例如:
QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17
DEFINES += FBXSDK_SHARED
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    Common/Common.cpp \
    main.cpp \
    mainwindow.cpp

HEADERS += \
    Common/Common.h \
    mainwindow.h

FORMS += \
    mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/FBXSdk/lib/vs2022/x64/release/ -llibfbxsdk
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/FBXSdk/lib/vs2022/x64/debug/ -llibfbxsdk

INCLUDEPATH += $$PWD/FBXSdk/lib/vs2022/x64/debug
DEPENDPATH += $$PWD/FBXSdk/lib/vs2022/x64/debug

INCLUDEPATH += $$PWD/FBXSdk/include
  • 静态链接库(/MD)使用Qt的导入库功能导入静态库之后
  • 静态链接库(/MT)使用Qt的导入库功能导入静态库之后

Qt相关设置添加

https://blog.csdn.net/libaineu2004/article/details/105718847 Qt在pro中设置运行时库MT、MTd、MD、MDd重点关注QMAKE_CFLAGS

多线程调试Dll (/MDd) 对应的是MD_DynamicDebug 多线程Dll (/MD) 对应的是MD_DynamicRelease 多线程(/MT) 对应的是MD_StaticRelease 多线程(/MTd)对应的是MD_StaticDebug

 /NODEFAULTLIB:library

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../LIBRARYNAME/Lib/ -lLIBRARY /NODEFAULTLIB:library

Ubuntu安装需要额外安装Qt

sudo apt install --reinstall libgl-dev

新版本fbxsdk需要自己link xml2库所以需要手动安装一下

sudo apt-get install libxml2-dev
sudo apt-get install libxml2

之后再qt的pro中添加LIBS += -lxml2即可。

之后运行程序会提示# (error while loading shared libraries: libfbxsdk.so: cannot open shared object file: No) 这是因为Linux的动态链接库寻找方式与windows不同所致我们需要添加lib搜索路径 使用VSCode打开/etc/ld.so.conf 输入libfbxsdk.so的路径再运行ldconfig即可解决问题

1>  vim /etc/ld.so.conf      //在新的一行中加入库文件所在目录
2> /usr/lib  				 //添加的目录路径
3> /usr/local/lib  				 //添加的目录路径
3> ldconfig                 //更新/etc/ld.so.cache文件

参考 https://blog.csdn.net/sinat_14854721/article/details/111191139

另一种思路就是使用linuxdeployqt打成类似MAC的APP包

FBX结构

FBX SDK场景图是通过FbxScene类抽象出来的。场景被组织为节点层次结构 ( FbxNode)。场景的根节点通过 访问FbxScene::GetRootNode()。场景元素(例如网格、灯光或相机)是通过将FbxNode与 的子类组合来定义的FbxNodeAttribute

使用Ansii方式输出就可以使用vscode直接查看内部数据结构。

  • GlobalMaterial世界坐标矩阵
  • LocalMaterial相对空间矩阵

动画

  • 动画堆栈 ( FbxAnimStack):动画数据最顶层容器,每一个AnimStack可以视为一个镜头,包含多个FbxAnimLayer
  • 动画层 ( FbxAnimLayer):每个AnimLayer中可以包含多个FbxAnimCurve
  • 动画曲线节点 ( FbxAnimCurveNode)
  • 动画曲线 ( FbxAnimCurve) 动画以曲线的方式存在。可以针对骨骼的Location、Rotation分别添加曲线。
  • 动画曲线关键点 ( FbxAnimCurveKey):动画关键帧。

每个动画数据都存在对应的节点的属性中Maya中可以给Shape的属性K帧可以通过类似lAnimCurve = pNode->LclTranslation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y);的方式取得动画曲线。

UE导出的FBX相关属性为

添加动画关键帧的方式

FbxAnimCurve* lCurve = lRoot->LclRotation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, true);
if (lCurve)
{
	lCurve->KeyModifyBegin();
	lTime.SetSecondDouble(0.0);
	//添加时间
	lKeyIndex = lCurve->KeyAdd(lTime);
	//添加数值与插值模式
	lCurve->KeySetValue(lKeyIndex, 0.0);
	lCurve->KeySetInterpolation(lKeyIndex, FbxAnimCurveDef::eInterpolationCubic);

	lTime.SetSecondDouble(1.0);
	lKeyIndex = lCurve->KeyAdd(lTime);
	lCurve->KeySetValue(lKeyIndex, 45.0);
	lCurve->KeySetInterpolation(lKeyIndex, FbxAnimCurveDef::eInterpolationCubic);

	lTime.SetSecondDouble(2.0);
	lKeyIndex = lCurve->KeyAdd(lTime);
	lCurve->KeySetValue(lKeyIndex, -45.0);
	lCurve->KeySetInterpolation(lKeyIndex, FbxAnimCurveDef::eInterpolationCubic);

	lTime.SetSecondDouble(3.0);
	lKeyIndex = lCurve->KeyAdd(lTime);
	lCurve->KeySetValue(lKeyIndex, 0.0);
	lCurve->KeySetInterpolation(lKeyIndex, FbxAnimCurveDef::eInterpolationCubic);
	lCurve->KeyModifyEnd();
}

BindPose

遍历所有节点并对取得GlobalTransform矩阵最后添加到Pose里。

    // Now create a bind pose with the link list
    if (lClusteredFbxNodes.GetCount())
    {
        // A pose must be named. Arbitrarily use the name of the patch node.
        FbxPose* lPose = FbxPose::Create(pScene,pPatch->GetName());

        // default pose type is rest pose, so we need to set the type as bind pose
        lPose->SetIsBindPose(true);

        for (i=0; i<lClusteredFbxNodes.GetCount(); i++)
        {
            FbxNode*  lKFbxNode   = lClusteredFbxNodes.GetAt(i);
            FbxMatrix lBindMatrix = lKFbxNode->EvaluateGlobalTransform();

            lPose->Add(lKFbxNode, lBindMatrix);
        }

        // Add the pose to the scene
        pScene->AddPose(lPose);
    }

ResetPose

void StoreRestPose(FbxScene* pScene, FbxNode* pSkeletonRoot)
{
    // This example show an arbitrary rest pose assignment.
    // This rest pose will set the bone rotation to the same value 
    // as time 1 second in the first stack of animation, but the 
    // position of the bone will be set elsewhere in the scene.
    FbxString     lNodeName;
    FbxNode*   lKFbxNode;
    FbxMatrix  lTransformMatrix;
    FbxVector4 lT,lR,lS(1.0, 1.0, 1.0);

    // Create the rest pose
    FbxPose* lPose = FbxPose::Create(pScene,"A Bind Pose");

    // Set the skeleton root node to the global position (10, 10, 10)
    // and global rotation of 45deg along the Z axis.
    lT.Set(10.0, 10.0, 10.0);
    lR.Set( 0.0,  0.0, 45.0);

    lTransformMatrix.SetTRS(lT, lR, lS);

    // 添加Root骨骼矩阵到Pose中
    lKFbxNode = pSkeletonRoot;
    lPose->Add(lKFbxNode, lTransformMatrix, false /*GlobalMatrix*/);

    // Set the lLimbNode1 node to the local position of (0, 40, 0)
    // and local rotation of -90deg along the Z axis. This show that
    // you can mix local and global coordinates in a rest pose.
    lT.Set(0.0, 40.0,   0.0);
    lR.Set(0.0,  0.0, -90.0);

    lTransformMatrix.SetTRS(lT, lR, lS);

    // 添加第二个骨骼节点到Pose中
    lKFbxNode = lKFbxNode->GetChild(0);
    lPose->Add(lKFbxNode, lTransformMatrix, true /*LocalMatrix*/);

    // Set the lLimbNode2 node to the local position of (0, 40, 0)
    // and local rotation of 45deg along the Z axis.
    lT.Set(0.0, 40.0, 0.0);
    lR.Set(0.0,  0.0, 45.0);

    lTransformMatrix.SetTRS(lT, lR, lS);

    // Add the skeleton second node to the pose
    lKFbxNode = lKFbxNode->GetChild(0);
    lNodeName = lKFbxNode->GetName();
    lPose->Add(lKFbxNode, lTransformMatrix, true /*LocalMatrix*/);

    // Now add the pose to the scene
    pScene->AddPose(lPose);
}

GlobalSettings

场景的轴系统、系统单位、环境照明和时间设置可以通过FbxScene::GetGlobalSettings()获取FbxGlobalSettings来进行定义。