-
如何将
Fbx
格式转
换成
VVO
格式
一、
Fbx
文件格式简介
1.1
KFbxSdkManage
和
KFbxScene
Fbx
文
件是
Auto
desk
开发的文件格式,其开发目的就是为了实现
Autod
esk
旗下软件之间的数据交换。
Fbx
文件格式本身是不公开的,
而是通过
FBX SDK
实现对
Fbx
文件的读取以及写入。
使用
FBX
SDK<
/p>
时,最先遇到的两个对象就是
KFbxSdkManage
和
KFbxScene
。
KFbxSdkManage
是
sdk
中的中心类,负责了整个
sdk
内部状态的管理,
很
多
其
他
对
象
创
< br>建
也
依
赖
于
KFbxSdkManage
,
程
序
中
只
需
p>
要
有
一
个
KFbxSdkManage
类的实例即可。
KFbxScene
如其名所示,代表了一个场景,而这里的场
景就是
fbx
文件中
包含的所有信息,
fbx
文件导入以后,在程序中就是一个
KFbxScene
对象
,
所
以一个
fbx
文件只需要一个
KFbxScene
类的实例。
1.2 Fbx
的数据组织方式
<
/p>
Fbx
的数据组织方式是
scene
p>
tree
,即场景树。由
KFbxScene
所声明的
对象可以得到
该场景树的根节点,根节点包含了一系列子节点
KFbxNode
,每
个
KFbxNode
又有其自己的子节点,以此往下类推。这样通过递归循环就可以
遍历到每一个节点,然
后获取该节点的信息。
RootNode
是该
Fbx
文件所对应的根节点,由以下语句得到:
KFbxNode
* pNode = p
Scene->
GetRootNode
();//
获得根节点
图
1
是一个圆柱体的例子。
该圆柱体总共有四个节点,
Patch
、
SkeletonRoot
< br>、
SkeletonLim
bNode1
、
SkeletonLimbNode2
是这四个节点的名称
。其中
Patch
、
SkeletonRoot
是
RootNode
的孩
子
,<
/p>
SkeletonLimbNode1
是
SkeletonRoot
的孩子,
SkeletonLimb
Node2
是
SkeletonLimbNode1
的孩
子。
RootNode
Patch
KFbxNode
SkeletonRoot
KFbxNode
SkeletonLimbNode1
KFbxNode
Ske
letonLimbNode2
KFbxNode
图
1 <
/p>
kFbxObject
KFbxCollection
KFbxNode
KFbxNodeAttribute
< br>KFbxDocument
KFbxSkeleton
K
FbxLight
KFbxLayerContainer
KF
bxScene
KFbxGeometryBase
KFbxG
eometry
KFbxMesh
KFbxNurb
KFbxPatch
1.3 Fbx
中节点
KFbxNo
de
说明
1.3.1
节点坐标
场景树中每个节点都是
p>
KFbxNode
,
KFbxNode
p>
类本身包含了坐标变换信息,
例如可以用函数
EvaluateGlobalTransform
(
KTi
me
pTime)
获得在
pTime
时刻
该节点的全球变换矩阵。
获得全球变换矩阵后,
我们可以得到节点在该时刻的世
< br>界坐标系下的平移、旋转和缩放。同理由
EvaluateLocalTrans
form
(
KTime
pTime)
获得在
pTime
时刻该节点的本地变换矩阵,
进而获得该时刻本地坐标系下
节点的平移、旋转和缩放。
1.3.2
节点类型
一个节点
< br>KFbxNode
包含其他数据作为
KFbxNodeA
ttribute
对象,包含在其
内部,这里的其他数据是指<
/p>
mesh
,
Nurbs
< br>,
skeleton
,
cama
ra
,
light
等定
义在
KFbxNodeAttribute
::
EAttributeType
中的枚举类型。获得一个节点
的类型可用以下函数语句来实现
:
KFbxN
odeAttribute
::
EAttributeType
lAttributeType;
lAttributeType
=
pNode->
GetNodeAttribute
()-><
/p>
GetAttributeType
();
1.3.3
节点中层次
Layer
层次
Layer
:
法线、
纹理坐标等是存储在层次
Layer
中的,
每个节点可以有
多个层次,然后在每个层次中包
含一套纹理,法线等。但是,通常我们只会用到
一个层次,
很多
建模软件也只支持一个层次。
比如在一个节点类型为
eMESH
的结
点中层次概念如下所示:
mesh
-------
layer
0{
K
FbxLayerElementNormal
,
KFbxLa
yerElementUV
……
}
|
|------
layer
1{
K
FbxLayerElementNormal
,
KFbxLa
yerElementUV
………}
|
|--
………………..
|
|------
layer
n
{
KFbxLayerEleme
ntNormal
,
KFbxLayerElementUV<
/p>
………}
关于层次的常用函数:
//
求
pMesh
中包含
U
V
的层次数
pMesh->
GetElementUVCount
()
;
//
获得第
i
层中的
UV
对象
KFbxGeometryElementUV
* leUV
= pMesh->
GetElementUV
(
i
)
;
每种保存在
Layer
中的元素
(如上面提到的
UV
)
都继承于
KFb
xLayerElement
,
比如
K
FbxLayerElementNormal
对应
norma
l
数据,
KFbxLayerElementUV
对应的
UV
数据,可以通过
KFbxLayer
中定义的各种
Get
函数得到,如
GetElementNormal()
和
p>
GetElementUV
,
返回需要的<
/p>
KFbxLayerElement
,
如
果为空,
则说明当前
layer
中没有
这种元素。
下面是关于
KFbxLayerElement
p>
的类的大概的继承图。
KFbxLaye
rElement
KFbxLayerElementTemplate
< KFbxVector4>
KFbxLayerElementTempl
ate
< KFbxVector2>
KFbxLayerEl
ementTemplate
< KFbxColor>
KFb
xLayerElement
Normal
KFbxLayer
Element
Binormal
KFbxLayerElem
ent
Tangent
KFbxLayerElement
p>
UV
KFbxLayerElement
V
ertexColor
KFbxLayerElement<
/p>
还中包含了两个非常重要的属性
EMappingMode
和
EReferenceMode
。
typedef
enum
{
eNONE
,
eBY_CONTROL_POINT
,
//
对于每一个
Control
Point
有一个贴图坐标
eBY_POLYGON_VERTEX
,
< br>//
对于
polygon
中每一
个顶点有一个贴图坐标
eBY_POLYGON
,
//
p>
对于一个
polygon
有一个贴图坐标<
/p>
eBY_EDGE
,
eALL_SAME
}
EMappingMode
;
typedef
enum
{
eDIRECT
,
eINDEX
,
eINDEX_TO_DIRECT
}
EReferenceMode
;
?
MappingMode
定义了当前类型的元素如何映射到
mesh
上。
举例来说,
对于
KFbxLayer
ElementNormal
,
MappingMode=eB
Y_POLYGON_VERTEX
表示如
果一个顶点被
n
个多边形共享,那么这个顶点就有
n
条法线与之相对应;
eBY_CONTROL_POINT
则表示每个顶点无论被几个多边形共享,都只有一条
normal
;
eBY_POLYGON
则表示构成多边形的
n
个顶点只对应着一条
normal<
/p>
。
?
ReferenceMode
定义了如何访问相关的数据。同样举例来
说,每个
KFbxLayerElement
内部通常可能包含两个数组,分别称为
DirectArray
和
IndexArray
。如果
reference
mode
为<
/p>
eDIRECT
,则第
i
个顶点相对的
element
元素就在
DirectArray
的第
i
位置
(
第
i
个顶点的
normal
在
KFbxLa
yerElementNormal
.
DirectArray
[i]
中
)
,此时
< br>IndexArray
为空。
eINDEX_TO_DI
RECT
通常和
eBY_POLYGON_VERTEX
一起使用,因为一个控点
可能对应多个值,
所
以这时必须用多边形顶点索引来获得某个多边形顶点所对应
的值,例如
< br>
int
id
=
pNormal
->
GetIndexArray
().
GetAt
(
vertexId
);
KFbxVector4
* pTemp =
pNormal
->
GetDirectArray
().
GetAt
(
id
));
vertexId
是
polygon
顶点的索引。
1.4
两个重要的节点结构:
Mesh
、
S
keleton
1.4.1
mesh
节点
网格(
Mesh
)存储了模型结构的重要数据,包括顶点坐标,颜色,
UV
(纹
理坐标),法线(
N
ormal
)等。这些都是我们在新平台中所要用到的。
p>
Fbx
文件中包含的
Mesh
节点,我们一般称为蒙皮节点。该节点由多边形
组成,多边形至少是三角形,
除此之外还可能是四边形,五边形等等。如果要将
该
Fbx
p>
中的
mesh
节点三角面片化,可用下面方
法实现:
KFbxGeometryConverter
converter(sdkManager);
mesh = converter.
Triangulate
Mesh
(mesh);
?
顶点坐标
Mesh
中有两个概念控点(
Cont
rol point
)和顶点(
Polygon vertex
)。控
点只包含位置信息,
顶点就是多
边形中的顶点,
通过索引可以得到该多边形顶点
位置,法线,纹
理坐标等信息。
控点和顶点的关系:要看
mesh
中所有
layer(
通常
只用第一层
)
中所有元素的
Mappi
ngMode
:如果是
eBY_CONTROL_POINT<
/p>
,则控点的数量和顶点的数量是一
一对应的,如果是
eBY_POLYGON_VERTEX
,则需要分裂控点,一个控点可以出
现在不同的三角面中作为顶点,
这时候一个控点对应多个顶点。
一般来说当
mesh
由多个
Polygon
组成时,
MappingMode
的第二种
eBY_POLYGON_VERTEX
更常用。
不论是控点还是顶点,
p>
在求位置坐标时用的是控点中的位置信息。
对于多边
形
polygon
中顶点的位置,是通过求该顶点所对
应的控点在控点数组中的索引,
最后求得的。
下面列几个求坐标时常用函数:
//
求
mesh
中控点的数目
int
lControlPointsCount
=
pMesh<
/p>
->
GetControlPointsCount
();
//
求
mesh<
/p>
中控点数组
KFbxVector4
*
lControlPoints
=
pMesh
->
GetControlPoints
();
若是要求在多边形
polygon
中顶点坐标,则需求该顶点对应的控点的索引
//
如果这个
mesh
已经三角面片
化,得到三角形的个数;如果没有三角面片
化,则获得多边形的个数
int
numPoly
=
mesh
->
GetPolygonCount
();
for
(
int
i=0;i
{
int
vn =
mesh->
GetPolygonSize
(i);
//mesh
第
i
个
poly
的顶点个数
for
(int j=0;j
//
获得每个顶点的位置坐标
{
p>
//
获得第
i
个多
边形中第
j
个顶点相对应的索引
int
pControlPointsIndex =
mesh->
GetPolygonVertex
(i,j);
KFbxVector4
*
pTemp=lControlPoints[pControlPointsIndex];
}
}
?
纹理坐标
对于纹理坐标的求取,根据前面所写的
MappingMode
和
ReferenceMode
类
p>
-
-
-
-
-
-
-
-
-
上一篇:七年级英语培优试题.docx
下一篇:剧本例子