1/*
2Open Asset Import Library (assimp)
3----------------------------------------------------------------------
4
5Copyright (c) 2006-2017, assimp team
6
7All rights reserved.
8
9Redistribution and use of this software in source and binary forms,
10with or without modification, are permitted provided that the
11following conditions are met:
12
13* Redistributions of source code must retain the above
14 copyright notice, this list of conditions and the
15 following disclaimer.
16
17* Redistributions in binary form must reproduce the above
18 copyright notice, this list of conditions and the
19 following disclaimer in the documentation and/or other
20 materials provided with the distribution.
21
22* Neither the name of the assimp team, nor the names of its
23 contributors may be used to endorse or promote products
24 derived from this software without specific prior
25 written permission of the assimp team.
26
27THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
39----------------------------------------------------------------------
40*/
41
42#ifndef AI_OGREBINARYSERIALIZER_H_INC
43#define AI_OGREBINARYSERIALIZER_H_INC
44
45#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
46
47#include "OgreStructs.h"
48#include "StreamReader.h"
49
50namespace Assimp
51{
52namespace Ogre
53{
54
55typedef Assimp::StreamReaderLE MemoryStreamReader;
56typedef std::shared_ptr<MemoryStreamReader> MemoryStreamReaderPtr;
57
58class OgreBinarySerializer
59{
60public:
61 /// Imports mesh and returns the result.
62 /** @note Fatal unrecoverable errors will throw a DeadlyImportError. */
63 static Mesh *ImportMesh(MemoryStreamReader *reader);
64
65 /// Imports skeleton to @c mesh into Mesh::skeleton.
66 /** If mesh does not have a skeleton reference or the skeleton file
67 cannot be found it is not a fatal DeadlyImportError.
68 @return If skeleton import was successful. */
69 static bool ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh);
70 static bool ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *mesh);
71
72private:
73 enum AssetMode
74 {
75 AM_Mesh,
76 AM_Skeleton
77 };
78
79 OgreBinarySerializer(MemoryStreamReader *reader, AssetMode mode) :
80 m_currentLen(0),
81 m_reader(reader),
82 assetMode(mode)
83 {
84 }
85
86 static MemoryStreamReaderPtr OpenReader(Assimp::IOSystem *pIOHandler, const std::string &filename);
87
88 // Header
89
90 uint16_t ReadHeader(bool readLen = true);
91 void RollbackHeader();
92
93 // Mesh
94
95 void ReadMesh(Mesh *mesh);
96 void ReadMeshLodInfo(Mesh *mesh);
97 void ReadMeshSkeletonLink(Mesh *mesh);
98 void ReadMeshBounds(Mesh *mesh);
99 void ReadMeshExtremes(Mesh *mesh);
100
101 void ReadSubMesh(Mesh *mesh);
102 void ReadSubMeshNames(Mesh *mesh);
103 void ReadSubMeshOperation(SubMesh *submesh);
104 void ReadSubMeshTextureAlias(SubMesh *submesh);
105
106 void ReadBoneAssignment(VertexData *dest);
107
108 void ReadGeometry(VertexData *dest);
109 void ReadGeometryVertexDeclaration(VertexData *dest);
110 void ReadGeometryVertexElement(VertexData *dest);
111 void ReadGeometryVertexBuffer(VertexData *dest);
112
113 void ReadEdgeList(Mesh *mesh);
114 void ReadPoses(Mesh *mesh);
115 void ReadPoseVertices(Pose *pose);
116
117 void ReadAnimations(Mesh *mesh);
118 void ReadAnimation(Animation *anim);
119 void ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *track);
120
121 void NormalizeBoneWeights(VertexData *vertexData) const;
122
123 // Skeleton
124
125 void ReadSkeleton(Skeleton *skeleton);
126
127 void ReadBone(Skeleton *skeleton);
128 void ReadBoneParent(Skeleton *skeleton);
129
130 void ReadSkeletonAnimation(Skeleton *skeleton);
131 void ReadSkeletonAnimationTrack(Skeleton *skeleton, Animation *dest);
132 void ReadSkeletonAnimationKeyFrame(VertexAnimationTrack *dest);
133 void ReadSkeletonAnimationLink(Skeleton *skeleton);
134
135 // Reader utils
136 bool AtEnd() const;
137
138 template<typename T>
139 inline T Read();
140
141 void ReadBytes(char *dest, size_t numBytes);
142 void ReadBytes(uint8_t *dest, size_t numBytes);
143 void ReadBytes(void *dest, size_t numBytes);
144 uint8_t *ReadBytes(size_t numBytes);
145
146 void ReadVector(aiVector3D &vec);
147 void ReadQuaternion(aiQuaternion &quat);
148
149 std::string ReadString(size_t len);
150 std::string ReadLine();
151
152 void SkipBytes(size_t numBytes);
153
154 uint32_t m_currentLen;
155 MemoryStreamReader *m_reader;
156
157 AssetMode assetMode;
158};
159
160enum MeshChunkId
161{
162 M_HEADER = 0x1000,
163 // char* version : Version number check
164 M_MESH = 0x3000,
165 // bool skeletallyAnimated // important flag which affects h/w buffer policies
166 // Optional M_GEOMETRY chunk
167 M_SUBMESH = 0x4000,
168 // char* materialName
169 // bool useSharedVertices
170 // unsigned int indexCount
171 // bool indexes32Bit
172 // unsigned int* faceVertexIndices (indexCount)
173 // OR
174 // unsigned short* faceVertexIndices (indexCount)
175 // M_GEOMETRY chunk (Optional: present only if useSharedVertices = false)
176 M_SUBMESH_OPERATION = 0x4010, // optional, trilist assumed if missing
177 // unsigned short operationType
178 M_SUBMESH_BONE_ASSIGNMENT = 0x4100,
179 // Optional bone weights (repeating section)
180 // unsigned int vertexIndex;
181 // unsigned short boneIndex;
182 // float weight;
183 // Optional chunk that matches a texture name to an alias
184 // a texture alias is sent to the submesh material to use this texture name
185 // instead of the one in the texture unit with a matching alias name
186 M_SUBMESH_TEXTURE_ALIAS = 0x4200, // Repeating section
187 // char* aliasName;
188 // char* textureName;
189
190 M_GEOMETRY = 0x5000, // NB this chunk is embedded within M_MESH and M_SUBMESH
191 // unsigned int vertexCount
192 M_GEOMETRY_VERTEX_DECLARATION = 0x5100,
193 M_GEOMETRY_VERTEX_ELEMENT = 0x5110, // Repeating section
194 // unsigned short source; // buffer bind source
195 // unsigned short type; // VertexElementType
196 // unsigned short semantic; // VertexElementSemantic
197 // unsigned short offset; // start offset in buffer in bytes
198 // unsigned short index; // index of the semantic (for colours and texture coords)
199 M_GEOMETRY_VERTEX_BUFFER = 0x5200, // Repeating section
200 // unsigned short bindIndex; // Index to bind this buffer to
201 // unsigned short vertexSize; // Per-vertex size, must agree with declaration at this index
202 M_GEOMETRY_VERTEX_BUFFER_DATA = 0x5210,
203 // raw buffer data
204 M_MESH_SKELETON_LINK = 0x6000,
205 // Optional link to skeleton
206 // char* skeletonName : name of .skeleton to use
207 M_MESH_BONE_ASSIGNMENT = 0x7000,
208 // Optional bone weights (repeating section)
209 // unsigned int vertexIndex;
210 // unsigned short boneIndex;
211 // float weight;
212 M_MESH_LOD = 0x8000,
213 // Optional LOD information
214 // string strategyName;
215 // unsigned short numLevels;
216 // bool manual; (true for manual alternate meshes, false for generated)
217 M_MESH_LOD_USAGE = 0x8100,
218 // Repeating section, ordered in increasing depth
219 // NB LOD 0 (full detail from 0 depth) is omitted
220 // LOD value - this is a distance, a pixel count etc, based on strategy
221 // float lodValue;
222 M_MESH_LOD_MANUAL = 0x8110,
223 // Required if M_MESH_LOD section manual = true
224 // String manualMeshName;
225 M_MESH_LOD_GENERATED = 0x8120,
226 // Required if M_MESH_LOD section manual = false
227 // Repeating section (1 per submesh)
228 // unsigned int indexCount;
229 // bool indexes32Bit
230 // unsigned short* faceIndexes; (indexCount)
231 // OR
232 // unsigned int* faceIndexes; (indexCount)
233 M_MESH_BOUNDS = 0x9000,
234 // float minx, miny, minz
235 // float maxx, maxy, maxz
236 // float radius
237
238 // Added By DrEvil
239 // optional chunk that contains a table of submesh indexes and the names of
240 // the sub-meshes.
241 M_SUBMESH_NAME_TABLE = 0xA000,
242 // Subchunks of the name table. Each chunk contains an index & string
243 M_SUBMESH_NAME_TABLE_ELEMENT = 0xA100,
244 // short index
245 // char* name
246 // Optional chunk which stores precomputed edge data
247 M_EDGE_LISTS = 0xB000,
248 // Each LOD has a separate edge list
249 M_EDGE_LIST_LOD = 0xB100,
250 // unsigned short lodIndex
251 // bool isManual // If manual, no edge data here, loaded from manual mesh
252 // bool isClosed
253 // unsigned long numTriangles
254 // unsigned long numEdgeGroups
255 // Triangle* triangleList
256 // unsigned long indexSet
257 // unsigned long vertexSet
258 // unsigned long vertIndex[3]
259 // unsigned long sharedVertIndex[3]
260 // float normal[4]
261
262 M_EDGE_GROUP = 0xB110,
263 // unsigned long vertexSet
264 // unsigned long triStart
265 // unsigned long triCount
266 // unsigned long numEdges
267 // Edge* edgeList
268 // unsigned long triIndex[2]
269 // unsigned long vertIndex[2]
270 // unsigned long sharedVertIndex[2]
271 // bool degenerate
272 // Optional poses section, referred to by pose keyframes
273 M_POSES = 0xC000,
274 M_POSE = 0xC100,
275 // char* name (may be blank)
276 // unsigned short target // 0 for shared geometry,
277 // 1+ for submesh index + 1
278 // bool includesNormals [1.8+]
279 M_POSE_VERTEX = 0xC111,
280 // unsigned long vertexIndex
281 // float xoffset, yoffset, zoffset
282 // float xnormal, ynormal, znormal (optional, 1.8+)
283 // Optional vertex animation chunk
284 M_ANIMATIONS = 0xD000,
285 M_ANIMATION = 0xD100,
286 // char* name
287 // float length
288 M_ANIMATION_BASEINFO = 0xD105,
289 // [Optional] base keyframe information (pose animation only)
290 // char* baseAnimationName (blank for self)
291 // float baseKeyFrameTime
292 M_ANIMATION_TRACK = 0xD110,
293 // unsigned short type // 1 == morph, 2 == pose
294 // unsigned short target // 0 for shared geometry,
295 // 1+ for submesh index + 1
296 M_ANIMATION_MORPH_KEYFRAME = 0xD111,
297 // float time
298 // bool includesNormals [1.8+]
299 // float x,y,z // repeat by number of vertices in original geometry
300 M_ANIMATION_POSE_KEYFRAME = 0xD112,
301 // float time
302 M_ANIMATION_POSE_REF = 0xD113, // repeat for number of referenced poses
303 // unsigned short poseIndex
304 // float influence
305 // Optional submesh extreme vertex list chink
306 M_TABLE_EXTREMES = 0xE000
307 // unsigned short submesh_index;
308 // float extremes [n_extremes][3];
309};
310
311/*
312static std::string MeshHeaderToString(MeshChunkId id)
313{
314 switch(id)
315 {
316 case M_HEADER: return "HEADER";
317 case M_MESH: return "MESH";
318 case M_SUBMESH: return "SUBMESH";
319 case M_SUBMESH_OPERATION: return "SUBMESH_OPERATION";
320 case M_SUBMESH_BONE_ASSIGNMENT: return "SUBMESH_BONE_ASSIGNMENT";
321 case M_SUBMESH_TEXTURE_ALIAS: return "SUBMESH_TEXTURE_ALIAS";
322 case M_GEOMETRY: return "GEOMETRY";
323 case M_GEOMETRY_VERTEX_DECLARATION: return "GEOMETRY_VERTEX_DECLARATION";
324 case M_GEOMETRY_VERTEX_ELEMENT: return "GEOMETRY_VERTEX_ELEMENT";
325 case M_GEOMETRY_VERTEX_BUFFER: return "GEOMETRY_VERTEX_BUFFER";
326 case M_GEOMETRY_VERTEX_BUFFER_DATA: return "GEOMETRY_VERTEX_BUFFER_DATA";
327 case M_MESH_SKELETON_LINK: return "MESH_SKELETON_LINK";
328 case M_MESH_BONE_ASSIGNMENT: return "MESH_BONE_ASSIGNMENT";
329 case M_MESH_LOD: return "MESH_LOD";
330 case M_MESH_LOD_USAGE: return "MESH_LOD_USAGE";
331 case M_MESH_LOD_MANUAL: return "MESH_LOD_MANUAL";
332 case M_MESH_LOD_GENERATED: return "MESH_LOD_GENERATED";
333 case M_MESH_BOUNDS: return "MESH_BOUNDS";
334 case M_SUBMESH_NAME_TABLE: return "SUBMESH_NAME_TABLE";
335 case M_SUBMESH_NAME_TABLE_ELEMENT: return "SUBMESH_NAME_TABLE_ELEMENT";
336 case M_EDGE_LISTS: return "EDGE_LISTS";
337 case M_EDGE_LIST_LOD: return "EDGE_LIST_LOD";
338 case M_EDGE_GROUP: return "EDGE_GROUP";
339 case M_POSES: return "POSES";
340 case M_POSE: return "POSE";
341 case M_POSE_VERTEX: return "POSE_VERTEX";
342 case M_ANIMATIONS: return "ANIMATIONS";
343 case M_ANIMATION: return "ANIMATION";
344 case M_ANIMATION_BASEINFO: return "ANIMATION_BASEINFO";
345 case M_ANIMATION_TRACK: return "ANIMATION_TRACK";
346 case M_ANIMATION_MORPH_KEYFRAME: return "ANIMATION_MORPH_KEYFRAME";
347 case M_ANIMATION_POSE_KEYFRAME: return "ANIMATION_POSE_KEYFRAME";
348 case M_ANIMATION_POSE_REF: return "ANIMATION_POSE_REF";
349 case M_TABLE_EXTREMES: return "TABLE_EXTREMES";
350 }
351 return "Unknown_MeshChunkId";
352}
353*/
354
355enum SkeletonChunkId
356{
357 SKELETON_HEADER = 0x1000,
358 // char* version : Version number check
359 SKELETON_BLENDMODE = 0x1010, // optional
360 // unsigned short blendmode : SkeletonAnimationBlendMode
361 SKELETON_BONE = 0x2000,
362 // Repeating section defining each bone in the system.
363 // Bones are assigned indexes automatically based on their order of declaration
364 // starting with 0.
365 // char* name : name of the bone
366 // unsigned short handle : handle of the bone, should be contiguous & start at 0
367 // Vector3 position : position of this bone relative to parent
368 // Quaternion orientation : orientation of this bone relative to parent
369 // Vector3 scale : scale of this bone relative to parent
370 SKELETON_BONE_PARENT = 0x3000,
371 // Record of the parent of a single bone, used to build the node tree
372 // Repeating section, listed in Bone Index order, one per Bone
373 // unsigned short handle : child bone
374 // unsigned short parentHandle : parent bone
375 SKELETON_ANIMATION = 0x4000,
376 // A single animation for this skeleton
377 // char* name : Name of the animation
378 // float length : Length of the animation in seconds
379 SKELETON_ANIMATION_BASEINFO = 0x4010,
380 // [Optional] base keyframe information
381 // char* baseAnimationName (blank for self)
382 // float baseKeyFrameTime
383 SKELETON_ANIMATION_TRACK = 0x4100,
384 // A single animation track (relates to a single bone)
385 // Repeating section (within SKELETON_ANIMATION)
386 // unsigned short boneIndex : Index of bone to apply to
387 SKELETON_ANIMATION_TRACK_KEYFRAME = 0x4110,
388 // A single keyframe within the track
389 // Repeating section
390 // float time : The time position (seconds)
391 // Quaternion rotate : Rotation to apply at this keyframe
392 // Vector3 translate : Translation to apply at this keyframe
393 // Vector3 scale : Scale to apply at this keyframe
394 SKELETON_ANIMATION_LINK = 0x5000
395 // Link to another skeleton, to re-use its animations
396 // char* skeletonName : name of skeleton to get animations from
397 // float scale : scale to apply to trans/scale keys
398};
399
400/*
401static std::string SkeletonHeaderToString(SkeletonChunkId id)
402{
403 switch(id)
404 {
405 case SKELETON_HEADER: return "HEADER";
406 case SKELETON_BLENDMODE: return "BLENDMODE";
407 case SKELETON_BONE: return "BONE";
408 case SKELETON_BONE_PARENT: return "BONE_PARENT";
409 case SKELETON_ANIMATION: return "ANIMATION";
410 case SKELETON_ANIMATION_BASEINFO: return "ANIMATION_BASEINFO";
411 case SKELETON_ANIMATION_TRACK: return "ANIMATION_TRACK";
412 case SKELETON_ANIMATION_TRACK_KEYFRAME: return "ANIMATION_TRACK_KEYFRAME";
413 case SKELETON_ANIMATION_LINK: return "ANIMATION_LINK";
414 }
415 return "Unknown_SkeletonChunkId";
416}
417*/
418} // Ogre
419} // Assimp
420
421#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
422#endif // AI_OGREBINARYSERIALIZER_H_INC
423