os/graphics/m3g/m3gcore11/src/m3g_animationtrack.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
/*
sl@0
     2
* Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     3
* All rights reserved.
sl@0
     4
* This component and the accompanying materials are made available
sl@0
     5
* under the terms of the License "Eclipse Public License v1.0"
sl@0
     6
* which accompanies this distribution, and is available
sl@0
     7
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     8
*
sl@0
     9
* Initial Contributors:
sl@0
    10
* Nokia Corporation - initial contribution.
sl@0
    11
*
sl@0
    12
* Contributors:
sl@0
    13
*
sl@0
    14
* Description: AnimationTrack implementation
sl@0
    15
*
sl@0
    16
*/
sl@0
    17
sl@0
    18
sl@0
    19
/*!
sl@0
    20
 * \internal
sl@0
    21
 * \file
sl@0
    22
 * \brief AnimationTrack implementation
sl@0
    23
 */
sl@0
    24
sl@0
    25
#ifndef M3G_CORE_INCLUDE
sl@0
    26
#   error included by m3g_core.c; do not compile separately.
sl@0
    27
#endif
sl@0
    28
sl@0
    29
#include "m3g_animationtrack.h"
sl@0
    30
#include "m3g_keyframesequence.h"
sl@0
    31
#include "m3g_memory.h"
sl@0
    32
sl@0
    33
sl@0
    34
/*----------------------------------------------------------------------
sl@0
    35
 * Internal functions
sl@0
    36
 *--------------------------------------------------------------------*/
sl@0
    37
sl@0
    38
/*!
sl@0
    39
 * \internal
sl@0
    40
 * \brief Destroys this AnimationTrack object.
sl@0
    41
 *
sl@0
    42
 * \param obj AnimationTrack object
sl@0
    43
 */
sl@0
    44
static void m3gDestroyAnimationTrack(Object *obj)
sl@0
    45
{
sl@0
    46
    AnimationTrack *animTrack = (AnimationTrack *) obj;
sl@0
    47
    M3G_VALIDATE_OBJECT(animTrack);
sl@0
    48
    
sl@0
    49
    M3G_ASSIGN_REF(animTrack->sequence,   NULL);
sl@0
    50
    M3G_ASSIGN_REF(animTrack->controller, NULL);
sl@0
    51
    
sl@0
    52
    m3gDestroyObject(&animTrack->object);
sl@0
    53
}
sl@0
    54
sl@0
    55
/*!
sl@0
    56
 * \internal
sl@0
    57
 * \brief Calculates animation track contribution.
sl@0
    58
 *
sl@0
    59
 * \param track AnimationTrack object
sl@0
    60
 * \param time current world time
sl@0
    61
 * \param accumSamples accumulated samples
sl@0
    62
 * \param sampleInfo sample information
sl@0
    63
 */
sl@0
    64
static void m3gGetContribution(const AnimationTrack *track, M3Gint time,
sl@0
    65
                               M3Gfloat *accumSamples, SampleInfo *sampleInfo)
