Ogre的模型数据(模型顶点数,每个顶点的3D坐标值等等)保存在.mesh文件中,mesh文件的结构如下(版本号:MeshSerializer_v1.8):
1 enum MeshChunkID { 2 M_HEADER = 0x1000, 3 // char* version : Version number check 4 M_MESH = 0x3000, 5 // bool skeletallyAnimated // important flag which affects h/w buffer policies 6 // Optional M_GEOMETRY chunk 7 M_SUBMESH = 0x4000, 8 // char* materialName 9 // bool useSharedVertices 10 // unsigned int indexCount 11 // bool indexes32Bit 12 // unsigned int* faceVertexIndices (indexCount) 13 // OR 14 // unsigned short* faceVertexIndices (indexCount) 15 // M_GEOMETRY chunk (Optional: present only if useSharedVertices = false) 16 M_SUBMESH_OPERATION = 0x4010, // optional, trilist assumed if missing 17 // unsigned short operationType 18 M_SUBMESH_BONE_ASSIGNMENT = 0x4100, 19 // Optional bone weights (repeating section) 20 // unsigned int vertexIndex; 21 // unsigned short boneIndex; 22 // float weight; 23 // Optional chunk that matches a texture name to an alias 24 // a texture alias is sent to the submesh material to use this texture name 25 // instead of the one in the texture unit with a matching alias name 26 M_SUBMESH_TEXTURE_ALIAS = 0x4200, // Repeating section 27 // char* aliasName; 28 // char* textureName; 29 30 M_GEOMETRY = 0x5000, // NB this chunk is embedded within M_MESH and M_SUBMESH 31 // unsigned int vertexCount 32 M_GEOMETRY_VERTEX_DECLARATION = 0x5100, 33 M_GEOMETRY_VERTEX_ELEMENT = 0x5110, // Repeating section 34 // unsigned short source; // buffer bind source 35 // unsigned short type; // VertexElementType 36 // unsigned short semantic; // VertexElementSemantic 37 // unsigned short offset; // start offset in buffer in bytes 38 // unsigned short index; // index of the semantic (for colours and texture coords) 39 M_GEOMETRY_VERTEX_BUFFER = 0x5200, // Repeating section 40 // unsigned short bindIndex; // Index to bind this buffer to 41 // unsigned short vertexSize; // Per-vertex size, must agree with declaration at this index 42 M_GEOMETRY_VERTEX_BUFFER_DATA = 0x5210, 43 // raw buffer data 44 M_MESH_SKELETON_LINK = 0x6000, 45 // Optional link to skeleton 46 // char* skeletonName : name of .skeleton to use 47 M_MESH_BONE_ASSIGNMENT = 0x7000, 48 // Optional bone weights (repeating section) 49 // unsigned int vertexIndex; 50 // unsigned short boneIndex; 51 // float weight; 52 M_MESH_LOD = 0x8000, 53 // Optional LOD information 54 // string strategyName; 55 // unsigned short numLevels; 56 // bool manual; (true for manual alternate meshes, false for generated) 57 M_MESH_LOD_USAGE = 0x8100, 58 // Repeating section, ordered in increasing depth 59 // NB LOD 0 (full detail from 0 depth) is omitted 60 // LOD value - this is a distance, a pixel count etc, based on strategy 61 // float lodValue; 62 M_MESH_LOD_MANUAL = 0x8110, 63 // Required if M_MESH_LOD section manual = true 64 // String manualMeshName; 65 M_MESH_LOD_GENERATED = 0x8120, 66 // Required if M_MESH_LOD section manual = false 67 // Repeating section (1 per submesh) 68 // unsigned int indexCount; 69 // bool indexes32Bit 70 // unsigned short* faceIndexes; (indexCount) 71 // OR 72 // unsigned int* faceIndexes; (indexCount) 73 M_MESH_BOUNDS = 0x9000, 74 // float minx, miny, minz 75 // float maxx, maxy, maxz 76 // float radius 77 78 // Added By DrEvil 79 // optional chunk that contains a table of submesh indexes and the names of 80 // the sub-meshes. 81 M_SUBMESH_NAME_TABLE = 0xA000, 82 // Subchunks of the name table. Each chunk contains an index & string 83 M_SUBMESH_NAME_TABLE_ELEMENT = 0xA100, 84 // short index 85 // char* name 86 87 // Optional chunk which stores precomputed edge data 88 M_EDGE_LISTS = 0xB000, 89 // Each LOD has a separate edge list 90 M_EDGE_LIST_LOD = 0xB100, 91 // unsigned short lodIndex 92 // bool isManual // If manual, no edge data here, loaded from manual mesh 93 // bool isClosed 94 // unsigned long numTriangles 95 // unsigned long numEdgeGroups 96 // Triangle* triangleList 97 // unsigned long indexSet 98 // unsigned long vertexSet 99 // unsigned long vertIndex[3] 100 // unsigned long sharedVertIndex[3] 101 // float normal[4] 102 103 M_EDGE_GROUP = 0xB110, 104 // unsigned long vertexSet 105 // unsigned long triStart 106 // unsigned long triCount 107 // unsigned long numEdges 108 // Edge* edgeList 109 // unsigned long triIndex[2] 110 // unsigned long vertIndex[2] 111 // unsigned long sharedVertIndex[2] 112 // bool degenerate 113 114 // Optional poses section, referred to by pose keyframes 115 M_POSES = 0xC000, 116 M_POSE = 0xC100, 117 // char* name (may be blank) 118 // unsigned short target // 0 for shared geometry, 119 // 1+ for submesh index + 1 120 // bool includesNormals [1.8+] 121 M_POSE_VERTEX = 0xC111, 122 // unsigned long vertexIndex 123 // float xoffset, yoffset, zoffset 124 // float xnormal, ynormal, znormal (optional, 1.8+) 125 // Optional vertex animation chunk 126 M_ANIMATIONS = 0xD000, 127 M_ANIMATION = 0xD100, 128 // char* name 129 // float length 130 M_ANIMATION_BASEINFO = 0xD105, 131 // [Optional] base keyframe information (pose animation only) 132 // char* baseAnimationName (blank for self) 133 // float baseKeyFrameTime 134 135 M_ANIMATION_TRACK = 0xD110, 136 // unsigned short type // 1 == morph, 2 == pose 137 // unsigned short target // 0 for shared geometry, 138 // 1+ for submesh index + 1 139 M_ANIMATION_MORPH_KEYFRAME = 0xD111, 140 // float time 141 // bool includesNormals [1.8+] 142 // float x,y,z // repeat by number of vertices in original geometry 143 M_ANIMATION_POSE_KEYFRAME = 0xD112, 144 // float time 145 M_ANIMATION_POSE_REF = 0xD113, // repeat for number of referenced poses 146 // unsigned short poseIndex 147 // float influence 148 149 // Optional submesh extreme vertex list chink 150 M_TABLE_EXTREMES = 0xE000, 151 // unsigned short submesh_index; 152 // float extremes [n_extremes][3]; 153 154 /* Version 1.2 of the .mesh format (deprecated) 155 enum MeshChunkID { 156 M_HEADER = 0x1000, 157 // char* version : Version number check 158 M_MESH = 0x3000, 159 // bool skeletallyAnimated // important flag which affects h/w buffer policies 160 // Optional M_GEOMETRY chunk 161 M_SUBMESH = 0x4000, 162 // char* materialName 163 // bool useSharedVertices 164 // unsigned int indexCount 165 // bool indexes32Bit 166 // unsigned int* faceVertexIndices (indexCount) 167 // OR 168 // unsigned short* faceVertexIndices (indexCount) 169 // M_GEOMETRY chunk (Optional: present only if useSharedVertices = false) 170 M_SUBMESH_OPERATION = 0x4010, // optional, trilist assumed if missing 171 // unsigned short operationType 172 M_SUBMESH_BONE_ASSIGNMENT = 0x4100, 173 // Optional bone weights (repeating section) 174 // unsigned int vertexIndex; 175 // unsigned short boneIndex; 176 // float weight; 177 M_GEOMETRY = 0x5000, // NB this chunk is embedded within M_MESH and M_SUBMESH 178 */ 179 // unsigned int vertexCount 180 // float* pVertices (x, y, z order x numVertices) 181 M_GEOMETRY_NORMALS = 0x5100, //(Optional) 182 // float* pNormals (x, y, z order x numVertices) 183 M_GEOMETRY_COLOURS = 0x5200, //(Optional) 184 // unsigned long* pColours (RGBA 8888 format x numVertices) 185 M_GEOMETRY_TEXCOORDS = 0x5300 //(Optional, REPEATABLE, each one adds an extra set) 186 // unsigned short dimensions (1 for 1D, 2 for 2D, 3 for 3D) 187 // float* pTexCoords (u [v] [w] order, dimensions x numVertices) 188 /* 189 M_MESH_SKELETON_LINK = 0x6000, 190 // Optional link to skeleton 191 // char* skeletonName : name of .skeleton to use 192 M_MESH_BONE_ASSIGNMENT = 0x7000, 193 // Optional bone weights (repeating section) 194 // unsigned int vertexIndex; 195 // unsigned short boneIndex; 196 // float weight; 197 M_MESH_LOD = 0x8000, 198 // Optional LOD information 199 // unsigned short numLevels; 200 // bool manual; (true for manual alternate meshes, false for generated) 201 M_MESH_LOD_USAGE = 0x8100, 202 // Repeating section, ordered in increasing depth 203 // NB LOD 0 (full detail from 0 depth) is omitted 204 // float fromSquaredDepth; 205 M_MESH_LOD_MANUAL = 0x8110, 206 // Required if M_MESH_LOD section manual = true 207 // String manualMeshName; 208 M_MESH_LOD_GENERATED = 0x8120, 209 // Required if M_MESH_LOD section manual = false 210 // Repeating section (1 per submesh) 211 // unsigned int indexCount; 212 // bool indexes32Bit 213 // unsigned short* faceIndexes; (indexCount) 214 // OR 215 // unsigned int* faceIndexes; (indexCount) 216 M_MESH_BOUNDS = 0x9000 217 // float minx, miny, minz 218 // float maxx, maxy, maxz 219 // float radius 220 221 // Added By DrEvil 222 // optional chunk that contains a table of submesh indexes and the names of 223 // the sub-meshes. 224 M_SUBMESH_NAME_TABLE, 225 // Subchunks of the name table. Each chunk contains an index & string 226 M_SUBMESH_NAME_TABLE_ELEMENT, 227 // short index 228 // char* name 229 230 */ 231 };
与一般的3D文件格式类似,Ogre的mesh文件数据结构为树。构成mesh文件的基本数据单位是chunk,每个chunk由三部分组成:
1 unsigned short CHUNK_ID : one of the following chunk ids identifying the chunk 2 unsigned long LENGTH : length of the chunk in bytes, including this header 3 void* DATA : the data, which may contain other sub-chunks (various data types)
CHUNK_ID用来标示各个chunk,而各chunk的实际数据则保存在相应的DATA域中。各chunk在id和数据域之外还有一个长度域(长度域也可以看作是数据域中的一项),用来描述本chunk的数据字节数。如果自定义的mesh文件结构比较复杂,嵌套层比较深,有了长度域就可以在文件读取过程中,帮助程序快速定位到指定的数据段;chunk的长度域还有一个作用,就是可以在文件读取过程中进行数据校验。
另外,随着Ogre引擎的不断改进,mesh文件衍生出多个版本,不同版本的文件结构是有所变化的,这一点从上面第一段代码(154-178行与2-30行的对比)中可以反应出来。mesh文件数据用二进制格式保存,所有版本的mesh文件开头两个字节都以0x1000作为文件标识,接下来的21-22个字节是一个字符串,用来表示mesh文件的版本号。在对文件数据进行读取时,Ogre会根据版本号的不同选择相应的文件串行器(MeshSerializer),对mesh文件数据进行读取。