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 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
55struct aiNodeAnim;
56struct aiVectorKey;
57
58namespace Assimp {
59namespace LWO {
60
61// ---------------------------------------------------------------------------
62/** \brief List of recognized LWO envelopes
63 */
64enum 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 */
93enum 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 */
102enum 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 */
115struct Key
116{
117 Key()
118 : time(),
119 value(),
120 inter (IT_LINE),
121 params()
122 {}
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 operator double () {
139 return time;
140 }
141};
142
143// ---------------------------------------------------------------------------
144/** \brief Data structure for a LWO animation envelope
145 */
146struct Envelope
147{
148 Envelope()
149 : index()
150 , type (EnvelopeType_Unknown)
151 , pre (PrePostBehaviour_Constant)
152 , post (PrePostBehaviour_Constant)
153
154 , old_first (0)
155 , old_last (0)
156 {}
157
158 //! Index of this envelope
159 unsigned int index;
160
161 //! Type of envelope
162 EnvelopeType type;
163
164 //! Pre and post-behaviour
165 PrePostBehaviour pre,post;
166
167 //! Keyframes for this envelope
168 std::vector<Key> keys;
169
170 // temporary data for AnimResolver
171 size_t old_first,old_last;
172};
173
174// ---------------------------------------------------------------------------
175//! @def AI_LWO_ANIM_FLAG_SAMPLE_ANIMS
176//! Flag for AnimResolver, subsamples the input data with the rate specified
177//! by AnimResolver::SetSampleRate().
178#define AI_LWO_ANIM_FLAG_SAMPLE_ANIMS 0x1
179
180
181// ---------------------------------------------------------------------------
182//! @def AI_LWO_ANIM_FLAG_START_AT_ZERO
183//! Flag for AnimResolver, ensures that the animations starts at zero.
184#define AI_LWO_ANIM_FLAG_START_AT_ZERO 0x2
185
186// ---------------------------------------------------------------------------
187/** @brief Utility class to build Assimp animations from LWO envelopes.
188 *
189 * Used for both LWO and LWS (MOT also).
190 */
191class AnimResolver
192{
193public:
194
195 // ------------------------------------------------------------------
196 /** @brief Construct an AnimResolver from a given list of envelopes
197 * @param envelopes Input envelopes. May be empty.
198 * @param Output tick rate, per second
199 * @note The input envelopes are possibly modified.
200 */
201 AnimResolver(std::list<Envelope>& envelopes, double tick);
202
203public:
204
205 // ------------------------------------------------------------------
206 /** @brief Extract the bind-pose transformation matrix.
207 * @param out Receives bind-pose transformation matrix
208 */
209 void ExtractBindPose(aiMatrix4x4& out);
210
211 // ------------------------------------------------------------------
212 /** @brief Extract a node animation channel
213 * @param out Receives a pointer to a newly allocated node anim.
214 * If there's just one keyframe defined, *out is set to NULL and
215 * no animation channel is computed.
216 * @param flags Any combination of the AI_LWO_ANIM_FLAG_XXX flags.
217 */
218 void ExtractAnimChannel(aiNodeAnim** out, unsigned int flags = 0);
219
220
221 // ------------------------------------------------------------------
222 /** @brief Set the sampling rate for ExtractAnimChannel().
223 *
224 * Non-linear interpolations are subsampled with this rate (keys
225 * per second). Closer sampling positions, if existent, are kept.
226 * The sampling rate defaults to 0, if this value is not changed and
227 * AI_LWO_ANIM_FLAG_SAMPLE_ANIMS is specified for ExtractAnimChannel(),
228 * the class finds a suitable sample rate by itself.
229 */
230 void SetSampleRate(double sr) {
231 sample_rate = sr;
232 }
233
234 // ------------------------------------------------------------------
235 /** @brief Getter for SetSampleRate()
236 */
237 double GetSampleRate() const {
238 return sample_rate;
239 }
240
241 // ------------------------------------------------------------------
242 /** @brief Set the animation time range
243 *
244 * @param first Time where the animation starts, in ticks
245 * @param last Time where the animation ends, in ticks
246 */
247 void SetAnimationRange(double _first, double _last) {
248 first = _first;
249 last = _last;
250
251 ClearAnimRangeSetup();
252 UpdateAnimRangeSetup();
253 }
254
255protected:
256
257 // ------------------------------------------------------------------
258 /** @brief Build linearly subsampled keys from 3 single envelopes
259 * @param out Receives output keys
260 * @param envl_x X-component envelope
261 * @param envl_y Y-component envelope
262 * @param envl_z Z-component envelope
263 * @param flags Any combination of the AI_LWO_ANIM_FLAG_XXX flags.
264 * @note Up to two input envelopes may be NULL
265 */
266 void GetKeys(std::vector<aiVectorKey>& out,
267 LWO::Envelope* envl_x,
268 LWO::Envelope* envl_y,
269 LWO::Envelope* envl_z,
270 unsigned int flags);
271
272 // ------------------------------------------------------------------
273 /** @brief Resolve a single animation key by applying the right
274 * interpolation to it.
275 * @param cur Current key
276 * @param envl Envelope working on
277 * @param time time to be interpolated
278 * @param fill Receives the interpolated output value.
279 */
280 void DoInterpolation(std::vector<LWO::Key>::const_iterator cur,
281 LWO::Envelope* envl,double time, float& fill);
282
283 // ------------------------------------------------------------------
284 /** @brief Almost the same, except we won't handle pre/post
285 * conditions here.
286 * @see DoInterpolation
287 */
288 void DoInterpolation2(std::vector<LWO::Key>::const_iterator beg,
289 std::vector<LWO::Key>::const_iterator end,double time, float& fill);
290
291 // ------------------------------------------------------------------
292 /** @brief Interpolate 2 tracks if one is given
293 *
294 * @param out Receives extra output keys
295 * @param key_out Primary output key
296 * @param time Time to interpolate for
297 */
298 void InterpolateTrack(std::vector<aiVectorKey>& out,
299 aiVectorKey& key_out,double time);
300
301 // ------------------------------------------------------------------
302 /** @brief Subsample an animation track by a given sampling rate
303 *
304 * @param out Receives output keys. Last key at input defines the
305 * time where subsampling starts.
306 * @param time Time to end subsampling at
307 * @param sample_delta Time delta between two samples
308 */
309 void SubsampleAnimTrack(std::vector<aiVectorKey>& out,
310 double time,double sample_delta);
311
312 // ------------------------------------------------------------------
313 /** @brief Delete all keys which we inserted to match anim setup
314 */
315 void ClearAnimRangeSetup();
316
317 // ------------------------------------------------------------------
318 /** @brief Insert extra keys to match LWO's pre and post behaviours
319 * in a given time range [first...last]
320 */
321 void UpdateAnimRangeSetup();
322
323private:
324 std::list<Envelope>& envelopes;
325 double sample_rate;
326
327 LWO::Envelope* trans_x, *trans_y, *trans_z;
328 LWO::Envelope* rotat_x, *rotat_y, *rotat_z;
329 LWO::Envelope* scale_x, *scale_y, *scale_z;
330
331 double first, last;
332 bool need_to_setup;
333
334 // temporary storage
335 LWO::Envelope* envl_x, * envl_y, * envl_z;
336 std::vector<LWO::Key>::const_iterator cur_x,cur_y,cur_z;
337 bool end_x, end_y, end_z;
338
339 unsigned int flags;
340 double sample_delta;
341};
342
343} // end namespace LWO
344} // end namespace Assimp
345
346#endif // !! AI_LWO_ANIMATION_INCLUDED
347