ImageVerifierCode 换一换
格式:DOCX , 页数:13 ,大小:84.94KB ,
资源ID:24583132      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/24583132.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(读取Fbx文件中的信息.docx)为本站会员(b****4)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

读取Fbx文件中的信息.docx

1、读取Fbx文件中的信息如何将Fbx格式转换成VVO格式一、Fbx文件格式简介1.1 KFbxSdkManage和KFbxSceneFbx文件是Autodesk开发的文件格式,其开发目的就是为了实现Autodesk旗下软件之间的数据交换。Fbx文件格式本身是不公开的,而是通过FBX SDK实现对Fbx文件的读取以及写入。使用FBX SDK时,最先遇到的两个对象就是KFbxSdkManage和KFbxScene。KFbxSdkManage是sdk中的中心类,负责了整个sdk内部状态的管理,很多其他对象创建也依赖于KFbxSdkManage,程序中只需要有一个KFbxSdkManage类的实例即可。

2、KFbxScene如其名所示,代表了一个场景,而这里的场景就是fbx文件中包含的所有信息,fbx文件导入以后,在程序中就是一个KFbxScene对象,所以一个fbx文件只需要一个KFbxScene类的实例。1.2 Fbx的数据组织方式Fbx的数据组织方式是scene tree,即场景树。由KFbxScene所声明的对象可以得到该场景树的根节点,根节点包含了一系列子节点KFbxNode,每个KFbxNode又有其自己的子节点,以此往下类推。这样通过递归循环就可以遍历到每一个节点,然后获取该节点的信息。RootNode是该Fbx文件所对应的根节点,由以下语句得到:KFbxNode* pNode =

3、 pScene-GetRootNode();/获得根节点图1是一个圆柱体的例子。该圆柱体总共有四个节点,Patch、SkeletonRoot、SkeletonLimbNode1、SkeletonLimbNode2是这四个节点的名称。其中Patch、SkeletonRoot是RootNode的孩子,SkeletonLimbNode1是SkeletonRoot的孩子,SkeletonLimbNode2是SkeletonLimbNode1的孩子。 图 11.3 Fbx中节点KFbxNode说明1.3.1 节点坐标场景树中每个节点都是KFbxNode,KFbxNode类本身包含了坐标变换信息,例如可以

4、用函数EvaluateGlobalTransform(KTime pTime)获得在pTime时刻该节点的全球变换矩阵。获得全球变换矩阵后,我们可以得到节点在该时刻的世界坐标系下的平移、旋转和缩放。同理由EvaluateLocalTransform(KTime pTime)获得在pTime时刻该节点的本地变换矩阵,进而获得该时刻本地坐标系下节点的平移、旋转和缩放。1.3.2 节点类型一个节点KFbxNode包含其他数据作为KFbxNodeAttribute对象,包含在其内部,这里的其他数据是指mesh,Nurbs,skeleton,camara,light等定义在KFbxNodeAttribu

5、te:EAttributeType中的枚举类型。获得一个节点的类型可用以下函数语句来实现:KFbxNodeAttribute:EAttributeType lAttributeType;lAttributeType = pNode-GetNodeAttribute()-GetAttributeType();1.3.3 节点中层次Layer层次Layer:法线、纹理坐标等是存储在层次Layer中的,每个节点可以有多个层次,然后在每个层次中包含一套纹理,法线等。但是,通常我们只会用到一个层次,很多建模软件也只支持一个层次。比如在一个节点类型为eMESH的结点中层次概念如下所示:mesh -laye

6、r 0 KFbxLayerElementNormal,KFbxLayerElementUV | |-layer 1 KFbxLayerElementNormal,KFbxLayerElementUV | |- . | |-layer n KFbxLayerElementNormal,KFbxLayerElementUV关于层次的常用函数:/求pMesh中包含UV的层次数pMesh-GetElementUVCount();/获得第i层中的UV对象KFbxGeometryElementUV* leUV = pMesh-GetElementUV(i);每种保存在Layer中的元素(如上面提到的UV)

