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<? extends JointModelTransform> modelTransformClass = MatrixJointModelTransform.class;
+    private Class<? extends JointModelTransform> 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<Joint> children = new ArrayList<>();
+    private SafeArrayList<Joint> 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<Joint> getChildren() {
+    public List<Joint> 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;
     }
 
+    /**
+     * <code>toTransformMatrix</code> 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;
+    }
+
     /**
      * <code>toRotationMatrix</code> 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<SkinningControl> skControls = new ArrayList<SkinningControl>();
     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<SkeletonControl> skControls = new ArrayList<SkeletonControl>();
+    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