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/** @file SMDLoader.h
43 * @brief Definition of the Valve SMD file format
44 */
45
46#ifndef AI_SMDLOADER_H_INCLUDED
47#define AI_SMDLOADER_H_INCLUDED
48
49// internal headers
50#include "BaseImporter.h"
51#include "ParsingUtils.h"
52
53// public Assimp headers
54#include <assimp/types.h>
55#include <assimp/texture.h>
56#include <assimp/anim.h>
57#include <assimp/material.h>
58
59struct aiNode;
60
61// STL headers
62#include <vector>
63
64namespace Assimp {
65
66namespace SMD {
67
68// ---------------------------------------------------------------------------
69/** Data structure for a vertex in a SMD file
70*/
71struct Vertex
72{
73 Vertex() : iParentNode(UINT_MAX)
74 {}
75
76 //! Vertex position, normal and texture coordinate
77 aiVector3D pos,nor,uv;
78
79 //! Vertex parent node
80 unsigned int iParentNode;
81
82 //! Links to bones: pair.first is the bone index,
83 //! pair.second is the vertex weight.
84 //! WARN: The remaining weight (to reach 1.0f) is assigned
85 //! to the parent node/bone
86 std::vector<std::pair<unsigned int, float> > aiBoneLinks;
87};
88
89// ---------------------------------------------------------------------------
90/** Data structure for a face in a SMD file
91*/
92struct Face
93{
94 Face() : iTexture(0x0)
95 {}
96
97 //! Texture index for the face
98 unsigned int iTexture;
99
100 //! The three vertices of the face
101 Vertex avVertices[3];
102};
103
104// ---------------------------------------------------------------------------
105/** Data structure for a bone in a SMD file
106*/
107struct Bone
108{
109 //! Default constructor
110 Bone() : iParent(UINT_MAX), bIsUsed(false)
111 {
112 }
113
114 //! Destructor
115 ~Bone()
116 {
117 }
118
119 //! Name of the bone
120 std::string mName;
121
122 //! Parent of the bone
123 uint32_t iParent;
124
125 //! Animation of the bone
126 struct Animation
127 {
128 //! Public default constructor
129 Animation()
130 : iFirstTimeKey()
131 {
132 asKeys.reserve(20);
133 }
134
135 //! Data structure for a matrix key
136 struct MatrixKey
137 {
138 //! Matrix at this time
139 aiMatrix4x4 matrix;
140
141 //! Absolute transformation matrix
142 aiMatrix4x4 matrixAbsolute;
143
144 //! Position
145 aiVector3D vPos;
146
147 //! Rotation (euler angles)
148 aiVector3D vRot;
149
150 //! Current time. may be negative, this
151 //! will be fixed later
152 double dTime;
153 };
154
155 //! Index of the key with the smallest time value
156 uint32_t iFirstTimeKey;
157
158 //! Array of matrix keys
159 std::vector<MatrixKey> asKeys;
160
161 } sAnim;
162
163 //! Offset matrix of the bone
164 aiMatrix4x4 mOffsetMatrix;
165
166 //! true if the bone is referenced by at least one mesh
167 bool bIsUsed;
168};
169
170} //! namespace SMD
171
172// ---------------------------------------------------------------------------
173/** Used to load Half-life 1 and 2 SMD models
174*/
175class ASSIMP_API SMDImporter : public BaseImporter
176{
177public:
178 SMDImporter();
179 ~SMDImporter();
180
181
182public:
183
184 // -------------------------------------------------------------------
185 /** Returns whether the class can handle the format of the given file.
186 * See BaseImporter::CanRead() for details.
187 */
188 bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
189 bool checkSig) const;
190
191 // -------------------------------------------------------------------
192 /** Called prior to ReadFile().
193 * The function is a request to the importer to update its configuration
194 * basing on the Importer's configuration property list.
195 */
196 void SetupProperties(const Importer* pImp);
197
198protected:
199
200
201 // -------------------------------------------------------------------
202 /** Return importer meta information.
203 * See #BaseImporter::GetInfo for the details
204 */
205 const aiImporterDesc* GetInfo () const;
206
207 // -------------------------------------------------------------------
208 /** Imports the given file into the given scene structure.
209 * See BaseImporter::InternReadFile() for details
210 */
211 void InternReadFile( const std::string& pFile, aiScene* pScene,
212 IOSystem* pIOHandler);
213
214protected:
215
216 // -------------------------------------------------------------------
217 /** Parse the SMD file and create the output scene
218 */
219 void ParseFile();
220
221 // -------------------------------------------------------------------
222 /** Parse the triangles section of the SMD file
223 * \param szCurrent Current position in the file. Points to the first
224 * data line of the section.
225 * \param szCurrentOut Receives a pointer to the heading line of
226 * the next section (or to EOF)
227 */
228 void ParseTrianglesSection(const char* szCurrent,
229 const char** szCurrentOut);
230
231 // -------------------------------------------------------------------
232 /** Parse the vertex animation section in VTA files
233 * \param szCurrent Current position in the file. Points to the first
234 * data line of the section.
235 * \param szCurrentOut Receives a pointer to the heading line of
236 * the next section (or to EOF)
237 */
238 void ParseVASection(const char* szCurrent,
239 const char** szCurrentOut);
240
241 // -------------------------------------------------------------------
242 /** Parse the nodes section of the SMD file
243 * \param szCurrent Current position in the file. Points to the first
244 * data line of the section.
245 * \param szCurrentOut Receives a pointer to the heading line of
246 * the next section (or to EOF)
247 */
248 void ParseNodesSection(const char* szCurrent,
249 const char** szCurrentOut);
250
251 // -------------------------------------------------------------------
252 /** Parse the skeleton section of the SMD file
253 * \param szCurrent Current position in the file. Points to the first
254 * data line of the section.
255 * \param szCurrentOut Receives a pointer to the heading line of
256 * the next section (or to EOF)
257 */
258 void ParseSkeletonSection(const char* szCurrent,
259 const char** szCurrentOut);
260
261 // -------------------------------------------------------------------
262 /** Parse a single triangle in the SMD file
263 * \param szCurrent Current position in the file. Points to the first
264 * data line of the section.
265 * \param szCurrentOut Receives the output cursor position
266 */
267 void ParseTriangle(const char* szCurrent,
268 const char** szCurrentOut);
269
270
271 // -------------------------------------------------------------------
272 /** Parse a single vertex in the SMD file
273 * \param szCurrent Current position in the file. Points to the first
274 * data line of the section.
275 * \param szCurrentOut Receives the output cursor position
276 * \param vertex Vertex to be filled
277 */
278 void ParseVertex(const char* szCurrent,
279 const char** szCurrentOut, SMD::Vertex& vertex,
280 bool bVASection = false);
281
282 // -------------------------------------------------------------------
283 /** Get the index of a texture. If the texture was not yet known
284 * it will be added to the internal texture list.
285 * \param filename Name of the texture
286 * \return Value texture index
287 */
288 unsigned int GetTextureIndex(const std::string& filename);
289
290 // -------------------------------------------------------------------
291 /** Computes absolute bone transformations
292 * All output transformations are in worldspace.
293 */
294 void ComputeAbsoluteBoneTransformations();
295
296
297 // -------------------------------------------------------------------
298 /** Parse a line in the skeleton section
299 */
300 void ParseSkeletonElement(const char* szCurrent,
301 const char** szCurrentOut,int iTime);
302
303 // -------------------------------------------------------------------
304 /** Parse a line in the nodes section
305 */
306 void ParseNodeInfo(const char* szCurrent,
307 const char** szCurrentOut);
308
309
310 // -------------------------------------------------------------------
311 /** Parse a floating-point value
312 */
313 bool ParseFloat(const char* szCurrent,
314 const char** szCurrentOut, float& out);
315
316 // -------------------------------------------------------------------
317 /** Parse an unsigned integer. There may be no sign!
318 */
319 bool ParseUnsignedInt(const char* szCurrent,
320 const char** szCurrentOut, unsigned int& out);
321
322 // -------------------------------------------------------------------
323 /** Parse a signed integer. Signs (+,-) are handled.
324 */
325 bool ParseSignedInt(const char* szCurrent,
326 const char** szCurrentOut, int& out);
327
328 // -------------------------------------------------------------------
329 /** Fix invalid time values in the file
330 */
331 void FixTimeValues();
332
333 // -------------------------------------------------------------------
334 /** Add all children of a bone as subnodes to a node
335 * \param pcNode Parent node
336 * \param iParent Parent bone index
337 */
338 void AddBoneChildren(aiNode* pcNode, uint32_t iParent);
339
340 // -------------------------------------------------------------------
341 /** Build output meshes/materials/nodes/animations
342 */
343 void CreateOutputMeshes();
344 void CreateOutputNodes();
345 void CreateOutputAnimations();
346 void CreateOutputMaterials();
347
348
349 // -------------------------------------------------------------------
350 /** Print a log message together with the current line number
351 */
352 void LogErrorNoThrow(const char* msg);
353 void LogWarning(const char* msg);
354
355
356 // -------------------------------------------------------------------
357 inline bool SkipLine( const char* in, const char** out)
358 {
359 Assimp::SkipLine(in,out);
360 ++iLineNumber;
361 return true;
362 }
363 // -------------------------------------------------------------------
364 inline bool SkipSpacesAndLineEnd( const char* in, const char** out)
365 {
366 ++iLineNumber;
367 return Assimp::SkipSpacesAndLineEnd(in,out);
368 }
369
370private:
371
372 /** Configuration option: frame to be loaded */
373 unsigned int configFrameID;
374
375 /** Buffer to hold the loaded file */
376 std::vector<char> mBuffer;
377
378 /** Output scene to be filled
379 */
380 aiScene* pScene;
381
382 /** Size of the input file in bytes
383 */
384 unsigned int iFileSize;
385
386 /** Array of textures found in the file
387 */
388 std::vector<std::string> aszTextures;
389
390 /** Array of triangles found in the file
391 */
392 std::vector<SMD::Face> asTriangles;
393
394 /** Array of bones found in the file
395 */
396 std::vector<SMD::Bone> asBones;
397
398 /** Smallest frame index found in the skeleton
399 */
400 int iSmallestFrame;
401
402 /** Length of the whole animation, in frames
403 */
404 double dLengthOfAnim;
405
406 /** Do we have texture coordinates?
407 */
408 bool bHasUVs;
409
410 /** Current line numer
411 */
412 unsigned int iLineNumber;
413
414};
415
416} // end of namespace Assimp
417
418#endif // AI_SMDIMPORTER_H_INC
419