159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/* 259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Copyright (c) 2009-2011 jMonkeyEngine 359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * All rights reserved. 459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Redistribution and use in source and binary forms, with or without 659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * modification, are permitted provided that the following conditions are 759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * met: 859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions of source code must retain the above copyright 1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * notice, this list of conditions and the following disclaimer. 1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions in binary form must reproduce the above copyright 1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * notice, this list of conditions and the following disclaimer in the 1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * documentation and/or other materials provided with the distribution. 1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * may be used to endorse or promote products derived from this software 1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * without specific prior written permission. 1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.animation; 3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.FastMath; 3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Quaternion; 3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Transform; 3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Vector3f; 3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/** 4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * A convenience class to easily setup a spatial keyframed animation 4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * you can add some keyFrames for a given time or a given keyFrameIndex, for translation rotation and scale. 4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * The animationHelper will then generate an appropriate SpatialAnimation by interpolating values between the keyFrames. 4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <br><br> 4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Usage is : <br> 4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * - Create the AnimationHelper<br> 4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * - add some keyFrames<br> 4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * - call the buildAnimation() method that will retruna new Animation<br> 4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * - add the generated Animation to any existing AnimationControl<br> 4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <br><br> 5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Note that the first keyFrame (index 0) is defaulted with the identy transforms. 5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * If you want to change that you have to replace this keyFrame with any transform you want. 5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author Nehon 5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class AnimationFactory { 5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * step for splitting rotation that have a n ange above PI/2 5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private final static float EULER_STEP = FastMath.QUARTER_PI * 3; 6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * enum to determine the type of interpolation 6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private enum Type { 6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Translation, Rotation, Scale; 6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Inner Rotation type class to kep track on a rotation Euler angle 7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected class Rotation { 7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * The rotation Quaternion 7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Quaternion rotation = new Quaternion(); 7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This rotation expressed in Euler angles 8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f eulerAngles = new Vector3f(); 8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the index of the parent key frame is this keyFrame is a splitted rotation 8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int masterKeyFrame = -1; 8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Rotation() { 8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rotation.loadIdentity(); 9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta void set(Quaternion rot) { 9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rotation.set(rot); 9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float[] a = new float[3]; 9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rotation.toAngles(a); 9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta eulerAngles.set(a[0], a[1], a[2]); 9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta void set(float x, float y, float z) { 10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float[] a = {x, y, z}; 10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rotation.fromAngles(a); 10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta eulerAngles.set(x, y, z); 10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Name of the animation 10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected String name; 10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * frames per seconds 11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected int fps; 11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Animation duration in seconds 11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected float duration; 11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * total number of frames 11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected int totalFrames; 12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * time per frame 12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected float tpf; 12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Time array for this animation 12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected float[] times; 12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Translation array for this animation 13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected Vector3f[] translations; 13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * rotation array for this animation 13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected Quaternion[] rotations; 13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * scales array for this animation 13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected Vector3f[] scales; 14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * The map of keyFrames to compute the animation. The key is the index of the frame 14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected Vector3f[] keyFramesTranslation; 14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected Vector3f[] keyFramesScale; 14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected Rotation[] keyFramesRotation; 14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Creates and AnimationHelper 15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param duration the desired duration for the resulting animation 15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param name the name of the resulting animation 15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public AnimationFactory(float duration, String name) { 15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this(duration, name, 30); 15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Creates and AnimationHelper 15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param duration the desired duration for the resulting animation 16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param name the name of the resulting animation 16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param fps the number of frames per second for this animation (default is 30) 16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public AnimationFactory(float duration, String name, int fps) { 16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.name = name; 16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.duration = duration; 16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.fps = fps; 16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta totalFrames = (int) (fps * duration) + 1; 16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tpf = 1 / (float) fps; 16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta times = new float[totalFrames]; 17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta translations = new Vector3f[totalFrames]; 17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rotations = new Quaternion[totalFrames]; 17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta scales = new Vector3f[totalFrames]; 17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta keyFramesTranslation = new Vector3f[totalFrames]; 17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta keyFramesTranslation[0] = new Vector3f(); 17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta keyFramesScale = new Vector3f[totalFrames]; 17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta keyFramesScale[0] = new Vector3f(1, 1, 1); 17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta keyFramesRotation = new Rotation[totalFrames]; 17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta keyFramesRotation[0] = new Rotation(); 17959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 18059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 18159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 18259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 18359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Adds a key frame for the given Transform at the given time 18459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param time the time at which the keyFrame must be inserted 18559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param transform the transforms to use for this keyFrame 18659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 18759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void addTimeTransform(float time, Transform transform) { 18859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta addKeyFrameTransform((int) (time / tpf), transform); 18959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 19059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 19159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 19259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Adds a key frame for the given Transform at the given keyFrame index 19359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param keyFrameIndex the index at which the keyFrame must be inserted 19459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param transform the transforms to use for this keyFrame 19559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 19659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void addKeyFrameTransform(int keyFrameIndex, Transform transform) { 19759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta addKeyFrameTranslation(keyFrameIndex, transform.getTranslation()); 19859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta addKeyFrameScale(keyFrameIndex, transform.getScale()); 19959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta addKeyFrameRotation(keyFrameIndex, transform.getRotation()); 20059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 20159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 20259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 20359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Adds a key frame for the given translation at the given time 20459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param time the time at which the keyFrame must be inserted 20559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param translation the translation to use for this keyFrame 20659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 20759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void addTimeTranslation(float time, Vector3f translation) { 20859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta addKeyFrameTranslation((int) (time / tpf), translation); 20959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 21059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 21159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 21259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Adds a key frame for the given translation at the given keyFrame index 21359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param keyFrameIndex the index at which the keyFrame must be inserted 21459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param translation the translation to use for this keyFrame 21559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 21659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void addKeyFrameTranslation(int keyFrameIndex, Vector3f translation) { 21759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f t = getTranslationForFrame(keyFrameIndex); 21859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta t.set(translation); 21959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 22059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 22159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 22259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Adds a key frame for the given rotation at the given time<br> 22359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This can't be used if the interpolated angle is higher than PI (180°)<br> 22459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Use {@link addTimeRotationAngles(float time, float x, float y, float z)} instead that uses Euler angles rotations.<br> * 22559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param time the time at which the keyFrame must be inserted 22659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param rotation the rotation Quaternion to use for this keyFrame 22759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @see #addTimeRotationAngles(float time, float x, float y, float z) 22859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 22959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void addTimeRotation(float time, Quaternion rotation) { 23059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta addKeyFrameRotation((int) (time / tpf), rotation); 23159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 23259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 23359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 23459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Adds a key frame for the given rotation at the given keyFrame index<br> 23559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This can't be used if the interpolated angle is higher than PI (180°)<br> 23659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Use {@link addKeyFrameRotationAngles(int keyFrameIndex, float x, float y, float z)} instead that uses Euler angles rotations. 23759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param keyFrameIndex the index at which the keyFrame must be inserted 23859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param rotation the rotation Quaternion to use for this keyFrame 23959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @see #addKeyFrameRotationAngles(int keyFrameIndex, float x, float y, float z) 24059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 24159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void addKeyFrameRotation(int keyFrameIndex, Quaternion rotation) { 24259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Rotation r = getRotationForFrame(keyFrameIndex); 24359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta r.set(rotation); 24459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 24559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 24659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 24759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Adds a key frame for the given rotation at the given time.<br> 24859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Rotation is expressed by Euler angles values in radians.<br> 24959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Note that the generated rotation will be stored as a quaternion and interpolated using a spherical linear interpolation (slerp)<br> 25059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Hence, this method may create intermediate keyFrames if the interpolation angle is higher than PI to ensure continuity in animation<br> 25159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 25259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param time the time at which the keyFrame must be inserted 25359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param x the rotation around the x axis (aka yaw) in radians 25459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param y the rotation around the y axis (aka roll) in radians 25559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param z the rotation around the z axis (aka pitch) in radians 25659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 25759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void addTimeRotationAngles(float time, float x, float y, float z) { 25859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta addKeyFrameRotationAngles((int) (time / tpf), x, y, z); 25959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 26059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 26159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 26259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Adds a key frame for the given rotation at the given key frame index.<br> 26359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Rotation is expressed by Euler angles values in radians.<br> 26459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Note that the generated rotation will be stored as a quaternion and interpolated using a spherical linear interpolation (slerp)<br> 26559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Hence, this method may create intermediate keyFrames if the interpolation angle is higher than PI to ensure continuity in animation<br> 26659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 26759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param keyFrameIndex the index at which the keyFrame must be inserted 26859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param x the rotation around the x axis (aka yaw) in radians 26959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param y the rotation around the y axis (aka roll) in radians 27059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param z the rotation around the z axis (aka pitch) in radians 27159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 27259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void addKeyFrameRotationAngles(int keyFrameIndex, float x, float y, float z) { 27359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Rotation r = getRotationForFrame(keyFrameIndex); 27459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta r.set(x, y, z); 27559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 27659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // if the delta of euler angles is higher than PI, we create intermediate keyframes 27759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // since we are using quaternions and slerp for rotation interpolation, we cannot interpolate over an angle higher than PI 27859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int prev = getPreviousKeyFrame(keyFrameIndex, keyFramesRotation); 27959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //previous rotation keyframe 28059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Rotation prevRot = keyFramesRotation[prev]; 28159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //the maximum delta angle (x,y or z) 28259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float delta = Math.max(Math.abs(x - prevRot.eulerAngles.x), Math.abs(y - prevRot.eulerAngles.y)); 28359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta delta = Math.max(delta, Math.abs(z - prevRot.eulerAngles.z)); 28459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //if delta > PI we have to create intermediates key frames 28559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (delta >= FastMath.PI) { 28659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //frames delta 28759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int dF = keyFrameIndex - prev; 28859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //angle per frame for x,y ,z 28959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float dXAngle = (x - prevRot.eulerAngles.x) / (float) dF; 29059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float dYAngle = (y - prevRot.eulerAngles.y) / (float) dF; 29159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float dZAngle = (z - prevRot.eulerAngles.z) / (float) dF; 29259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 29359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // the keyFrame step 29459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int keyStep = (int) (((float) (dF)) / delta * (float) EULER_STEP); 29559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // the current keyFrame 29659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int cursor = prev + keyStep; 29759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta while (cursor < keyFrameIndex) { 29859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //for each step we create a new rotation by interpolating the angles 29959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Rotation dr = getRotationForFrame(cursor); 30059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta dr.masterKeyFrame = keyFrameIndex; 30159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta dr.set(prevRot.eulerAngles.x + cursor * dXAngle, prevRot.eulerAngles.y + cursor * dYAngle, prevRot.eulerAngles.z + cursor * dZAngle); 30259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta cursor += keyStep; 30359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 30459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 30559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 30659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 30759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 30859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 30959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 31059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Adds a key frame for the given scale at the given time 31159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param time the time at which the keyFrame must be inserted 31259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param scale the scale to use for this keyFrame 31359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 31459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void addTimeScale(float time, Vector3f scale) { 31559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta addKeyFrameScale((int) (time / tpf), scale); 31659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 31759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 31859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 31959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Adds a key frame for the given scale at the given keyFrame index 32059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param keyFrameIndex the index at which the keyFrame must be inserted 32159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param scale the scale to use for this keyFrame 32259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 32359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void addKeyFrameScale(int keyFrameIndex, Vector3f scale) { 32459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f s = getScaleForFrame(keyFrameIndex); 32559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta s.set(scale); 32659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 32759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 32859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 32959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * returns the translation for a given frame index 33059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * creates the translation if it doesn't exists 33159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param keyFrameIndex index 33259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return the translation 33359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 33459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private Vector3f getTranslationForFrame(int keyFrameIndex) { 33559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (keyFrameIndex < 0 || keyFrameIndex > totalFrames) { 33659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new ArrayIndexOutOfBoundsException("keyFrameIndex must be between 0 and " + totalFrames + " (received " + keyFrameIndex + ")"); 33759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 33859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f v = keyFramesTranslation[keyFrameIndex]; 33959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (v == null) { 34059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta v = new Vector3f(); 34159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta keyFramesTranslation[keyFrameIndex] = v; 34259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 34359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return v; 34459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 34559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 34659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 34759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * returns the scale for a given frame index 34859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * creates the scale if it doesn't exists 34959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param keyFrameIndex index 35059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return the scale 35159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 35259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private Vector3f getScaleForFrame(int keyFrameIndex) { 35359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (keyFrameIndex < 0 || keyFrameIndex > totalFrames) { 35459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new ArrayIndexOutOfBoundsException("keyFrameIndex must be between 0 and " + totalFrames + " (received " + keyFrameIndex + ")"); 35559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 35659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f v = keyFramesScale[keyFrameIndex]; 35759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (v == null) { 35859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta v = new Vector3f(); 35959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta keyFramesScale[keyFrameIndex] = v; 36059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 36159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return v; 36259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 36359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 36459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 36559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * returns the rotation for a given frame index 36659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * creates the rotation if it doesn't exists 36759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param keyFrameIndex index 36859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return the rotation 36959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 37059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private Rotation getRotationForFrame(int keyFrameIndex) { 37159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (keyFrameIndex < 0 || keyFrameIndex > totalFrames) { 37259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new ArrayIndexOutOfBoundsException("keyFrameIndex must be between 0 and " + totalFrames + " (received " + keyFrameIndex + ")"); 37359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 37459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Rotation v = keyFramesRotation[keyFrameIndex]; 37559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (v == null) { 37659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta v = new Rotation(); 37759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta keyFramesRotation[keyFrameIndex] = v; 37859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 37959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return v; 38059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 38159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 38259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 38359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Creates an Animation based on the keyFrames previously added to the helper. 38459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return the generated animation 38559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 38659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Animation buildAnimation() { 38759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta interpolateTime(); 38859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta interpolate(keyFramesTranslation, Type.Translation); 38959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta interpolate(keyFramesRotation, Type.Rotation); 39059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta interpolate(keyFramesScale, Type.Scale); 39159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 39259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta SpatialTrack spatialTrack = new SpatialTrack(times, translations, rotations, scales); 39359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 39459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //creating the animation 39559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Animation spatialAnimation = new Animation(name, duration); 39659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta spatialAnimation.setTracks(new SpatialTrack[]{spatialTrack}); 39759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 39859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return spatialAnimation; 39959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 40059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 40159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 40259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * interpolates time values 40359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 40459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private void interpolateTime() { 40559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < totalFrames; i++) { 40659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta times[i] = i * tpf; 40759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 40859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 40959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 41059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 41159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Interpolates over the key frames for the given keyFrame array and the given type of transform 41259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param keyFrames the keyFrames array 41359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param type the type of transforms 41459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 41559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private void interpolate(Object[] keyFrames, Type type) { 41659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int i = 0; 41759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta while (i < totalFrames) { 41859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //fetching the next keyFrame index transform in the array 41959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int key = getNextKeyFrame(i, keyFrames); 42059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (key != -1) { 42159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //computing the frame span to interpolate over 42259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int span = key - i; 42359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //interating over the frames 42459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int j = i; j <= key; j++) { 42559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // computing interpolation value 42659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float val = (float) (j - i) / (float) span; 42759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //interpolationg depending on the transform type 42859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (type) { 42959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Translation: 43059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta translations[j] = FastMath.interpolateLinear(val, (Vector3f) keyFrames[i], (Vector3f) keyFrames[key]); 43159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 43259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Rotation: 43359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Quaternion rot = new Quaternion(); 43459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rotations[j] = rot.slerp(((Rotation) keyFrames[i]).rotation, ((Rotation) keyFrames[key]).rotation, val); 43559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 43659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Scale: 43759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta scales[j] = FastMath.interpolateLinear(val, (Vector3f) keyFrames[i], (Vector3f) keyFrames[key]); 43859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 43959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 44059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 44159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //jumping to the next keyFrame 44259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta i = key; 44359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 44459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //No more key frame, filling the array witht he last transform computed. 44559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int j = i; j < totalFrames; j++) { 44659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 44759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (type) { 44859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Translation: 44959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta translations[j] = ((Vector3f) keyFrames[i]).clone(); 45059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 45159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Rotation: 45259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rotations[j] = ((Quaternion) ((Rotation) keyFrames[i]).rotation).clone(); 45359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 45459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Scale: 45559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta scales[j] = ((Vector3f) keyFrames[i]).clone(); 45659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 45759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 45859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 45959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //we're done 46059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta i = totalFrames; 46159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 46259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 46359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 46459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 46559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 46659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Get the index of the next keyFrame that as a transform 46759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param index the start index 46859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param keyFrames the keyFrames array 46959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return the index of the next keyFrame 47059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 47159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int getNextKeyFrame(int index, Object[] keyFrames) { 47259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = index + 1; i < totalFrames; i++) { 47359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (keyFrames[i] != null) { 47459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return i; 47559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 47659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 47759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return -1; 47859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 47959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 48059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 48159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Get the index of the previous keyFrame that as a transform 48259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param index the start index 48359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param keyFrames the keyFrames array 48459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return the index of the previous keyFrame 48559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 48659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int getPreviousKeyFrame(int index, Object[] keyFrames) { 48759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = index - 1; i >= 0; i--) { 48859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (keyFrames[i] != null) { 48959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return i; 49059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 49159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 49259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return -1; 49359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 49459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta} 495