在PhysX 3.2中 ,Sample结合了D3D9来做显示。
在SampleVehicle中,使用了raw格式的文件来存储车辆模型和天空。
最初的时候,我以为这个raw格式就是网上说的那个原生照片格式,但是后来跟进到程序里面发现这个raw格式包含的有更多的内容。
下面从一个函数来说明,这个raw格式的文件是怎么回事。
1 bool loadRAWfile(const char* filename, RAWImportCallback& cb, PxReal scale) 2 { 3 FILE* fp = NULL; 4 physx::fopen_s(&fp, filename, "rb"); 5 if(!fp) 6 return false; 7 8 // General info 从文件中读取的通用信息 9 const PxU32 tag = read32(fp); 10 const PxU32 generalVersion = read32(fp); 11 const PxU32 nbMaterials = read32(fp); 12 const PxU32 nbTextures = read32(fp); 13 const PxU32 nbMeshes = read32(fp); //mesh的部分数 14 const PxU32 nbShapes = read32(fp); 15 const PxU32 nbHelpers = read32(fp); 16 17 char objectName[512]; 18 19 // Textures 20 for(PxU32 i=0;i
1.首先,从 physx::fopen_s(&fp, filename, "rb"); 看出,.raw格式文件是以二进制方式读取的。
这里的filename是 car2.raw,在PhysXSample中提供,大小为136k。
2.这几个read32(fp)分别从文件中读取到了,tag信息、通用版本信息、材质数目、纹理数目、Mesh数目、Shape数目、还有Helper的数目。
// General info 从文件中读取的通用信息 const PxU32 tag = read32(fp); const PxU32 generalVersion = read32(fp); const PxU32 nbMaterials = read32(fp); const PxU32 nbTextures = read32(fp); const PxU32 nbMeshes = read32(fp); //mesh的部分数 const PxU32 nbShapes = read32(fp); const PxU32 nbHelpers = read32(fp);
下面这个函数是在RawLoader.cpp里面定义的,其调用了fread(buffer, elemSize, count , stream),这里用的是fread( data, 4, 1, fb),表示一次从文件中读取4个字节,32位数据。
//从FILE中读32个字节,并返回static PxU32 read32(FILE* fp){ PxU32 data; fread(&data, 4, 1, fp); if(gFlip) Flip(data); return data;}
文件的开头4个字节是RAW!,表示了文件的格式是raw。
接下来4个字节是generalVersion,表示版本号。
接下来4个字节是nbMaterials,表示材质数目。
接下来4个字节是nbTextTures,表示纹理数目。
接下来4个字节是nbMeshes,表示网格数目。
接下来4个字节是nbShapes,表示形状数目。
接下来4个字节是nbHelpers,表示帮助信息数目。
- 接下来文件中存储的是纹理信息。
根据从文件头中读取的纹理数目,来读取纹理数据:包含储存纹理的文件名(长度不定),纹理的ID(4个字节)。还有可能包含的纹理的宽度、高度、alpha值,以及RGB值等。
最后根据这些纹理data,来NewTexture。
- 接下来文件中存储的是材质信息。
根据从文件头中读取的材质数目,来读取材质数据:包括材质ID(4个字节),漫反射ID(4个字节),不透明度(浮点类型,4个字节),是否双面(bool类型,在文件中是2个字节),之后就是环境光、漫反射光和镜面反射光(高光)的三个颜色分量的值,各占4个字节,共(3*3*4)=9个字节。
最后根据这些材质data,来NewMaterial。
- 接下来文件中存储的是网格(Mesh)数据。
根据从文件头中读取的网格数目,来读取网格数据:包含储存网格的文件名(长度不定),网格的Transform(7*4个字节),顶点个数(4个字节),面片个数(4个字节),是否包含顶点颜色(bool型,4个字节),是否包含UV坐标(bool型,4个字节),材质的ID(4个字节),然后根据从之前文件中读取的顶点数目,来读取相应数目的顶点和法线。
下面根据是否包含顶点颜色和UV的情况,读取文件中存储的相应个数的顶点颜色和UV(这两个不一定有)。
然后是读取 (4*3*data.mNbFaces)个字节数的数据,这些包含的就是网格的顶点数据。
最后根据这些data,来NewMesh。
- 接下来文件中存储的是形状数据。
根据从文件头中读取的形状数目,来读取形状数据:包含存储形状的文件名(长度不定),形状的Transform(7*4个字节),然后是顶点的数目(4个字节),之后是根据顶点的数目,来读取(顶点数目*4)个字节的顶点数据。
最后根据这些data,来NewShape。
- 接下来文件中存储的是帮助信息。
根据从文件头中读取的帮助信息数目,来读取帮助信息:包含存储帮助信息的文件名(长度不定),帮助信息的Transform(7*4个字节)。然后就没有了,帮助信息比较简单。
Conclusion:这个RAW格式的文件,并非度娘说的和大家所认识的。而是一种nvidia自己搞的格式,可以看成是类似索引文件,其中包含索引信息(指向存储纹理、网格、形状等的文件),和一些其它的数据(包括各类数据的数目、顶点数据等等。)
题外话:本来打算弄清楚这个raw格式是怎么回事之后,把这个用起来。结果弄完发现是这么个货,要用这个raw格式,就必须用到RawLoader,虽然提供了源文件,但是你以为他是独立的吗?拿过去就能用了?图样图森破!他里面包含了PhysXSample里面的newTexture之类的回调函数啊。最重要的是,这raw格式的东西没几个呀,就车、天空,桥,车就只有一个样式。就算用起来了,到时候你的场景里面所有的车都长一样,你乐意啊?而且这个raw格式的东东,也不知道他们是怎么弄出来的,你想自己弄吧,还不行,上网搜吧,也没有。所以我决定要放弃使用这个东西,我还是回归我的3ds和flt吧,毕竟可以网上搜到大把,只是数据和车辆的结构(主要是轮子与车身)需要自己组织罢了。
——————————分割线—7月25号补充————————————
在继续研究了程序之后,发现这个raw文件包含的东西还真不少,就我关心的Mesh部分的数据来说,它包含了顶点的个数,mesh的个数,每一个顶点的数据,然后还有Transform!(在车轮的Mesh里面,Transform表示了车轮的位置)。Nvidia你弄这个Sample真的是逗我们玩呢。哼!