Animations refactoring.
- Track is a generic interface now - all kinds of tracks implement Track<T> - Animation is the only animation class that should be used now (other classes like BoneAnimation or SpatialAnimation are deprecated now) - Pose and PoseTrack are made Cloneable to easier clone the tracks and Animation - one update to OgreLoader (using Animation instead of BoneAnimation) - one update to tests git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8302 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
7967cc1c33
commit
c773395ace
@ -31,15 +31,174 @@
|
||||
*/
|
||||
package com.jme3.animation;
|
||||
|
||||
import com.jme3.export.Savable;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public interface Animation extends Savable, Cloneable {
|
||||
import com.jme3.export.InputCapsule;
|
||||
import com.jme3.export.JmeExporter;
|
||||
import com.jme3.export.JmeImporter;
|
||||
import com.jme3.export.OutputCapsule;
|
||||
import com.jme3.export.Savable;
|
||||
import com.jme3.scene.Geometry;
|
||||
import com.jme3.scene.Mesh;
|
||||
import com.jme3.scene.Node;
|
||||
import com.jme3.scene.Spatial;
|
||||
|
||||
/**
|
||||
* The animation class updates the animation target with the tracks of a given type.
|
||||
* @author Kirill Vainer, Marcin Roguski (Kaelthas)
|
||||
*/
|
||||
public class Animation implements Savable, Cloneable {
|
||||
/** The name of the animation. */
|
||||
private String name;
|
||||
/** The length of the animation. */
|
||||
private float length;
|
||||
/** The tracks of the animation. */
|
||||
private Track<?>[] tracks;
|
||||
|
||||
public String getName();
|
||||
/**
|
||||
* Serialization-only. Do not use.
|
||||
*/
|
||||
public Animation() {}
|
||||
|
||||
public float getLength();
|
||||
/**
|
||||
* Creates a new BoneAnimation with the given name and length.
|
||||
*
|
||||
* @param name The name of the bone animation.
|
||||
* @param length Length in seconds of the bone animation.
|
||||
*/
|
||||
public Animation(String name, float length) {
|
||||
this.name = name;
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
public void setTime(float time, float blendAmount, AnimControl control, AnimChannel channel);
|
||||
/**
|
||||
* @return the name of the animation
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Animation clone();
|
||||
/**
|
||||
* @return the length of the animation
|
||||
*/
|
||||
public float getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sets the current time of the animation.
|
||||
* This method behaves differently for every known track type.
|
||||
* Override this method if you have your own type of track.
|
||||
* @param time the time of the animation
|
||||
* @param blendAmount the blend amount factor
|
||||
* @param control the nimation control
|
||||
* @param channel the animation channel
|
||||
*/
|
||||
void setTime(float time, float blendAmount, AnimControl control, AnimChannel channel) {
|
||||
if(tracks != null && tracks.length > 0) {
|
||||
Track<?> trackInstance = tracks[0];
|
||||
if(trackInstance instanceof SpatialTrack) {
|
||||
Spatial spatial = control.getSpatial();
|
||||
if (spatial != null) {
|
||||
((SpatialTrack)tracks[0]).setTime(time, spatial, blendAmount);
|
||||
}
|
||||
} else if(trackInstance instanceof BoneTrack) {
|
||||
BitSet affectedBones = channel.getAffectedBones();
|
||||
Skeleton skeleton = control.getSkeleton();
|
||||
for (int i = 0; i < tracks.length; ++i) {
|
||||
if (affectedBones == null || affectedBones.get(((BoneTrack)tracks[i]).getTargetIndex())) {
|
||||
((BoneTrack)tracks[i]).setTime(time, skeleton, blendAmount);
|
||||
}
|
||||
}
|
||||
} else if(trackInstance instanceof PoseTrack) {
|
||||
Spatial spatial = control.getSpatial();
|
||||
List<Mesh> meshes = new ArrayList<Mesh>();
|
||||
this.getMeshes(spatial, meshes);
|
||||
if(meshes.size() > 0) {
|
||||
Mesh[] targets = meshes.toArray(new Mesh[meshes.size()]);
|
||||
for (int i = 0; i < tracks.length; ++i){
|
||||
((PoseTrack)tracks[i]).setTime(time, targets, blendAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the meshes within the given spatial.
|
||||
* @param spatial the spatial to search the meshes from
|
||||
* @param meshes the collection that will have the found meshes
|
||||
*/
|
||||
private void getMeshes(Spatial spatial, Collection<Mesh> meshes) {
|
||||
if(spatial instanceof Geometry) {
|
||||
meshes.add(((Geometry) spatial).getMesh());
|
||||
} else if(spatial instanceof Node) {
|
||||
for(Spatial child : ((Node) spatial).getChildren()) {
|
||||
this.getMeshes(child, meshes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link Track}s to be used by this animation.
|
||||
* <p>
|
||||
* The array should be organized so that the appropriate BoneTrack can
|
||||
* be retrieved based on a bone index.
|
||||
*
|
||||
* @param tracks the tracks to set
|
||||
*/
|
||||
public void setTracks(Track<?>[] tracks){
|
||||
this.tracks = tracks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the tracks of the animation
|
||||
*/
|
||||
public Track<?>[] getTracks() {
|
||||
return tracks;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates a clone of the current object.
|
||||
* @return a clone of the current object
|
||||
*/
|
||||
public Animation clone() {
|
||||
try {
|
||||
Animation result = (Animation) super.clone();
|
||||
if (tracks != null) {
|
||||
result.tracks = tracks.clone();
|
||||
for (int i = 0; i < tracks.length; ++i) {
|
||||
result.tracks[i] = this.tracks[i].clone();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Animation[name=" + name + ", length=" + length + ']';
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(JmeExporter ex) throws IOException {
|
||||
OutputCapsule out = ex.getCapsule(this);
|
||||
out.write(name, "name", null);
|
||||
out.write(length, "length", 0f);
|
||||
out.write(tracks, "tracks", null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(JmeImporter im) throws IOException {
|
||||
InputCapsule in = im.getCapsule(this);
|
||||
name = in.readString("name", null);
|
||||
length = in.readFloat("length", 0f);
|
||||
tracks = (Track<?>[]) in.readSavableArray("tracks", null);
|
||||
}
|
||||
}
|
||||
|
@ -47,8 +47,10 @@ import java.util.BitSet;
|
||||
* to apply the animation.
|
||||
*
|
||||
* @author Kirill Vainer
|
||||
* @deprecated use Animation instead with tracks of selected type (ie. BoneTrack, SpatialTrack, MeshTrack)
|
||||
*/
|
||||
public final class BoneAnimation implements Animation, Savable, Cloneable {
|
||||
@Deprecated
|
||||
public final class BoneAnimation extends Animation {
|
||||
|
||||
private String name;
|
||||
private float length;
|
||||
@ -118,7 +120,7 @@ public final class BoneAnimation implements Animation, Savable, Cloneable {
|
||||
|
||||
for (int i = 0; i < tracks.length; i++) {
|
||||
if (affectedBones == null
|
||||
|| affectedBones.get(tracks[i].getTargetBoneIndex())) {
|
||||
|| affectedBones.get(tracks[i].getTargetIndex())) {
|
||||
tracks[i].setTime(time, skeleton, blendAmount);
|
||||
}
|
||||
}
|
||||
@ -131,12 +133,7 @@ public final class BoneAnimation implements Animation, Savable, Cloneable {
|
||||
|
||||
@Override
|
||||
public BoneAnimation clone() {
|
||||
BoneAnimation result;
|
||||
try {
|
||||
result = (BoneAnimation) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
BoneAnimation result = (BoneAnimation) super.clone();
|
||||
if (result.tracks == null) {
|
||||
result.tracks = new BoneTrack[tracks.length];
|
||||
}
|
||||
@ -157,7 +154,7 @@ public final class BoneAnimation implements Animation, Savable, Cloneable {
|
||||
scales[j] = sourceScales != null ? sourceScales[j].clone() : new Vector3f(1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
// times do not change, no need to clone them
|
||||
result.tracks[i] = new BoneTrack(tracks[i].getTargetBoneIndex(), times,
|
||||
result.tracks[i] = new BoneTrack(tracks[i].getTargetIndex(), times,
|
||||
translations, rotations, scales);
|
||||
}
|
||||
return result;
|
||||
|
@ -45,7 +45,7 @@ import java.io.IOException;
|
||||
*
|
||||
* @author Kirill Vainer
|
||||
*/
|
||||
public final class BoneTrack implements Savable {
|
||||
public final class BoneTrack implements Track<Skeleton> {
|
||||
|
||||
/**
|
||||
* Bone index in the skeleton which this track effects.
|
||||
@ -105,14 +105,22 @@ public final class BoneTrack implements Savable {
|
||||
this.targetBoneIndex = targetBoneIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the bone index of this bone track
|
||||
* @return
|
||||
/**
|
||||
* @return the bone index of this bone track
|
||||
* @deprecated use getTargetIndex() instead
|
||||
*/
|
||||
@Deprecated
|
||||
public int getTargetBoneIndex() {
|
||||
return targetBoneIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the bone index of this bone track
|
||||
*/
|
||||
public int getTargetIndex() {
|
||||
return targetBoneIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* return the array of rotations of this track
|
||||
* @return
|
||||
@ -245,6 +253,30 @@ public final class BoneTrack implements Savable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates a clone of the current object.
|
||||
* @return a clone of the current object
|
||||
*/
|
||||
public BoneTrack clone() {
|
||||
int tablesLength = times.length;
|
||||
|
||||
float[] times = this.times.clone();
|
||||
Vector3f[] sourceTranslations = this.getTranslations();
|
||||
Quaternion[] sourceRotations = this.getRotations();
|
||||
Vector3f[] sourceScales = this.getScales();
|
||||
|
||||
Vector3f[] translations = new Vector3f[tablesLength];
|
||||
Quaternion[] rotations = new Quaternion[tablesLength];
|
||||
Vector3f[] scales = new Vector3f[tablesLength];
|
||||
for (int i = 0; i < tablesLength; ++i) {
|
||||
translations[i] = sourceTranslations[i].clone();
|
||||
rotations[i] = sourceRotations[i].clone();
|
||||
scales[i] = sourceScales != null ? sourceScales[i].clone() : new Vector3f(1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
//need to use the constructor here because of the final fields used in this class
|
||||
return new BoneTrack(targetBoneIndex, times, translations, rotations, scales);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(JmeExporter ex) throws IOException {
|
||||
OutputCapsule oc = ex.getCapsule(this);
|
||||
|
@ -32,21 +32,25 @@
|
||||
|
||||
package com.jme3.animation;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.jme3.export.InputCapsule;
|
||||
import com.jme3.export.JmeExporter;
|
||||
import com.jme3.export.JmeImporter;
|
||||
import com.jme3.export.InputCapsule;
|
||||
import com.jme3.export.OutputCapsule;
|
||||
import com.jme3.export.Savable;
|
||||
import com.jme3.scene.Mesh;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class MeshAnimation implements Animation, Savable {
|
||||
/**
|
||||
*
|
||||
* @author Kirill Vainer
|
||||
* @deprecated use Animation instead with tracks of selected type (ie. BoneTrack, SpatialTrack, MeshTrack)
|
||||
*/
|
||||
@Deprecated
|
||||
public class MeshAnimation extends Animation {
|
||||
|
||||
private String name;
|
||||
private float length;
|
||||
private Track[] tracks;
|
||||
private PoseTrack[] tracks;
|
||||
|
||||
public MeshAnimation(String name, float length){
|
||||
this.name = name;
|
||||
@ -61,11 +65,11 @@ public class MeshAnimation implements Animation, Savable {
|
||||
return length;
|
||||
}
|
||||
|
||||
public void setTracks(Track[] tracks){
|
||||
public void setTracks(PoseTrack[] tracks){
|
||||
this.tracks = tracks;
|
||||
}
|
||||
|
||||
public Track[] getTracks(){
|
||||
public PoseTrack[] getTracks(){
|
||||
return tracks;
|
||||
}
|
||||
|
||||
@ -92,18 +96,6 @@ public class MeshAnimation implements Animation, Savable {
|
||||
InputCapsule in = i.getCapsule(this);
|
||||
name = in.readString("name", "");
|
||||
length = in.readFloat("length", -1f);
|
||||
tracks = (Track[]) in.readSavableArray("tracks", null);
|
||||
tracks = (PoseTrack[]) in.readSavableArray("tracks", null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Animation clone() {
|
||||
try {
|
||||
return (Animation) super.clone();
|
||||
} catch (CloneNotSupportedException ex) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -32,20 +32,21 @@
|
||||
|
||||
package com.jme3.animation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import com.jme3.export.InputCapsule;
|
||||
import com.jme3.export.JmeExporter;
|
||||
import com.jme3.export.JmeImporter;
|
||||
import com.jme3.export.InputCapsule;
|
||||
import com.jme3.export.OutputCapsule;
|
||||
import com.jme3.export.Savable;
|
||||
import com.jme3.math.Vector3f;
|
||||
import com.jme3.util.BufferUtils;
|
||||
import java.io.IOException;
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
/**
|
||||
* A pose is a list of offsets that say where a mesh vertices should be for this pose.
|
||||
*/
|
||||
public final class Pose implements Savable {
|
||||
public final class Pose implements Savable, Cloneable {
|
||||
|
||||
private String name;
|
||||
private int targetMeshIndex;
|
||||
@ -91,6 +92,26 @@ public final class Pose implements Savable {
|
||||
BufferUtils.setInBuffer(tempVec2, vertbuf, vertIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates a clone of the current object.
|
||||
* @return a clone of the current object
|
||||
*/
|
||||
public Pose clone() {
|
||||
try {
|
||||
Pose result = (Pose) super.clone();
|
||||
result.indices = this.indices.clone();
|
||||
if(this.offsets!=null) {
|
||||
result.offsets = new Vector3f[this.offsets.length];
|
||||
for(int i=0;i<this.offsets.length;++i) {
|
||||
result.offsets[i] = this.offsets[i].clone();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
public void write(JmeExporter e) throws IOException {
|
||||
OutputCapsule out = e.getCapsule(this);
|
||||
|
@ -37,6 +37,8 @@ import com.jme3.export.JmeImporter;
|
||||
import com.jme3.export.InputCapsule;
|
||||
import com.jme3.export.OutputCapsule;
|
||||
import com.jme3.export.Savable;
|
||||
import com.jme3.math.Quaternion;
|
||||
import com.jme3.math.Vector3f;
|
||||
import com.jme3.scene.Mesh;
|
||||
import com.jme3.scene.VertexBuffer;
|
||||
import com.jme3.scene.VertexBuffer.Type;
|
||||
@ -46,12 +48,13 @@ import java.nio.FloatBuffer;
|
||||
/**
|
||||
* A single track of pose animation associated with a certain mesh.
|
||||
*/
|
||||
public final class PoseTrack extends Track {
|
||||
public final class PoseTrack implements Track<Mesh[]> {
|
||||
|
||||
protected int targetMeshIndex;
|
||||
private PoseFrame[] frames;
|
||||
private float[] times;
|
||||
|
||||
public static class PoseFrame implements Savable {
|
||||
public static class PoseFrame implements Savable, Cloneable {
|
||||
|
||||
Pose[] poses;
|
||||
float[] weights;
|
||||
@ -60,6 +63,26 @@ public final class PoseTrack extends Track {
|
||||
this.poses = poses;
|
||||
this.weights = weights;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates a clone of the current object.
|
||||
* @return a clone of the current object
|
||||
*/
|
||||
public PoseFrame clone() {
|
||||
try {
|
||||
PoseFrame result = (PoseFrame) super.clone();
|
||||
result.weights = this.weights.clone();
|
||||
if(this.poses != null) {
|
||||
result.poses = new Pose[this.poses.length];
|
||||
for(int i=0;i<this.poses.length;++i) {
|
||||
result.poses[i] = this.poses[i].clone();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
public void write(JmeExporter e) throws IOException {
|
||||
OutputCapsule out = e.getCapsule(this);
|
||||
@ -75,10 +98,17 @@ public final class PoseTrack extends Track {
|
||||
}
|
||||
|
||||
public PoseTrack(int targetMeshIndex, float[] times, PoseFrame[] frames){
|
||||
super(targetMeshIndex);
|
||||
this.targetMeshIndex = targetMeshIndex;
|
||||
this.times = times;
|
||||
this.frames = frames;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the index of the target object for this track
|
||||
*/
|
||||
public int getTargetIndex() {
|
||||
return targetMeshIndex;
|
||||
}
|
||||
|
||||
private void applyFrame(Mesh target, int frameIndex, float weight){
|
||||
PoseFrame frame = frames[frameIndex];
|
||||
@ -114,9 +144,30 @@ public final class PoseTrack extends Track {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates a clone of the current object.
|
||||
* @return a clone of the current object
|
||||
*/
|
||||
public PoseTrack clone() {
|
||||
try {
|
||||
PoseTrack result = (PoseTrack) super.clone();
|
||||
result.times = this.times.clone();
|
||||
if(this.frames!=null) {
|
||||
result.frames = new PoseFrame[this.frames.length];
|
||||
for(int i=0;i<this.frames.length;++i) {
|
||||
result.frames[i] = this.frames[i].clone();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(JmeExporter e) throws IOException {
|
||||
OutputCapsule out = e.getCapsule(this);
|
||||
out.write(targetMeshIndex, "meshIndex", 0);
|
||||
out.write(frames, "frames", null);
|
||||
out.write(times, "times", null);
|
||||
}
|
||||
@ -124,7 +175,33 @@ public final class PoseTrack extends Track {
|
||||
@Override
|
||||
public void read(JmeImporter i) throws IOException {
|
||||
InputCapsule in = i.getCapsule(this);
|
||||
targetMeshIndex = in.readInt("meshIndex", 0);
|
||||
frames = (PoseFrame[]) in.readSavableArray("frames", null);
|
||||
times = in.readFloatArray("times", null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Quaternion[] getRotations() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3f[] getScales() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] getTimes() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3f[] getTranslations() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setKeyframes(float[] times, Vector3f[] translations,
|
||||
Quaternion[] rotations, Vector3f[] scales) {
|
||||
}
|
||||
}
|
||||
|
@ -13,14 +13,16 @@ import com.jme3.scene.Spatial;
|
||||
* affected by their parent's movement.
|
||||
*
|
||||
* @author Marcin Roguski (Kaelthas)
|
||||
* @deprecated use Animation instead with tracks of selected type (ie. BoneTrack, SpatialTrack, MeshTrack)
|
||||
*/
|
||||
public class SpatialAnimation implements Animation {
|
||||
@Deprecated
|
||||
public class SpatialAnimation extends Animation {
|
||||
/** The name of the animation. */
|
||||
private String name;
|
||||
/** The length of the animation. */
|
||||
private float length;
|
||||
/** The track of the animation. */
|
||||
private SpatialTrack track;
|
||||
private SpatialTrack[] tracks;
|
||||
|
||||
/**
|
||||
* Constructor. Stores the name and length of the animation.
|
||||
@ -37,7 +39,7 @@ public class SpatialAnimation implements Animation {
|
||||
AnimChannel channel) {
|
||||
Spatial spatial = control.getSpatial();
|
||||
if (spatial != null) {
|
||||
track.setTime(time, spatial);
|
||||
tracks[0].setTime(time, spatial, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,14 +48,14 @@ public class SpatialAnimation implements Animation {
|
||||
* @param track the animation track
|
||||
*/
|
||||
public void setTrack(SpatialTrack track) {
|
||||
this.track = track;
|
||||
this.tracks[0] = track;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the animation track
|
||||
*/
|
||||
public SpatialTrack getTracks() {
|
||||
return track;
|
||||
public SpatialTrack[] getTracks() {
|
||||
return tracks;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -71,21 +73,12 @@ public class SpatialAnimation implements Animation {
|
||||
return "SpatialAnim[name=" + name + ", length=" + length + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Animation clone() {
|
||||
try {
|
||||
return (Animation) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(JmeExporter ex) throws IOException {
|
||||
OutputCapsule oc = ex.getCapsule(this);
|
||||
oc.write(name, "name", null);
|
||||
oc.write(length, "length", 0);
|
||||
oc.write(track, "track", null);
|
||||
oc.write(tracks, "tracks", null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -93,6 +86,6 @@ public class SpatialAnimation implements Animation {
|
||||
InputCapsule in = im.getCapsule(this);
|
||||
name = in.readString("name", null);
|
||||
length = in.readFloat("length", 0);
|
||||
track = (SpatialTrack) in.readSavable("track", null);
|
||||
tracks = (SpatialTrack[]) in.readSavableArray("track", null);
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import com.jme3.export.InputCapsule;
|
||||
import com.jme3.export.JmeExporter;
|
||||
import com.jme3.export.JmeImporter;
|
||||
import com.jme3.export.OutputCapsule;
|
||||
import com.jme3.export.Savable;
|
||||
import com.jme3.math.Quaternion;
|
||||
import com.jme3.math.Vector3f;
|
||||
import com.jme3.scene.Spatial;
|
||||
@ -16,7 +15,7 @@ import com.jme3.scene.Spatial;
|
||||
*
|
||||
* @author Marcin Roguski (Kaelthas)
|
||||
*/
|
||||
public class SpatialTrack implements Savable {
|
||||
public class SpatialTrack implements Track<Spatial> {
|
||||
/** Translations of the track. */
|
||||
private CompactVector3Array translations;
|
||||
/** Rotations of the track. */
|
||||
@ -63,7 +62,7 @@ public class SpatialTrack implements Savable {
|
||||
* @param spatial
|
||||
* the spatial that should be animated with this track
|
||||
*/
|
||||
public void setTime(float time, Spatial spatial) {
|
||||
public void setTime(float time, Spatial spatial, float weight) {
|
||||
int lastFrame = times.length - 1;
|
||||
if (time < 0 || lastFrame == 0) {
|
||||
rotations.get(0, tempQ);
|
||||
@ -147,6 +146,13 @@ public class SpatialTrack implements Savable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the index of the target object for this track
|
||||
*/
|
||||
public int getTargetIndex() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the array of rotations of this track
|
||||
*/
|
||||
@ -175,6 +181,30 @@ public class SpatialTrack implements Savable {
|
||||
return translations.toObjectArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates a clone of the current object.
|
||||
* @return a clone of the current object
|
||||
*/
|
||||
public SpatialTrack clone() {
|
||||
int tablesLength = times.length;
|
||||
|
||||
float[] times = this.times.clone();
|
||||
Vector3f[] sourceTranslations = this.getTranslations();
|
||||
Quaternion[] sourceRotations = this.getRotations();
|
||||
Vector3f[] sourceScales = this.getScales();
|
||||
|
||||
Vector3f[] translations = new Vector3f[tablesLength];
|
||||
Quaternion[] rotations = new Quaternion[tablesLength];
|
||||
Vector3f[] scales = new Vector3f[tablesLength];
|
||||
for (int i = 0; i < tablesLength; ++i) {
|
||||
translations[i] = sourceTranslations[i].clone();
|
||||
rotations[i] = sourceRotations[i].clone();
|
||||
scales[i] = sourceScales != null ? sourceScales[i].clone() : new Vector3f(1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
//need to use the constructor here because of the final fields used in this class
|
||||
return new SpatialTrack(times, translations, rotations, scales);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(JmeExporter ex) throws IOException {
|
||||
OutputCapsule oc = ex.getCapsule(this);
|
||||
|
@ -31,49 +31,66 @@
|
||||
*/
|
||||
package com.jme3.animation;
|
||||
|
||||
import com.jme3.export.JmeExporter;
|
||||
import com.jme3.export.JmeImporter;
|
||||
import com.jme3.export.Savable;
|
||||
import com.jme3.scene.Mesh;
|
||||
import java.io.IOException;
|
||||
import com.jme3.math.Quaternion;
|
||||
import com.jme3.math.Vector3f;
|
||||
|
||||
/**
|
||||
* A single track of mesh animation (either morph or pose based).
|
||||
* Currently morph animations are not supported (only pose).
|
||||
*/
|
||||
public abstract class Track implements Savable {
|
||||
|
||||
protected int targetMeshIndex;
|
||||
|
||||
/**
|
||||
* build a track for a an index
|
||||
* @param targetMeshIndex
|
||||
*/
|
||||
public Track(int targetMeshIndex) {
|
||||
this.targetMeshIndex = targetMeshIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* return the mesh index
|
||||
* @return
|
||||
*/
|
||||
public int getTargetMeshIndex() {
|
||||
return targetMeshIndex;
|
||||
}
|
||||
|
||||
public interface Track<T> extends Savable, Cloneable {
|
||||
/**
|
||||
* sets time for this track
|
||||
* @param time
|
||||
* @param targets
|
||||
* @param target
|
||||
* @param weight
|
||||
*/
|
||||
public abstract void setTime(float time, Mesh[] targets, float weight);
|
||||
void setTime(float time, T target, float weight);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
void setKeyframes(float[] times, Vector3f[] translations,
|
||||
Quaternion[] rotations, Vector3f[] scales);
|
||||
|
||||
/**
|
||||
* @return the index of the target object for this track
|
||||
*/
|
||||
int getTargetIndex();
|
||||
|
||||
/**
|
||||
* @return the array of rotations of this track
|
||||
*/
|
||||
Quaternion[] getRotations();
|
||||
|
||||
public void write(JmeExporter ex) throws IOException {
|
||||
ex.getCapsule(this).write(targetMeshIndex, "meshIndex", 0);
|
||||
}
|
||||
/**
|
||||
* @return the array of scales for this track
|
||||
*/
|
||||
Vector3f[] getScales();
|
||||
|
||||
public void read(JmeImporter im) throws IOException {
|
||||
targetMeshIndex = im.getCapsule(this).readInt("meshIndex", 0);
|
||||
}
|
||||
/**
|
||||
* @return the arrays of time for this track
|
||||
*/
|
||||
float[] getTimes();
|
||||
|
||||
/**
|
||||
* @return the array of translations of this track
|
||||
*/
|
||||
Vector3f[] getTranslations();
|
||||
|
||||
/**
|
||||
* This method creates a clone of the current object.
|
||||
* @return a clone of the current object
|
||||
*/
|
||||
Track<T> clone();
|
||||
}
|
||||
|
@ -31,30 +31,16 @@
|
||||
*/
|
||||
package com.jme3.scene.plugins.ogre;
|
||||
|
||||
import com.jme3.animation.Animation;
|
||||
import com.jme3.animation.Bone;
|
||||
import com.jme3.animation.BoneAnimation;
|
||||
import com.jme3.animation.BoneTrack;
|
||||
import com.jme3.animation.Skeleton;
|
||||
import com.jme3.asset.AssetInfo;
|
||||
import com.jme3.asset.AssetLoader;
|
||||
import com.jme3.asset.AssetManager;
|
||||
import com.jme3.math.Quaternion;
|
||||
import com.jme3.math.Vector3f;
|
||||
import com.jme3.system.JmeSystem;
|
||||
import com.jme3.util.xml.SAXUtil;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
@ -62,7 +48,17 @@ import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
import com.jme3.animation.Animation;
|
||||
import com.jme3.animation.Bone;
|
||||
import com.jme3.animation.BoneTrack;
|
||||
import com.jme3.animation.Skeleton;
|
||||
import com.jme3.asset.AssetInfo;
|
||||
import com.jme3.asset.AssetLoader;
|
||||
import com.jme3.asset.AssetManager;
|
||||
import com.jme3.math.Quaternion;
|
||||
import com.jme3.math.Vector3f;
|
||||
import com.jme3.util.xml.SAXUtil;
|
||||
|
||||
public class SkeletonLoader extends DefaultHandler implements AssetLoader {
|
||||
|
||||
@ -73,7 +69,7 @@ public class SkeletonLoader extends DefaultHandler implements AssetLoader {
|
||||
private HashMap<String, Bone> nameToBone = new HashMap<String, Bone>();
|
||||
private BoneTrack track;
|
||||
private ArrayList<BoneTrack> tracks = new ArrayList<BoneTrack>();
|
||||
private BoneAnimation animation;
|
||||
private Animation animation;
|
||||
private ArrayList<Animation> animations;
|
||||
private Bone bone;
|
||||
private Skeleton skeleton;
|
||||
@ -132,7 +128,7 @@ public class SkeletonLoader extends DefaultHandler implements AssetLoader {
|
||||
assert elementStack.peek().equals("animations");
|
||||
String name = SAXUtil.parseString(attribs.getValue("name"));
|
||||
float length = SAXUtil.parseFloat(attribs.getValue("length"));
|
||||
animation = new BoneAnimation(name, length);
|
||||
animation = new Animation(name, length);
|
||||
} else if (qName.equals("bonehierarchy")) {
|
||||
assert elementStack.peek().equals("skeleton");
|
||||
} else if (qName.equals("animations")) {
|
||||
|
@ -4,7 +4,6 @@ import java.util.HashMap;
|
||||
|
||||
import com.jme3.animation.AnimControl;
|
||||
import com.jme3.animation.Animation;
|
||||
import com.jme3.animation.SpatialAnimation;
|
||||
import com.jme3.animation.SpatialTrack;
|
||||
import com.jme3.app.SimpleApplication;
|
||||
import com.jme3.light.AmbientLight;
|
||||
@ -71,8 +70,8 @@ public class TestSpatialAnim extends SimpleApplication {
|
||||
SpatialTrack spatialTrack = new SpatialTrack(times, translations, rotations, scales);
|
||||
|
||||
//creating the animation
|
||||
SpatialAnimation spatialAnimation = new SpatialAnimation("anim", animTime);
|
||||
spatialAnimation.setTrack(spatialTrack);
|
||||
Animation spatialAnimation = new Animation("anim", animTime);
|
||||
spatialAnimation.setTracks(new SpatialTrack[] { spatialTrack });
|
||||
|
||||
//create spatial animation control
|
||||
AnimControl control = new AnimControl();
|
||||
|
Loading…
x
Reference in New Issue
Block a user