PhysX 3.2中RAW格式文件的解析

在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<nbTextures;i++)
 21     {
 22         RAWTexture data;
 23 
 24         readName(fp, objectName);
 25         data.mName                = objectName;
 26         data.mTransform            = PxTransform::createIdentity();    // PT: texture transform not supported yet
 27         data.mID                = read32(fp);
 28 
 29         RendererColorAlloc* pixels = NULL;
 30         if(read8(fp))
 31         {
 32             data.mWidth            = read32(fp);
 33             data.mHeight        = read32(fp);
 34             data.mHasAlpha        = read8(fp)!=0;
 35             const PxU32 nbPixels = data.mWidth*data.mHeight; 
 36             pixels                = SAMPLE_NEW(RendererColorAlloc)[nbPixels];
 37             data.mPixels        = pixels;
 38             for(PxU32 i=0;i<nbPixels;i++)
 39             {
 40                 pixels[i].r = read8(fp);
 41                 pixels[i].g = read8(fp);
 42                 pixels[i].b = read8(fp);
 43                 if(data.mHasAlpha)
 44                     pixels[i].a = read8(fp);
 45                 else
 46                     pixels[i].a = 0xff;
 47             }
 48         }
 49         else
 50         {
 51             data.mWidth            = 0;
 52             data.mHeight        = 0;
 53             data.mHasAlpha        = false;
 54             data.mPixels        = NULL;
 55         }
 56 
 57         cb.newTexture(data);
 58         DELETEARRAY(pixels);
 59     }
 60 
 61     // Materials
 62     for(PxU32 i=0;i<nbMaterials;i++)
 63     {
 64         RAWMaterial data;
 65         data.mID                = read32(fp);
 66         data.mDiffuseID            = read32(fp);
 67         data.mOpacity            = readFloat(fp);
 68         data.mDoubleSided        = read32(fp)!=0;
 69 
 70         data.mAmbientColor.x    = readFloat(fp);
 71         data.mAmbientColor.y    = readFloat(fp);
 72         data.mAmbientColor.z    = readFloat(fp);
 73 
 74         data.mDiffuseColor.x    = readFloat(fp);
 75         data.mDiffuseColor.y    = readFloat(fp);
 76         data.mDiffuseColor.z    = readFloat(fp);
 77 
 78         data.mSpecularColor.x    = readFloat(fp);
 79         data.mSpecularColor.y    = readFloat(fp);
 80         data.mSpecularColor.z    = readFloat(fp);
 81 
 82         cb.newMaterial(data);
 83     }
 84 
 85     // Meshes   这个nbMeshes是凸包的个数
 86     for(PxU32 i=0;i<nbMeshes;i++)
 87     {
 88         RAWMesh data;
 89 
 90         readName(fp, objectName);
 91         data.mName                    = objectName;
 92         data.mTransform                = readTransform(fp, scale);
 93         //
 94         data.mNbVerts                = read32(fp);
 95         data.mNbFaces                = read32(fp);
 96         const PxU32 hasVertexColors = read32(fp);
 97         const PxU32 hasUVs            = read32(fp);
 98         data.mMaterialID            = read32(fp);
 99 
100         PxVec3Alloc* tmpVerts        = SAMPLE_NEW(PxVec3Alloc)[data.mNbVerts];
101         PxVec3Alloc* tmpNormals        = SAMPLE_NEW(PxVec3Alloc)[data.mNbVerts];
102         PxVec3Alloc* tmpColors        = NULL;
103         PxReal* tmpUVs                = NULL;
104 
105         data.mVerts                    = tmpVerts;
106         data.mVertexNormals            = tmpNormals;
107         data.mVertexColors            = NULL;
108         data.mUVs                    = NULL;
109 
110         readVertices(fp, tmpVerts, data.mNbVerts, scale);
111         readNormals(fp, tmpNormals, data.mNbVerts);
112 
113         if(hasVertexColors)
114         {
115             tmpColors = SAMPLE_NEW(PxVec3Alloc)[data.mNbVerts];
116             data.mVertexColors = tmpColors;
117             readVertexColors(fp, tmpColors, data.mNbVerts);
118         }
119 
120         if(hasUVs)
121         {
122             tmpUVs = (PxReal*)SAMPLE_ALLOC(sizeof(PxReal)*data.mNbVerts*2);
123             data.mUVs = tmpUVs;
124             readUVs(fp, tmpUVs, data.mNbVerts);
125         }
126 
127         PxU32* tmpIndices = (PxU32*)SAMPLE_ALLOC(sizeof(PxU32)*data.mNbFaces*3);
128         data.mIndices = tmpIndices;
129         fread(tmpIndices, 4*3*data.mNbFaces, 1, fp);
130         if(gFlip)
131         {
132             for(PxU32 j=0;j<data.mNbFaces*3;j++)
133             {
134                 Flip(tmpIndices[j]);
135             }
136         }
137 
138         cb.newMesh(data);
139 
140         SAMPLE_FREE(tmpIndices);
141         SAMPLE_FREE(tmpUVs);
142         DELETEARRAY(tmpColors);
143         DELETEARRAY(tmpNormals);
144         DELETEARRAY(tmpVerts);
145     }
146 
147     // Shapes
148     for(PxU32 i=0;i<nbShapes;i++)
149     {
150         RAWShape data;
151 
152         readName(fp, objectName);
153         data.mName        = objectName;
154         data.mTransform = readTransform(fp, scale);
155         //
156         data.mNbVerts    = read32(fp);
157         PxVec3Alloc* tmp = SAMPLE_NEW(PxVec3Alloc)[data.mNbVerts];
158         data.mVerts        = tmp;
159         readVertices(fp, tmp, data.mNbVerts, scale);
160 
161         cb.newShape(data);
162 
163         DELETEARRAY(tmp);
164     }
165 
166     // Helpers
167     for(PxU32 i=0;i<nbHelpers;i++)
168     {
169         RAWHelper data;
170 
171         readName(fp, objectName);
172         data.mName        = objectName;
173         data.mTransform    = readTransform(fp, scale);
174     }
175     return true;
176 }

 

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格式的文件,并非度娘说的和大家所认识的raw格式。而是一种nvidia自己搞的格式,可以看成是类似索引文件,其中包含索引信息(指向存储纹理、网格、形状等的文件),和一些其它的数据(包括各类数据的数目、顶点数据等等。)

