1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/graphics/m3g/m3gcore11/src/m3g_animationtrack.c Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,387 @@
1.4 +/*
1.5 +* Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
1.6 +* All rights reserved.
1.7 +* This component and the accompanying materials are made available
1.8 +* under the terms of the License "Eclipse Public License v1.0"
1.9 +* which accompanies this distribution, and is available
1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +*
1.12 +* Initial Contributors:
1.13 +* Nokia Corporation - initial contribution.
1.14 +*
1.15 +* Contributors:
1.16 +*
1.17 +* Description: AnimationTrack implementation
1.18 +*
1.19 +*/
1.20 +
1.21 +
1.22 +/*!
1.23 + * \internal
1.24 + * \file
1.25 + * \brief AnimationTrack implementation
1.26 + */
1.27 +
1.28 +#ifndef M3G_CORE_INCLUDE
1.29 +# error included by m3g_core.c; do not compile separately.
1.30 +#endif
1.31 +
1.32 +#include "m3g_animationtrack.h"
1.33 +#include "m3g_keyframesequence.h"
1.34 +#include "m3g_memory.h"
1.35 +
1.36 +
1.37 +/*----------------------------------------------------------------------
1.38 + * Internal functions
1.39 + *--------------------------------------------------------------------*/
1.40 +
1.41 +/*!
1.42 + * \internal
1.43 + * \brief Destroys this AnimationTrack object.
1.44 + *
1.45 + * \param obj AnimationTrack object
1.46 + */
1.47 +static void m3gDestroyAnimationTrack(Object *obj)
1.48 +{
1.49 + AnimationTrack *animTrack = (AnimationTrack *) obj;
1.50 + M3G_VALIDATE_OBJECT(animTrack);
1.51 +
1.52 + M3G_ASSIGN_REF(animTrack->sequence, NULL);
1.53 + M3G_ASSIGN_REF(animTrack->controller, NULL);
1.54 +
1.55 + m3gDestroyObject(&animTrack->object);
1.56 +}
1.57 +
1.58 +/*!
1.59 + * \internal
1.60 + * \brief Calculates animation track contribution.
1.61 + *
1.62 + * \param track AnimationTrack object
1.63 + * \param time current world time
1.64 + * \param accumSamples accumulated samples
1.65 + * \param sampleInfo sample information
1.66 + */
1.67 +static void m3gGetContribution(const AnimationTrack *track, M3Gint time,
1.68 + M3Gfloat *accumSamples, SampleInfo *sampleInfo)
1.69 +{
1.70 + if (track->controller == NULL || !m3gIsActive(track->controller, time)) {
1.71 + sampleInfo->weight = 0;
1.72 + sampleInfo->validity = (track->controller ?
1.73 + m3gTimeToActivation(track->controller, time) :
1.74 + 0x7FFFFFFF);
1.75 + if (sampleInfo->validity < 1)
1.76 + sampleInfo->validity = 1;
1.77 + return;
1.78 + }
1.79 + {
1.80 + M3Gfloat stackSampleVector[4];
1.81 + Interface *m3g = M3G_INTERFACE(track);
1.82 + M3Gint i, sampleTime, sampleValidity;
1.83 + M3Gfloat weight;
1.84 + M3Gint sampleLength = m3gGetNumComponents(track->sequence);
1.85 + M3Gfloat *sample;
1.86 +
1.87 + /* Before sampling, make sure that this track has some effect
1.88 + * on the end result */
1.89 +
1.90 + weight = m3gGetWeight(track->controller);
1.91 + sampleInfo->weight = weight;
1.92 +
1.93 + if (weight <= 0.0f) {
1.94 + sampleInfo->validity = 0x7FFFFFFF;
1.95 + return;
1.96 + }
1.97 +
1.98 + /* We use the stack-allocated sample vector by default, but
1.99 + * the MORPH_WEIGHTS target may have more than 4 components,
1.100 + * in which case we resort to the global temp vector. This
1.101 + * means that the temp vector can not be used in the keyframe
1.102 + * sampling code, but it doesn't seem likely that it would be
1.103 + * needed there. */
1.104 +
1.105 + if (sampleLength > 4) {
1.106 + sample = (M3Gfloat*) m3gAllocTemp(m3g, (M3Gsize) sampleLength * sizeof(M3Gfloat));
1.107 + if (!sample) {
1.108 + sampleInfo->validity = 0;
1.109 + return; /* automatic out-of-memory error */
1.110 + }
1.111 + }
1.112 + else {
1.113 + sample = stackSampleVector;
1.114 + }
1.115 +
1.116 + sampleTime = m3gRoundToInt(m3gGetPosition(track->controller, time));
1.117 + sampleValidity = m3gGetSample(track->sequence, sampleTime, sample);
1.118 + sampleInfo->validity = sampleValidity;
1.119 +
1.120 + /* Only bother if there was no error in GetSample... */
1.121 +
1.122 + if (sampleValidity > 0) {
1.123 +
1.124 + /* Resolve the validity time of the sample */
1.125 +
1.126 + sampleValidity = m3gTimeToDeactivation(track->controller, time);
1.127 + if (sampleValidity < sampleInfo->validity) {
1.128 + sampleInfo->validity = sampleValidity;
1.129 + }
1.130 +
1.131 + /* Add the weighted sample to the accumulated value
1.132 + * and return */
1.133 +
1.134 + for (i = 0; i < sampleLength; ++i) {
1.135 + accumSamples[i] = m3gAdd(accumSamples[i],
1.136 + m3gMul(sample[i], weight));
1.137 + }
1.138 + }
1.139 + if (sample != stackSampleVector) {
1.140 + m3gFreeTemp(m3g);
1.141 + }
1.142 + }
1.143 +}
1.144 +
1.145 +/*!
1.146 + * \internal
1.147 + * \brief Checks animation property size.
1.148 + *
1.149 + * \param m3g M3G interface
1.150 + * \param property animation property
1.151 + * \param numComponents number of components
1.152 + * \retval M3G_TRUE valid size for property
1.153 + * \retval M3G_FALSE invalid size for property
1.154 + */
1.155 +static M3Gbool m3gIsValidSize(Interface *m3g, M3Gint property, M3Gint numComponents)
1.156 +{
1.157 + switch (property) {
1.158 + case M3G_ANIM_ALPHA:
1.159 + case M3G_ANIM_DENSITY:
1.160 + case M3G_ANIM_FAR_DISTANCE:
1.161 + case M3G_ANIM_FIELD_OF_VIEW:
1.162 + case M3G_ANIM_INTENSITY:
1.163 + case M3G_ANIM_NEAR_DISTANCE:
1.164 + case M3G_ANIM_PICKABILITY:
1.165 + case M3G_ANIM_SHININESS:
1.166 + case M3G_ANIM_SPOT_ANGLE:
1.167 + case M3G_ANIM_SPOT_EXPONENT:
1.168 + case M3G_ANIM_VISIBILITY:
1.169 + return (numComponents == 1);
1.170 + case M3G_ANIM_CROP:
1.171 + return (numComponents == 2 || numComponents == 4);
1.172 + case M3G_ANIM_COLOR:
1.173 + case M3G_ANIM_AMBIENT_COLOR:
1.174 + case M3G_ANIM_DIFFUSE_COLOR:
1.175 + case M3G_ANIM_EMISSIVE_COLOR:
1.176 + case M3G_ANIM_SPECULAR_COLOR:
1.177 + return (numComponents == 3);
1.178 + case M3G_ANIM_TRANSLATION:
1.179 + return (numComponents == 3);
1.180 + case M3G_ANIM_ORIENTATION:
1.181 + return (numComponents == 4);
1.182 + case M3G_ANIM_SCALE:
1.183 + return (numComponents == 1 || numComponents == 3);
1.184 + case M3G_ANIM_MORPH_WEIGHTS:
1.185 + return (numComponents > 0);
1.186 + default:
1.187 + m3gRaiseError(m3g, M3G_INVALID_ENUM);
1.188 + }
1.189 + return M3G_FALSE;
1.190 +}
1.191 +
1.192 +/*!
1.193 + * \internal
1.194 + * \brief Overloaded Object3D method.
1.195 + *
1.196 + * \param self AnimationTrack object
1.197 + * \param references array of reference objects
1.198 + * \return number of references
1.199 + */
1.200 +static M3Gint m3gAnimationTrackDoGetReferences(Object *self, Object **references)
1.201 +{
1.202 + AnimationTrack *track = (AnimationTrack *) self;
1.203 + M3Gint num = m3gObjectDoGetReferences(self, references);
1.204 + if (track->sequence != NULL) {
1.205 + if (references != NULL)
1.206 + references[num] = (Object *)track->sequence;
1.207 + num++;
1.208 + }
1.209 + if (track->controller != NULL) {
1.210 + if (references != NULL)
1.211 + references[num] = (Object *)track->controller;
1.212 + num++;
1.213 + }
1.214 + return num;
1.215 +}
1.216 +
1.217 +/*!
1.218 + * \internal
1.219 + * \brief Overloaded Object3D method
1.220 + */
1.221 +static Object *m3gAnimationTrackFindID(Object *self, M3Gint userID)
1.222 +{
1.223 + AnimationTrack *track = (AnimationTrack *) self;
1.224 + Object *found = m3gObjectFindID(self, userID);
1.225 +
1.226 + if (!found && track->sequence != NULL) {
1.227 + found = m3gFindID((Object*) track->sequence, userID);
1.228 + }
1.229 + if (!found && track->controller != NULL) {
1.230 + found = m3gFindID((Object*) track->controller, userID);
1.231 + }
1.232 + return found;
1.233 +}
1.234 +
1.235 +/*!
1.236 + * \internal
1.237 + * \brief Overloaded Object3D method.
1.238 + *
1.239 + * \param originalObj original AnimationTrack object
1.240 + * \param cloneObj pointer to cloned AnimationTrack object
1.241 + * \param pairs array for all object-duplicate pairs
1.242 + * \param numPairs number of pairs
1.243 + */
1.244 +static M3Gbool m3gAnimationTrackDuplicate(const Object *originalObj,
1.245 + Object **cloneObj,
1.246 + Object **pairs,
1.247 + M3Gint *numPairs)
1.248 +{
1.249 + AnimationTrack *original = (AnimationTrack *)originalObj;
1.250 + AnimationTrack *clone =
1.251 + (AnimationTrack *)m3gCreateAnimationTrack(originalObj->interface,
1.252 + original->sequence,
1.253 + original->property);
1.254 + *cloneObj = (Object *)clone;
1.255 + if (*cloneObj == NULL) {
1.256 + return M3G_FALSE;
1.257 + }
1.258 +
1.259 + if(m3gObjectDuplicate(originalObj, cloneObj, pairs, numPairs)) {
1.260 + M3G_ASSIGN_REF(clone->controller, original->controller);
1.261 + return M3G_TRUE;
1.262 + }
1.263 + else {
1.264 + return M3G_FALSE;
1.265 + }
1.266 +}
1.267 +
1.268 +/*----------------------------------------------------------------------
1.269 + * Virtual function table
1.270 + *--------------------------------------------------------------------*/
1.271 +
1.272 +static const ObjectVFTable m3gvf_AnimationTrack = {
1.273 + m3gObjectApplyAnimation,
1.274 + m3gObjectIsCompatible,
1.275 + m3gObjectUpdateProperty,
1.276 + m3gAnimationTrackDoGetReferences,
1.277 + m3gAnimationTrackFindID,
1.278 + m3gAnimationTrackDuplicate,
1.279 + m3gDestroyAnimationTrack
1.280 +};
1.281 +
1.282 +
1.283 +/*----------------------------------------------------------------------
1.284 + * Public API functions
1.285 + *--------------------------------------------------------------------*/
1.286 +
1.287 +/*!
1.288 + * \brief Creates a new AnimationTrack with default values
1.289 + *
1.290 + * \param hInterface M3G interface
1.291 + * \param hSequence KeyframeSequence object
1.292 + * \param property target animation property
1.293 + * \retval AnimationTrack new AnimationTrack object
1.294 + * \retval NULL AnimationTrack creating failed
1.295 + */
1.296 +M3G_API M3GAnimationTrack m3gCreateAnimationTrack(M3GInterface hInterface,
1.297 + M3GKeyframeSequence hSequence,
1.298 + M3Gint property)
1.299 +{
1.300 + KeyframeSequence *sequence = (KeyframeSequence *)hSequence;
1.301 + Interface *m3g = (Interface *) hInterface;
1.302 + M3G_VALIDATE_INTERFACE(m3g);
1.303 +
1.304 + /* Check for invalid arguments */
1.305 +
1.306 + if (sequence == NULL) {
1.307 + m3gRaiseError(m3g, M3G_NULL_POINTER);
1.308 + return NULL;
1.309 + }
1.310 + if (property < M3G_ANIM_ALPHA || property > M3G_ANIM_VISIBILITY) {
1.311 + m3gRaiseError(m3g, M3G_INVALID_ENUM);
1.312 + return NULL;
1.313 + }
1.314 + if (!m3gIsValidSize(m3g, property, m3gGetNumComponents(sequence))) {
1.315 + m3gRaiseError(m3g, M3G_INVALID_VALUE);
1.316 + return NULL;
1.317 + }
1.318 +
1.319 + /* Allocate and initialize the object */
1.320 +
1.321 + {
1.322 + AnimationTrack *track = m3gAllocZ(m3g, sizeof(AnimationTrack));
1.323 +
1.324 + if (track != NULL) {
1.325 + M3G_ASSIGN_REF(track->sequence, sequence);
1.326 + track->property = property;
1.327 + m3gInitObject(&track->object, m3g, M3G_CLASS_ANIMATION_TRACK);
1.328 + }
1.329 +
1.330 + return track;
1.331 + }
1.332 +}
1.333 +
1.334 +/*!
1.335 + * \brief Get animation controller.
1.336 + *
1.337 + * \param hTrack AnimationTrack object
1.338 + * \retval AnimationController object
1.339 + */
1.340 +M3G_API M3GAnimationController m3gGetController(M3GAnimationTrack hTrack)
1.341 +{
1.342 + AnimationTrack *track = (AnimationTrack *) hTrack;
1.343 + M3G_VALIDATE_OBJECT(track);
1.344 +
1.345 + return track->controller;
1.346 +}
1.347 +
1.348 +/*!
1.349 + * \brief Get key frame sequence.
1.350 + *
1.351 + * \param hTrack AnimationTrack object
1.352 + * \retval KeyframeSequence object
1.353 + */
1.354 +M3G_API M3GKeyframeSequence m3gGetSequence(M3GAnimationTrack hTrack)
1.355 +{
1.356 + AnimationTrack *track = (AnimationTrack *) hTrack;
1.357 + M3G_VALIDATE_OBJECT(track);
1.358 +
1.359 + return track->sequence;
1.360 +}
1.361 +
1.362 +/*!
1.363 + * \brief Get animation target property.
1.364 + *
1.365 + * \param hTrack AnimationTrack object
1.366 + * \retval target property
1.367 + */
1.368 +M3G_API M3Gint m3gGetTargetProperty(M3GAnimationTrack hTrack)
1.369 +{
1.370 + AnimationTrack *track = (AnimationTrack *) hTrack;
1.371 + M3G_VALIDATE_OBJECT(track);
1.372 +
1.373 + return track->property;
1.374 +}
1.375 +
1.376 +/*!
1.377 + * \brief Set animation controller.
1.378 + *
1.379 + * \param hTrack AnimationTrack object
1.380 + * \param hController AnimationController object
1.381 + */
1.382 +M3G_API void m3gSetController(M3GAnimationTrack hTrack,
1.383 + M3GAnimationController hController)
1.384 +{
1.385 + AnimationTrack *track = (AnimationTrack *) hTrack;
1.386 + M3G_VALIDATE_OBJECT(track);
1.387 +
1.388 + M3G_ASSIGN_REF(track->controller, hController);
1.389 +}
1.390 +