import java.util.logging.Logger;\r
\r
import com.jme3.animation.Bone;\r
+import com.jme3.animation.BoneTrack;\r
import com.jme3.animation.Track;\r
import com.jme3.math.Matrix4f;\r
import com.jme3.math.Quaternion;\r
* an exception is thrown when there are problems with the blend\r
* file\r
*/\r
- public Track<?>[] getTracks(Structure actionStructure, BlenderContext blenderContext) throws BlenderFileException {\r
+ public BoneTrack[] getTracks(Structure actionStructure, BlenderContext blenderContext) throws BlenderFileException {\r
if (blenderVersion < 250) {\r
return this.getTracks249(actionStructure, blenderContext);\r
} else {\r
* an exception is thrown when there are problems with the blend\r
* file\r
*/\r
- private Track<?>[] getTracks250(Structure actionStructure, BlenderContext blenderContext) throws BlenderFileException {\r
+ private BoneTrack[] getTracks250(Structure actionStructure, BlenderContext blenderContext) throws BlenderFileException {\r
LOGGER.log(Level.INFO, "Getting tracks!");\r
int fps = blenderContext.getBlenderKey().getFps();\r
Structure groups = (Structure) actionStructure.getFieldValue("groups");\r
throw new IllegalStateException("No bones found! Cannot proceed to calculating tracks!");\r
}\r
\r
- List<Track<?>> tracks = new ArrayList<Track<?>>();\r
+ List<BoneTrack> tracks = new ArrayList<BoneTrack>();\r
for (Structure actionGroup : actionGroups) {\r
String name = actionGroup.getFieldValue("name").toString();\r
Integer boneIndex = bonesMap.get(name);\r
}\r
\r
Ipo ipo = new Ipo(bezierCurves);\r
- tracks.add(ipo.calculateTrack(boneIndex.intValue(), 0, ipo.getLastFrame(), fps));\r
+ tracks.add( (BoneTrack) ipo.calculateTrack(boneIndex.intValue(), 0, ipo.getLastFrame(), fps) );\r
}\r
}\r
- return tracks.toArray(new Track<?>[tracks.size()]);\r
+ return tracks.toArray(new BoneTrack[tracks.size()]);\r
}\r
\r
/**\r
* an exception is thrown when there are problems with the blend\r
* file\r
*/\r
- private Track<?>[] getTracks249(Structure actionStructure, BlenderContext blenderContext) throws BlenderFileException {\r
+ private BoneTrack[] getTracks249(Structure actionStructure, BlenderContext blenderContext) throws BlenderFileException {\r
LOGGER.log(Level.INFO, "Getting tracks!");\r
IpoHelper ipoHelper = blenderContext.getHelper(IpoHelper.class);\r
int fps = blenderContext.getBlenderKey().getFps();\r
if (actionChannels != null && actionChannels.size() > 0 && (bonesMap == null || bonesMap.size() == 0)) {\r
throw new IllegalStateException("No bones found! Cannot proceed to calculating tracks!");\r
}\r
- List<Track<?>> tracks = new ArrayList<Track<?>>();\r
+ List<BoneTrack> tracks = new ArrayList<BoneTrack>();\r
for (Structure bActionChannel : actionChannels) {\r
String name = bActionChannel.getFieldValue("name").toString();\r
Integer boneIndex = bonesMap.get(name);\r
if (!p.isNull()) {\r
Structure ipoStructure = p.fetchData(blenderContext.getInputStream()).get(0);\r
Ipo ipo = ipoHelper.createIpo(ipoStructure, blenderContext);\r
- tracks.add(ipo.calculateTrack(boneIndex.intValue(), 0, ipo.getLastFrame(), fps));\r
+ tracks.add( (BoneTrack) ipo.calculateTrack(boneIndex.intValue(), 0, ipo.getLastFrame(), fps));\r
}\r
}\r
}\r
- return tracks.toArray(new Track<?>[tracks.size()]);\r
+ return tracks.toArray(new BoneTrack[tracks.size()]);\r
}\r
\r
/**\r
public static final int AC_QUAT_X = 26;\r
public static final int AC_QUAT_Y = 27;\r
public static final int AC_QUAT_Z = 28;\r
- /** A list of bezier curves for this interpolation object. */\r
+ \r
+ /** \r
+ * A list of bezier curves for this interpolation object. \r
+ */\r
private BezierCurve[] bezierCurves;\r
- /** Each ipo contains one bone track. */\r
- private Track<?> calculatedTrack;\r
+ \r
+ /** \r
+ * Each ipo contains one bone track. \r
+ */\r
+ private Track calculatedTrack;\r
\r
/**\r
* Constructor. Stores the bezier curves.\r
return result;\r
}\r
\r
+ /*\r
public void modifyTranslation(int frame, Vector3f translation) {\r
if (calculatedTrack != null) {\r
calculatedTrack.getTranslations()[frame].set(translation);\r
calculatedTrack.getScales()[frame].set(scale);\r
}\r
}\r
+ */\r
\r
/**\r
* This method calculates the value of the curves as a bone track between the specified frames.\r
* frame rate (frames per second)\r
* @return bone track for the specified bone\r
*/\r
- public Track<?> calculateTrack(int targetIndex, int startFrame, int stopFrame, int fps) {\r
+ public Track calculateTrack(int targetIndex, int startFrame, int stopFrame, int fps) {\r
if(calculatedTrack == null) {\r
//preparing data for track\r
int framesAmount = stopFrame - startFrame;\r
package com.jme3.scene.plugins.blender.constraints;\r
\r
import com.jme3.animation.Animation;\r
+import com.jme3.animation.BoneTrack;\r
import com.jme3.animation.Track;\r
import com.jme3.math.Quaternion;\r
import com.jme3.math.Vector3f;\r
*/\r
public abstract ConstraintType getType();\r
\r
- /**\r
+ /**\r
* This method returns the bone traces for the bone that is affected by the given constraint.\r
* @param skeleton\r
* the skeleton containing bones\r
* the bone animation that affects the skeleton\r
* @return the bone track for the bone that is being affected by the constraint\r
*/\r
- protected Track<?> getTrack(Animation animation, int targetIndex) {\r
- if(boneOMA >= 0) {//bone animation\r
- for(Track<?> track : animation.getTracks()) {\r
- if(track.getTargetIndex() == targetIndex) {\r
- return track;\r
- }\r
- }\r
- } else {//spatial animation\r
- return animation.getTracks()[0];\r
- }\r
- return null;\r
+ protected Track getTrack(Animation animation, int targetIndex) {\r
+ if (boneOMA >= 0) {//bone animation\r
+ for (Track track : animation.getTracks()) {\r
+ if (((BoneTrack) track).getTargetBoneIndex() == targetIndex) {\r
+ return track;\r
+ }\r
+ }\r
+ } else {//spatial animation\r
+ return animation.getTracks()[0];\r
+ }\r
+ return null;\r
}\r
\r
/**\r
package com.jme3.scene.plugins.blender.constraints;\r
\r
import com.jme3.animation.Animation;\r
+import com.jme3.animation.BoneTrack;\r
import com.jme3.animation.Track;\r
import com.jme3.math.Vector3f;\r
import com.jme3.scene.plugins.blender.BlenderContext;\r
@Override\r
public void affectAnimation(Animation animation, int targetIndex) {\r
Vector3f targetLocation = this.getTargetLocation();\r
- Track<?> boneTrack = this.getTrack(animation, targetIndex);\r
+ BoneTrack boneTrack = (BoneTrack) this.getTrack(animation, targetIndex);\r
if (boneTrack != null) {\r
//TODO: target vertex group !!!\r
float dist = ((Number) data.getFieldValue("dist")).floatValue();\r
package com.jme3.scene.plugins.blender.constraints;\r
\r
import com.jme3.animation.Animation;\r
+import com.jme3.animation.BoneTrack;\r
import com.jme3.animation.Track;\r
import com.jme3.math.Vector3f;\r
import com.jme3.scene.plugins.blender.BlenderContext;\r
\r
@Override\r
public void affectAnimation(Animation animation, int targetIndex) {\r
- Track<?> track = this.getTrack(animation, targetIndex);\r
+ BoneTrack track = (BoneTrack) this.getTrack(animation, targetIndex);\r
if (track != null) {\r
Vector3f targetLocation = this.getTargetLocation();\r
int flag = ((Number) data.getFieldValue("flag")).intValue();\r
package com.jme3.scene.plugins.blender.constraints;\r
\r
import com.jme3.animation.Animation;\r
+import com.jme3.animation.BoneTrack;\r
import com.jme3.animation.Track;\r
import com.jme3.math.Vector3f;\r
import com.jme3.scene.plugins.blender.BlenderContext;\r
\r
@Override\r
public void affectAnimation(Animation animation, int targetIndex) {\r
- Track<?> track = this.getTrack(animation, targetIndex);\r
+ BoneTrack track = (BoneTrack) this.getTrack(animation, targetIndex);\r
if (track != null) {\r
int flag = ((Number) data.getFieldValue("flag")).intValue();\r
Vector3f[] translations = track.getTranslations();\r
package com.jme3.scene.plugins.blender.constraints;\r
\r
import com.jme3.animation.Animation;\r
+import com.jme3.animation.BoneTrack;\r
import com.jme3.animation.Track;\r
import com.jme3.math.Quaternion;\r
import com.jme3.scene.plugins.blender.BlenderContext;\r
\r
@Override\r
public void affectAnimation(Animation animation, int targetIndex) {\r
- Track<?> track = this.getTrack(animation, targetIndex);\r
+ BoneTrack track = (BoneTrack) this.getTrack(animation, targetIndex);\r
if (track != null) {\r
Quaternion targetRotation = this.getTargetRotation();\r
int flag = ((Number) data.getFieldValue("flag")).intValue();\r
package com.jme3.scene.plugins.blender.constraints;\r
\r
import com.jme3.animation.Animation;\r
+import com.jme3.animation.BoneTrack;\r
import com.jme3.animation.Track;\r
import com.jme3.math.FastMath;\r
import com.jme3.math.Quaternion;\r
\r
@Override\r
public void affectAnimation(Animation animation, int targetIndex) {\r
- Track<?> track = this.getTrack(animation, targetIndex);\r
+ BoneTrack track = (BoneTrack) this.getTrack(animation, targetIndex);\r
if (track != null) {\r
int flag = ((Number) data.getFieldValue("flag")).intValue();\r
Quaternion[] rotations = track.getRotations();\r
import java.util.logging.Logger;\r
\r
import com.jme3.animation.Animation;\r
+import com.jme3.animation.BoneTrack;\r
import com.jme3.animation.Track;\r
import com.jme3.math.Quaternion;\r
import com.jme3.math.Vector3f;\r
}\r
\r
//modifying traces\r
- Track<?> track = this.getTrack(animation, targetIndex);\r
+ BoneTrack track = (BoneTrack) this.getTrack(animation, targetIndex);\r
if (track != null) {\r
Vector3f[] translations = track.getTranslations();\r
Quaternion[] rotations = track.getRotations();\r
package com.jme3.scene.plugins.blender.constraints;\r
\r
import com.jme3.animation.Animation;\r
+import com.jme3.animation.BoneTrack;\r
import com.jme3.animation.Track;\r
import com.jme3.math.Vector3f;\r
import com.jme3.scene.plugins.blender.BlenderContext;\r
@Override\r
public void affectAnimation(Animation animation, int targetIndex) {\r
Vector3f targetScale = this.getTargetLocation();\r
- Track<?> track = this.getTrack(animation, targetIndex);\r
+ BoneTrack track = (BoneTrack) this.getTrack(animation, targetIndex);\r
if (track != null) {\r
int flag = ((Number) data.getFieldValue("flag")).intValue();\r
Vector3f[] scales = track.getScales();\r
package com.jme3.scene.plugins.blender.constraints;\r
\r
import com.jme3.animation.Animation;\r
+import com.jme3.animation.BoneTrack;\r
import com.jme3.animation.Track;\r
import com.jme3.math.Vector3f;\r
import com.jme3.scene.plugins.blender.BlenderContext;\r
\r
@Override\r
public void affectAnimation(Animation animation, int targetIndex) {\r
- Track<?> track = this.getTrack(animation, targetIndex);\r
+ BoneTrack track = (BoneTrack) this.getTrack(animation, targetIndex);\r
if (track != null) {\r
int flag = ((Number) data.getFieldValue("flag")).intValue();\r
Vector3f[] scales = track.getScales();\r
}\r
if(texture.getType()==Type.TwoDimensional) {//so far only 2D textures can be mapped in other way than color\r
if ((mapto & MaterialContext.MTEX_NOR) != 0 && !materialContext.shadeless) {\r
- Structure mTex = materialContext.getMTex(texture);\r
- Texture normalMapTexture = textureHelper.convertToNormalMapTexture(texture, ((Number) mTex.getFieldValue("norfac")).floatValue());\r
- texturesMap.put(TEXTURE_TYPE_NORMAL, normalMapTexture);\r
+ //Structure mTex = materialContext.getMTex(texture);\r
+ //Texture normalMapTexture = textureHelper.convertToNormalMapTexture(texture, ((Number) mTex.getFieldValue("norfac")).floatValue());\r
+ //texturesMap.put(TEXTURE_TYPE_NORMAL, normalMapTexture);\r
+ texturesMap.put(TEXTURE_TYPE_NORMAL, texture);\r
}\r
if ((mapto & MaterialContext.MTEX_EMIT) != 0) {\r
texturesMap.put(TEXTURE_TYPE_GLOW, texture);\r
import com.jme3.animation.AnimControl;\r
import com.jme3.animation.Animation;\r
import com.jme3.animation.Bone;\r
+import com.jme3.animation.BoneTrack;\r
import com.jme3.animation.Skeleton;\r
import com.jme3.animation.SkeletonControl;\r
import com.jme3.animation.Track;\r
Structure actionStructure = header.getStructure(blenderContext);\r
String actionName = actionStructure.getName();\r
\r
- Track<?>[] tracks = armatureHelper.getTracks(actionStructure, blenderContext);\r
+ BoneTrack[] tracks = armatureHelper.getTracks(actionStructure, blenderContext);\r
//determining the animation time\r
float maximumTrackLength = 0;\r
- for(Track<?> track : tracks) {\r
+ for(BoneTrack track : tracks) {\r
float length = track.getLength();\r
if(length > maximumTrackLength) {\r
maximumTrackLength = length;\r
\r
import com.jme3.animation.AnimControl;\r
import com.jme3.animation.Animation;\r
+import com.jme3.animation.BoneTrack;\r
import com.jme3.animation.Track;\r
import com.jme3.scene.Node;\r
import com.jme3.scene.plugins.blender.BlenderContext;\r
int fps = blenderContext.getBlenderKey().getFps();\r
\r
// calculating track for the only bone in this skeleton\r
- Track<?> track = ipo.calculateTrack(-1, 0, ipo.getLastFrame(), fps);\r
+ BoneTrack track = (BoneTrack) ipo.calculateTrack(-1, 0, ipo.getLastFrame(), fps);\r
\r
Animation animation = new Animation(objectAnimationName, ipo.getLastFrame() / fps);\r
- animation.setTracks(new Track<?>[] { track });\r
+ animation.setTracks(new BoneTrack[] { track });\r
ArrayList<Animation> animations = new ArrayList<Animation>(1);\r
animations.add(animation);\r
\r
package com.jme3.animation;
import com.jme3.math.FastMath;
+import com.jme3.util.TempVars;
import java.util.BitSet;
/**
private AnimControl control;
-// private ArrayList<Integer> affectedBones;
private BitSet affectedBones;
private Animation animation;
/**
* Returns the parent control of this AnimChannel.
+ *
* @return the parent control of this AnimChannel.
* @see AnimControl
*/
return affectedBones;
}
- void update(float tpf) {
+ void update(float tpf, TempVars vars) {
if (animation == null)
return;
if (blendFrom != null){
- blendFrom.setTime(timeBlendFrom, 1f - blendAmount, control, this);
+ blendFrom.setTime(timeBlendFrom, 1f - blendAmount, control, this, vars);
//blendFrom.setTime(timeBlendFrom, control.skeleton, 1f - blendAmount, affectedBones);
timeBlendFrom += tpf * speedBlendFrom;
timeBlendFrom = clampWrapTime(timeBlendFrom,
}
}
- animation.setTime(time, blendAmount, control, this);
+ animation.setTime(time, blendAmount, control, this, vars);
//animation.setTime(time, control.skeleton, blendAmount, affectedBones);
time += tpf * speed;
import com.jme3.scene.Spatial;\r
import com.jme3.scene.control.AbstractControl;\r
import com.jme3.scene.control.Control;\r
+import com.jme3.util.TempVars;\r
import java.io.IOException;\r
import java.util.ArrayList;\r
import java.util.Collection;\r
* @param skeleton The skeleton to animate\r
*/\r
public AnimControl(Skeleton skeleton) {\r
- //if (skeleton == null)\r
- // throw new IllegalArgumentException("skeleton cannot be null");\r
-\r
this.skeleton = skeleton;\r
reset();\r
}\r
try {\r
AnimControl clone = (AnimControl) super.clone();\r
clone.spatial = spatial;\r
+ clone.channels = new ArrayList<AnimChannel>();\r
+ \r
if (skeleton != null){\r
clone.skeleton = new Skeleton(skeleton);\r
}\r
- clone.channels = new ArrayList<AnimChannel>();\r
\r
// animationMap is reference-copied, animation data should be shared\r
// to reduce memory usage.\r
skeleton.reset(); // reset skeleton to bind pose\r
}\r
\r
+ TempVars vars = TempVars.get();\r
for (int i = 0; i < channels.size(); i++) {\r
- channels.get(i).update(tpf);\r
+ channels.get(i).update(tpf, vars);\r
}\r
+ vars.release();\r
\r
if (skeleton != null){\r
skeleton.updateWorldVectors();\r
animationMap = (HashMap<String, Animation>) in.readStringSavableMap("animations", null);\r
\r
if (im.getFormatVersion() == 0){\r
- //changed for backward compatibility with j3o files generated before the AnimControl/SkeletonControl split\r
- //if we find a target mesh array the AnimControl creates the SkeletonControl for old files and add it to the spatial. \r
- //When backward compatibility won't be needed anymore this can deleted \r
+ // Changed for backward compatibility with j3o files generated \r
+ // before the AnimControl/SkeletonControl split.\r
+ \r
+ // If we find a target mesh array the AnimControl creates the \r
+ // SkeletonControl for old files and add it to the spatial. \r
+ // When backward compatibility won't be needed anymore this can deleted \r
Savable[] sav = in.readSavableArray("targets", null);\r
if (sav != null) {\r
Mesh[] targets = new Mesh[sav.length];\r
package com.jme3.animation;
import java.io.IOException;
-import java.util.ArrayList;
-import java.util.BitSet;
-import java.util.Collection;
-import java.util.List;
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;
+import com.jme3.util.TempVars;
/**
* 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. */
+
+ /**
+ * The name of the animation.
+ */
+ private String name;
+
+ /**
+ * The length of the animation.
+ */
private float length;
- /** The tracks of the animation. */
- private Track<?>[] tracks;
+
+ /**
+ * The tracks of the animation.
+ */
+ private Track[] tracks;
/**
* Serialization-only. Do not use.
public Animation() {}
/**
- * Creates a new BoneAnimation with the given name and length.
+ * Creates a new <code>Animation</code> with the given name and length.
*
- * @param name The name of the bone animation.
- * @param length Length in seconds of the bone animation.
+ * @param name The name of the animation.
+ * @param length Length in seconds of the animation.
*/
public Animation(String name, float length) {
this.name = name;
}
/**
- * @return the name of the animation
+ * The name of the bone animation
+ * @return name of the bone animation
*/
public String getName() {
return name;
}
/**
- * @return the length of the animation
+ * Returns the length in seconds of this animation
+ *
+ * @return the length in seconds of this 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 control the animation 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);
- }
- }
+ void setTime(float time, float blendAmount, AnimControl control, AnimChannel channel, TempVars vars) {
+ for (int i = 0; i < tracks.length; i++){
+ tracks[i].setTime(time, blendAmount, control, channel, vars);
+ }
+
+ /*
+ 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);
+ }
+ }
+ }
+ }
+ */
}
/**
* Set the {@link Track}s to be used by this animation.
* <p>
- * The array should be organized so that the appropriate BoneTrack can
+ * The array should be organized so that the appropriate Track can
* be retrieved based on a bone index.
*
- * @param tracks the tracks to set
+ * @param tracks The tracks to set.
*/
- public void setTracks(Track<?>[] tracks){
+ public void setTracks(Track[] tracks){
this.tracks = tracks;
}
/**
- * @return the tracks of the animation
+ * Returns the tracks set in {@link #setTracks(com.jme3.animation.Track[]) }.
+ *
+ * @return the tracks set previously
*/
- public Track<?>[] getTracks() {
+ 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();
- }
+ @Override
+ public Animation clone() {
+ try {
+ Animation result = (Animation) super.clone();
+ result.tracks = tracks.clone();
+ for (int i = 0; i < tracks.length; ++i) {
+ result.tracks[i] = this.tracks[i].clone();
}
- return result;
+ return result;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
@Override
public String toString() {
- return "Animation[name=" + name + ", length=" + length + ']';
+ return getClass().getSimpleName() + "[name=" + name + ", length=" + length + ']';
}
- @Override
- public void write(JmeExporter ex) throws IOException {
- OutputCapsule out = ex.getCapsule(this);
+ @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);
+ @Override
+ public void read(JmeImporter im) throws IOException {
+ InputCapsule in = im.getCapsule(this);
name = in.readString("name", null);
length = in.readFloat("length", 0f);
- Object[] arr = in.readSavableArray("tracks", null);
- tracks = new Track<?>[arr.length];
+
+ Savable[] arr = in.readSavableArray("tracks", null);
+ tracks = new Track[arr.length];
System.arraycopy(arr, 0, tracks, 0, arr.length);
- }
+ }
}
}
}
- /**
+ /**
* Stores the skinning transform in the specified Matrix4f.
* The skinning transform applies the animation of the bone to a vertex.
- * @param m
+ *
+ * This assumes that the world transforms for the entire bone hierarchy
+ * have already been computed, otherwise this method will return undefined
+ * results.
+ *
+ * @param outTransform
*/
- void getOffsetTransform(Matrix4f m, Quaternion tmp1, Vector3f tmp2, Vector3f tmp3, Matrix3f rotMat) {
-
- //Computing scale
+ void getOffsetTransform(Matrix4f outTransform, Quaternion tmp1, Vector3f tmp2, Vector3f tmp3, Matrix3f tmp4) {
+ // Computing scale
Vector3f scale = worldScale.mult(worldBindInverseScale, tmp3);
- //computing rotation
+ // Computing rotation
Quaternion rotate = worldRot.mult(worldBindInverseRot, tmp1);
- //computing translation
- //translation depend on rotation and scale
+ // Computing translation
+ // Translation depend on rotation and scale
Vector3f translate = worldPos.add(rotate.mult(scale.mult(worldBindInversePos, tmp2), tmp2), tmp2);
- //populating the matrix
- m.loadIdentity();
- m.setTransform(translate, scale, rotate.toRotationMatrix(rotMat));
-
+ // Populating the matrix
+ outTransform.loadIdentity();
+ outTransform.setTransform(translate, scale, rotate.toRotationMatrix(tmp4));
}
/**
*/
package com.jme3.animation;
-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.Quaternion;
-import com.jme3.math.Vector3f;
-
-import java.io.IOException;
-import java.util.BitSet;
-
/**
- * <code>BoneAnimation</code> updates each of its tracks with the skeleton and time
- * to apply the animation.
- *
- * @author Kirill Vainer
* @deprecated use Animation instead with tracks of selected type (ie. BoneTrack, SpatialTrack, MeshTrack)
*/
@Deprecated
public final class BoneAnimation extends Animation {
- private String name;
- private float length;
- private BoneTrack[] tracks;
-
- /**
- * 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.
- */
+ @Deprecated
public BoneAnimation(String name, float length) {
- this.name = name;
- this.length = length;
- }
-
- /**
- * Serialization-only. Do not use.
- */
- public BoneAnimation() {
- }
-
- /**
- * The name of the bone animation
- * @return name of the bone animation
- */
- public String getName(){
- return name;
- }
-
- /**
- * Returns the length in seconds of this animation
- *
- * @return the length in seconds of this animation
- */
- public float getLength(){
- return length;
- }
-
- /**
- * Set the {@link BoneTrack}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(BoneTrack[] tracks){
- this.tracks = tracks;
- }
-
- /**
- * Returns the tracks set in {@link #setTracks(com.jme3.animation.BoneTrack[]) }.
- *
- * @return the tracks set previously
- */
- public BoneTrack[] getTracks(){
- return tracks;
- }
-
- public void setTime(float time, float blendAmount, AnimControl control, AnimChannel channel){
- BitSet affectedBones = channel.getAffectedBones();
- Skeleton skeleton = control.getSkeleton();
-
- if (tracks == null)
- return;
-
- for (int i = 0; i < tracks.length; i++) {
- if (affectedBones == null
- || affectedBones.get(tracks[i].getTargetIndex())) {
- tracks[i].setTime(time, skeleton, blendAmount);
- }
- }
- }
-
- @Override
- public String toString() {
- return "BoneAnim[name=" + name + ", length=" + length + "]";
- }
-
- @Override
- public BoneAnimation clone() {
- BoneAnimation result = (BoneAnimation) super.clone();
- if (result.tracks == null) {
- result.tracks = new BoneTrack[tracks.length];
- }
- for (int i = 0; i < tracks.length; ++i) {
- int tablesLength = tracks[i].getTimes().length;
-
- float[] times = tracks[i].getTimes().clone();
- Vector3f[] sourceTranslations = tracks[i].getTranslations();
- Quaternion[] sourceRotations = tracks[i].getRotations();
- Vector3f[] sourceScales = tracks[i].getScales();
-
- Vector3f[] translations = new Vector3f[tablesLength];
- Quaternion[] rotations = new Quaternion[tablesLength];
- Vector3f[] scales = new Vector3f[tablesLength];
- for (int j = 0; j < tablesLength; ++j) {
- translations[j] = sourceTranslations[j].clone();
- rotations[j] = sourceRotations[j].clone();
- 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].getTargetIndex(), times,
- translations, rotations, scales);
- }
- return result;
- }
-
- @Override
- public void write(JmeExporter e) throws IOException {
- OutputCapsule out = e.getCapsule(this);
- out.write(name, "name", null);
- out.write(length, "length", 0f);
- out.write(tracks, "tracks", null);
- }
-
- @Override
- public void read(JmeImporter i) throws IOException {
- InputCapsule in = i.getCapsule(this);
- name = in.readString("name", null);
- length = in.readFloat("length", 0f);
-
- Savable[] sav = in.readSavableArray("tracks", null);
- if (sav != null) {
- tracks = new BoneTrack[sav.length];
- System.arraycopy(sav, 0, tracks, 0, sav.length);
- }
+ super(name, length);
}
}
import com.jme3.export.Savable;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
+import com.jme3.util.TempVars;
import java.io.IOException;
+import java.util.BitSet;
/**
* Contains a list of transforms and times for each keyframe.
*
* @author Kirill Vainer
*/
-public final class BoneTrack implements Track<Skeleton> {
+public final class BoneTrack implements Track {
/**
* Bone index in the skeleton which this track effects.
*/
private int targetBoneIndex;
+
/**
* Transforms and times for track.
*/
private CompactQuaternionArray rotations;
private CompactVector3Array scales;
private float[] times;
- // temp vectors for interpolation
- private transient final Vector3f tempV = new Vector3f();
- private transient final Quaternion tempQ = new Quaternion();
- private transient final Vector3f tempS = new Vector3f();
- private transient final Vector3f tempV2 = new Vector3f();
- private transient final Quaternion tempQ2 = new Quaternion();
- private transient final Vector3f tempS2 = new Vector3f();
-
+
/**
* Serialization-only. Do not use.
*/
this.targetBoneIndex = targetBoneIndex;
}
- /**
- * @return the bone index of this bone track
- * @deprecated use getTargetIndex() instead
+ /**
+ * @return the bone index of this bone track.
*/
- @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
*/
}
/**
- * Set the translations, rotations and scales for this bone track
+ * Set the translations, rotations and scales for this bone 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 skeleton the skeleton to which the bone belong
* @param weight the weight of the animation
*/
- public void setTime(float time, Skeleton skeleton, float weight) {
- Bone target = skeleton.getBone(targetBoneIndex);
+ public void setTime(float time, float weight, AnimControl control, AnimChannel channel, TempVars vars) {
+ BitSet affectedBones = channel.getAffectedBones();
+ if (affectedBones != null && !affectedBones.get(targetBoneIndex)) {
+ return;
+ }
+
+ Bone target = control.getSkeleton().getBone(targetBoneIndex);
+ 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) {
rotations.get(0, tempQ);
}
/**
- * @return the length of the track
- */
- public float getLength() {
- return times == null ? 0 : times[times.length - 1] - times[0];
- }
+ * @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
*/
- public BoneTrack clone() {
+ @Override
+ public BoneTrack clone() {
int tablesLength = times.length;
float[] times = this.times.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
+
+ // 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 {
targetBoneIndex = ic.readInt("boneIndex", 0);
translations = (CompactVector3Array) ic.readSavable("translations", null);
-
rotations = (CompactQuaternionArray) ic.readSavable("rotations", null);
times = ic.readFloatArray("times", null);
scales = (CompactVector3Array) ic.readSavable("scales", null);
-
//Backward compatibility for old j3o files generated before revision 6807
if (im.getFormatVersion() == 0){
if (translations == null) {
}
}
}
+
+ public void setTime(float time, float weight, AnimControl control, AnimChannel channel) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
}
+++ /dev/null
-/*
- * Copyright (c) 2009-2010 jMonkeyEngine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-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.OutputCapsule;
-import com.jme3.scene.Mesh;
-
-/**
- *
- * @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 PoseTrack[] tracks;
-
- public MeshAnimation(String name, float length){
- this.name = name;
- this.length = length;
- }
-
- public String getName(){
- return name;
- }
-
- public float getLength(){
- return length;
- }
-
- public void setTracks(PoseTrack[] tracks){
- this.tracks = tracks;
- }
-
- public PoseTrack[] getTracks(){
- return tracks;
- }
-
- public void setTime(float time, Mesh[] targets, float weight){
- for (int i = 0; i < tracks.length; i++){
- tracks[i].setTime(time, targets, weight);
- }
- }
-
- @Override
- public void setTime(float time, float blendAmount, AnimControl control, AnimChannel channel) {
- // TODO: ...
- }
-
- public void write(JmeExporter e) throws IOException {
- OutputCapsule out = e.getCapsule(this);
- out.write(name, "name", "");
- out.write(length, "length", -1f);
- out.write(tracks, "tracks", null);
- }
-
-
- public void read(JmeImporter i) throws IOException {
- InputCapsule in = i.getCapsule(this);
- name = in.readString("name", "");
- length = in.readFloat("length", -1f);
- tracks = (PoseTrack[]) in.readSavableArray("tracks", null);
- }
-}
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;
+import com.jme3.util.TempVars;
import java.io.IOException;
import java.nio.FloatBuffer;
/**
* A single track of pose animation associated with a certain mesh.
*/
-public final class PoseTrack implements Track<Mesh[]> {
+@Deprecated
+public final class PoseTrack implements Track {
- protected int targetMeshIndex;
+ private int targetMeshIndex;
private PoseFrame[] frames;
- private float[] times;
+ private float[] times;
public static class PoseFrame implements Savable, Cloneable {
Pose[] poses;
float[] weights;
- public PoseFrame(Pose[] poses, float[] weights){
+ public PoseFrame(Pose[] poses, float[] weights) {
this.poses = poses;
this.weights = weights;
}
* This method creates a clone of the current object.
* @return a clone of the current object
*/
+ @Override
public PoseFrame clone() {
- try {
- PoseFrame result = (PoseFrame) super.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();
- }
+ 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;
+ return result;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
- }
+ }
public void write(JmeExporter e) throws IOException {
OutputCapsule out = e.getCapsule(this);
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];
VertexBuffer pb = target.getBuffer(Type.Position);
pb.updateData(pb.getData());
}
- public void setTime(float time, Mesh[] targets, float weight) {
+ public void setTime(float time, float weight, AnimControl control, AnimChannel channel, TempVars vars) {
+ // TODO: When MeshControl is created, it will gather targets
+ // list automatically which is then retrieved here.
+
+ /*
Mesh target = targets[targetMeshIndex];
- if (time < times[0]){
+ if (time < times[0]) {
applyFrame(target, 0, weight);
- }else if (time > times[times.length-1]){
- applyFrame(target, times.length-1, weight);
- } else{
+ } else if (time > times[times.length - 1]) {
+ applyFrame(target, times.length - 1, weight);
+ } else {
int startFrame = 0;
- for (int i = 0; i < times.length; i++){
- if (times[i] < time)
+ for (int i = 0; i < times.length; i++) {
+ if (times[i] < time) {
startFrame = i;
+ }
}
int endFrame = startFrame + 1;
float blend = (time - times[startFrame]) / (times[endFrame] - times[startFrame]);
applyFrame(target, startFrame, blend * weight);
- applyFrame(target, endFrame, (1f-blend) * weight);
+ applyFrame(target, endFrame, (1f - blend) * weight);
}
+ */
}
/**
- * @return the length of the track
- */
- public float getLength() {
- return times == null ? 0 : times[times.length - 1] - times[0];
- }
+ * @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 PoseTrack clone() {
- try {
- PoseTrack result = (PoseTrack) super.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();
- }
+ 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;
+ return result;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
- }
+ }
@Override
public void write(JmeExporter e) throws IOException {
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) {
- }
}
private Bone[] rootBones;
private Bone[] boneList;
+
/**
* Contains the skinning matrices, multiplying it by a vertex effected by a bone
* will cause it to go to the animated position.
* @param skeleton the skeleton
*/
@Deprecated
- public SkeletonControl(Mesh[] targets, Skeleton skeleton){
+ SkeletonControl(Mesh[] targets, Skeleton skeleton){
this.skeleton = skeleton;
this.targets = targets;
}
import com.jme3.math.Quaternion;\r
import com.jme3.math.Vector3f;\r
import com.jme3.scene.Spatial;\r
+import com.jme3.util.TempVars;\r
\r
/**\r
* This class represents the track for spatial animation.\r
* \r
* @author Marcin Roguski (Kaelthas)\r
*/\r
-public class SpatialTrack implements Track<Spatial> {\r
- /** Translations of the track. */\r
- private CompactVector3Array translations;\r
- /** Rotations of the track. */\r
- private CompactQuaternionArray rotations;\r
- /** Scales of the track. */\r
- private CompactVector3Array scales;\r
- /** The times of the animations frames. */\r
- private float[] times;\r
-\r
- // temp vectors for interpolation\r
- private transient final Vector3f tempV = new Vector3f();\r
- private transient final Quaternion tempQ = new Quaternion();\r
- private transient final Vector3f tempS = new Vector3f();\r
- private transient final Vector3f tempV2 = new Vector3f();\r
- private transient final Quaternion tempQ2 = new Quaternion();\r
- private transient final Vector3f tempS2 = new Vector3f();\r
-\r
- public SpatialTrack() {\r
- }\r
-\r
- /**\r
- * Creates a spatial track for the given track data.\r
- * \r
- * @param times\r
- * a float array with the time of each frame\r
- * @param translations\r
- * the translation of the bone for each frame\r
- * @param rotations\r
- * the rotation of the bone for each frame\r
- * @param scales\r
- * the scale of the bone for each frame\r
- */\r
- public SpatialTrack(float[] times, Vector3f[] translations,\r
- Quaternion[] rotations, Vector3f[] scales) {\r
- this.setKeyframes(times, translations, rotations, scales);\r
- }\r
-\r
- /**\r
- * \r
- * Modify the spatial which this track modifies.\r
- * \r
- * @param time\r
- * the current time of the animation\r
- * @param spatial\r
- * the spatial that should be animated with this track\r
- */\r
- public void setTime(float time, Spatial spatial, float weight) {\r
- int lastFrame = times.length - 1;\r
- if (time < 0 || lastFrame == 0) {\r
- rotations.get(0, tempQ);\r
- translations.get(0, tempV);\r
- if (scales != null) {\r
- scales.get(0, tempS);\r
- }\r
- } else if (time >= times[lastFrame]) {\r
- rotations.get(lastFrame, tempQ);\r
- translations.get(lastFrame, tempV);\r
- if (scales != null) {\r
- scales.get(lastFrame, tempS);\r
- }\r
- } else {\r
- int startFrame = 0;\r
- int endFrame = 1;\r
- // use lastFrame so we never overflow the array\r
- for (int i = 0; i < lastFrame && times[i] < time; ++i) {\r
- startFrame = i;\r
- endFrame = i + 1;\r
- }\r
-\r
- float blend = (time - times[startFrame]) / (times[endFrame] - times[startFrame]);\r
-\r
- rotations.get(startFrame, tempQ);\r
- translations.get(startFrame, tempV);\r
- if (scales != null) {\r
- scales.get(startFrame, tempS);\r
- }\r
- rotations.get(endFrame, tempQ2);\r
- translations.get(endFrame, tempV2);\r
- if (scales != null) {\r
- scales.get(endFrame, tempS2);\r
- }\r
- tempQ.nlerp(tempQ2, blend);\r
- tempV.interpolate(tempV2, blend);\r
- tempS.interpolate(tempS2, blend);\r
- }\r
- spatial.setLocalTranslation(tempV);\r
- spatial.setLocalRotation(tempQ);\r
- if (scales != null) {\r
- spatial.setLocalScale(tempS);\r
- }\r
- }\r
-\r
- /**\r
- * Set the translations, rotations and scales for this track.\r
- * \r
- * @param times\r
- * a float array with the time of each frame\r
- * @param translations\r
- * the translation of the bone for each frame\r
- * @param rotations\r
- * the rotation of the bone for each frame\r
- * @param scales\r
- * the scale of the bone for each frame\r
- */\r
- public void setKeyframes(float[] times, Vector3f[] translations,\r
- Quaternion[] rotations, Vector3f[] scales) {\r
- if (times.length == 0) {\r
- throw new RuntimeException("BoneTrack with no keyframes!");\r
- }\r
-\r
- assert times.length == translations.length\r
- && times.length == rotations.length;\r
-\r
- this.times = times;\r
- this.translations = new CompactVector3Array();\r
- this.translations.add(translations);\r
- this.translations.freeze();\r
- this.rotations = new CompactQuaternionArray();\r
- this.rotations.add(rotations);\r
- this.rotations.freeze();\r
-\r
- assert times.length == scales.length;\r
-\r
- if (scales != null) {\r
- this.scales = new CompactVector3Array();\r
- this.scales.add(scales);\r
- this.scales.freeze();\r
- }\r
- }\r
-\r
- /**\r
- * @return the index of the target object for this track\r
- */\r
- public int getTargetIndex() {\r
- return 0;\r
- }\r
- \r
- /**\r
- * @return the array of rotations of this track\r
- */\r
- public Quaternion[] getRotations() {\r
- return rotations.toObjectArray();\r
- }\r
-\r
- /**\r
- * @return the array of scales for this track\r
- */\r
- public Vector3f[] getScales() {\r
- return scales == null ? null : scales.toObjectArray();\r
- }\r
-\r
- /**\r
- * @return the arrays of time for this track\r
- */\r
- public float[] getTimes() {\r
- return times;\r
- }\r
-\r
- /**\r
- * @return the array of translations of this track\r
- */\r
- public Vector3f[] getTranslations() {\r
- return translations.toObjectArray();\r
- }\r
- \r
- /**\r
- * @return the length of the track\r
- */\r
- public float getLength() {\r
- return times == null ? 0 : times[times.length - 1] - times[0];\r
- }\r
-\r
- /**\r
+public class SpatialTrack implements Track {\r
+ \r
+ /** \r
+ * Translations of the track. \r
+ */\r
+ private CompactVector3Array translations;\r
+ \r
+ /** \r
+ * Rotations of the track. \r
+ */\r
+ private CompactQuaternionArray rotations;\r
+ \r
+ /**\r
+ * Scales of the track. \r
+ */\r
+ private CompactVector3Array scales;\r
+ \r
+ /** \r
+ * The times of the animations frames. \r
+ */\r
+ private float[] times;\r
+\r
+ public SpatialTrack() {\r
+ }\r
+\r
+ /**\r
+ * Creates a spatial track for the given track data.\r
+ * \r
+ * @param times\r
+ * a float array with the time of each frame\r
+ * @param translations\r
+ * the translation of the bone for each frame\r
+ * @param rotations\r
+ * the rotation of the bone for each frame\r
+ * @param scales\r
+ * the scale of the bone for each frame\r
+ */\r
+ public SpatialTrack(float[] times, Vector3f[] translations,\r
+ Quaternion[] rotations, Vector3f[] scales) {\r
+ setKeyframes(times, translations, rotations, scales);\r
+ }\r
+\r
+ /**\r
+ * \r
+ * Modify the spatial which this track modifies.\r
+ * \r
+ * @param time\r
+ * the current time of the animation\r
+ * @param spatial\r
+ * the spatial that should be animated with this track\r
+ */\r
+ public void setTime(float time, float weight, AnimControl control, AnimChannel channel, TempVars vars) {\r
+ Spatial spatial = control.getSpatial();\r
+ \r
+ Vector3f tempV = vars.vect1;\r
+ Vector3f tempS = vars.vect2;\r
+ Quaternion tempQ = vars.quat1;\r
+ Vector3f tempV2 = vars.vect3;\r
+ Vector3f tempS2 = vars.vect4;\r
+ Quaternion tempQ2 = vars.quat2;\r
+ \r
+ int lastFrame = times.length - 1;\r
+ if (time < 0 || lastFrame == 0) {\r
+ rotations.get(0, tempQ);\r
+ translations.get(0, tempV);\r
+ if (scales != null) {\r
+ scales.get(0, tempS);\r
+ }\r
+ } else if (time >= times[lastFrame]) {\r
+ rotations.get(lastFrame, tempQ);\r
+ translations.get(lastFrame, tempV);\r
+ if (scales != null) {\r
+ scales.get(lastFrame, tempS);\r
+ }\r
+ } else {\r
+ int startFrame = 0;\r
+ int endFrame = 1;\r
+ // use lastFrame so we never overflow the array\r
+ for (int i = 0; i < lastFrame && times[i] < time; ++i) {\r
+ startFrame = i;\r
+ endFrame = i + 1;\r
+ }\r
+\r
+ float blend = (time - times[startFrame]) / (times[endFrame] - times[startFrame]);\r
+\r
+ rotations.get(startFrame, tempQ);\r
+ translations.get(startFrame, tempV);\r
+ if (scales != null) {\r
+ scales.get(startFrame, tempS);\r
+ }\r
+ rotations.get(endFrame, tempQ2);\r
+ translations.get(endFrame, tempV2);\r
+ if (scales != null) {\r
+ scales.get(endFrame, tempS2);\r
+ }\r
+ tempQ.nlerp(tempQ2, blend);\r
+ tempV.interpolate(tempV2, blend);\r
+ tempS.interpolate(tempS2, blend);\r
+ }\r
+ \r
+ spatial.setLocalTranslation(tempV);\r
+ spatial.setLocalRotation(tempQ);\r
+ if (scales != null) {\r
+ spatial.setLocalScale(tempS);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Set the translations, rotations and scales for this track.\r
+ * \r
+ * @param times\r
+ * a float array with the time of each frame\r
+ * @param translations\r
+ * the translation of the bone for each frame\r
+ * @param rotations\r
+ * the rotation of the bone for each frame\r
+ * @param scales\r
+ * the scale of the bone for each frame\r
+ */\r
+ public void setKeyframes(float[] times, Vector3f[] translations,\r
+ Quaternion[] rotations, Vector3f[] scales) {\r
+ if (times.length == 0) {\r
+ throw new RuntimeException("BoneTrack with no keyframes!");\r
+ }\r
+\r
+ assert times.length == translations.length\r
+ && times.length == rotations.length;\r
+\r
+ this.times = times;\r
+ this.translations = new CompactVector3Array();\r
+ this.translations.add(translations);\r
+ this.translations.freeze();\r
+ this.rotations = new CompactQuaternionArray();\r
+ this.rotations.add(rotations);\r
+ this.rotations.freeze();\r
+\r
+ if (scales != null) {\r
+ assert times.length == scales.length;\r
+ \r
+ this.scales = new CompactVector3Array();\r
+ this.scales.add(scales);\r
+ this.scales.freeze();\r
+ \r
+ \r
+ }\r
+ }\r
+\r
+ /**\r
+ * @return the array of rotations of this track\r
+ */\r
+ public Quaternion[] getRotations() {\r
+ return rotations.toObjectArray();\r
+ }\r
+\r
+ /**\r
+ * @return the array of scales for this track\r
+ */\r
+ public Vector3f[] getScales() {\r
+ return scales == null ? null : scales.toObjectArray();\r
+ }\r
+\r
+ /**\r
+ * @return the arrays of time for this track\r
+ */\r
+ public float[] getTimes() {\r
+ return times;\r
+ }\r
+\r
+ /**\r
+ * @return the array of translations of this track\r
+ */\r
+ public Vector3f[] getTranslations() {\r
+ return translations.toObjectArray();\r
+ }\r
+\r
+ /**\r
+ * @return the length of the track\r
+ */\r
+ public float getLength() {\r
+ return times == null ? 0 : times[times.length - 1] - times[0];\r
+ }\r
+\r
+ /**\r
* This method creates a clone of the current object.\r
* @return a clone of the current object\r
*/\r
- public SpatialTrack clone() {\r
+ @Override\r
+ public SpatialTrack clone() {\r
int tablesLength = times.length;\r
\r
float[] times = this.times.clone();\r
}\r
//need to use the constructor here because of the final fields used in this class\r
return new SpatialTrack(times, translations, rotations, scales);\r
- }\r
+ }\r
\r
- @Override\r
- public void write(JmeExporter ex) throws IOException {\r
- OutputCapsule oc = ex.getCapsule(this);\r
- oc.write(translations, "translations", null);\r
- oc.write(rotations, "rotations", null);\r
- oc.write(times, "times", null);\r
- oc.write(scales, "scales", null);\r
- }\r
-\r
- @Override\r
- public void read(JmeImporter im) throws IOException {\r
- InputCapsule ic = im.getCapsule(this);\r
- translations = (CompactVector3Array) ic.readSavable("translations", null);\r
- rotations = (CompactQuaternionArray) ic.readSavable("rotations", null);\r
- times = ic.readFloatArray("times", null);\r
- scales = (CompactVector3Array) ic.readSavable("scales", null);\r
- }\r
+ @Override\r
+ public void write(JmeExporter ex) throws IOException {\r
+ OutputCapsule oc = ex.getCapsule(this);\r
+ oc.write(translations, "translations", null);\r
+ oc.write(rotations, "rotations", null);\r
+ oc.write(times, "times", null);\r
+ oc.write(scales, "scales", null);\r
+ }\r
+\r
+ @Override\r
+ public void read(JmeImporter im) throws IOException {\r
+ InputCapsule ic = im.getCapsule(this);\r
+ translations = (CompactVector3Array) ic.readSavable("translations", null);\r
+ rotations = (CompactQuaternionArray) ic.readSavable("rotations", null);\r
+ times = ic.readFloatArray("times", null);\r
+ scales = (CompactVector3Array) ic.readSavable("scales", null);\r
+ }\r
}\r
package com.jme3.animation;
import com.jme3.export.Savable;
-import com.jme3.math.Quaternion;
-import com.jme3.math.Vector3f;
+import com.jme3.util.TempVars;
+
+public interface Track extends Savable, Cloneable {
-/**
- * A single track of mesh animation (either morph or pose based).
- * Currently morph animations are not supported (only pose).
- */
-public interface Track<T> extends Savable, Cloneable {
/**
- * sets time for this track
- * @param time
- * @param target
- * @param weight
+ * Sets the time of the animation.
+ *
+ * Internally, the track will retrieve objects from the control
+ * and modify them according to the properties of the channel and the
+ * given parameters.
+ *
+ * @param time The time in the animation
+ * @param weight The weight from 0 to 1 on how much to apply the track
+ * @param control The control which the track should effect
+ * @param channel The channel which the track should effect
*/
- 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 setTime(float time, float weight, AnimControl control, AnimChannel channel, TempVars vars);
- /**
- * @return the array of scales for this track
- */
- Vector3f[] getScales();
-
- /**
- * @return the arrays of time for this track
- */
- float[] getTimes();
+ /**
+ * @return the length of the track
+ */
+ public float getLength();
- /**
- * @return the array of translations of this track
- */
- Vector3f[] getTranslations();
-
- /**
- * @return the length of the track
- */
- float getLength();
-
- /**
+ /**
* This method creates a clone of the current object.
* @return a clone of the current object
*/
- Track<T> clone();
+ public Track clone();
}
*/
package com.jme3.export;
+import com.jme3.animation.Animation;
import com.jme3.effect.shapes.EmitterBoxShape;
import com.jme3.effect.shapes.EmitterMeshConvexHullShape;
import com.jme3.effect.shapes.EmitterMeshFaceShape;
addRemapping("com.jme3.effect.EmitterMeshVertexShape", EmitterMeshVertexShape.class);
addRemapping("com.jme3.effect.EmitterPointShape", EmitterPointShape.class);
addRemapping("com.jme3.material.Material$MatParamTexture", MatParamTexture.class);
+ addRemapping("com.jme3.animation.BoneAnimation", Animation.class);
+ addRemapping("com.jme3.animation.SpatialAnimation", Animation.class);
}
private static String remapClass(String className) throws ClassNotFoundException {