/src/assimp/code/AssetLib/LWO/LWOAnimation.h
Line | Count | Source |
1 | | /* |
2 | | Open Asset Import Library (assimp) |
3 | | ---------------------------------------------------------------------- |
4 | | |
5 | | Copyright (c) 2006-2026, assimp team |
6 | | |
7 | | All rights reserved. |
8 | | |
9 | | Redistribution and use of this software in source and binary forms, |
10 | | with or without modification, are permitted provided that the |
11 | | following 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 | | |
27 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
28 | | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
29 | | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
30 | | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
31 | | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
32 | | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
33 | | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
34 | | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
35 | | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
36 | | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
37 | | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
38 | | |
39 | | ---------------------------------------------------------------------- |
40 | | */ |
41 | | |
42 | | /** @file LWOAnimation.h |
43 | | * @brief LWOAnimationResolver utility class |
44 | | * |
45 | | * This is for all lightwave-related file format, not only LWO. |
46 | | * LWS isthe main purpose. |
47 | | */ |
48 | | #ifndef AI_LWO_ANIMATION_INCLUDED |
49 | | #define AI_LWO_ANIMATION_INCLUDED |
50 | | |
51 | | // |
52 | | #include <vector> |
53 | | #include <list> |
54 | | |
55 | | struct aiNodeAnim; |
56 | | struct aiVectorKey; |
57 | | |
58 | | namespace Assimp { |
59 | | namespace LWO { |
60 | | |
61 | | // --------------------------------------------------------------------------- |
62 | | /** \brief List of recognized LWO envelopes |
63 | | */ |
64 | | enum EnvelopeType |
65 | | { |
66 | | EnvelopeType_Position_X = 0x1, |
67 | | EnvelopeType_Position_Y = 0x2, |
68 | | EnvelopeType_Position_Z = 0x3, |
69 | | |
70 | | EnvelopeType_Rotation_Heading = 0x4, |
71 | | EnvelopeType_Rotation_Pitch = 0x5, |
72 | | EnvelopeType_Rotation_Bank = 0x6, |
73 | | |
74 | | EnvelopeType_Scaling_X = 0x7, |
75 | | EnvelopeType_Scaling_Y = 0x8, |
76 | | EnvelopeType_Scaling_Z = 0x9, |
77 | | |
78 | | // -- currently not yet handled |
79 | | EnvelopeType_Color_R = 0xa, |
80 | | EnvelopeType_Color_G = 0xb, |
81 | | EnvelopeType_Color_B = 0xc, |
82 | | |
83 | | EnvelopeType_Falloff_X = 0xd, |
84 | | EnvelopeType_Falloff_Y = 0xe, |
85 | | EnvelopeType_Falloff_Z = 0xf, |
86 | | |
87 | | EnvelopeType_Unknown |
88 | | }; |
89 | | |
90 | | // --------------------------------------------------------------------------- |
91 | | /** \brief List of recognized LWO interpolation modes |
92 | | */ |
93 | | enum InterpolationType |
94 | | { |
95 | | IT_STEP, IT_LINE, IT_TCB, IT_HERM, IT_BEZI, IT_BEZ2 |
96 | | }; |
97 | | |
98 | | |
99 | | // --------------------------------------------------------------------------- |
100 | | /** \brief List of recognized LWO pre or post range behaviours |
101 | | */ |
102 | | enum PrePostBehaviour |
103 | | { |
104 | | PrePostBehaviour_Reset = 0x0, |
105 | | PrePostBehaviour_Constant = 0x1, |
106 | | PrePostBehaviour_Repeat = 0x2, |
107 | | PrePostBehaviour_Oscillate = 0x3, |
108 | | PrePostBehaviour_OffsetRepeat = 0x4, |
109 | | PrePostBehaviour_Linear = 0x5 |
110 | | }; |
111 | | |
112 | | // --------------------------------------------------------------------------- |
113 | | /** \brief Data structure for a LWO animation keyframe |
114 | | */ |
115 | | struct Key { |
116 | | Key() AI_NO_EXCEPT |
117 | | : time() |
118 | | , value() |
119 | 0 | , inter(IT_LINE) |
120 | 0 | , params() { |
121 | | // empty |
122 | 0 | } |
123 | | |
124 | | //! Current time |
125 | | double time; |
126 | | |
127 | | //! Current value |
128 | | float value; |
129 | | |
130 | | //! How to interpolate this key with previous key? |
131 | | InterpolationType inter; |
132 | | |
133 | | //! Interpolation parameters |
134 | | float params[5]; |
135 | | |
136 | | |
137 | | // for std::find() |
138 | 0 | operator double () { |
139 | 0 | return time; |
140 | 0 | } |
141 | | }; |
142 | | |
143 | | // --------------------------------------------------------------------------- |
144 | | /** \brief Data structure for a LWO animation envelope |
145 | | */ |
146 | | struct Envelope { |
147 | | Envelope() AI_NO_EXCEPT |
148 | | : index() |
149 | 0 | , type(EnvelopeType_Unknown) |
150 | 0 | , pre(PrePostBehaviour_Constant) |
151 | 0 | , post(PrePostBehaviour_Constant) |
152 | 0 | , old_first(0) |
153 | 0 | , old_last(0) { |
154 | | // empty |
155 | 0 | } |
156 | | |
157 | | //! Index of this envelope |
158 | | unsigned int index; |
159 | | |
160 | | //! Type of envelope |
161 | | EnvelopeType type; |
162 | | |
163 | | //! Pre- and post-behavior |
164 | | PrePostBehaviour pre,post; |
165 | | |
166 | | //! Keyframes for this envelope |
167 | | std::vector<Key> keys; |
168 | | |
169 | | // temporary data for AnimResolver |
170 | | size_t old_first,old_last; |
171 | | }; |
172 | | |
173 | | // --------------------------------------------------------------------------- |
174 | | //! @def AI_LWO_ANIM_FLAG_SAMPLE_ANIMS |
175 | | //! Flag for AnimResolver, subsamples the input data with the rate specified |
176 | | //! by AnimResolver::SetSampleRate(). |
177 | 0 | #define AI_LWO_ANIM_FLAG_SAMPLE_ANIMS 0x1 |
178 | | |
179 | | |
180 | | // --------------------------------------------------------------------------- |
181 | | //! @def AI_LWO_ANIM_FLAG_START_AT_ZERO |
182 | | //! Flag for AnimResolver, ensures that the animations starts at zero. |
183 | 0 | #define AI_LWO_ANIM_FLAG_START_AT_ZERO 0x2 |
184 | | |
185 | | // --------------------------------------------------------------------------- |
186 | | /** @brief Utility class to build Assimp animations from LWO envelopes. |
187 | | * |
188 | | * Used for both LWO and LWS (MOT also). |
189 | | */ |
190 | | class AnimResolver |
191 | | { |
192 | | public: |
193 | | |
194 | | // ------------------------------------------------------------------ |
195 | | /** @brief Construct an AnimResolver from a given list of envelopes |
196 | | * @param envelopes Input envelopes. May be empty. |
197 | | * @param Output tick rate, per second |
198 | | * @note The input envelopes are possibly modified. |
199 | | */ |
200 | | AnimResolver(std::list<Envelope>& envelopes, double tick); |
201 | | |
202 | | public: |
203 | | |
204 | | // ------------------------------------------------------------------ |
205 | | /** @brief Extract the bind-pose transformation matrix. |
206 | | * @param out Receives bind-pose transformation matrix |
207 | | */ |
208 | | void ExtractBindPose(aiMatrix4x4& out); |
209 | | |
210 | | // ------------------------------------------------------------------ |
211 | | /** @brief Extract a node animation channel |
212 | | * @param out Receives a pointer to a newly allocated node anim. |
213 | | * If there's just one keyframe defined, *out is set to nullptr and |
214 | | * no animation channel is computed. |
215 | | * @param flags Any combination of the AI_LWO_ANIM_FLAG_XXX flags. |
216 | | */ |
217 | | void ExtractAnimChannel(aiNodeAnim** out, unsigned int flags = 0); |
218 | | |
219 | | |
220 | | // ------------------------------------------------------------------ |
221 | | /** @brief Set the sampling rate for ExtractAnimChannel(). |
222 | | * |
223 | | * Non-linear interpolations are subsampled with this rate (keys |
224 | | * per second). Closer sampling positions, if existent, are kept. |
225 | | * The sampling rate defaults to 0, if this value is not changed and |
226 | | * AI_LWO_ANIM_FLAG_SAMPLE_ANIMS is specified for ExtractAnimChannel(), |
227 | | * the class finds a suitable sample rate by itself. |
228 | | */ |
229 | 0 | void SetSampleRate(double sr) { |
230 | 0 | sample_rate = sr; |
231 | 0 | } |
232 | | |
233 | | // ------------------------------------------------------------------ |
234 | | /** @brief Getter for SetSampleRate() |
235 | | */ |
236 | 0 | double GetSampleRate() const { |
237 | 0 | return sample_rate; |
238 | 0 | } |
239 | | |
240 | | // ------------------------------------------------------------------ |
241 | | /** @brief Set the animation time range |
242 | | * |
243 | | * @param first Time where the animation starts, in ticks |
244 | | * @param last Time where the animation ends, in ticks |
245 | | */ |
246 | 0 | void SetAnimationRange(double _first, double _last) { |
247 | 0 | first = _first; |
248 | 0 | last = _last; |
249 | |
|
250 | 0 | ClearAnimRangeSetup(); |
251 | 0 | UpdateAnimRangeSetup(); |
252 | 0 | } |
253 | | |
254 | | protected: |
255 | | |
256 | | // ------------------------------------------------------------------ |
257 | | /** @brief Build linearly subsampled keys from 3 single envelopes |
258 | | * @param out Receives output keys |
259 | | * @param envl_x X-component envelope |
260 | | * @param envl_y Y-component envelope |
261 | | * @param envl_z Z-component envelope |
262 | | * @param flags Any combination of the AI_LWO_ANIM_FLAG_XXX flags. |
263 | | * @note Up to two input envelopes may be nullptr |
264 | | */ |
265 | | void GetKeys(std::vector<aiVectorKey>& out, |
266 | | LWO::Envelope* envl_x, |
267 | | LWO::Envelope* envl_y, |
268 | | LWO::Envelope* envl_z, |
269 | | unsigned int flags); |
270 | | |
271 | | // ------------------------------------------------------------------ |
272 | | /** @brief Resolve a single animation key by applying the right |
273 | | * interpolation to it. |
274 | | * @param cur Current key |
275 | | * @param envl Envelope working on |
276 | | * @param time time to be interpolated |
277 | | * @param fill Receives the interpolated output value. |
278 | | */ |
279 | | void DoInterpolation(std::vector<LWO::Key>::const_iterator cur, |
280 | | LWO::Envelope* envl,double time, float& fill); |
281 | | |
282 | | // ------------------------------------------------------------------ |
283 | | /** @brief Almost the same, except we won't handle pre/post |
284 | | * conditions here. |
285 | | * @see DoInterpolation |
286 | | */ |
287 | | void DoInterpolation2(std::vector<LWO::Key>::const_iterator beg, |
288 | | std::vector<LWO::Key>::const_iterator end,double time, float& fill); |
289 | | |
290 | | // ------------------------------------------------------------------ |
291 | | /** @brief Interpolate 2 tracks if one is given |
292 | | * |
293 | | * @param out Receives extra output keys |
294 | | * @param key_out Primary output key |
295 | | * @param time Time to interpolate for |
296 | | */ |
297 | | void InterpolateTrack(std::vector<aiVectorKey>& out, |
298 | | aiVectorKey& key_out,double time); |
299 | | |
300 | | // ------------------------------------------------------------------ |
301 | | /** @brief Subsample an animation track by a given sampling rate |
302 | | * |
303 | | * @param out Receives output keys. Last key at input defines the |
304 | | * time where subsampling starts. |
305 | | * @param time Time to end subsampling at |
306 | | * @param sample_delta Time delta between two samples |
307 | | */ |
308 | | void SubsampleAnimTrack(std::vector<aiVectorKey>& out, |
309 | | double time,double sample_delta); |
310 | | |
311 | | // ------------------------------------------------------------------ |
312 | | /** @brief Delete all keys which we inserted to match anim setup |
313 | | */ |
314 | | void ClearAnimRangeSetup(); |
315 | | |
316 | | // ------------------------------------------------------------------ |
317 | | /** @brief Insert extra keys to match LWO's pre and post behaviours |
318 | | * in a given time range [first...last] |
319 | | */ |
320 | | void UpdateAnimRangeSetup(); |
321 | | |
322 | | private: |
323 | | std::list<Envelope>& envelopes; |
324 | | double sample_rate; |
325 | | |
326 | | LWO::Envelope* trans_x, *trans_y, *trans_z; |
327 | | LWO::Envelope* rotat_x, *rotat_y, *rotat_z; |
328 | | LWO::Envelope* scale_x, *scale_y, *scale_z; |
329 | | |
330 | | double first, last; |
331 | | bool need_to_setup; |
332 | | |
333 | | // temporary storage |
334 | | LWO::Envelope* envl_x, * envl_y, * envl_z; |
335 | | std::vector<LWO::Key>::const_iterator cur_x,cur_y,cur_z; |
336 | | bool end_x, end_y, end_z; |
337 | | |
338 | | unsigned int flags; |
339 | | double sample_delta; |
340 | | }; |
341 | | |
342 | | } // end namespace LWO |
343 | | } // end namespace Assimp |
344 | | |
345 | | #endif // !! AI_LWO_ANIMATION_INCLUDED |