addionnal javadoc for com.jme3.animation

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7636 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
rem..om 14 years ago
parent 15e099e160
commit 4c18882032
  1. 57
      engine/src/core/com/jme3/animation/BoneAnimation.java
  2. 63
      engine/src/core/com/jme3/animation/BoneTrack.java
  3. 71
      engine/src/core/com/jme3/animation/CompactArray.java
  4. 27
      engine/src/core/com/jme3/animation/CompactQuaternionArray.java
  5. 8
      engine/src/core/com/jme3/animation/CompactVector3Array.java
  6. 37
      engine/src/core/com/jme3/animation/Skeleton.java
  7. 55
      engine/src/core/com/jme3/animation/SkeletonControl.java
  8. 23
      engine/src/core/com/jme3/animation/Track.java
  9. 6
      engine/src/core/com/jme3/post/FilterPostProcessor.java

@ -29,7 +29,6 @@
* 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 com.jme3.export.JmeExporter;
@ -43,12 +42,13 @@ import java.util.BitSet;
/**
* Bone animation updates each of its tracks with the skeleton and time
* to apply the animation.
*
* @author Kirill Vainer
*/
public final class BoneAnimation implements Savable {
private String name;
private float length;
private BoneTrack[] tracks;
/**
@ -57,7 +57,7 @@ public final class BoneAnimation implements Savable {
* @param name The name of the bone animation.
* @param length Length in seconds of the bone animation.
*/
public BoneAnimation(String name, float length){
public BoneAnimation(String name, float length) {
this.name = name;
this.length = length;
}
@ -65,43 +65,55 @@ public final class BoneAnimation implements Savable {
/**
* Serialization-only. Do not use.
*/
public BoneAnimation(){
public BoneAnimation() {
}
public String getName(){
/**
* Returns the animation name
* @return
*/
public String getName() {
return name;
}
public float getLength(){
/**
* returns the animation length (in seconds)
* @return
*/
public float getLength() {
return length;
}
public void setTracks(BoneTrack[] tracks){
/**
* Sets the bone tracks to this bone animation
* @see BoneTrack
* @param tracks
*/
public void setTracks(BoneTrack[] tracks) {
this.tracks = tracks;
}
public BoneTrack[] getTracks(){
/**
* returns the bone tracks of this animation
* @see BoneTrack
* @return
*/
public BoneTrack[] getTracks() {
return tracks;
}
void setTime(float time, Skeleton skeleton, float weight, BitSet affectedBones){
for (int i = 0; i < tracks.length; i++){
void setTime(float time, Skeleton skeleton, float weight, BitSet affectedBones) {
for (int i = 0; i < tracks.length; i++) {
if (affectedBones == null
|| affectedBones.get(tracks[i].getTargetBoneIndex()))
|| affectedBones.get(tracks[i].getTargetBoneIndex())) {
tracks[i].setTime(time, skeleton, weight);
}
}
}
// void setTime(float time, Skeleton skeleton, float weight, ArrayList<Integer> affectedBones){
// for (int i = 0; i < tracks.length; i++){
// if (affectedBones == null
// || affectedBones.contains(tracks[i].getTargetBoneIndex()))
// tracks[i].setTime(time, skeleton, weight);
// }
// }
public String toString(){
return "BoneAnim[name="+name+", length="+length+"]";
@Override
public String toString() {
return "BoneAnim[name=" + name + ", length=" + length + "]";
}
public void write(JmeExporter e) throws IOException {
@ -117,10 +129,9 @@ public final class BoneAnimation implements Savable {
length = in.readFloat("length", 0f);
Savable[] sav = in.readSavableArray("tracks", null);
if (sav != null){
if (sav != null) {
tracks = new BoneTrack[sav.length];
System.arraycopy(sav, 0, tracks, 0, sav.length);
}
}
}

@ -42,6 +42,8 @@ import java.io.IOException;
/**
* Contains a list of transforms and times for each keyframe.
*
* @author Kirill Vainer
*/
public final class BoneTrack implements Savable {
@ -56,7 +58,6 @@ public final class BoneTrack implements Savable {
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();
@ -71,40 +72,85 @@ public final class BoneTrack implements Savable {
public BoneTrack() {
}
/**
* Creates a bone track for the given bone index
* @param targetBoneIndex the bone index
* @param times a float array with the time of each frame
* @param translations the translation of the bone for each frame
* @param rotations the rontation of the bone for each frame
*/
public BoneTrack(int targetBoneIndex, float[] times, Vector3f[] translations, Quaternion[] rotations) {
this.targetBoneIndex = targetBoneIndex;
this.setKeyframes(times, translations, rotations);
}
/**
* Creates a bone track for the given bone index
* @param targetBoneIndex the bone index
* @param times a float array with the time of each frame
* @param translations the translation of the bone for each frame
* @param rotations the rontation of the bone for each frame
* @param scales the scale of the bone for each frame
*/
public BoneTrack(int targetBoneIndex, float[] times, Vector3f[] translations, Quaternion[] rotations, Vector3f[] scales) {
this(targetBoneIndex, times, translations, rotations);
this.setKeyframes(times, translations, rotations);
}
/**
* Creates a bone track for the given bone index
* @param targetBoneIndex the bone's index
*/
public BoneTrack(int targetBoneIndex) {
this.targetBoneIndex = targetBoneIndex;
}
/**
* returns the bone index of this bone track
* @return
*/
public int getTargetBoneIndex() {
return targetBoneIndex;
}
/**
* return the array of rotations of this track
* @return
*/
public Quaternion[] getRotations() {
return rotations.toObjectArray();
}
/**
* returns the array of scales for this track
* @return
*/
public Vector3f[] getScales() {
return scales == null ? null : scales.toObjectArray();
}
/**
* returns the arrays of time for this track
* @return
*/
public float[] getTimes() {
return times;
}
/**
* returns the array of translations of this track
* @return
*/
public Vector3f[] getTranslations() {
return translations.toObjectArray();
}
/**
* Set the translations and rotations 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 rontation of the bone for each frame
*/
public void setKeyframes(float[] times, Vector3f[] translations, Quaternion[] rotations) {
if (times.length == 0) {
throw new RuntimeException("BoneTrack with no keyframes!");
@ -121,6 +167,13 @@ public final class BoneTrack implements Savable {
this.rotations.freeze();
}
/**
* 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 rontation 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) {
this.setKeyframes(times, translations, rotations);
assert times.length == scales.length;
@ -132,9 +185,14 @@ public final class BoneTrack implements Savable {
}
/**
*
* Modify the bone which this track modifies in the skeleton to contain
* the correct animation transforms for a given time.
* The transforms can be interpolated in some method from the keyframes.
*
* @param time the current time of the animation
* @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);
@ -181,10 +239,7 @@ public final class BoneTrack implements Savable {
}
if (weight != 1f) {
// tempQ.slerp(Quaternion.IDENTITY, 1f - weight);
// tempV.multLocal(weight);
target.blendAnimTransforms(tempV, tempQ, scales != null ? tempS : null, weight);
// target.setAnimTransforms(tempV, tempQ);
} else {
target.setAnimTransforms(tempV, tempQ, scales != null ? tempS : null);
}

@ -29,15 +29,12 @@
* 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.lang.reflect.Array;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* Object is indexed and stored in primitive float[]
* @author Lim, YongHoon
@ -45,12 +42,14 @@ import java.util.Map;
*/
public abstract class CompactArray<T> {
private Map<T,Integer> indexPool = new HashMap<T, Integer>();
private Map<T, Integer> indexPool = new HashMap<T, Integer>();
protected int[] index;
protected float[] array;
private boolean invalid;
/**
* Creates a compact array
*/
public CompactArray() {
}
@ -70,8 +69,9 @@ public abstract class CompactArray<T> {
* @param objArray
*/
public void add(T... objArray) {
if (objArray == null || objArray.length == 0)
if (objArray == null || objArray.length == 0) {
return;
}
invalid = true;
int base = 0;
if (index == null) {
@ -87,21 +87,21 @@ public abstract class CompactArray<T> {
index = tmp;
//index = Arrays.copyOf(index, base+objArray.length);
}
for (int j=0; j < objArray.length; j++) {
for (int j = 0; j < objArray.length; j++) {
T obj = objArray[j];
if (obj == null) {
index[base+j] = -1;
index[base + j] = -1;
} else {
Integer i = indexPool.get(obj);
if (i == null) {
i = indexPool.size();
indexPool.put(obj, i);
}
index[base+j] = i;
index[base + j] = i;
}
}
}
/**
* release objects.
* add() method call is not allowed anymore.
@ -120,22 +120,35 @@ public abstract class CompactArray<T> {
serialize(j, value);
}
/**
* returns the object for the given index
* @param index the index
* @param store an object to store the result
* @return
*/
public final T get(int index, T store) {
serialize();
int j = getCompactIndex(index);
return deserialize(j, store);
}
/**
* return a float array of serialized data
* @return
*/
public final float[] getSerializedData() {
serialize();
return array;
}
/**
* serialize this compact array
*/
public final void serialize() {
if (invalid) {
int newSize = indexPool.size()*getTupleSize();
int newSize = indexPool.size() * getTupleSize();
if (array == null || Array.getLength(array) < newSize) {
array = ensureCapacity(array, newSize);
array = ensureCapacity(array, newSize);
for (Map.Entry<T, Integer> entry : indexPool.entrySet()) {
int i = entry.getValue();
T obj = entry.getKey();
@ -153,6 +166,12 @@ public abstract class CompactArray<T> {
return Array.getLength(getSerializedData());
}
/**
* Ensure the capacity for the given array and the given size
* @param arr the array
* @param size the size
* @return
*/
protected float[] ensureCapacity(float[] arr, int size) {
if (arr == null) {
return new float[size];
@ -166,37 +185,43 @@ public abstract class CompactArray<T> {
}
}
/**
* retrun an array of indices for the given objects
* @param objArray
* @return
*/
public final int[] getIndex(T... objArray) {
int[] index = new int[objArray.length];
for (int i = 0; i < index.length; i++) {
T obj = objArray[i];
index[i] = obj!=null? indexPool.get(obj): -1;
index[i] = obj != null ? indexPool.get(obj) : -1;
}
return index;
}
/**
* returns the corresponding index in the compact array
* @param objIndex
* @return object index in the compacted object array
*/
public int getCompactIndex(int objIndex) {
return index!=null ? index[objIndex]: objIndex;
return index != null ? index[objIndex] : objIndex;
}
/**
* @return uncompressed object size
*/
public final int getTotalObjectSize() {
assert getSerializedSize()%getTupleSize() == 0;
return index!=null? index.length: getSerializedSize()/getTupleSize();
assert getSerializedSize() % getTupleSize() == 0;
return index != null ? index.length : getSerializedSize() / getTupleSize();
}
/**
* @return compressed object size
*/
public final int getCompactObjectSize() {
assert getSerializedSize()%getTupleSize() == 0;
return getSerializedSize()/getTupleSize();
assert getSerializedSize() % getTupleSize() == 0;
return getSerializedSize() / getTupleSize();
}
/**
@ -205,12 +230,12 @@ public abstract class CompactArray<T> {
*/
public final T[] toObjectArray() {
try {
T[] compactArr = (T[]) Array.newInstance(getElementClass(), getSerializedSize()/getTupleSize());
T[] compactArr = (T[]) Array.newInstance(getElementClass(), getSerializedSize() / getTupleSize());
for (int i = 0; i < compactArr.length; i++) {
compactArr[i] = getElementClass().newInstance();
deserialize(i, compactArr[i]);
}
T[] objArr = (T[]) Array.newInstance(getElementClass(), getTotalObjectSize());
for (int i = 0; i < objArr.length; i++) {
int compactIndex = getCompactIndex(i);
@ -222,7 +247,6 @@ public abstract class CompactArray<T> {
}
}
/**
* serialize object
* @param compactIndex compacted object index
@ -241,7 +265,6 @@ public abstract class CompactArray<T> {
* serialized size of one object element
*/
protected abstract int getTupleSize();
protected abstract Class<T> getElementClass();
protected abstract Class<T> getElementClass();
}

@ -29,7 +29,6 @@
* 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;
@ -48,9 +47,17 @@ import com.jme3.math.Quaternion;
*/
public class CompactQuaternionArray extends CompactArray<Quaternion> implements Savable {
/**
* creates a compact quaternion array
*/
public CompactQuaternionArray() {
}
/**
* creates a compact quaternion array
* @param dataArray the data array
* @param index the indices array
*/
public CompactQuaternionArray(float[] dataArray, int[] index) {
super(dataArray, index);
}
@ -64,7 +71,7 @@ public class CompactQuaternionArray extends CompactArray<Quaternion> implements
protected final Class<Quaternion> getElementClass() {
return Quaternion.class;
}
@Override
public void write(JmeExporter ex) throws IOException {
serialize();
@ -72,27 +79,27 @@ public class CompactQuaternionArray extends CompactArray<Quaternion> implements
out.write(array, "array", null);
out.write(index, "index", null);
}
@Override
public void read(JmeImporter im) throws IOException {
InputCapsule in = im.getCapsule(this);
array = in.readFloatArray("array", null);
index = in.readIntArray("index", null);
}
@Override
protected void serialize(int i, Quaternion store) {
int j = i*getTupleSize();
int j = i * getTupleSize();
array[j] = store.getX();
array[j+1] = store.getY();
array[j+2] = store.getZ();
array[j+3] = store.getW();
array[j + 1] = store.getY();
array[j + 2] = store.getZ();
array[j + 3] = store.getW();
}
@Override
protected Quaternion deserialize(int i, Quaternion store) {
int j = i*getTupleSize();
store.set(array[j], array[j+1], array[j+2], array[j+3]);
int j = i * getTupleSize();
store.set(array[j], array[j + 1], array[j + 2], array[j + 3]);
return store;
}
}

@ -47,9 +47,17 @@ import com.jme3.math.Vector3f;
*/
public class CompactVector3Array extends CompactArray<Vector3f> implements Savable {
/**
* Creates a compact vector array
*/
public CompactVector3Array() {
}
/**
* creates a compact vector array
* @param dataArray the data array
* @param index the indices
*/
public CompactVector3Array(float[] dataArray, int[] index) {
super(dataArray, index);
}

@ -163,6 +163,9 @@ public final class Skeleton implements Savable {
}
}
/**
* Reset the skeleton to bind pose and updates the bones
*/
public final void resetAndUpdate() {
for (int i = rootBones.length - 1; i >= 0; i--) {
Bone rootBone = rootBones[i];
@ -171,14 +174,28 @@ public final class Skeleton implements Savable {
}
}
/**
* returns the array of all root bones of this skeleton
* @return
*/
public Bone[] getRoots() {
return rootBones;
}
/**
* return a bone for the given index
* @param index
* @return
*/
public Bone getBone(int index) {
return boneList[index];
}
/**
* returns the bone with the given name
* @param name
* @return
*/
public Bone getBone(String name) {
for (int i = 0; i < boneList.length; i++) {
if (boneList[i].getName().equals(name)) {
@ -189,6 +206,11 @@ public final class Skeleton implements Savable {
return null;
}
/**
* returns the bone index of the given bone
* @param bone
* @return
*/
public int getBoneIndex(Bone bone) {
for (int i = 0; i < boneList.length; i++) {
if (boneList[i] == bone) {
@ -199,8 +221,13 @@ public final class Skeleton implements Savable {
return -1;
}
/**
* returns the bone index of the bone that has the given name
* @param name
* @return
*/
public int getBoneIndex(String name) {
for (int i = 0; i < boneList.length; i++) {
for (int i = 0; i < boneList.length; i++) {
if (boneList[i].getName().equals(name)) {
return i;
}
@ -209,6 +236,10 @@ public final class Skeleton implements Savable {
return -1;
}
/**
* Compute the skining matrices for each bone of the skeleton that would be used to transform vertices of associated meshes
* @return
*/
public Matrix4f[] computeSkinningMatrices() {
TempVars vars = TempVars.get();
assert vars.lock();
@ -219,6 +250,10 @@ public final class Skeleton implements Savable {
return skinningMatrixes;
}
/**
* returns the number of bones of this skeleton
* @return
*/
public int getBoneCount() {
return boneList.length;
}

@ -27,30 +27,38 @@ import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
/**
*
* @author Nehon
* The Skeleton control deforms a model according to a skeleton,
* It handles the computation of the deformtation matrices and performs the transformations on the mesh
*
* @author Rémy Bouquet Based on AnimControl by Kirill Vainer
*/
public class SkeletonControl extends AbstractControl implements Savable, Cloneable {
/**
* The skelrton of the model
* The skeleton of the model
*/
private Skeleton skeleton;
/**
* List of targets which this controller effects.
*/
private Mesh[] targets;
/**
* Used to track when a mesh was updated. Meshes are only updated
* if they are visible in at least one camera.
*/
private boolean wasMeshUpdated = false;
/**
* for serialization only
*/
public SkeletonControl() {
}
/**
* Creates a skeleton control
* @param targets the meshes controled by the skeleton
* @param skeleton the skeleton
*/
public SkeletonControl(Mesh[] targets, Skeleton skeleton) {
this.skeleton = skeleton;
this.targets = targets;
@ -58,7 +66,7 @@ public class SkeletonControl extends AbstractControl implements Savable, Cloneab
@Override
protected void controlRender(RenderManager rm, ViewPort vp) {
if (!wasMeshUpdated){
if (!wasMeshUpdated) {
resetToBind(); // reset morph meshes to bind pose
Matrix4f[] offsetMatrices = skeleton.computeSkinningMatrices();
@ -71,7 +79,7 @@ public class SkeletonControl extends AbstractControl implements Savable, Cloneab
softwareSkinUpdate(targets[i], offsetMatrices);
}
}
wasMeshUpdated = true;
}
}
@ -79,19 +87,7 @@ public class SkeletonControl extends AbstractControl implements Savable, Cloneab
@Override
protected void controlUpdate(float tpf) {
wasMeshUpdated = false;
// resetToBind(); // reset morph meshes to bind pose
//
// Matrix4f[] offsetMatrices = skeleton.computeSkinningMatrices();
//
// // if hardware skinning is supported, the matrices and weight buffer
// // will be sent by the SkinningShaderLogic object assigned to the shader
// for (int i = 0; i < targets.length; i++) {
// // only update targets with bone-vertex assignments
// if (targets[i].getBuffer(Type.BoneIndex) != null) {
// softwareSkinUpdate(targets[i], offsetMatrices);
// }
// }
}
void resetToBind() {
@ -169,26 +165,43 @@ public class SkeletonControl extends AbstractControl implements Savable, Cloneab
return n;
}
/**
* returns the skeleton of this control
* @return
*/
public Skeleton getSkeleton() {
return skeleton;
}
/**
* sets the skeleton for this control
* @param skeleton
*/
public void setSkeleton(Skeleton skeleton) {
this.skeleton = skeleton;
}
/**
* retuns the targets meshes of this ocntrol
* @return
*/
public Mesh[] getTargets() {
return targets;
}
/**
* sets the target meshes of this control
* @param targets
*/
public void setTargets(Mesh[] targets) {
this.targets = targets;
}
private void softwareSkinUpdate(Mesh mesh, Matrix4f[] offsetMatrices) {
int maxWeightsPerVert = mesh.getMaxNumWeights();
if (maxWeightsPerVert <= 0)
if (maxWeightsPerVert <= 0) {
throw new IllegalStateException("Max weights per vert is incorrectly set!");
}
int fourMinusMaxWeights = 4 - maxWeightsPerVert;

@ -29,7 +29,6 @@
* 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 com.jme3.export.JmeExporter;
@ -46,21 +45,35 @@ public abstract class Track implements Savable {
protected int targetMeshIndex;
public Track(int targetMeshIndex){
/**
* build a track for a an index
* @param targetMeshIndex
*/
public Track(int targetMeshIndex) {
this.targetMeshIndex = targetMeshIndex;
}
public int getTargetMeshIndex(){
/**
* return the mesh index
* @return
*/
public int getTargetMeshIndex() {
return targetMeshIndex;
}
/**
* sets time for this track
* @param time
* @param targets
* @param weight
*/
public abstract void setTime(float time, Mesh[] targets, float weight);
public void write(JmeExporter ex) throws IOException{
public void write(JmeExporter ex) throws IOException {
ex.getCapsule(this).write(targetMeshIndex, "meshIndex", 0);
}
public void read(JmeImporter im) throws IOException{
public void read(JmeImporter im) throws IOException {
targetMeshIndex = im.getCapsule(this).readInt("meshIndex", 0);
}
}

@ -123,11 +123,7 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
* @param filter
*/
public void removeFilter(Filter filter) {
for (Iterator<Filter> it = filters.iterator(); it.hasNext();) {
if (it.next() == filter) {
it.remove();
}
}
filters.remove(filter);
filter.cleanup(renderer);
updateLastFilterIndex();
}

Loading…
Cancel
Save