topical media & game development
student-ar-org-ascollada-core-DaeAnimationCurve.ax
student-ar-org-ascollada-core-DaeAnimationCurve.ax
[swf]
flex
/*
* Copyright 2007 (c) Tim Knip, ascollada.org.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package org.ascollada.core
{
import org.ascollada.core.DaeEntity;
public class @ax-student-ar-org-ascollada-core-DaeAnimationCurve extends DaeEntity
{
public static const INTERPOLATION_STEP:uint = 0; //equivalent to no interpolation
public static const INTERPOLATION_LINEAR:uint = 1;
public static const INTERPOLATION_BEZIER:uint = 2;
public static const INTERPOLATION_TCB:uint = 3;
public static const INTERPOLATION_UNKNOWN:uint = 4;
public static const INTERPOLATION_DEFAULT:uint = 0;
public static const INFINITY_CONSTANT:uint = 0;
public static const INFINITY_LINEAR:uint = 1;
public static const INFINITY_CYCLE:uint = 2;
public static const INFINITY_CYCLE_RELATIVE:uint = 3;
public static const INFINITY_OSCILLATE:uint = 4;
public static const INFINITY_UNKNOWN:uint = 5;
public static const INFINITY_DEFAULT:uint = 0;
public var keys:Array;
public var keyValues:Array;
public var interpolations:Array;
public var inTangents:Array;
public var outTangents:Array;
public var tcbParameters:Array;
public var easeInOuts:Array;
public var preInfinity:uint = 0;
public var postInfinity:uint = 0;
public var interpolationType:uint = 1;
@param keys
@param keyValues
public function @ax-student-ar-org-ascollada-core-DaeAnimationCurve( keys:Array = null, keyValues:Array = null ):void
{
this.keys = keys || new Array();
this.keyValues = keyValues || new Array();
this.interpolations = new Array();
}
main workhorse for the animation system.
@param time
@return
public function evaluate( dt:Number ):Number
{
// Check for empty curves and poses (curves with 1 key).
if( !this.keys.length ) return 0.0;
if( this.keys.length == 1 ) return this.keyValues[0];
var i:int;
var outputStart:Number = this.keyValues[0];
var outputEnd:Number = this.keyValues[this.keyValues.length-1];
var inputStart:Number = this.keys[0];
var inputEnd:Number = this.keys[this.keys.length-1];
var inputSpan:Number = inputEnd - inputStart;
var cycleCount:Number;
dt = dt % inputEnd;
// Account for pre-infinity mode
var outputOffset:Number = 0.0;
if( dt <= inputStart )
{
switch( preInfinity )
{
case INFINITY_CONSTANT: return outputStart;
case INFINITY_LINEAR: return outputStart + (dt - inputStart) * (keyValues[1] - outputStart) / (keys[1] - inputStart);
case INFINITY_CYCLE: { cycleCount = Math.ceil((inputStart - dt) / inputSpan); dt += cycleCount * inputSpan; break; }
case INFINITY_CYCLE_RELATIVE: { cycleCount = Math.ceil((inputStart - dt) / inputSpan); dt += cycleCount * inputSpan; outputOffset -= cycleCount * (outputEnd - outputStart); break; }
case INFINITY_OSCILLATE: { cycleCount = Math.ceil((inputStart - dt) / (2.0 * inputSpan)); dt += cycleCount * 2.0 * inputSpan; dt = inputEnd - Math.abs(dt - inputEnd); break; }
case INFINITY_UNKNOWN: default: return outputStart;
}
}
else if (dt >= inputEnd)
{
// Account for post-infinity mode
switch (postInfinity)
{
case INFINITY_CONSTANT: return outputEnd;
case INFINITY_LINEAR: return outputEnd + (dt - inputEnd) * (keyValues[keys.length - 2] - outputEnd) / (keys[keys.length - 2] - inputEnd);
case INFINITY_CYCLE: { cycleCount = Math.ceil((dt - inputEnd) / inputSpan); dt -= cycleCount * inputSpan; break; }
case INFINITY_CYCLE_RELATIVE: { cycleCount = Math.ceil((dt - inputEnd) / inputSpan); dt -= cycleCount * inputSpan; outputOffset += cycleCount * (outputEnd - outputStart); break; }
case INFINITY_OSCILLATE: { cycleCount = Math.ceil((dt - inputEnd) / (2.0 * inputSpan)); dt -= cycleCount * 2.0 * inputSpan; dt = inputStart + Math.abs(dt - inputStart); break; }
case INFINITY_UNKNOWN: default: return outputEnd;
}
}
// speed up interval search
var approxi:int = Math.ceil((dt/inputEnd) * this.keys.length);
// Find the current interval
for( i = approxi; i < this.keys.length; ++i )
if( this.keys[i] > dt ) break;
var index:int = i;
// Get the keys and values for this interval
var endKey:Number = this.keys[index];
var startKey:Number = this.keys[index - 1];
var endValue:Number = this.keyValues[index];
var startValue:Number = this.keyValues[index - 1];
var output:Number;
switch( interpolationType )
{
case INTERPOLATION_LINEAR:
output = (dt - startKey) / (endKey - startKey) * (endValue - startValue) + startValue;
break;
case INTERPOLATION_STEP:
default:
output = startValue;
break;
}
return outputOffset + output;
}
}
}
(C) Æliens
27/08/2009
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.