sl@0
    66
{
sl@0
    67
    if (track->controller == NULL || !m3gIsActive(track->controller, time)) {
sl@0
    68
        sampleInfo->weight = 0;
sl@0
    69
        sampleInfo->validity = (track->controller ?
sl@0
    70
                                m3gTimeToActivation(track->controller, time) :
sl@0
    71
                                0x7FFFFFFF);
sl@0
    72
        if (sampleInfo->validity < 1)
sl@0
    73
            sampleInfo->validity = 1;
sl@0
    74
        return;
sl@0
    75
    }
sl@0
    76
    {
sl@0
    77
        M3Gfloat stackSampleVector[4];
sl@0
    78
        Interface *m3g = M3G_INTERFACE(track);
sl@0
    79
        M3Gint i, sampleTime, sampleValidity;
sl@0
    80
        M3Gfloat weight;
sl@0
    81
        M3Gint sampleLength = m3gGetNumComponents(track->sequence);
sl@0
    82
        M3Gfloat *sample;
sl@0
    83
sl@0
    84
        /* Before sampling, make sure that this track has some effect
sl@0
    85
         * on the end result */
sl@0
    86
        
sl@0
    87
        weight = m3gGetWeight(track->controller);
sl@0
    88
        sampleInfo->weight = weight;
sl@0
    89
        
sl@0
    90
        if (weight <= 0.0f) {
sl@0
    91
            sampleInfo->validity = 0x7FFFFFFF;
sl@0
    92
            return;
sl@0
    93
        }
sl@0
    94
            
sl@0
    95
        /* We use the stack-allocated sample vector by default, but
sl@0
    96
         * the MORPH_WEIGHTS target may have more than 4 components,
sl@0
    97
         * in which case we resort to the global temp vector. This
sl@0
    98
         * means that the temp vector can not be used in the keyframe
sl@0
    99
         * sampling code, but it doesn't seem likely that it would be
sl@0
   100
         * needed there. */
sl@0
   101
        
sl@0
   102
        if (sampleLength > 4) {
sl@0
   103
            sample = (M3Gfloat*) m3gAllocTemp(m3g, (M3Gsize) sampleLength * sizeof(M3Gfloat));
sl@0
   104
            if (!sample) {
sl@0
   105
                sampleInfo->validity = 0;
sl@0
   106
                return; /* automatic out-of-memory error */
sl@0
   107
            }
sl@0
   108
        }
sl@0
   109
        else {
sl@0
   110
            sample = stackSampleVector;
sl@0
   111
        }
sl@0
   112
        
sl@0
   113
        sampleTime = m3gRoundToInt(m3gGetPosition(track->controller, time));
sl@0
   114
        sampleValidity = m3gGetSample(track->sequence, sampleTime, sample);
sl@0
   115
        sampleInfo->validity = sampleValidity;
sl@0
   116
sl@0
   117
        /* Only bother if there was no error in GetSample... */
sl@0
   118
            
sl@0
   119
        if (sampleValidity > 0) {
sl@0
   120
sl@0
   121
            /* Resolve the validity time of the sample */
sl@0
   122
                
sl@0
   123
            sampleValidity = m3gTimeToDeactivation(track->controller, time);
sl@0
   124
            if (sampleValidity < sampleInfo->validity) {
sl@0
   125
                sampleInfo->validity = sampleValidity;
sl@0
   126
            }
sl@0
   127
                
sl@0
   128
            /* Add the weighted sample to the accumulated value
sl@0
   129
             * and return */
sl@0
   130
                
sl@0
   131
            for (i = 0; i < sampleLength; ++i) {
sl@0
   132
                accumSamples[i] = m3gAdd(accumSamples[i],
sl@0
   133
                                         m3gMul(sample[i], weight));
sl@0
   134
            }
sl@0
   135
        }
sl@0
   136
        if (sample != stackSampleVector) {
sl@0
   137
            m3gFreeTemp(m3g);
sl@0
   138
        }
sl@0
   139
    }
sl@0
   140
}
sl@0
   141
sl@0
   142
/*!
sl@0
   143
 * \internal
sl@0
   144
 * \brief Checks animation property size.
sl@0
   145
 *
sl@0
   146
 * \param m3g M3G interface
sl@0
   147
 * \param property animation property
sl@0
   148
 * \param numComponents number of components
sl@0
   149
 * \retval M3G_TRUE valid size for property
sl@0
   150
 * \retval M3G_FALSE invalid size for property
sl@0
   151
 */
sl@0
   152
