aboutsummaryrefslogtreecommitdiff
path: root/engine/src/core/com/jme3/animation/SpatialTrack.java
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/core/com/jme3/animation/SpatialTrack.java')
-rw-r--r--engine/src/core/com/jme3/animation/SpatialTrack.java242
1 files changed, 242 insertions, 0 deletions
diff --git a/engine/src/core/com/jme3/animation/SpatialTrack.java b/engine/src/core/com/jme3/animation/SpatialTrack.java
new file mode 100644
index 0000000..5704317
--- /dev/null
+++ b/engine/src/core/com/jme3/animation/SpatialTrack.java
@@ -0,0 +1,242 @@
+package com.jme3.animation;
+
+import com.jme3.export.InputCapsule;
+import com.jme3.export.JmeExporter;
+import com.jme3.export.JmeImporter;
+import com.jme3.export.OutputCapsule;
+import com.jme3.math.Quaternion;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Spatial;
+import com.jme3.util.TempVars;
+import java.io.IOException;
+import java.util.Arrays;
+
+/**
+ * This class represents the track for spatial animation.
+ *
+ * @author Marcin Roguski (Kaelthas)
+ */
+public class SpatialTrack implements Track {
+
+ /**
+ * Translations of the track.
+ */
+ private CompactVector3Array translations;
+
+ /**
+ * Rotations of the track.
+ */
+ private CompactQuaternionArray rotations;
+
+ /**
+ * Scales of the track.
+ */
+ private CompactVector3Array scales;
+
+ /**
+ * The times of the animations frames.
+ */
+ private float[] times;
+
+ public SpatialTrack() {
+ }
+
+ /**
+ * Creates a spatial track for the given track data.
+ *
+ * @param times
+ * a float array with the time of each frame
+ * @param translations
+ * the translation of the bone for each frame
+ * @param rotations
+ * the rotation of the bone for each frame
+ * @param scales
+ * the scale of the bone for each frame
+ */
+ public SpatialTrack(float[] times, Vector3f[] translations,
+ Quaternion[] rotations, Vector3f[] scales) {
+ setKeyframes(times, translations, rotations, scales);
+ }
+
+ /**
+ *
+ * Modify the spatial which this track modifies.
+ *
+ * @param time
+ * the current time of the animation
+ */
+ public void setTime(float time, float weight, AnimControl control, AnimChannel channel, TempVars vars) {
+ Spatial spatial = control.getSpatial();
+
+ Vector3f tempV = vars.vect1;
+ Vector3f tempS = vars.vect2;
+ Quaternion tempQ = vars.quat1;
+ Vector3f tempV2 = vars.vect3;
+ Vector3f tempS2 = vars.vect4;
+ Quaternion tempQ2 = vars.quat2;
+
+ int lastFrame = times.length - 1;
+ if (time < 0 || lastFrame == 0) {
+ if (rotations != null)
+ rotations.get(0, tempQ);
+ if (translations != null)
+ translations.get(0, tempV);
+ if (scales != null) {
+ scales.get(0, tempS);
+ }
+ } else if (time >= times[lastFrame]) {
+ if (rotations != null)
+ rotations.get(lastFrame, tempQ);
+ if (translations != null)
+ translations.get(lastFrame, tempV);
+ if (scales != null) {
+ scales.get(lastFrame, tempS);
+ }
+ } else {
+ int startFrame = 0;
+ int endFrame = 1;
+ // use lastFrame so we never overflow the array
+ for (int i = 0; i < lastFrame && times[i] < time; ++i) {
+ startFrame = i;
+ endFrame = i + 1;
+ }
+
+ float blend = (time - times[startFrame]) / (times[endFrame] - times[startFrame]);
+
+ if (rotations != null)
+ rotations.get(startFrame, tempQ);
+ if (translations != null)
+ translations.get(startFrame, tempV);
+ if (scales != null) {
+ scales.get(startFrame, tempS);
+ }
+ if (rotations != null)
+ rotations.get(endFrame, tempQ2);
+ if (translations != null)
+ translations.get(endFrame, tempV2);
+ if (scales != null) {
+ scales.get(endFrame, tempS2);
+ }
+ tempQ.nlerp(tempQ2, blend);
+ tempV.interpolate(tempV2, blend);
+ tempS.interpolate(tempS2, blend);
+ }
+
+ if (translations != null)
+ spatial.setLocalTranslation(tempV);
+ if (rotations != null)
+ spatial.setLocalRotation(tempQ);
+ if (scales != null) {
+ spatial.setLocalScale(tempS);
+ }
+ }
+
+ /**
+ * Set the translations, rotations and scales for this track.
+ *
+ * @param times
+ * a float array with the time of each frame
+ * @param translations
+ * the translation of the bone for each frame
+ * @param rotations
+ * the rotation of the bone for each frame
+ * @param scales
+ * the scale of the bone for each frame
+ */
+ public void setKeyframes(float[] times, Vector3f[] translations,
+ Quaternion[] rotations, Vector3f[] scales) {
+ if (times.length == 0) {
+ throw new RuntimeException("BoneTrack with no keyframes!");
+ }
+
+ this.times = times;
+ if (translations != null) {
+ assert times.length == translations.length;
+ this.translations = new CompactVector3Array();
+ this.translations.add(translations);
+ this.translations.freeze();
+ }
+ if (rotations != null) {
+ assert times.length == rotations.length;
+ this.rotations = new CompactQuaternionArray();
+ this.rotations.add(rotations);
+ this.rotations.freeze();
+ }
+ if (scales != null) {
+ assert times.length == scales.length;
+ this.scales = new CompactVector3Array();
+ this.scales.add(scales);
+ this.scales.freeze();
+ }
+ }
+
+ /**
+ * @return the array of rotations of this track
+ */
+ public Quaternion[] getRotations() {
+ return rotations == null ? null : rotations.toObjectArray();
+ }
+
+ /**
+ * @return the array of scales for this track
+ */
+ public Vector3f[] getScales() {
+ return scales == null ? null : scales.toObjectArray();
+ }
+
+ /**
+ * @return the arrays of time for this track
+ */
+ public float[] getTimes() {
+ return times;
+ }
+
+ /**
+ * @return the array of translations of this track
+ */
+ public Vector3f[] getTranslations() {
+ return translations == null ? null : translations.toObjectArray();
+ }
+
+ /**
+ * @return the length of the track
+ */
+ public float getLength() {
+ return times == null ? 0 : times[times.length - 1] - times[0];
+ }
+
+ /**
+ * This method creates a clone of the current object.
+ * @return a clone of the current object
+ */
+ @Override
+ public SpatialTrack clone() {
+ int tablesLength = times.length;
+
+ float[] timesCopy = this.times.clone();
+ Vector3f[] translationsCopy = this.getTranslations() == null ? null : Arrays.copyOf(this.getTranslations(), tablesLength);
+ Quaternion[] rotationsCopy = this.getRotations() == null ? null : Arrays.copyOf(this.getRotations(), tablesLength);
+ Vector3f[] scalesCopy = this.getScales() == null ? null : Arrays.copyOf(this.getScales(), tablesLength);
+
+ //need to use the constructor here because of the final fields used in this class
+ return new SpatialTrack(timesCopy, translationsCopy, rotationsCopy, scalesCopy);
+ }
+
+ @Override
+ public void write(JmeExporter ex) throws IOException {
+ OutputCapsule oc = ex.getCapsule(this);
+ oc.write(translations, "translations", null);
+ oc.write(rotations, "rotations", null);
+ oc.write(times, "times", null);
+ oc.write(scales, "scales", null);
+ }
+
+ @Override
+ public void read(JmeImporter im) throws IOException {
+ InputCapsule ic = im.getCapsule(this);
+ translations = (CompactVector3Array) ic.readSavable("translations", null);
+ rotations = (CompactQuaternionArray) ic.readSavable("rotations", null);
+ times = ic.readFloatArray("times", null);
+ scales = (CompactVector3Array) ic.readSavable("scales", null);
+ }
+}