1 | /* |
2 | --------------------------------------------------------------------------- |
3 | Open Asset Import Library (assimp) |
4 | --------------------------------------------------------------------------- |
5 | |
6 | Copyright (c) 2006-2019, assimp team |
7 | |
8 | |
9 | |
10 | All rights reserved. |
11 | |
12 | Redistribution and use of this software in source and binary forms, |
13 | with or without modification, are permitted provided that the following |
14 | conditions are met: |
15 | |
16 | * Redistributions of source code must retain the above |
17 | copyright notice, this list of conditions and the |
18 | following disclaimer. |
19 | |
20 | * Redistributions in binary form must reproduce the above |
21 | copyright notice, this list of conditions and the |
22 | following disclaimer in the documentation and/or other |
23 | materials provided with the distribution. |
24 | |
25 | * Neither the name of the assimp team, nor the names of its |
26 | contributors may be used to endorse or promote products |
27 | derived from this software without specific prior |
28 | written permission of the assimp team. |
29 | |
30 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
31 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
32 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
33 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
34 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
35 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
36 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
37 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
38 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
39 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
40 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
41 | --------------------------------------------------------------------------- |
42 | */ |
43 | |
44 | /** |
45 | * @file anim.h |
46 | * @brief Defines the data structures in which the imported animations |
47 | * are returned. |
48 | */ |
49 | #pragma once |
50 | #ifndef AI_ANIM_H_INC |
51 | #define AI_ANIM_H_INC |
52 | |
53 | #include <assimp/types.h> |
54 | #include <assimp/quaternion.h> |
55 | |
56 | #ifdef __cplusplus |
57 | extern "C" { |
58 | #endif |
59 | |
60 | // --------------------------------------------------------------------------- |
61 | /** A time-value pair specifying a certain 3D vector for the given time. */ |
62 | struct aiVectorKey |
63 | { |
64 | /** The time of this key */ |
65 | double mTime; |
66 | |
67 | /** The value of this key */ |
68 | C_STRUCT aiVector3D mValue; |
69 | |
70 | #ifdef __cplusplus |
71 | |
72 | /// @brief The default constructor. |
73 | aiVectorKey() AI_NO_EXCEPT |
74 | : mTime( 0.0 ) |
75 | , mValue() { |
76 | // empty |
77 | } |
78 | |
79 | /// @brief Construction from a given time and key value. |
80 | |
81 | aiVectorKey(double time, const aiVector3D& value) |
82 | : mTime( time ) |
83 | , mValue( value ) { |
84 | // empty |
85 | } |
86 | |
87 | typedef aiVector3D elem_type; |
88 | |
89 | // Comparison operators. For use with std::find(); |
90 | bool operator == (const aiVectorKey& rhs) const { |
91 | return rhs.mValue == this->mValue; |
92 | } |
93 | bool operator != (const aiVectorKey& rhs ) const { |
94 | return rhs.mValue != this->mValue; |
95 | } |
96 | |
97 | // Relational operators. For use with std::sort(); |
98 | bool operator < (const aiVectorKey& rhs ) const { |
99 | return mTime < rhs.mTime; |
100 | } |
101 | bool operator > (const aiVectorKey& rhs ) const { |
102 | return mTime > rhs.mTime; |
103 | } |
104 | #endif // __cplusplus |
105 | }; |
106 | |
107 | // --------------------------------------------------------------------------- |
108 | /** A time-value pair specifying a rotation for the given time. |
109 | * Rotations are expressed with quaternions. */ |
110 | struct aiQuatKey |
111 | { |
112 | /** The time of this key */ |
113 | double mTime; |
114 | |
115 | /** The value of this key */ |
116 | C_STRUCT aiQuaternion mValue; |
117 | |
118 | #ifdef __cplusplus |
119 | aiQuatKey() AI_NO_EXCEPT |
120 | : mTime( 0.0 ) |
121 | , mValue() { |
122 | // empty |
123 | } |
124 | |
125 | /** Construction from a given time and key value */ |
126 | aiQuatKey(double time, const aiQuaternion& value) |
127 | : mTime (time) |
128 | , mValue (value) |
129 | {} |
130 | |
131 | typedef aiQuaternion elem_type; |
132 | |
133 | // Comparison operators. For use with std::find(); |
134 | bool operator == (const aiQuatKey& rhs ) const { |
135 | return rhs.mValue == this->mValue; |
136 | } |
137 | bool operator != (const aiQuatKey& rhs ) const { |
138 | return rhs.mValue != this->mValue; |
139 | } |
140 | |
141 | // Relational operators. For use with std::sort(); |
142 | bool operator < (const aiQuatKey& rhs ) const { |
143 | return mTime < rhs.mTime; |
144 | } |
145 | bool operator > (const aiQuatKey& rhs ) const { |
146 | return mTime > rhs.mTime; |
147 | } |
148 | #endif |
149 | }; |
150 | |
151 | // --------------------------------------------------------------------------- |
152 | /** Binds a anim-mesh to a specific point in time. */ |
153 | struct aiMeshKey |
154 | { |
155 | /** The time of this key */ |
156 | double mTime; |
157 | |
158 | /** Index into the aiMesh::mAnimMeshes array of the |
159 | * mesh corresponding to the #aiMeshAnim hosting this |
160 | * key frame. The referenced anim mesh is evaluated |
161 | * according to the rules defined in the docs for #aiAnimMesh.*/ |
162 | unsigned int mValue; |
163 | |
164 | #ifdef __cplusplus |
165 | |
166 | aiMeshKey() AI_NO_EXCEPT |
167 | : mTime(0.0) |
168 | , mValue(0) |
169 | { |
170 | } |
171 | |
172 | /** Construction from a given time and key value */ |
173 | aiMeshKey(double time, const unsigned int value) |
174 | : mTime (time) |
175 | , mValue (value) |
176 | {} |
177 | |
178 | typedef unsigned int elem_type; |
179 | |
180 | // Comparison operators. For use with std::find(); |
181 | bool operator == (const aiMeshKey& o) const { |
182 | return o.mValue == this->mValue; |
183 | } |
184 | bool operator != (const aiMeshKey& o) const { |
185 | return o.mValue != this->mValue; |
186 | } |
187 | |
188 | // Relational operators. For use with std::sort(); |
189 | bool operator < (const aiMeshKey& o) const { |
190 | return mTime < o.mTime; |
191 | } |
192 | bool operator > (const aiMeshKey& o) const { |
193 | return mTime > o.mTime; |
194 | } |
195 | |
196 | #endif |
197 | }; |
198 | |
199 | // --------------------------------------------------------------------------- |
200 | /** Binds a morph anim mesh to a specific point in time. */ |
201 | struct aiMeshMorphKey |
202 | { |
203 | /** The time of this key */ |
204 | double mTime; |
205 | |
206 | /** The values and weights at the time of this key */ |
207 | unsigned int *mValues; |
208 | double *mWeights; |
209 | |
210 | /** The number of values and weights */ |
211 | unsigned int mNumValuesAndWeights; |
212 | #ifdef __cplusplus |
213 | aiMeshMorphKey() AI_NO_EXCEPT |
214 | : mTime(0.0) |
215 | , mValues(nullptr) |
216 | , mWeights(nullptr) |
217 | , mNumValuesAndWeights(0) |
218 | { |
219 | |
220 | } |
221 | |
222 | ~aiMeshMorphKey() |
223 | { |
224 | if (mNumValuesAndWeights && mValues && mWeights) { |
225 | delete [] mValues; |
226 | delete [] mWeights; |
227 | } |
228 | } |
229 | #endif |
230 | }; |
231 | |
232 | // --------------------------------------------------------------------------- |
233 | /** Defines how an animation channel behaves outside the defined time |
234 | * range. This corresponds to aiNodeAnim::mPreState and |
235 | * aiNodeAnim::mPostState.*/ |
236 | enum aiAnimBehaviour |
237 | { |
238 | /** The value from the default node transformation is taken*/ |
239 | aiAnimBehaviour_DEFAULT = 0x0, |
240 | |
241 | /** The nearest key value is used without interpolation */ |
242 | aiAnimBehaviour_CONSTANT = 0x1, |
243 | |
244 | /** The value of the nearest two keys is linearly |
245 | * extrapolated for the current time value.*/ |
246 | aiAnimBehaviour_LINEAR = 0x2, |
247 | |
248 | /** The animation is repeated. |
249 | * |
250 | * If the animation key go from n to m and the current |
251 | * time is t, use the value at (t-n) % (|m-n|).*/ |
252 | aiAnimBehaviour_REPEAT = 0x3, |
253 | |
254 | /** This value is not used, it is just here to force the |
255 | * the compiler to map this enum to a 32 Bit integer */ |
256 | #ifndef SWIG |
257 | _aiAnimBehaviour_Force32Bit = INT_MAX |
258 | #endif |
259 | }; |
260 | |
261 | // --------------------------------------------------------------------------- |
262 | /** Describes the animation of a single node. The name specifies the |
263 | * bone/node which is affected by this animation channel. The keyframes |
264 | * are given in three separate series of values, one each for position, |
265 | * rotation and scaling. The transformation matrix computed from these |
266 | * values replaces the node's original transformation matrix at a |
267 | * specific time. |
268 | * This means all keys are absolute and not relative to the bone default pose. |
269 | * The order in which the transformations are applied is |
270 | * - as usual - scaling, rotation, translation. |
271 | * |
272 | * @note All keys are returned in their correct, chronological order. |
273 | * Duplicate keys don't pass the validation step. Most likely there |
274 | * will be no negative time values, but they are not forbidden also ( so |
275 | * implementations need to cope with them! ) */ |
276 | struct aiNodeAnim { |
277 | /** The name of the node affected by this animation. The node |
278 | * must exist and it must be unique.*/ |
279 | C_STRUCT aiString mNodeName; |
280 | |
281 | /** The number of position keys */ |
282 | unsigned int mNumPositionKeys; |
283 | |
284 | /** The position keys of this animation channel. Positions are |
285 | * specified as 3D vector. The array is mNumPositionKeys in size. |
286 | * |
287 | * If there are position keys, there will also be at least one |
288 | * scaling and one rotation key.*/ |
289 | C_STRUCT aiVectorKey* mPositionKeys; |
290 | |
291 | /** The number of rotation keys */ |
292 | unsigned int mNumRotationKeys; |
293 | |
294 | /** The rotation keys of this animation channel. Rotations are |
295 | * given as quaternions, which are 4D vectors. The array is |
296 | * mNumRotationKeys in size. |
297 | * |
298 | * If there are rotation keys, there will also be at least one |
299 | * scaling and one position key. */ |
300 | C_STRUCT aiQuatKey* mRotationKeys; |
301 | |
302 | /** The number of scaling keys */ |
303 | unsigned int mNumScalingKeys; |
304 | |
305 | /** The scaling keys of this animation channel. Scalings are |
306 | * specified as 3D vector. The array is mNumScalingKeys in size. |
307 | * |
308 | * If there are scaling keys, there will also be at least one |
309 | * position and one rotation key.*/ |
310 | C_STRUCT aiVectorKey* mScalingKeys; |
311 | |
312 | /** Defines how the animation behaves before the first |
313 | * key is encountered. |
314 | * |
315 | * The default value is aiAnimBehaviour_DEFAULT (the original |
316 | * transformation matrix of the affected node is used).*/ |
317 | C_ENUM aiAnimBehaviour mPreState; |
318 | |
319 | /** Defines how the animation behaves after the last |
320 | * key was processed. |
321 | * |
322 | * The default value is aiAnimBehaviour_DEFAULT (the original |
323 | * transformation matrix of the affected node is taken).*/ |
324 | C_ENUM aiAnimBehaviour mPostState; |
325 | |
326 | #ifdef __cplusplus |
327 | aiNodeAnim() AI_NO_EXCEPT |
328 | : mNumPositionKeys( 0 ) |
329 | , mPositionKeys( nullptr ) |
330 | , mNumRotationKeys( 0 ) |
331 | , mRotationKeys( nullptr ) |
332 | , mNumScalingKeys( 0 ) |
333 | , mScalingKeys( nullptr ) |
334 | , mPreState( aiAnimBehaviour_DEFAULT ) |
335 | , mPostState( aiAnimBehaviour_DEFAULT ) { |
336 | // empty |
337 | } |
338 | |
339 | ~aiNodeAnim() { |
340 | delete [] mPositionKeys; |
341 | delete [] mRotationKeys; |
342 | delete [] mScalingKeys; |
343 | } |
344 | #endif // __cplusplus |
345 | }; |
346 | |
347 | // --------------------------------------------------------------------------- |
348 | /** Describes vertex-based animations for a single mesh or a group of |
349 | * meshes. Meshes carry the animation data for each frame in their |
350 | * aiMesh::mAnimMeshes array. The purpose of aiMeshAnim is to |
351 | * define keyframes linking each mesh attachment to a particular |
352 | * point in time. */ |
353 | struct aiMeshAnim |
354 | { |
355 | /** Name of the mesh to be animated. An empty string is not allowed, |
356 | * animated meshes need to be named (not necessarily uniquely, |
357 | * the name can basically serve as wild-card to select a group |
358 | * of meshes with similar animation setup)*/ |
359 | C_STRUCT aiString mName; |
360 | |
361 | /** Size of the #mKeys array. Must be 1, at least. */ |
362 | unsigned int mNumKeys; |
363 | |
364 | /** Key frames of the animation. May not be NULL. */ |
365 | C_STRUCT aiMeshKey* mKeys; |
366 | |
367 | #ifdef __cplusplus |
368 | |
369 | aiMeshAnim() AI_NO_EXCEPT |
370 | : mNumKeys() |
371 | , mKeys() |
372 | {} |
373 | |
374 | ~aiMeshAnim() |
375 | { |
376 | delete[] mKeys; |
377 | } |
378 | |
379 | #endif |
380 | }; |
381 | |
382 | // --------------------------------------------------------------------------- |
383 | /** Describes a morphing animation of a given mesh. */ |
384 | struct aiMeshMorphAnim |
385 | { |
386 | /** Name of the mesh to be animated. An empty string is not allowed, |
387 | * animated meshes need to be named (not necessarily uniquely, |
388 | * the name can basically serve as wildcard to select a group |
389 | * of meshes with similar animation setup)*/ |
390 | C_STRUCT aiString mName; |
391 | |
392 | /** Size of the #mKeys array. Must be 1, at least. */ |
393 | unsigned int mNumKeys; |
394 | |
395 | /** Key frames of the animation. May not be NULL. */ |
396 | C_STRUCT aiMeshMorphKey* mKeys; |
397 | |
398 | #ifdef __cplusplus |
399 | |
400 | aiMeshMorphAnim() AI_NO_EXCEPT |
401 | : mNumKeys() |
402 | , mKeys() |
403 | {} |
404 | |
405 | ~aiMeshMorphAnim() |
406 | { |
407 | delete[] mKeys; |
408 | } |
409 | |
410 | #endif |
411 | }; |
412 | |
413 | // --------------------------------------------------------------------------- |
414 | /** An animation consists of key-frame data for a number of nodes. For |
415 | * each node affected by the animation a separate series of data is given.*/ |
416 | struct aiAnimation { |
417 | /** The name of the animation. If the modeling package this data was |
418 | * exported from does support only a single animation channel, this |
419 | * name is usually empty (length is zero). */ |
420 | C_STRUCT aiString mName; |
421 | |
422 | /** Duration of the animation in ticks. */ |
423 | double mDuration; |
424 | |
425 | /** Ticks per second. 0 if not specified in the imported file */ |
426 | double mTicksPerSecond; |
427 | |
428 | /** The number of bone animation channels. Each channel affects |
429 | * a single node. */ |
430 | unsigned int mNumChannels; |
431 | |
432 | /** The node animation channels. Each channel affects a single node. |
433 | * The array is mNumChannels in size. */ |
434 | C_STRUCT aiNodeAnim** mChannels; |
435 | |
436 | |
437 | /** The number of mesh animation channels. Each channel affects |
438 | * a single mesh and defines vertex-based animation. */ |
439 | unsigned int mNumMeshChannels; |
440 | |
441 | /** The mesh animation channels. Each channel affects a single mesh. |
442 | * The array is mNumMeshChannels in size. */ |
443 | C_STRUCT aiMeshAnim** mMeshChannels; |
444 | |
445 | /** The number of mesh animation channels. Each channel affects |
446 | * a single mesh and defines morphing animation. */ |
447 | unsigned int mNumMorphMeshChannels; |
448 | |
449 | /** The morph mesh animation channels. Each channel affects a single mesh. |
450 | * The array is mNumMorphMeshChannels in size. */ |
451 | C_STRUCT aiMeshMorphAnim **mMorphMeshChannels; |
452 | |
453 | #ifdef __cplusplus |
454 | aiAnimation() AI_NO_EXCEPT |
455 | : mDuration(-1.) |
456 | , mTicksPerSecond(0.) |
457 | , mNumChannels(0) |
458 | , mChannels(nullptr) |
459 | , mNumMeshChannels(0) |
460 | , mMeshChannels(nullptr) |
461 | , mNumMorphMeshChannels(0) |
462 | , mMorphMeshChannels(nullptr) { |
463 | // empty |
464 | } |
465 | |
466 | ~aiAnimation() { |
467 | // DO NOT REMOVE THIS ADDITIONAL CHECK |
468 | if ( mNumChannels && mChannels ) { |
469 | for( unsigned int a = 0; a < mNumChannels; a++) { |
470 | delete mChannels[ a ]; |
471 | } |
472 | |
473 | delete [] mChannels; |
474 | } |
475 | if (mNumMeshChannels && mMeshChannels) { |
476 | for( unsigned int a = 0; a < mNumMeshChannels; a++) { |
477 | delete mMeshChannels[a]; |
478 | } |
479 | |
480 | delete [] mMeshChannels; |
481 | } |
482 | if (mNumMorphMeshChannels && mMorphMeshChannels) { |
483 | for( unsigned int a = 0; a < mNumMorphMeshChannels; a++) { |
484 | delete mMorphMeshChannels[a]; |
485 | } |
486 | |
487 | delete [] mMorphMeshChannels; |
488 | } |
489 | } |
490 | #endif // __cplusplus |
491 | }; |
492 | |
493 | #ifdef __cplusplus |
494 | |
495 | } |
496 | |
497 | /// @brief Some C++ utilities for inter- and extrapolation |
498 | namespace Assimp { |
499 | |
500 | // --------------------------------------------------------------------------- |
501 | /** |
502 | * @brief CPP-API: Utility class to simplify interpolations of various data types. |
503 | * |
504 | * The type of interpolation is chosen automatically depending on the |
505 | * types of the arguments. |
506 | */ |
507 | template <typename T> |
508 | struct Interpolator |
509 | { |
510 | // ------------------------------------------------------------------ |
511 | /** @brief Get the result of the interpolation between a,b. |
512 | * |
513 | * The interpolation algorithm depends on the type of the operands. |
514 | * aiQuaternion's and aiQuatKey's SLERP, the rest does a simple |
515 | * linear interpolation. */ |
516 | void operator () (T& out,const T& a, const T& b, ai_real d) const { |
517 | out = a + (b-a)*d; |
518 | } |
519 | }; // ! Interpolator <T> |
520 | |
521 | //! @cond Never |
522 | |
523 | template <> |
524 | struct Interpolator <aiQuaternion> { |
525 | void operator () (aiQuaternion& out,const aiQuaternion& a, |
526 | const aiQuaternion& b, ai_real d) const |
527 | { |
528 | aiQuaternion::Interpolate(pOut&: out,pStart: a,pEnd: b,pFactor: d); |
529 | } |
530 | }; // ! Interpolator <aiQuaternion> |
531 | |
532 | template <> |
533 | struct Interpolator <unsigned int> { |
534 | void operator () (unsigned int& out,unsigned int a, |
535 | unsigned int b, ai_real d) const |
536 | { |
537 | out = d>0.5f ? b : a; |
538 | } |
539 | }; // ! Interpolator <aiQuaternion> |
540 | |
541 | template <> |
542 | struct Interpolator<aiVectorKey> { |
543 | void operator () (aiVector3D& out,const aiVectorKey& a, |
544 | const aiVectorKey& b, ai_real d) const |
545 | { |
546 | Interpolator<aiVector3D> ipl; |
547 | ipl(out,a.mValue,b.mValue,d); |
548 | } |
549 | }; // ! Interpolator <aiVectorKey> |
550 | |
551 | template <> |
552 | struct Interpolator<aiQuatKey> { |
553 | void operator () (aiQuaternion& out, const aiQuatKey& a, |
554 | const aiQuatKey& b, ai_real d) const |
555 | { |
556 | Interpolator<aiQuaternion> ipl; |
557 | ipl(out,a.mValue,b.mValue,d); |
558 | } |
559 | }; // ! Interpolator <aiQuatKey> |
560 | |
561 | template <> |
562 | struct Interpolator<aiMeshKey> { |
563 | void operator () (unsigned int& out, const aiMeshKey& a, |
564 | const aiMeshKey& b, ai_real d) const |
565 | { |
566 | Interpolator<unsigned int> ipl; |
567 | ipl(out,a.mValue,b.mValue,d); |
568 | } |
569 | }; // ! Interpolator <aiQuatKey> |
570 | |
571 | //! @endcond |
572 | |
573 | } // ! end namespace Assimp |
574 | |
575 | #endif // __cplusplus |
576 | |
577 | #endif // AI_ANIM_H_INC |
578 | |