static M3Gbool m3gIsValidSize(Interface *m3g, M3Gint property, M3Gint numComponents)
sl@0
   153
{
sl@0
   154
    switch (property) {
sl@0
   155
    case M3G_ANIM_ALPHA:
sl@0
   156
    case M3G_ANIM_DENSITY:
sl@0
   157
    case M3G_ANIM_FAR_DISTANCE:
sl@0
   158
    case M3G_ANIM_FIELD_OF_VIEW:
sl@0
   159
    case M3G_ANIM_INTENSITY:
sl@0
   160
    case M3G_ANIM_NEAR_DISTANCE:
sl@0
   161
    case M3G_ANIM_PICKABILITY:
sl@0
   162
    case M3G_ANIM_SHININESS:
sl@0
   163
    case M3G_ANIM_SPOT_ANGLE:
sl@0
   164
    case M3G_ANIM_SPOT_EXPONENT:
sl@0
   165
    case M3G_ANIM_VISIBILITY:
sl@0
   166
        return (numComponents == 1);
sl@0
   167
    case M3G_ANIM_CROP:
sl@0
   168
        return (numComponents == 2 || numComponents == 4);
sl@0
   169
    case M3G_ANIM_COLOR:
sl@0
   170
    case M3G_ANIM_AMBIENT_COLOR:
sl@0
   171
    case M3G_ANIM_DIFFUSE_COLOR:
sl@0
   172
    case M3G_ANIM_EMISSIVE_COLOR:
sl@0
   173
    case M3G_ANIM_SPECULAR_COLOR:
sl@0
   174
        return (numComponents == 3);
sl@0
   175
    case M3G_ANIM_TRANSLATION:
sl@0
   176
        return (numComponents == 3);
sl@0
   177
    case M3G_ANIM_ORIENTATION:
sl@0
   178
        return (numComponents == 4);
sl@0
   179
    case M3G_ANIM_SCALE:
sl@0
   180
        return (numComponents == 1 || numComponents == 3);
sl@0
   181
    case M3G_ANIM_MORPH_WEIGHTS:
sl@0
   182
        return (numComponents > 0);
sl@0
   183
    default:
sl@0
   184
        m3gRaiseError(m3g, M3G_INVALID_ENUM);
sl@0
   185
    }
sl@0
   186
    return M3G_FALSE;
sl@0
   187
}
sl@0
   188
sl@0
   189
/*!
sl@0
   190
 * \internal
sl@0
   191
 * \brief Overloaded Object3D method.
sl@0
   192
 *
sl@0
   193
 * \param self AnimationTrack object
sl@0
   194
 * \param references array of reference objects
sl@0
   195
 * \return number of references
sl@0
   196
 */
sl@0
   197
static M3Gint m3gAnimationTrackDoGetReferences(Object *self, Object **references)
sl@0
   198
{
sl@0
   199
    AnimationTrack *track = (AnimationTrack *) self;
sl@0
   200
    M3Gint num = m3gObjectDoGetReferences(self, references);
sl@0
   201
    if (track->sequence != NULL) {
sl@0
   202
        if (references != NULL)
sl@0
   203
            references[num] = (Object *)track->sequence;
sl@0
   204
        num++;
sl@0
   205
    }
sl@0
   206
    if (track->controller != NULL) {
sl@0
   207
        if (references != NULL)
sl@0
   208
            references[num] = (Object *)track->controller;
sl@0
   209
        num++;
sl@0
   210
    }
sl@0
   211
    return num;
sl@0
   212
}
sl@0
   213
sl@0
   214
/*!
sl@0
   215
 * \internal
sl@0
   216
 * \brief Overloaded Object3D method
sl@0
   217
 */
sl@0
   218
static Object *m3gAnimationTrackFindID(Object *self, M3Gint userID)
sl@0
   219
{
sl@0
   220
    AnimationTrack *track = (AnimationTrack *) self;
sl@0
   221
    Object *found = m3gObjectFindID(self, userID);
sl@0
   222
    
sl@0
   223
    if (!found && track->sequence != NULL) {
sl@0
   224
        found = m3gFindID((Object*) track->sequence, userID);
sl@0
   225
    }
sl@0
   226
    if (!found && track->controller != NULL) {
sl@0
   227
        found = m3gFindID((Object*) track->controller, userID);
sl@0
   228
    }
sl@0
   229
    return found;
sl@0
   230
}
sl@0
   231
sl@0
   232
