Better performance

shader-nodes-enhancement
Nehon 7 years ago committed by Rémy Bouquet
parent d6b05553b5
commit c769611f9f
  1. 2
      jme3-core/src/main/java/com/jme3/anim/AnimClip.java
  2. 2
      jme3-core/src/main/java/com/jme3/anim/Armature.java
  3. 11
      jme3-core/src/main/java/com/jme3/anim/Joint.java
  4. 7
      jme3-core/src/main/java/com/jme3/anim/JointTrack.java
  5. 9
      jme3-core/src/main/java/com/jme3/anim/SpatialTrack.java
  6. 45
      jme3-core/src/main/java/com/jme3/anim/TransformTrack.java
  7. 133
      jme3-core/src/main/java/com/jme3/math/Matrix4f.java
  8. 51
      jme3-core/src/main/java/com/jme3/math/Quaternion.java
  9. 11
      jme3-core/src/main/java/com/jme3/math/Transform.java
  10. 9
      jme3-examples/src/main/java/jme3test/model/anim/TestHWSkinning.java
  11. 115
      jme3-examples/src/main/java/jme3test/model/anim/TestHWSkinningOld.java

@ -66,8 +66,10 @@ public class AnimClip implements Tween, JmeCloneable, Savable {
}
for (Tween track : tracks.getArray()) {
if (t <= track.getLength()) {
track.interpolate(t);
}
}
return t <= length;
}

@ -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

@ -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);
}
}

@ -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);
}
}
@Override
public void cloneFields(Cloner cloner, Object original) {
super.cloneFields(cloner, original);
this.target = cloner.clone(target);
}

@ -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);
}
}
@Override
public void cloneFields(Cloner cloner, Object original) {
super.cloneFields(cloner, original);
this.target = cloner.clone(target);
}

@ -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);
}
}

@ -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() {
@ -1754,14 +1755,15 @@ 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;
}
}
/**

@ -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,10 +450,55 @@ 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.

@ -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() {

@ -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();

@ -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);
}
}
Loading…
Cancel
Save