7、都继承于KFbxLayerElement,比如KFbxLayerElementNormal对应normal数据,KFbxLayerElementUV对应的UV数据,可以通过KFbxLayer中定义的各种Get函数得到,如GetElementNormal()和GetElementUV,返回需要的KFbxLayerElement,如果为空,则说明当前layer中没有这种元素。下面是关于KFbxLayerElement的类的大概的继承图。KFbxLayerElement还中包含了两个非常重要的属性EMappingMode和EReferenceMode。 typedef enum eNONE, eBY

8、_CONTROL_POINT, /对于每一个Control Point有一个贴图坐标 eBY_POLYGON_VERTEX, /对于polygon中每一个顶点有一个贴图坐标 eBY_POLYGON, /对于一个polygon有一个贴图坐标 eBY_EDGE, eALL_SAME EMappingMode; typedef enum eDIRECT, eINDEX, eINDEX_TO_DIRECT EReferenceMode;MappingMode定义了当前类型的元素如何映射到mesh上。举例来说,对于KFbxLayerElementNormal,MappingMode=eBY_POLYGO

9、N_VERTEX表示如果一个顶点被n个多边形共享,那么这个顶点就有n条法线与之相对应;eBY_CONTROL_POINT则表示每个顶点无论被几个多边形共享,都只有一条normal;eBY_POLYGON则表示构成多边形的n个顶点只对应着一条normal。ReferenceMode定义了如何访问相关的数据。同样举例来说,每个KFbxLayerElement内部通常可能包含两个数组,分别称为DirectArray和IndexArray。如果reference mode为eDIRECT,则第i个顶点相对的element元素就在DirectArray的第i位置(第i个顶点的normal在KFbxLay

10、erElementNormal.DirectArrayi中) ,此时IndexArray为空。eINDEX_TO_DIRECT通常和eBY_POLYGON_VERTEX一起使用,因为一个控点可能对应多个值,所以这时必须用多边形顶点索引来获得某个多边形顶点所对应的值,例如int id = pNormal-GetIndexArray().GetAt(vertexId);KFbxVector4* pTemp = pNormal-GetDirectArray().GetAt(id);vertexId 是polygon顶点的索引。1.4 两个重要的节点结构:Mesh、Skeleton1.4.1 mesh

11、节点网格(Mesh)存储了模型结构的重要数据,包括顶点坐标,颜色,UV(纹理坐标),法线(Normal)等。这些都是我们在新平台中所要用到的。Fbx文件中包含的Mesh节点,我们一般称为蒙皮节点。该节点由多边形组成,多边形至少是三角形,除此之外还可能是四边形,五边形等等。如果要将该Fbx中的mesh节点三角面片化,可用下面方法实现:KFbxGeometryConverterconverter(sdkManager);mesh=converter.TriangulateMesh(mesh);顶点坐标Mesh中有两个概念控点(Control point)和顶点(Polygon vertex)。控点

12、只包含位置信息,顶点就是多边形中的顶点,通过索引可以得到该多边形顶点位置,法线,纹理坐标等信息。控点和顶点的关系:要看mesh中所有layer(通常只用第一层)中所有元素的MappingMode:如果是eBY_CONTROL_POINT,则控点的数量和顶点的数量是一一对应的,如果是eBY_POLYGON_VERTEX,则需要分裂控点,一个控点可以出现在不同的三角面中作为顶点,这时候一个控点对应多个顶点。一般来说当mesh由多个Polygon组成时,MappingMode的第二种eBY_POLYGON_VERTEX 更常用。不论是控点还是顶点,在求位置坐标时用的是控点中的位置信息。对于多边形po