/*!
sl@0
   233
 * \internal
sl@0
   234
 * \brief Overloaded Object3D method.
sl@0
   235
 *
sl@0
   236
 * \param originalObj original AnimationTrack object
sl@0
   237
 * \param cloneObj pointer to cloned AnimationTrack object
sl@0
   238
 * \param pairs array for all object-duplicate pairs
sl@0
   239
 * \param numPairs number of pairs
sl@0
   240
 */
sl@0
   241
static M3Gbool m3gAnimationTrackDuplicate(const Object *originalObj,
sl@0
   242
                                          Object **cloneObj,
sl@0
   243
                                          Object **pairs,
sl@0
   244
                                          M3Gint *numPairs)
sl@0
   245
{
sl@0
   246
    AnimationTrack *original = (AnimationTrack *)originalObj;
sl@0
   247
    AnimationTrack *clone =
sl@0
   248
        (AnimationTrack *)m3gCreateAnimationTrack(originalObj->interface,
sl@0
   249
                                                  original->sequence,
sl@0
   250
                                                  original->property);
sl@0
   251
    *cloneObj = (Object *)clone;
sl@0
   252
    if (*cloneObj == NULL) {
sl@0
   253
        return M3G_FALSE;
sl@0
   254
    }
sl@0
   255
sl@0
   256
    if(m3gObjectDuplicate(originalObj, cloneObj, pairs, numPairs)) {
sl@0
   257
        M3G_ASSIGN_REF(clone->controller, original->controller);
sl@0
   258
        return M3G_TRUE;
sl@0
   259
    }
sl@0
   260
    else {
sl@0
   261
        return M3G_FALSE;
sl@0
   262
    }
sl@0
   263
}
sl@0
   264
sl@0
   265
/*----------------------------------------------------------------------
sl@0
   266
 * Virtual function table
sl@0
   267
 *--------------------------------------------------------------------*/
sl@0
   268
sl@0
   269
static const ObjectVFTable m3gvf_AnimationTrack = {
sl@0
   270
    m3gObjectApplyAnimation,
sl@0
   271
    m3gObjectIsCompatible,
sl@0
   272
    m3gObjectUpdateProperty,
sl@0
   273
    m3gAnimationTrackDoGetReferences,
sl@0
   274
    m3gAnimationTrackFindID,
sl@0
   275
    m3gAnimationTrackDuplicate,
sl@0
   276
    m3gDestroyAnimationTrack
sl@0
   277
};
sl@0
   278
sl@0
   279
sl@0
   280
/*----------------------------------------------------------------------
sl@0
   281
 * Public API functions
sl@0
   282
 *--------------------------------------------------------------------*/
sl@0
   283
sl@0
   284
/*!
sl@0
   285
 * \brief Creates a new AnimationTrack with default values
sl@0
   286
 *
sl@0
   287
 * \param hInterface            M3G interface
sl@0
   288
 * \param hSequence             KeyframeSequence object
sl@0
   289
 * \param property              target animation property
sl@0
   290
 * \retval AnimationTrack new AnimationTrack object
sl@0
   291
 * \retval NULL AnimationTrack creating failed
sl@0
   292
 */
sl@0
   293
M3G_API M3GAnimationTrack m3gCreateAnimationTrack(M3GInterface hInterface,
sl@0
   294
                                                  M3GKeyframeSequence hSequence,
sl@0
   295
                                                  M3Gint property)
