Coverage Report

Created: 2026-05-16 07:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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