13、lygon中顶点的位置,是通过求该顶点所对应的控点在控点数组中的索引,最后求得的。下面列几个求坐标时常用函数:/求mesh中控点的数目int lControlPointsCount = pMesh-GetControlPointsCount();/求mesh中控点数组KFbxVector4* lControlPoints = pMesh-GetControlPoints();若是要求在多边形polygon中顶点坐标,则需求该顶点对应的控点的索引/如果这个mesh已经三角面片化,得到三角形的个数;如果没有三角面片化,则获得多边形的个数int numPoly = mesh-GetPolygonCo

14、unt(); for(int i=0;iGetPolygonSize(i); /mesh第i个poly的顶点个数for(int j=0;jGetPolygonVertex(i,j); KFbxVector4* pTemp=lControlPointspControlPointsIndex; 纹理坐标对于纹理坐标的求取,根据前面所写的MappingMode和ReferenceMode类型,总共分三种情况:KFbxGeometryElementUV* leUV = pMesh-GetElementUV(0);(1)MappingMode是eBY_CONTROL_POINT,而ReferenceMo

15、de是eDIRECT时,KFbxVector2* pTemp;pTemp = leUV-GetDirectArray().GetAt(lControlPointIndex);(2)MappingMode是eBY_CONTROL_POINT,而ReferenceMode是eINDEX_TO_DIRECT时,KFbxVector2* pTemp;int id = leUV-GetIndexArray().GetAt(lControlPointIndex);pTemp = leUV-GetDirectArray().GetAt(id);(3)MappingMode是eBY_POLYGON_VERTE

16、X,无论ReferenceMode是eDIRECT,还是eINDEX_TO_DIRECT,都用下面方法读取:int lTextureUVIndex = pMesh-GetTextureUVIndex(i, j);KFbxVector2* pTemp;pTemp = leUV-GetDirectArray().GetAt(lTextureUVIndex);另外读取法向Normal、顶点颜色时基本类似,这里不再赘述。1.4.2 skeleton节点Fbx骨骼动画中的骨骼节点,一般用skeleton节点,即KFbxNode类型为eSKELETON的节点来表示。对于骨骼节点,我们要读取的信息包括:节点

17、的关键帧个数、每个关键帧的时间、在关键帧时刻节点的本地变换矩阵。要获得以上信息,首先要了解Fbx中动画组织方式。对于一个含有动画信息的fbx模型,它可以包含一个或多个动画栈(KFbxAnimStack),每个动画栈存储一套动作。比如一个人的模型,他有两套动作,一套是由走到跑的动作,另一套是中枪倒下。那么每一套动作就可以用一个动画栈来表示。一个动画栈中可以包含一个或多个动画层(KFbxAnimLayer),每一个动画层存储一个动作,上例中由跑到走这套动作中总共有两个动作:跑、走,那么每个动作就可以用一个动画层来表示,这样在这个动画栈中就有两个动画层。关于动画相关类的继承图如下:在Fbx中关键帧是

18、打在每个属性上的,动画层组织这些关键帧动画,动画栈再组织这些动画层。比如动画师建一个动画模型时,总的动画有十个关键帧。他在第2、8、10帧给平移属性Translation打了关键帧,而在第2、3、6、9帧给旋转属性Rotation打了关键帧,因此这两个属性的关键帧数目是不同的,而且有的关键帧的时间点也是不同的。不但Translation和Rotation上的关键帧数不同,也可能在同一属性如Translation的不同值上的关键帧数也是不同的,比如在TranslationX和TranslationY上的关键帧数可以不同。这就是Fbx中动画的大概组织方式。下面用一个简单的例子,即Fbx中只有一个动

19、画栈,动画栈中只有一个动画层,来演示一下如何获取TranslationX上的关键帧个数,以及关键帧时间。/获取fbx的动画栈pAnimStack, 0代表第一个栈KFbxAnimStack* pAnimStack = KFbxCast(pScene-GetSrcObject(FBX_TYPE(KFbxAnimStack), 0);/获取动画栈中的动画层pAnimLayer, 0代表第一层。KFbxAnimLayer* pAnimLayer;pAnimLayer= pAnimStack-GetMember(FBX_TYPE(KFbxAnimLayer), 0);/获取动画层中的动画曲线Curve

20、,相当于属性的值。KFbxAnimCurve* pAnimCurveTX;pAnimCurveTX=pNode-LclTranslation.GetCurve(pAnimLayer, KFCURVENODE_T_X);/获取关于属性Translation的X的关键帧个数以及时间。 if (pAnimCurveTX) KFCurve* pCurve = pAnimCurveTX-GetKFCurve(); int pTXKeyCount = pCurve-KeyGetCount(); for (int k=0; kKeyGetTime(k); 用同样的方法可以获得其他的属性的各个值的关键帧个数和

21、时间。求出关键帧时间后再求节点的本地变换矩阵可用函数KFbxMatrix pMatrix;pMatrix=pNode-EvaluateLocalTransform(KTime pTime); KFbxVector4 pTranslation = pMatrix.GetT(); /平移KFbxVector4 pRotation = pMatrix.GetR(); /旋转KFbxVector4 pScale = pMatrix.GetS(); /缩放1.5 读取蒙皮信息1.5.1 关于蒙皮信息前面我们已经可以读取关节动画的信息,下面读取附着在骨骼上的蒙皮信息。在骨骼动画中,不是把Mesh直接放到世

22、界坐标系中,Mesh只是作为Skin使用的,是依附于骨骼的,真正决定模型在世界坐标系中的位置和朝向的是骨骼。Mesh节点是作为皮肤使用,蒙在骨骼之上。为了让普通的Mesh具有蒙皮的功能,必须添加蒙皮信息,即Skin info。我们知道Mesh是由顶点构成的,建模时这些顶点(就是我们前面说过的控点)是定义在模型自身坐标系的,即相对于Mesh原点的,而骨骼动画中决定模型顶点最终世界坐标的是骨骼,所以要让骨骼决定顶点的世界坐标,这就要将顶点和骨骼联系起来,Skin info正是起了这个作用。顶点的Skin info包含影响该顶点的骨骼数目,这些骨骼作用于该顶点的权重(Skin weight)。1.5

23、.2 Fbx中的蒙皮结构 在Fbx中蒙皮是由mesh节点来表示的,与普通mesh不同,这里的mesh加上了蒙皮信息即Skin info,我们要读取Skin info,首先应了解Fbx中的蒙皮结构。Mesh |-skin 0 |-Cluster 0 Vertex 0, Vertex 1Vertex n1 | |-Cluster 1 Vertex 0, Vertex 1Vertex n2 | |- | |-Cluster n Vertex 0, Vertex 1Vertex n3 |-skin 1 | |- . | |-skin n 从以上结构可以看出,Fbx的mesh中可以包含多重皮肤Skin,

24、但绝大多数情况下,我们只用到第一层皮肤Skin 0。在每层皮肤下一层是骨骼,在这里叫群聚Cluster,即和这层皮肤相关的骨骼有哪些。在每个骨骼下有顶点Vertex,即每一个骨骼影响的顶点,以及对这些顶点的权重都可以在这里得到。下面是获得蒙皮信息的常用代码。/获得pMesh中皮肤的个数,皮肤个数通常为1int lSkinCount=pMesh-GetDeformerCount(KFbxDeformer:eSKIN);/获得pMesh的第0层skin,若是多层皮肤,可用循环将0改为皮肤的索引i,就得到第i层皮肤KFbxSkin* lSkin=(KFbxSkin*)pMesh-GetDeformer(0, KFbxDeformer:eSKIN);/获得lSkin所包含的骨骼数int lClusterCount = lSkin-GetClusterCount();for(int i = 0;i GetControlPointIndicesCount();for (int k = 0; k GetControlPointIndices()k; if (lIndex = lVertexCount) continue; double lWeight = lCluster-GetControlPointWeights()k; if (lWeight = 0.0) continue;

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1