sl@0
   296
{
sl@0
   297
    KeyframeSequence *sequence = (KeyframeSequence *)hSequence;
sl@0
   298
    Interface *m3g = (Interface *) hInterface;
sl@0
   299
    M3G_VALIDATE_INTERFACE(m3g);
sl@0
   300
sl@0
   301
    /* Check for invalid arguments */
sl@0
   302
    
sl@0
   303
    if (sequence == NULL) {
sl@0
   304
        m3gRaiseError(m3g, M3G_NULL_POINTER);
sl@0
   305
        return NULL;
sl@0
   306
    }
sl@0
   307
    if (property < M3G_ANIM_ALPHA || property > M3G_ANIM_VISIBILITY) {
sl@0
   308
        m3gRaiseError(m3g, M3G_INVALID_ENUM);
sl@0
   309
        return NULL;
sl@0
   310
    }
sl@0
   311
    if (!m3gIsValidSize(m3g, property, m3gGetNumComponents(sequence))) {
sl@0
   312
        m3gRaiseError(m3g, M3G_INVALID_VALUE);
sl@0
   313
        return NULL;
sl@0
   314
    }
sl@0
   315
sl@0
   316
    /* Allocate and initialize the object */
sl@0
   317
    
sl@0
   318
    {
sl@0
   319
        AnimationTrack *track = m3gAllocZ(m3g, sizeof(AnimationTrack));
sl@0
   320
sl@0
   321
        if (track != NULL) {
sl@0
   322
            M3G_ASSIGN_REF(track->sequence, sequence);
sl@0
   323
            track->property = property;
sl@0
   324
            m3gInitObject(&track->object, m3g, M3G_CLASS_ANIMATION_TRACK);
sl@0
   325
        }
sl@0
   326
        
sl@0
   327
        return track;
sl@0
   328
    }
sl@0
   329
}
sl@0
   330
sl@0
   331
/*!
sl@0
   332
 * \brief Get animation controller.
sl@0
   333
 *
sl@0
   334
 * \param hTrack                AnimationTrack object
sl@0
   335
 * \retval                      AnimationController object
sl@0
   336
 */
sl@0
   337
M3G_API M3GAnimationController m3gGetController(M3GAnimationTrack hTrack)
sl@0
   338
{
sl@0
   339
    AnimationTrack *track = (AnimationTrack *) hTrack;
sl@0
   340
    M3G_VALIDATE_OBJECT(track);
sl@0
   341
sl@0
   342
    return track->controller;
sl@0
   343
}
sl@0
   344
sl@0
   345
/*!
sl@0
   346
 * \brief Get key frame sequence.
sl@0
   347
 *
sl@0
   348
 * \param hTrack                AnimationTrack object
sl@0
   349
 * \retval                      KeyframeSequence object
sl@0
   350
 */
sl@0
   351
M3G_API M3GKeyframeSequence m3gGetSequence(M3GAnimationTrack hTrack)
sl@0
   352
{
sl@0
   353
    AnimationTrack *track = (AnimationTrack *) hTrack;
sl@0
   354
    M3G_VALIDATE_OBJECT(track);
sl@0
   355
sl@0
   356
    return track->sequence;
sl@0
   357
}
sl@0
   358
sl@0
   359
/*!
sl@0
   360
 * \brief Get animation target property.
sl@0
   361
 *
sl@0
   362
 * \param hTrack                AnimationTrack object
sl@0
   363
 * \retval                      target property
sl@0
   364
 */
sl@0
   365
M3G_API M3Gint m3gGetTargetProperty(M3GAnimationTrack hTrack)
sl@0
   366
{
sl@0
   367
    AnimationTrack *track = (AnimationTrack *) hTrack;
sl@0
   368
    M3G_VALIDATE_OBJECT(track);
sl@0
   369
sl@0
   370
    return track->property;
sl@0
   371
}
sl@0
   372
sl@0
   373
/*!
sl@0
   374
 * \brief Set animation controller.
sl@0
   375
 *
sl@0
   376
 * \param hTrack                AnimationTrack object
sl@0
   377
 * \param hController           AnimationController object
sl@0
   378
 */
sl@0
   379
M3G_API void m3gSetController(M3GAnimationTrack hTrack,
sl@0
   380
                              M3GAnimationController hController)
sl@0
   381
{
sl@0
   382
    AnimationTrack *track = (AnimationTrack *) hTrack;
sl@0
   383
    M3G_VALIDATE_OBJECT(track);
sl@0
   384
sl@0
   385
    M3G_ASSIGN_REF(track->controller, hController);
sl@0
   386
}
sl@0
   387