题外话:本来打算弄清楚这个raw格式是怎么回事之后,把这个用起来。结果弄完发现是这么个货,要用这个raw格式,就必须用到RawLoader,虽然提供了源文件,但是你以为他是独立的吗?拿过去就能用了?图样图森破!他里面包含了PhysXSample里面的newTexture之类的回调函数啊。最重要的是,这raw格式的东西没几个呀,就车、天空,桥,车就只有一个样式。就算用起来了,到时候你的场景里面所有的车都长一样,你乐意啊?而且这个raw格式的东东,也不知道他们是怎么弄出来的,你想自己弄吧,还不行,上网搜吧,也没有。所以我决定要放弃使用这个东西,我还是回归我的3ds和flt吧,毕竟可以网上搜到大把,只是数据和车辆的结构(主要是轮子与车身)需要自己组织罢了。

——————————分割线—7月25号补充————————————

在继续研究了程序之后,发现这个raw文件包含的东西还真不少,就我关心的Mesh部分的数据来说,它包含了顶点的个数,mesh的个数,每一个顶点的数据,然后还有Transform!(在车轮的Mesh里面,Transform表示了车轮的位置)。Nvidia你弄这个Sample真的是逗我们玩呢。哼!

posted @ 2013-07-15 10:53  清凉一夏o0  阅读(610)  评论(0编辑  收藏  举报