From c769611f9f988fa0475926730a7080fcf79fb744 Mon Sep 17 00:00:00 2001 From: Nehon Date: Tue, 26 Dec 2017 23:38:05 +0100 Subject: [PATCH] Better performance --- .../src/main/java/com/jme3/anim/AnimClip.java | 4 +- .../src/main/java/com/jme3/anim/Armature.java | 2 +- .../src/main/java/com/jme3/anim/Joint.java | 11 +- .../main/java/com/jme3/anim/JointTrack.java | 9 +- .../main/java/com/jme3/anim/SpatialTrack.java | 11 +- .../java/com/jme3/anim/TransformTrack.java | 45 +----- .../src/main/java/com/jme3/math/Matrix4f.java | 135 +++++++++--------- .../main/java/com/jme3/math/Quaternion.java | 59 ++++++-- .../main/java/com/jme3/math/Transform.java | 11 +- .../jme3test/model/anim/TestHWSkinning.java | 9 +- .../model/anim/TestHWSkinningOld.java | 115 +++++++++++++++ 11 files changed, 269 insertions(+), 142 deletions(-) create mode 100644 jme3-examples/src/main/java/jme3test/model/anim/TestHWSkinningOld.java diff --git a/jme3-core/src/main/java/com/jme3/anim/AnimClip.java b/jme3-core/src/main/java/com/jme3/anim/AnimClip.java index 8bd64e0e1..6a23f4aff 100644 --- a/jme3-core/src/main/java/com/jme3/anim/AnimClip.java +++ b/jme3-core/src/main/java/com/jme3/anim/AnimClip.java @@ -66,7 +66,9 @@ public class AnimClip implements Tween, JmeCloneable, Savable { } for (Tween track : tracks.getArray()) { - track.interpolate(t); + if (t <= track.getLength()) { + track.interpolate(t); + } } return t <= length; } diff --git a/jme3-core/src/main/java/com/jme3/anim/Armature.java b/jme3-core/src/main/java/com/jme3/anim/Armature.java index 98b6299be..582dc8bce 100644 --- a/jme3-core/src/main/java/com/jme3/anim/Armature.java +++ b/jme3-core/src/main/java/com/jme3/anim/Armature.java @@ -23,7 +23,7 @@ public class Armature implements JmeCloneable, Savable { * will cause it to go to the animated position. */ private transient Matrix4f[] skinningMatrixes; - private Class modelTransformClass = MatrixJointModelTransform.class; + private Class modelTransformClass = SeparateJointModelTransform.class; /** * Serialization only diff --git a/jme3-core/src/main/java/com/jme3/anim/Joint.java b/jme3-core/src/main/java/com/jme3/anim/Joint.java index 6ff53f59c..267a5543a 100644 --- a/jme3-core/src/main/java/com/jme3/anim/Joint.java +++ b/jme3-core/src/main/java/com/jme3/anim/Joint.java @@ -12,6 +12,7 @@ import com.jme3.util.clone.JmeCloneable; import java.io.IOException; import java.util.ArrayList; +import java.util.List; /** * A Joint is the basic component of an armature designed to perform skeletal animation @@ -21,7 +22,7 @@ public class Joint implements Savable, JmeCloneable { private String name; private Joint parent; - private ArrayList children = new ArrayList<>(); + private SafeArrayList children = new SafeArrayList<>(Joint.class); private Geometry targetGeometry; /** @@ -61,7 +62,7 @@ public class Joint implements Savable, JmeCloneable { public final void update() { this.updateModelTransforms(); - for (Joint child : children) { + for (Joint child : children.getArray()) { child.update(); } } @@ -135,7 +136,7 @@ public class Joint implements Savable, JmeCloneable { jointModelTransform.applyBindPose(localTransform, inverseModelBindMatrix, parent); updateModelTransforms(); - for (Joint child : children) { + for (Joint child : children.getArray()) { child.resetToBindPose(); } } @@ -197,7 +198,7 @@ public class Joint implements Savable, JmeCloneable { return parent; } - public ArrayList getChildren() { + public List getChildren() { return children; } @@ -291,7 +292,7 @@ public class Joint implements Savable, JmeCloneable { output.write(attachedNode, "attachedNode", null); output.write(targetGeometry, "targetGeometry", null); output.write(inverseModelBindMatrix, "inverseModelBindMatrix", new Matrix4f()); - output.writeSavableArrayList(children, "children", null); + output.writeSavableArrayList(new ArrayList(children), "children", null); } } diff --git a/jme3-core/src/main/java/com/jme3/anim/JointTrack.java b/jme3-core/src/main/java/com/jme3/anim/JointTrack.java index bd5f24025..2a24bcd84 100644 --- a/jme3-core/src/main/java/com/jme3/anim/JointTrack.java +++ b/jme3-core/src/main/java/com/jme3/anim/JointTrack.java @@ -66,11 +66,11 @@ public final class JointTrack extends TransformTrack implements JmeCloneable, Sa public JointTrack(Joint target, float[] times, Vector3f[] translations, Quaternion[] rotations, Vector3f[] scales) { super(times, translations, rotations, scales); this.target = target; + this.defaultTransform = target.getLocalTransform(); } @Override public boolean interpolate(double t) { - setDefaultTransform(target.getLocalTransform()); boolean running = super.interpolate(t); Transform transform = getInterpolatedTransform(); target.setLocalTransform(transform); @@ -83,16 +83,11 @@ public final class JointTrack extends TransformTrack implements JmeCloneable, Sa @Override public Object jmeClone() { - try { - return super.clone(); - } catch (CloneNotSupportedException e) { - throw new RuntimeException("Error cloning", e); - } + return super.clone(); } @Override public void cloneFields(Cloner cloner, Object original) { - super.cloneFields(cloner, original); this.target = cloner.clone(target); } diff --git a/jme3-core/src/main/java/com/jme3/anim/SpatialTrack.java b/jme3-core/src/main/java/com/jme3/anim/SpatialTrack.java index b17235099..d796babfd 100644 --- a/jme3-core/src/main/java/com/jme3/anim/SpatialTrack.java +++ b/jme3-core/src/main/java/com/jme3/anim/SpatialTrack.java @@ -67,11 +67,12 @@ public final class SpatialTrack extends TransformTrack implements JmeCloneable, public SpatialTrack(Spatial target, float[] times, Vector3f[] translations, Quaternion[] rotations, Vector3f[] scales) { super(times, translations, rotations, scales); this.target = target; + defaultTransform = target.getLocalTransform(); } @Override public boolean interpolate(double t) { - setDefaultTransform(target.getLocalTransform()); + boolean running = super.interpolate(t); Transform transform = getInterpolatedTransform(); target.setLocalTransform(transform); @@ -84,16 +85,12 @@ public final class SpatialTrack extends TransformTrack implements JmeCloneable, @Override public Object jmeClone() { - try { - return super.clone(); - } catch (CloneNotSupportedException e) { - throw new RuntimeException("Error cloning", e); - } + return super.clone(); } @Override public void cloneFields(Cloner cloner, Object original) { - super.cloneFields(cloner, original); + this.target = cloner.clone(target); } diff --git a/jme3-core/src/main/java/com/jme3/anim/TransformTrack.java b/jme3-core/src/main/java/com/jme3/anim/TransformTrack.java index 5e0064ac5..bf06379ae 100644 --- a/jme3-core/src/main/java/com/jme3/anim/TransformTrack.java +++ b/jme3-core/src/main/java/com/jme3/anim/TransformTrack.java @@ -37,8 +37,6 @@ import com.jme3.animation.CompactQuaternionArray; import com.jme3.animation.CompactVector3Array; import com.jme3.export.*; import com.jme3.math.*; -import com.jme3.util.clone.Cloner; -import com.jme3.util.clone.JmeCloneable; import java.io.IOException; @@ -47,7 +45,7 @@ import java.io.IOException; * * @author Rémy Bouquet */ -public abstract class TransformTrack implements Tween, JmeCloneable, Savable { +public abstract class TransformTrack implements Tween, Cloneable, Savable { private double length; @@ -58,7 +56,7 @@ public abstract class TransformTrack implements Tween, JmeCloneable, Savable { private CompactQuaternionArray rotations; private CompactVector3Array scales; private Transform transform = new Transform(); - private Transform defaultTransform = new Transform(); + protected Transform defaultTransform = new Transform(); private FrameInterpolator interpolator = FrameInterpolator.DEFAULT; private float[] times; @@ -283,10 +281,6 @@ public abstract class TransformTrack implements Tween, JmeCloneable, Savable { return transform; } - public void setDefaultTransform(Transform transforms) { - defaultTransform.set(transforms); - } - public void setFrameInterpolator(FrameInterpolator interpolator) { this.interpolator = interpolator; } @@ -311,7 +305,7 @@ public abstract class TransformTrack implements Tween, JmeCloneable, Savable { } @Override - public Object jmeClone() { + public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { @@ -319,37 +313,4 @@ public abstract class TransformTrack implements Tween, JmeCloneable, Savable { } } - @Override - public void cloneFields(Cloner cloner, Object original) { - int tablesLength = times.length; - - setTimes(this.times.clone()); - if (translations != null) { - Vector3f[] sourceTranslations = this.getTranslations(); - Vector3f[] translations = new Vector3f[tablesLength]; - for (int i = 0; i < tablesLength; ++i) { - translations[i] = sourceTranslations[i].clone(); - } - setKeyframesTranslation(translations); - } - if (rotations != null) { - Quaternion[] sourceRotations = this.getRotations(); - Quaternion[] rotations = new Quaternion[tablesLength]; - for (int i = 0; i < tablesLength; ++i) { - rotations[i] = sourceRotations[i].clone(); - } - setKeyframesRotation(rotations); - } - - if (scales != null) { - Vector3f[] sourceScales = this.getScales(); - Vector3f[] scales = new Vector3f[tablesLength]; - for (int i = 0; i < tablesLength; ++i) { - scales[i] = sourceScales[i].clone(); - } - setKeyframesScale(scales); - } - - setFrameInterpolator(this.interpolator); - } } diff --git a/jme3-core/src/main/java/com/jme3/math/Matrix4f.java b/jme3-core/src/main/java/com/jme3/math/Matrix4f.java index 159e39932..6b260ee31 100644 --- a/jme3-core/src/main/java/com/jme3/math/Matrix4f.java +++ b/jme3-core/src/main/java/com/jme3/math/Matrix4f.java @@ -34,6 +34,7 @@ package com.jme3.math; import com.jme3.export.*; import com.jme3.util.BufferUtils; import com.jme3.util.TempVars; + import java.io.IOException; import java.nio.FloatBuffer; import java.util.logging.Logger; @@ -1023,96 +1024,95 @@ public final class Matrix4f implements Savable, Cloneable, java.io.Serializable store = new Matrix4f(); } - float temp00, temp01, temp02, temp03; - float temp10, temp11, temp12, temp13; - float temp20, temp21, temp22, temp23; - float temp30, temp31, temp32, temp33; + TempVars v = TempVars.get(); + float[] m = v.matrixWrite; - temp00 = m00 * in2.m00 + m[0] = m00 * in2.m00 + m01 * in2.m10 + m02 * in2.m20 + m03 * in2.m30; - temp01 = m00 * in2.m01 + m[1] = m00 * in2.m01 + m01 * in2.m11 + m02 * in2.m21 + m03 * in2.m31; - temp02 = m00 * in2.m02 + m[2] = m00 * in2.m02 + m01 * in2.m12 + m02 * in2.m22 + m03 * in2.m32; - temp03 = m00 * in2.m03 + m[3] = m00 * in2.m03 + m01 * in2.m13 + m02 * in2.m23 + m03 * in2.m33; - temp10 = m10 * in2.m00 + m[4] = m10 * in2.m00 + m11 * in2.m10 + m12 * in2.m20 + m13 * in2.m30; - temp11 = m10 * in2.m01 + m[5] = m10 * in2.m01 + m11 * in2.m11 + m12 * in2.m21 + m13 * in2.m31; - temp12 = m10 * in2.m02 + m[6] = m10 * in2.m02 + m11 * in2.m12 + m12 * in2.m22 + m13 * in2.m32; - temp13 = m10 * in2.m03 + m[7] = m10 * in2.m03 + m11 * in2.m13 + m12 * in2.m23 + m13 * in2.m33; - temp20 = m20 * in2.m00 + m[8] = m20 * in2.m00 + m21 * in2.m10 + m22 * in2.m20 + m23 * in2.m30; - temp21 = m20 * in2.m01 + m[9] = m20 * in2.m01 + m21 * in2.m11 + m22 * in2.m21 + m23 * in2.m31; - temp22 = m20 * in2.m02 + m[10] = m20 * in2.m02 + m21 * in2.m12 + m22 * in2.m22 + m23 * in2.m32; - temp23 = m20 * in2.m03 + m[11] = m20 * in2.m03 + m21 * in2.m13 + m22 * in2.m23 + m23 * in2.m33; - temp30 = m30 * in2.m00 + m[12] = m30 * in2.m00 + m31 * in2.m10 + m32 * in2.m20 + m33 * in2.m30; - temp31 = m30 * in2.m01 + m[13] = m30 * in2.m01 + m31 * in2.m11 + m32 * in2.m21 + m33 * in2.m31; - temp32 = m30 * in2.m02 + m[14] = m30 * in2.m02 + m31 * in2.m12 + m32 * in2.m22 + m33 * in2.m32; - temp33 = m30 * in2.m03 + m[15] = m30 * in2.m03 + m31 * in2.m13 + m32 * in2.m23 + m33 * in2.m33; - store.m00 = temp00; - store.m01 = temp01; - store.m02 = temp02; - store.m03 = temp03; - store.m10 = temp10; - store.m11 = temp11; - store.m12 = temp12; - store.m13 = temp13; - store.m20 = temp20; - store.m21 = temp21; - store.m22 = temp22; - store.m23 = temp23; - store.m30 = temp30; - store.m31 = temp31; - store.m32 = temp32; - store.m33 = temp33; + store.m00 = m[0]; + store.m01 = m[1]; + store.m02 = m[2]; + store.m03 = m[3]; + store.m10 = m[4]; + store.m11 = m[5]; + store.m12 = m[6]; + store.m13 = m[7]; + store.m20 = m[8]; + store.m21 = m[9]; + store.m22 = m[10]; + store.m23 = m[11]; + store.m30 = m[12]; + store.m31 = m[13]; + store.m32 = m[14]; + store.m33 = m[15]; + v.release(); return store; } @@ -1709,8 +1709,8 @@ public final class Matrix4f implements Savable, Cloneable, java.io.Serializable return new Vector3f(m03, m13, m23); } - public void toTranslationVector(Vector3f vector) { - vector.set(m03, m13, m23); + public Vector3f toTranslationVector(Vector3f vector) { + return vector.set(m03, m13, m23); } public Quaternion toRotationQuat() { @@ -1719,8 +1719,9 @@ public final class Matrix4f implements Savable, Cloneable, java.io.Serializable return quat; } - public void toRotationQuat(Quaternion q) { - q.fromRotationMatrix(toRotationMatrix()); + public Quaternion toRotationQuat(Quaternion q) { + return q.fromRotationMatrix(m00, m01, m02, m10, + m11, m12, m20, m21, m22); } public Matrix3f toRotationMatrix() { @@ -1753,15 +1754,16 @@ public final class Matrix4f implements Savable, Cloneable, java.io.Serializable /** * Retreives the scale vector from the matrix and stores it into a given * vector. - * - * @param the - * vector where the scale will be stored + * + * @param store the vector where the scale will be stored + * @return the store vector */ - public void toScaleVector(Vector3f vector) { + public Vector3f toScaleVector(Vector3f store) { float scaleX = (float) Math.sqrt(m00 * m00 + m10 * m10 + m20 * m20); float scaleY = (float) Math.sqrt(m01 * m01 + m11 * m11 + m21 * m21); float scaleZ = (float) Math.sqrt(m02 * m02 + m12 * m12 + m22 * m22); - vector.set(scaleX, scaleY, scaleZ); + store.set(scaleX, scaleY, scaleZ); + return store; } /** @@ -1775,25 +1777,30 @@ public final class Matrix4f implements Savable, Cloneable, java.io.Serializable * the Z scale */ public void setScale(float x, float y, float z) { - TempVars vars = TempVars.get(); - vars.vect1.set(m00, m10, m20); - vars.vect1.normalizeLocal().multLocal(x); - m00 = vars.vect1.x; - m10 = vars.vect1.y; - m20 = vars.vect1.z; - - vars.vect1.set(m01, m11, m21); - vars.vect1.normalizeLocal().multLocal(y); - m01 = vars.vect1.x; - m11 = vars.vect1.y; - m21 = vars.vect1.z; - - vars.vect1.set(m02, m12, m22); - vars.vect1.normalizeLocal().multLocal(z); - m02 = vars.vect1.x; - m12 = vars.vect1.y; - m22 = vars.vect1.z; - vars.release(); + + float length = m00 * m00 + m10 * m10 + m20 * m20; + if (length != 0f) { + length = length == 1 ? x : (x / FastMath.sqrt(length)); + m00 *= length; + m10 *= length; + m20 *= length; + } + + length = m01 * m01 + m11 * m11 + m21 * m21; + if (length != 0f) { + length = length == 1 ? y : (y / FastMath.sqrt(length)); + m01 *= length; + m11 *= length; + m21 *= length; + } + + length = m02 * m02 + m12 * m12 + m22 * m22; + if (length != 0f) { + length = length == 1 ? z : (z / FastMath.sqrt(length)); + m02 *= length; + m12 *= length; + m22 *= length; + } } /** diff --git a/jme3-core/src/main/java/com/jme3/math/Quaternion.java b/jme3-core/src/main/java/com/jme3/math/Quaternion.java index 89c7d8647..d592640e1 100644 --- a/jme3-core/src/main/java/com/jme3/math/Quaternion.java +++ b/jme3-core/src/main/java/com/jme3/math/Quaternion.java @@ -33,10 +33,8 @@ package com.jme3.math; import com.jme3.export.*; import com.jme3.util.TempVars; -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; + +import java.io.*; import java.util.logging.Logger; /** @@ -452,11 +450,56 @@ public final class Quaternion implements Savable, Cloneable, java.io.Serializabl return result; } + /** + * toTransformMatrix converts this quaternion to a transform + * matrix. The result is stored in result. + * Note this method won't preserve the scale of the given matrix. + * + * @param store The Matrix3f to store the result in. + * @return the transform matrix with the rotation representation of this quaternion. + */ + public Matrix4f toTransformMatrix(Matrix4f store) { + + float norm = norm(); + // we explicitly test norm against one here, saving a division + // at the cost of a test and branch. Is it worth it? + float s = (norm == 1f) ? 2f : (norm > 0f) ? 2f / norm : 0; + + // compute xs/ys/zs first to save 6 multiplications, since xs/ys/zs + // will be used 2-4 times each. + float xs = x * s; + float ys = y * s; + float zs = z * s; + float xx = x * xs; + float xy = x * ys; + float xz = x * zs; + float xw = w * xs; + float yy = y * ys; + float yz = y * zs; + float yw = w * ys; + float zz = z * zs; + float zw = w * zs; + + // using s=2/norm (instead of 1/norm) saves 9 multiplications by 2 here + store.m00 = 1 - (yy + zz); + store.m01 = (xy - zw); + store.m02 = (xz + yw); + store.m10 = (xy + zw); + store.m11 = 1 - (xx + zz); + store.m12 = (yz - xw); + store.m20 = (xz - yw); + store.m21 = (yz + xw); + store.m22 = 1 - (xx + yy); + + return store; + } + /** * toRotationMatrix converts this quaternion to a rotational * matrix. The result is stored in result. 4th row and 4th column values are * untouched. Note: the result is created from a normalized version of this quat. - * + * Note that this method will preserve the scale of the given matrix + * * @param result * The Matrix4f to store the result in. * @return the rotation matrix representation of this quaternion. @@ -464,7 +507,7 @@ public final class Quaternion implements Savable, Cloneable, java.io.Serializabl public Matrix4f toRotationMatrix(Matrix4f result) { TempVars tempv = TempVars.get(); Vector3f originalScale = tempv.vect1; - + result.toScaleVector(originalScale); result.setScale(1, 1, 1); float norm = norm(); @@ -499,9 +542,9 @@ public final class Quaternion implements Savable, Cloneable, java.io.Serializabl result.m22 = 1 - (xx + yy); result.setScale(originalScale); - + tempv.release(); - + return result; } diff --git a/jme3-core/src/main/java/com/jme3/math/Transform.java b/jme3-core/src/main/java/com/jme3/math/Transform.java index 6c8795a4a..41e911bac 100644 --- a/jme3-core/src/main/java/com/jme3/math/Transform.java +++ b/jme3-core/src/main/java/com/jme3/math/Transform.java @@ -32,6 +32,7 @@ package com.jme3.math; import com.jme3.export.*; +import com.jme3.util.TempVars; import java.io.IOException; @@ -267,15 +268,17 @@ public final class Transform implements Savable, Cloneable, java.io.Serializable store = new Matrix4f(); } store.setTranslation(translation); - store.setRotationQuaternion(rot); + rot.toTransformMatrix(store); store.setScale(scale); return store; } public void fromTransformMatrix(Matrix4f mat) { - translation.set(mat.toTranslationVector()); - rot.set(mat.toRotationQuat()); - scale.set(mat.toScaleVector()); + TempVars vars = TempVars.get(); + translation.set(mat.toTranslationVector(vars.vect1)); + rot.set(mat.toRotationQuat(vars.quat1)); + scale.set(mat.toScaleVector(vars.vect2)); + vars.release(); } public Transform invert() { diff --git a/jme3-examples/src/main/java/jme3test/model/anim/TestHWSkinning.java b/jme3-examples/src/main/java/jme3test/model/anim/TestHWSkinning.java index 980d8ca59..9e92cd35d 100644 --- a/jme3-examples/src/main/java/jme3test/model/anim/TestHWSkinning.java +++ b/jme3-examples/src/main/java/jme3test/model/anim/TestHWSkinning.java @@ -50,7 +50,7 @@ public class TestHWSkinning extends SimpleApplication implements ActionListener{ private AnimComposer composer; private String[] animNames = {"Dodge", "Walk", "pull", "push"}; - private final static int SIZE = 10; + private final static int SIZE = 50; private boolean hwSkinningEnable = true; private List skControls = new ArrayList(); private BitmapText hwsText; @@ -63,8 +63,11 @@ public class TestHWSkinning extends SimpleApplication implements ActionListener{ @Override public void simpleInitApp() { flyCam.setMoveSpeed(10f); - cam.setLocation(new Vector3f(3.8664846f, 6.2704787f, 9.664585f)); - cam.setRotation(new Quaternion(-0.054774776f, 0.94064945f, -0.27974048f, -0.18418397f)); + flyCam.setDragToRotate(true); + setPauseOnLostFocus(false); + cam.setLocation(new Vector3f(24.746134f, 13.081396f, 32.72753f)); + cam.setRotation(new Quaternion(-0.06867662f, 0.92435044f, -0.19981281f, -0.31770203f)); + makeHudText(); DirectionalLight dl = new DirectionalLight(); diff --git a/jme3-examples/src/main/java/jme3test/model/anim/TestHWSkinningOld.java b/jme3-examples/src/main/java/jme3test/model/anim/TestHWSkinningOld.java new file mode 100644 index 000000000..f0fa27d8f --- /dev/null +++ b/jme3-examples/src/main/java/jme3test/model/anim/TestHWSkinningOld.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2009-2012 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 jme3test.model.anim; + +import com.jme3.animation.*; +import com.jme3.app.SimpleApplication; +import com.jme3.font.BitmapText; +import com.jme3.input.KeyInput; +import com.jme3.input.controls.ActionListener; +import com.jme3.input.controls.KeyTrigger; +import com.jme3.light.DirectionalLight; +import com.jme3.math.*; +import com.jme3.scene.Spatial; + +import java.util.ArrayList; +import java.util.List; + +public class TestHWSkinningOld extends SimpleApplication implements ActionListener { + + private AnimChannel channel; + private AnimControl control; + private String[] animNames = {"Dodge", "Walk", "pull", "push"}; + private final static int SIZE = 50; + private boolean hwSkinningEnable = true; + private List skControls = new ArrayList(); + private BitmapText hwsText; + + public static void main(String[] args) { + TestHWSkinningOld app = new TestHWSkinningOld(); + app.start(); + } + + @Override + public void simpleInitApp() { + flyCam.setMoveSpeed(10f); + flyCam.setDragToRotate(true); + setPauseOnLostFocus(false); + cam.setLocation(new Vector3f(24.746134f, 13.081396f, 32.72753f)); + cam.setRotation(new Quaternion(-0.06867662f, 0.92435044f, -0.19981281f, -0.31770203f)); + makeHudText(); + + DirectionalLight dl = new DirectionalLight(); + dl.setDirection(new Vector3f(-0.1f, -0.7f, -1).normalizeLocal()); + dl.setColor(new ColorRGBA(1f, 1f, 1f, 1.0f)); + rootNode.addLight(dl); + + for (int i = 0; i < SIZE; i++) { + for (int j = 0; j < SIZE; j++) { + Spatial model = (Spatial) assetManager.loadModel("Models/Oto/OtoOldAnim.j3o"); + model.setLocalScale(0.1f); + model.setLocalTranslation(i - SIZE / 2, 0, j - SIZE / 2); + control = model.getControl(AnimControl.class); + + channel = control.createChannel(); + channel.setAnim(animNames[(i + j) % 4]); + SkeletonControl skeletonControl = model.getControl(SkeletonControl.class); + skeletonControl.setHardwareSkinningPreferred(hwSkinningEnable); + skControls.add(skeletonControl); + rootNode.attachChild(model); + } + } + + inputManager.addListener(this, "toggleHWS"); + inputManager.addMapping("toggleHWS", new KeyTrigger(KeyInput.KEY_SPACE)); + } + + @Override + public void onAction(String name, boolean isPressed, float tpf) { + if (isPressed && name.equals("toggleHWS")) { + hwSkinningEnable = !hwSkinningEnable; + for (SkeletonControl control : skControls) { + control.setHardwareSkinningPreferred(hwSkinningEnable); + hwsText.setText("HWS : " + hwSkinningEnable); + } + } + } + + private void makeHudText() { + guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt"); + hwsText = new BitmapText(guiFont, false); + hwsText.setSize(guiFont.getCharSet().getRenderedSize()); + hwsText.setText("HWS : " + hwSkinningEnable); + hwsText.setLocalTranslation(0, cam.getHeight(), 0); + guiNode.attachChild(hwsText); + } +} \ No newline at end of file