2023-08-18 20:11:04 +08:00
|
|
|
|
---
|
|
|
|
|
title: UE5动画重定向笔记
|
|
|
|
|
date: 2023-08-18 18:08:12
|
|
|
|
|
excerpt:
|
|
|
|
|
tags:
|
|
|
|
|
rating: ⭐
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
# ConvertAnimation()
|
2023-08-21 10:12:05 +08:00
|
|
|
|
主要逻辑位于`UAnimationEditorUtilityLibrary::ConvertAnimation()`或者`FIKRetargetBatchOperation::ConvertAnimation()`。核心重定向逻辑为`UIKRetargetProcessor::RunRetargeter()`。
|
2023-08-18 20:11:04 +08:00
|
|
|
|
|
2023-08-21 10:12:05 +08:00
|
|
|
|
## RunRootRetarget()
|
|
|
|
|
FRootRetargeter::EncodePose():
|
|
|
|
|
取得输入的根骨骼Transform数据并给`FRootSource Source`赋值。
|
2023-08-18 20:11:04 +08:00
|
|
|
|
|
2023-08-21 10:12:05 +08:00
|
|
|
|
FRootRetargeter::DecodePose():
|
|
|
|
|
```c++
|
|
|
|
|
// InitialTransform 为重定向Pose计算出的数值,通过比值计算出Target的Current数值
|
|
|
|
|
const FTransform InitialTransform = SourceSkeleton.RetargetGlobalPose[Source.BoneIndex];
|
|
|
|
|
float InitialHeight = InitialTransform.GetTranslation().Z;
|
|
|
|
|
Source.InitialHeightInverse = 1.0f / InitialHeight;
|
|
|
|
|
Source.CurrentPositionNormalized = Source.CurrentPosition * Source.InitialHeightInverse;
|
|
|
|
|
|
|
|
|
|
// generate basic retarget root position by scaling the normalized position by root height
|
|
|
|
|
const FVector RetargetedPosition = Source.CurrentPositionNormalized * Target.InitialHeight;
|
|
|
|
|
```
|
|
|
|
|
## RunFKRetarget()
|
|
|
|
|
FChainEncoderFK::EncodePose():
|
|
|
|
|
从骨骼链拷贝全局输入到CurrentGlobalTransforms
|
|
|
|
|
|
|
|
|
|
FChainDecoderFK::DecodePose():
|
|
|
|
|
|
|
|
|
|
## RunIKRetarget()
|
|
|
|
|
|
|
|
|
|
## RunPoleVectorMatching()
|
2023-08-18 20:11:04 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# UIKRetargetProcessor
|
2023-08-21 11:56:17 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-08-22 13:25:39 +08:00
|
|
|
|
# FBX SDK setup for Qt
|
2023-08-22 12:09:58 +08:00
|
|
|
|
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`即可。例如:
|
|
|
|
|
```qmake
|
|
|
|
|
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
|
|
|
|
|
```cpp
|
|
|
|
|
win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../LIBRARYNAME/Lib/ -lLIBRARY /NODEFAULTLIB:library
|
2023-08-22 13:25:39 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
# FBX结构
|
|
|
|
|

|
|
|
|
|
FBX SDK场景图是通过`FbxScene`类抽象出来的。场景被组织为节点层次结构 ( `FbxNode`)。场景的根节点通过 访问`FbxScene::GetRootNode()`。场景元素(例如网格、灯光或相机)是通过将`FbxNode`与 的子类组合来定义的`FbxNodeAttribute`。
|
|
|
|
|
|
2023-08-24 15:45:39 +08:00
|
|
|
|
使用Ansii方式输出就可以使用vscode直接查看内部数据结构。
|
|
|
|
|
- GlobalMaterial:世界坐标矩阵
|
|
|
|
|
- LocalMaterial:相对空间矩阵
|
2023-08-22 14:56:49 +08:00
|
|
|
|
## 动画
|
2023-08-24 15:45:39 +08:00
|
|
|
|
- 动画堆栈 ( `FbxAnimStack`):每一个**AnimStack**可以视为一个镜头,包含多个**FbxAnimLayer**。
|
|
|
|
|
- 动画层 ( `FbxAnimLayer`):每个**AnimLayer**中可以包含多个**FbxAnimCurve**。
|
2023-08-22 14:56:49 +08:00
|
|
|
|
- 动画曲线节点 ( `FbxAnimCurveNode`)
|
2023-08-24 15:45:39 +08:00
|
|
|
|
- 动画曲线 ( `FbxAnimCurve`) :动画以曲线的方式存在。可以针对骨骼的Location、Rotation分别添加曲线。
|
2023-08-24 21:29:01 +08:00
|
|
|
|
- 动画曲线关键点 ( `FbxAnimCurveKey`):动画关键帧。
|
|
|
|
|
|
|
|
|
|
每个动画数据都存在对应的节点的属性中(Maya中可以给Shape的属性K帧),可以通过类似`lAnimCurve = pNode->LclTranslation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y);`的方式取得动画曲线。
|
2023-08-22 14:56:49 +08:00
|
|
|
|
|
2023-08-24 15:45:39 +08:00
|
|
|
|
UE导出的FBX相关属性为:
|
|
|
|
|
```json
|
|
|
|
|
AnimationStack: 1767515526080, "AnimStack::Unreal Take", "" {
|
|
|
|
|
Properties70: {
|
|
|
|
|
P: "Description", "KString", "", "", "Animation Take for Unreal."
|
|
|
|
|
P: "LocalStop", "KTime", "Time", "",183205094709
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AnimationLayer: 1770224712128, "AnimLayer::Base Layer", "" {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NodeAttribute: 1767517959504, "NodeAttribute::Root", "Root" {
|
|
|
|
|
TypeFlags: "Null", "Skeleton", "Root"
|
|
|
|
|
}
|
|
|
|
|
NodeAttribute: 1767517960848, "NodeAttribute::Pelvis", "LimbNode" {
|
|
|
|
|
TypeFlags: "Skeleton"
|
|
|
|
|
}
|
|
|
|
|
NodeAttribute: 1767517959696, "NodeAttribute::L_Hip", "LimbNode" {
|
|
|
|
|
TypeFlags: "Skeleton"
|
|
|
|
|
}
|
|
|
|
|
NodeAttribute: 1767517960080, "NodeAttribute::L_Knee", "LimbNode" {
|
|
|
|
|
TypeFlags: "Skeleton"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AnimationCurve: 1770213770432, "AnimCurve::", "" {
|
|
|
|
|
Default: 0
|
|
|
|
|
KeyVer: 4009
|
|
|
|
|
KeyTime: *120 {
|
|
|
|
|
a: 0,1539538600,3079077200,4618615800,6158154400,7697693000,9237231600,10776770200,12316308800,13855847400,15395386000,16934924600,18474463200,20014001800,21553540400,23093079000,24632617600,26172156200,27711694800,29251233400,30790772000,32330310600,33869849200,35409387800,36948926400,38488465000,40028003600,41567542200,43107080800,44646619400,46186158000,47725696600,49265235200,50804773800,52344312400,53883851000,55423389600,56962928200,58502466800,60042005400,61581544000,63121082600,64660621200,66200159800,67739698400,69279237000,70818775600,72358314200,73897852800,75437391400,76976930000,78516468600,80056007200,81595545800,83135084400,84674623000,86214161600,87753700200,89293238800,90832777400,92372316000,93911854600,95451393200,96990931800,98530470400,100070009000,101609547600,103149086200,104688624800,106228163400,107767702000,109307240600,110846779200,112386317800,113925856400,115465395000,117004933600,118544472200,120084010800,121623549400,123163088000,124702626600,126242165200,127781703800,129321242400,130860781000,132400319600,133939858200,135479396800,137018935400,138558474000,140098012600,141637551200,143177089800,144716628400,146256167000,147795705600,149335244200,150874782800,152414321400,153953860000,155493398600,157032937200,158572475800,160112014400,161651553000,163191091600,164730630200,166270168800,167809707400,169349246000,170888784600,172428323200,173967861800,175507400400,177046939000,178586477600,180126016200,181665554800,183205093400
|
|
|
|
|
}
|
|
|
|
|
KeyValueFloat: *120 {
|
|
|
|
|
a: -0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0,-0
|
|
|
|
|
}
|
|
|
|
|
;KeyAttrFlags: Cubic|TangeantAuto|GenericTimeIndependent, Constant|ConstantStandard
|
|
|
|
|
KeyAttrFlags: *2 {
|
|
|
|
|
a: 8456,8194
|
|
|
|
|
}
|
|
|
|
|
;KeyAttrDataFloat: RightAuto:0, NextLeftAuto:0; RightSlope:0, NextLeftSlope:0, RightWeight:0.333333, NextLeftWeight:0.333333, RightVelocity:0, NextLeftVelocity:0
|
|
|
|
|
KeyAttrDataFloat: *8 {
|
|
|
|
|
a: 0,0,218434821,0,0,0,218434821,0
|
|
|
|
|
}
|
|
|
|
|
KeyAttrRefCount: *2 {
|
|
|
|
|
a: 119,1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
AnimationCurve: 1770213768992, "AnimCurve::", "" {
|
|
|
|
|
Default: 0
|
|
|
|
|
KeyVer: 4009
|
|
|
|
|
KeyTime: *120 {
|
|
|
|
|
a: 0,1539538600,3079077200,4618615800,6158154400,7697693000,9237231600,10776770200,12316308800,13855847400,15395386000,16934924600,18474463200,20014001800,21553540400,23093079000,24632617600,26172156200,27711694800,29251233400,30790772000,32330310600,33869849200,35409387800,36948926400,38488465000,40028003600,41567542200,43107080800,44646619400,46186158000,47725696600,49265235200,50804773800,52344312400,53883851000,55423389600,56962928200,58502466800,60042005400,61581544000,63121082600,64660621200,66200159800,67739698400,69279237000,70818775600,72358314200,73897852800,75437391400,76976930000,78516468600,80056007200,81595545800,83135084400,84674623000,86214161600,87753700200,89293238800,90832777400,92372316000,93911854600,95451393200,96990931800,98530470400,100070009000,101609547600,103149086200,104688624800,106228163400,107767702000,109307240600,110846779200,112386317800,113925856400,115465395000,117004933600,118544472200,120084010800,121623549400,123163088000,124702626600,126242165200,127781703800,129321242400,130860781000,132400319600,133939858200,135479396800,137018935400,138558474000,140098012600,141637551200,143177089800,144716628400,146256167000,147795705600,149335244200,150874782800,152414321400,153953860000,155493398600,157032937200,158572475800,160112014400,161651553000,163191091600,164730630200,166270168800,167809707400,169349246000,170888784600,172428323200,173967861800,175507400400,177046939000,178586477600,180126016200,181665554800,183205093400
|
|
|
|
|
}
|
|
|
|
|
KeyValueFloat: *120 {
|
|
|
|
|
a: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
|
|
|
}
|
|
|
|
|
;KeyAttrFlags: Cubic|TangeantAuto|GenericTimeIndependent, Constant|ConstantStandard
|
|
|
|
|
KeyAttrFlags: *2 {
|
|
|
|
|
a: 8456,8194
|
|
|
|
|
}
|
|
|
|
|
;KeyAttrDataFloat: RightAuto:0, NextLeftAuto:0; RightSlope:0, NextLeftSlope:0, RightWeight:0.333333, NextLeftWeight:0.333333, RightVelocity:0, NextLeftVelocity:0
|
|
|
|
|
KeyAttrDataFloat: *8 {
|
|
|
|
|
a: 0,0,218434821,0,0,0,218434821,0
|
|
|
|
|
}
|
|
|
|
|
KeyAttrRefCount: *2 {
|
|
|
|
|
a: 119,1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
添加动画关键帧的方式
|
|
|
|
|
```c++
|
|
|
|
|
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里。
|
|
|
|
|
```c++
|
|
|
|
|
// 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
|
|
|
|
|
```c++
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2023-08-22 14:56:49 +08:00
|
|
|
|
## GlobalSettings
|
|
|
|
|
场景的轴系统、系统单位、环境照明和时间设置可以通过`FbxScene::GetGlobalSettings()`获取FbxGlobalSettings来进行定义。
|