OpenClonk
StdMeshLoaderBinaryChunks.h
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2010-2016, The OpenClonk Team and contributors
5  *
6  * Distributed under the terms of the ISC license; see accompanying file
7  * "COPYING" for details.
8  *
9  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
10  * See accompanying file "TRADEMARK" for details.
11  *
12  * To redistribute this file separately, substitute the full license texts
13  * for the above references.
14  */
15 
16 #ifndef INC_StdMeshLoaderChunks
17 #define INC_StdMeshLoaderChunks
18 
19 #include "lib/StdMesh.h"
21 
22 // ==== Ogre file format ====
23 // The Ogre file format is a chunked format similar to PNG.
24 // Each chunk except for the file header (type 0x1000) has the following format:
25 // uint32_t chunk_type, values dependent on file type (mesh or skeleton)
26 // uint32_t chunk_length, in bytes; includes the size of the header
27 // uint8_t data[]
28 // The file header omits the length field.
29 // Ogre files can be stored in either big-endian or little-endian byte order. The
30 // byte order is determined by the first two bytes in the file, which must always
31 // be the chunk type of the file header (0x1000). If the bytes are 0x00 0x10, the
32 // file is assumed to be little-endian, if they are 0x10 0x00, the file is big-
33 // endian. If any other bytes are encountered, the file is invalid.
34 // This implementation only reads files stored in the platform's native byte order.
35 //
36 // ==== Data types ====
37 // Most of the numeric data is stored directly in binary as a memory representation.
38 // Strings are stored without a leading length field, and terminated by a 0x0A byte.
39 // Boolean fields are stored as a single byte, which is 0x00 for false or anything
40 // else for true.
41 //
42 // ==== Mesh chunks ====
43 // Unless specified, this section will only describe the data part of each chunk.
44 // Any values that are in parentheses are not available in this implementation.
45 //
46 // Type 0x1000: File Header
47 // string version
48 // Depending on the version, different features are enabled or disabled while
49 // loading the file.
50 // This implementation does not support fallback to different versions of the
51 // file format.
52 // This chunk does not contain a length field; the type id is directly followed
53 // by the version string.
54 // The file header must be immediately followed by a 0x3000 Mesh Data chunk.
55 // ----------
56 // Type 0x3000: Mesh Data
57 // bool skeletal_animation
58 // This field is only used by Ogre to optimize rendering. Set if the mesh has
59 // animation data associated with it.
60 // Allowed subchunks:
61 // 0x4000 Submesh Data
62 // 0x5000 Geometry Data (may occur at most once)
63 // 0x6000 Skeleton Link (may occur at most once)
64 // 0x7000 Mesh Bone Assignments
65 // (0x8000 Precomputed Level of Detail Data)
66 // 0x9000 Mesh Boundaries
67 // (0xA000 Submesh Name Table)
68 // (0xB000 Edge List)
69 // (0xC000 Animation Poses)
70 // (0xD000 Animation List)
71 // (0xE000 Table of Extremes)
72 // ----------
73 // Type 0x4000: Submesh data
74 // string material
75 // The name of a material to be used for this submesh. Must be loaded externally.
76 // bool vertices_shared
77 // If set, the submesh uses the geometry data of its parent mesh. In this case, the
78 // submesh may not contain its own 0x5000 Geometry Data chunk.
79 // uint32_t index_count
80 // The number of vertex indices used by this submesh.
81 // bool indices_are_32_bit
82 // If set, each vertex index is 32 bits wide. If unset, each vertex index is 16 bits
83 // wide.
84 // uint16_t/uint32_t indices[index_count]
85 // A list of vertex indices used by this submesh.
86 // Allowed subchunks:
87 // 0x5000 Geometry Data (only if vertices_shared == false)
88 // 0x4010 Submesh Operation
89 // 0x4100 Submesh Bone Assignments
90 // (0x4200 Submesh Texture Replacement)
91 // If no 0x4010 Submesh Operation chunk is present, the submesh uses SO_TriList.
92 // ----------
93 // Type 0x4010: Submesh Operation
94 // uint16_t operation
95 // This value specifies how the indices of a submesh are to be interpreted.
96 // Acceptable values:
97 // (0x01 SO_PointList)
98 // Each index defines a single point.
99 // (0x02 SO_LineList)
100 // Each pair (2k, 2k+1) of indices defines a line.
101 // (0x03 SO_LineStrip)
102 // Each pair (k, k+1) of indices defines a line.
103 // 0x04 SO_TriList
104 // Each triplet (3k, 3k+1, 3k+2) of indices defines a triangle.
105 // (0x05 SO_TriStrip)
106 // For odd k, (k, k+1, k+2) define a triangle. For even k, (k+1, k, k+2) define a triangle.
107 // (0x06 SO_TriFan)
108 // Indices (1, k+1, k+2) define a triangle.
109 // ----------
110 // Type 0x4100: Submesh Bone Assignments
111 // Type 0x7000: Mesh Bone Assignments
112 // uint32_t vertex_index
113 // uint32_t bone_index
114 // float weight
115 // This defines the strength of the influence a bone has on a vertex. The sum of
116 // the weights on each vertex is not guaranteed to be 1.0.
117 // These values repeat until the size of the chunk is exhausted.
118 // ----------
119 // Type 0x5000: Geometry Data
120 // uint32_t vertex_count
121 // The number of vertices stored in each contained 0x5020 Vertex Buffer chunk.
122 // Allowed subchunks:
123 // 0x5100 Vertex Declaration (required; must occur exactly once)
124 // 0x5200 Vertex Buffer (required; must occur at least once)
125 // ----------
126 // Type 0x5100 Vertex Declaration
127 // This chunk does not store any values itself. It only acts as a container for
128 // 0x5110 Vertex Declaration Element chunks.
129 // Allowed subchunks:
130 // 0x5110 Vertex Declaration Element (required; repeats until the size of the chunk is exhausted)
131 // ----------
132 // Type 0x5110 Vertex Declaration Element
133 // uint16_t source
134 // The index of the stream where this element is found.
135 // uint16_t type
136 // The type of data this element contains.
137 // Acceptable values:
138 // 0x00 VDET_Float1
139 // A single 32-bit float, expanded to (a, 0, 0, 1)
140 // 0x01 VDET_Float2
141 // Two 32-bit floats, expanded to (a, b, 0, 1)
142 // 0x02 VDET_Float3
143 // Three 32-bit floats, expanded to (a, b, c, 1)
144 // 0x03 VDET_Float4
145 // Four 32-bit floats
146 // (0x04 VDET_Reserved)
147 // (0x05 VDET_Short1)
148 // A single 16-bit integer
149 // (0x06 VDET_Short2)
150 // Two 16-bit integers
151 // (0x07 VDET_Short3)
152 // Three 16-bit integers
153 // (0x08 VDET_Short4)
154 // Four 16-bit integers
155 // (0x09 VDET_UByte4)
156 // Four 8-bit integers
157 // 0x0A VDET_Color_ARGB
158 // Four 8-bit integers, describing a color in the order Alpha, Red, Green, Blue.
159 // Acceptable values range from 0 to 255.
160 // 0x0B VDET_Color_ABGR
161 // Four 8-bit integers, describing a color in the order Alpha, Blue, Green, Red.
162 // Acceptable values range from 0 to 255.
163 // uint16_t semantic
164 // The semantic of the data this element contains.
165 // Acceptable values:
166 // 0x01 VDES_Position
167 // The element contains the vertex's position in world space.
168 // (0x02 VDES_Blend_Weights)
169 // (0x03 VDES_Blend_Indices)
170 // 0x04 VDES_Normals
171 // The element contains vertex normals.
172 // (0x05 VDES_Diffuse)
173 // The element contains the diffuse color of the vertex.
174 // (0x06 VDES_Specular)
175 // The element contains the specular color of the vertex.
176 // 0x07 VDES_Texcoords
177 // The element contains the texture coordinates of the vertex.
178 // uint16_t offset
179 // The element's offset in bytes from the beginning of the stream.
180 // uint16_t index
181 // Index of the element semantic. Used with colors and texture coordinates.
182 // ----------
183 // 0x5200 Vertex Buffer
184 // uint16_t index
185 // The index of the stream this buffer will get bound to.
186 // uint16_t stride
187 // The distance in bytes between two elements inside the buffer.
188 // Allowed subchunks:
189 // 0x5210 Vertex Buffer Data (required; must occur exactly once)
190 // ----------
191 // 0x5210 Vertex Buffer Data
192 // uint8_t data[]
193 // The buffered data. This field spans the whole extent of the chunk.
194 // ----------
195 // 0x6000 Skeleton Link
196 // string file
197 // The name of the file that contains the skeleton of this mesh.
198 // ----------
199 // 0x9000 Mesh Boundaries
200 // float min[3]
201 // The minimum extents of the axis-aligned bounding box of the mesh.
202 // float max[3]
203 // The maximum extents of the axis-aligned bounding box of the mesh.
204 // float radius
205 // The radius of the minimal enclosing sphere of the mesh.
206 //
207 // ==== Skeleton files ====
208 // Each skeleton file must begin with a 0x1000 File Header chunk. Afterwards,
209 // any combination of the following chunks may appear:
210 // 0x2000 Bone Data
211 // 0x3000 Bone Hierarchy
212 // 0x4000 Animation
213 // (0x5000 Animation Link)
214 //
215 // Unless specified, this section will only describe the data part of each chunk.
216 // Any values that are in parentheses are not available in this implementation.
217 //
218 // Type 0x1000: File Header
219 // string version
220 // Depending on the version, different features are enabled or disabled while
221 // loading the file.
222 // This implementation does not support fallback to different versions of the
223 // file format.
224 // This chunk does not contain a length field; the type id is directly followed
225 // by the version string.
226 // ----------
227 // Type 0x2000: Bone Data
228 // string name
229 // The name of the bone. This is only used to produce human-readable output.
230 // uint16_t handle
231 // The internal handle of the bone. All other chunks that refer to a bone reference
232 // this.
233 // float position[3]
234 // The position of the bone, relative to its parent.
235 // float orientation[4]
236 // The orientation of the bone, as a quaternion (x,y,z,w). Relative to the parent.
237 // float scale[3]
238 // The scale of the bone, relative to its parent. This element only appears if the
239 // chunk size is large enough; if it is omitted, it defaults to (1,1,1).
240 // ----------
241 // Type 0x3000 Bone Hierarchy
242 // uint16_t child
243 // The handle of the parent bone.
244 // uint16_t parent
245 // The handle of the parent bone.
246 // ----------
247 // Type 0x4000 Animation
248 // string name
249 // The name of this animation.
250 // float duration
251 // The length of this animation, in seconds.
252 // Allowed subchunks:
253 // 0x4100 Animation Track
254 // ----------
255 // Type 0x4100 Animation Track
256 // uint16_t bone
257 // The handle of the bone this track belongs to.
258 // Allowed subchunks:
259 // 0x4110 Animation Track Keyframe
260 // ----------
261 // Type 0x4110 Animation Track Keyframe
262 // float time
263 // The time this keyframe matches.
264 // float rotation[4]
265 // The rotation of the bone at the corresponding time, as a quaternion (x,y,z,w).
266 // float translation[3]
267 // The translation of the bone at the corresponding time.
268 // float scale[3]
269 // The scale of the bone at the time of the keyframe. This element only appears if the
270 // chunk size is large enough; if it is omitted, it defaults to (1,1,1).
271 
272 // Most of the chunk classes below faithfully match the abovementioned file format.
273 namespace Ogre
274 {
275  // used to have boost::ptr_vector. Behaves reasonably similar
276  template<typename T>
277  using unique_ptr_vector = std::vector<std::unique_ptr<T>>;
278 
279  class DataStream;
280  template<class _Type>
281  class ChunkBase
282  {
283  protected:
284  ChunkBase() : type(static_cast<Type>(0)) {}
285  virtual void ReadImpl(DataStream *stream) = 0;
286  typedef _Type Type;
288  size_t size;
289  public:
290  virtual ~ChunkBase() = default;
291  Type GetType() const { return type; }
292  size_t GetSize() const { return size; }
293 
294  static const size_t ChunkHeaderLength = sizeof(uint16_t) /* chunk type */ + sizeof(uint32_t) /* chunk length */;
295  static Type Peek(const DataStream *stream)
296  {
297  return static_cast<Type>(stream->Peek<uint16_t>());
298  }
299  };
300 
301  namespace Mesh
302  {
303  enum ChunkID
304  {
306  CID_Header = 0x1000,
307  CID_Mesh = 0x3000,
308  CID_Submesh = 0x4000,
309  CID_Submesh_Op = 0x4010,
312  CID_Geometry = 0x5000,
319  CID_Mesh_LOD = 0x8000,
323  CID_Mesh_Bounds = 0x9000,
326  CID_Edge_List = 0xB000,
328  CID_Edge_Group = 0xB110,
329  CID_Pose_List = 0xC000,
330  CID_Pose = 0xC100,
331  CID_Pose_Vertex = 0xC111,
333  CID_Animation = 0xD100,
338  CID_Table_Extremes = 0xE000
339  };
340 
342  {
343  uint32_t vertex;
344  uint32_t bone;
345  float weight;
346  };
347 
348  class Chunk : public ChunkBase<ChunkID>
349  {
350  public:
351  static std::unique_ptr<Chunk> Read(DataStream *stream);
352  };
353 
354  class ChunkUnknown; class
357  class ChunkSubmesh; class ChunkSubmeshOp;
359  class ChunkPoseList; class ChunkPose; class ChunkPoseVertex;
360  class ChunkAnimationList; class ChunkAnimation; class ChunkAnimationTrack;
361  class ChunkAnimationMorphKF; class ChunkAnimationPoseKF; class ChunkAnimationPoseRef;
362 
363  class ChunkUnknown : public Chunk
364  {
365  protected:
366  void ReadImpl(DataStream *stream) override;
367  };
368 
369  class ChunkFileHeader : public Chunk
370  {
371  typedef std::map<std::string, uint32_t> VersionTable_t;
372  static const VersionTable_t VersionTable;
373  static const uint32_t CurrentVersion;
374  public:
375  std::string version;
376 
377  protected:
378  void ReadImpl(DataStream *stream) override;
379  };
380 
381  class ChunkMesh : public Chunk
382  {
383  public:
384  ChunkMesh() = default;
385  bool hasAnimatedSkeleton{false};
386  std::string skeletonFile;
387  std::unique_ptr<ChunkGeometry> geometry;
389  std::vector<BoneAssignment> boneAssignments;
391  float radius{0.0f};
392 
393  protected:
394  void ReadImpl(DataStream *stream) override;
395  };
396 
398  {
399  public:
400  std::string skeleton;
401  protected:
402  void ReadImpl(DataStream *stream) override;
403  };
404 
405  class ChunkSubmesh : public Chunk
406  {
407  public:
408  ChunkSubmesh() = default;
409  std::string material;
411  std::vector<size_t> faceVertices;
412  std::unique_ptr<ChunkGeometry> geometry;
414  {
422  SO_MAX = SO_TriFan
423  } operation{SO_TriList};
424  std::vector<BoneAssignment> boneAssignments;
425  protected:
426  void ReadImpl(DataStream *stream) override;
427  };
428 
429  class ChunkSubmeshOp : public Chunk
430  {
431  public:
433  protected:
434  void ReadImpl(DataStream *stream) override;
435  };
436 
438  {
439  public:
440  std::vector<BoneAssignment> assignments;
441  protected:
442  void ReadImpl(DataStream *stream) override;
443  };
444 
445  class ChunkMeshBounds : public Chunk
446  {
447  public:
449  float radius;
450  protected:
451  void ReadImpl(DataStream *stream) override;
452  };
453 
454  class ChunkGeometry : public Chunk
455  {
456  public:
457  size_t vertexCount;
460  protected:
461  void ReadImpl(DataStream *stream) override;
462  };
463 
465  {
466  public:
468  protected:
469  void ReadImpl(DataStream *stream) override;
470  };
471 
473  {
474  public:
475  uint16_t source;
476  uint16_t offset;
477  enum Type
478  {
483  /* 4 omitted intentionally */
493  } type;
494  enum Semantic
495  {
508  uint16_t index;
509  protected:
510  void ReadImpl(DataStream *stream) override;
511  };
512 
514  {
515  public:
516  uint16_t index;
517  uint16_t vertexSize;
518  std::unique_ptr<ChunkGeometryVertexData> data;
519  protected:
520  void ReadImpl(DataStream *stream) override;
521  };
522 
524  {
525  public:
527  ~ChunkGeometryVertexData() override { delete[] static_cast<char*>(data); }
528  void *data{nullptr};
529  protected:
530  void ReadImpl(DataStream *stream) override;
531  };
532  }
533 
534  namespace Skeleton
535  {
536  enum ChunkID
537  {
539  CID_Header = 0x1000,
540  CID_BlendMode= 0x1010,
541  CID_Bone = 0x2000,
542  CID_Bone_Parent = 0x3000,
543  CID_Animation = 0x4000,
547  CID_Animation_Link = 0x5000
548  };
549 
550  class Chunk : public ChunkBase<ChunkID>
551  {
552  public:
553  static std::unique_ptr<Chunk> Read(DataStream *stream);
554  };
555 
556  class ChunkUnknown; class ChunkFileHeader;
557  class ChunkBone; class ChunkBoneParent;
559 
560  class ChunkUnknown : public Chunk
561  {
562  protected:
563  void ReadImpl(DataStream *stream) override;
564  };
565 
566  class ChunkFileHeader : public Chunk
567  {
568  typedef std::map<std::string, uint32_t> VersionTable_t;
569  static const VersionTable_t VersionTable;
570  static const uint32_t CurrentVersion;
571  public:
572  std::string version;
573 
574  protected:
575  void ReadImpl(DataStream *stream) override;
576  };
577 
578  class ChunkBlendMode : public Chunk
579  {
580  public:
581  uint16_t blend_mode;
582  protected:
583  void ReadImpl(DataStream* stream) override;
584  };
585 
586  class ChunkBone : public Chunk
587  {
588  public:
589  std::string name;
590  uint16_t handle;
591 
595  protected:
596  void ReadImpl(DataStream *stream) override;
597  };
598 
599  class ChunkBoneParent : public Chunk
600  {
601  public:
602  uint16_t childHandle;
603  uint16_t parentHandle;
604  protected:
605  void ReadImpl(DataStream *stream) override;
606  };
607 
608  class ChunkAnimation : public Chunk
609  {
610  public:
611  std::string name;
612  float duration;
614  protected:
615  void ReadImpl(DataStream *stream) override;
616  };
617 
619  {
620  public:
621  std::string base_animation_name;
623  protected:
624  void ReadImpl(DataStream* stream) override;
625  };
626 
627  class ChunkAnimationTrack : public Chunk
628  {
629  public:
630  uint16_t bone;
632  protected:
633  void ReadImpl(DataStream *stream) override;
634  };
635 
637  {
638  public:
639  float time;
643  protected:
644  void ReadImpl(DataStream *stream) override;
645  };
646 
647  class ChunkAnimationLink : public Chunk
648  {
649  public:
650  std::string file;
652  protected:
653  void ReadImpl(DataStream *stream) override;
654  };
655  }
656 }
657 
658 #endif
static Type Peek(const DataStream *stream)
virtual void ReadImpl(DataStream *stream)=0
virtual ~ChunkBase()=default
static const size_t ChunkHeaderLength
std::enable_if< std::is_pod< T >::value &&!std::is_pointer< T >::value, T >::type Peek() const
void ReadImpl(DataStream *stream) override
unique_ptr_vector< ChunkGeometryVertexDeclElement > vertexDeclaration
void ReadImpl(DataStream *stream) override
unique_ptr_vector< ChunkGeometryVertexBuffer > vertexBuffers
void ReadImpl(DataStream *stream) override
std::unique_ptr< ChunkGeometryVertexData > data
void ReadImpl(DataStream *stream) override
enum Ogre::Mesh::ChunkGeometryVertexDeclElement::Semantic semantic
enum Ogre::Mesh::ChunkGeometryVertexDeclElement::Type type
void ReadImpl(DataStream *stream) override
unique_ptr_vector< ChunkGeometryVertexDeclElement > declaration
static std::unique_ptr< Chunk > Read(DataStream *stream)
void ReadImpl(DataStream *stream) override
void ReadImpl(DataStream *stream) override
void ReadImpl(DataStream *stream) override
std::unique_ptr< ChunkGeometry > geometry
std::vector< BoneAssignment > boneAssignments
unique_ptr_vector< ChunkSubmesh > submeshes
std::vector< size_t > faceVertices
std::unique_ptr< ChunkGeometry > geometry
enum Ogre::Mesh::ChunkSubmesh::SubmeshOperation SO_TriList
std::vector< BoneAssignment > boneAssignments
void ReadImpl(DataStream *stream) override
ChunkSubmesh::SubmeshOperation operation
void ReadImpl(DataStream *stream) override
void ReadImpl(DataStream *stream) override
void ReadImpl(DataStream *stream) override
void ReadImpl(DataStream *stream) override
unique_ptr_vector< ChunkAnimationTrack > tracks
void ReadImpl(DataStream *stream) override
unique_ptr_vector< ChunkAnimationTrackKF > keyframes
void ReadImpl(DataStream *stream) override
void ReadImpl(DataStream *stream) override
void ReadImpl(DataStream *stream) override
void ReadImpl(DataStream *stream) override
void ReadImpl(DataStream *stream) override
static std::unique_ptr< Chunk > Read(DataStream *stream)
void ReadImpl(DataStream *stream) override
std::vector< std::unique_ptr< T > > unique_ptr_vector