From 53d7052301ee45c5a77fd2e212d1532d7a6dfa9c Mon Sep 17 00:00:00 2001 From: Stephen Gold Date: Fri, 14 Dec 2018 18:26:06 -0800 Subject: [PATCH] test and fix for issue #970 (#973) --- .../jme3/bullet/objects/PhysicsRigidBody.java | 4 + .../java/jme3test/bullet/TestIssue970.java | 139 ++++++++++++++++++ .../jme3/bullet/objects/PhysicsRigidBody.java | 16 ++ 3 files changed, 159 insertions(+) create mode 100644 jme3-examples/src/main/java/jme3test/bullet/TestIssue970.java diff --git a/jme3-bullet/src/main/java/com/jme3/bullet/objects/PhysicsRigidBody.java b/jme3-bullet/src/main/java/com/jme3/bullet/objects/PhysicsRigidBody.java index 80285f62a..2cbbf3c42 100644 --- a/jme3-bullet/src/main/java/com/jme3/bullet/objects/PhysicsRigidBody.java +++ b/jme3-bullet/src/main/java/com/jme3/bullet/objects/PhysicsRigidBody.java @@ -1031,6 +1031,8 @@ public class PhysicsRigidBody extends PhysicsCollisionObject { capsule.write(getPhysicsLocation(new Vector3f()), "physicsLocation", new Vector3f()); capsule.write(getPhysicsRotationMatrix(new Matrix3f()), "physicsRotation", new Matrix3f()); + capsule.write(getLinearVelocity(), "linearVelocity", null); + capsule.write(getAngularVelocity(), "angularVelocity", null); capsule.writeSavableArrayList(joints, "joints", null); } @@ -1069,6 +1071,8 @@ public class PhysicsRigidBody extends PhysicsCollisionObject { setPhysicsLocation((Vector3f) capsule.readSavable("physicsLocation", new Vector3f())); setPhysicsRotation((Matrix3f) capsule.readSavable("physicsRotation", new Matrix3f())); + setLinearVelocity((Vector3f) capsule.readSavable("linearVelocity", new Vector3f())); + setAngularVelocity((Vector3f) capsule.readSavable("angularVelocity", new Vector3f())); joints = capsule.readSavableArrayList("joints", null); } diff --git a/jme3-examples/src/main/java/jme3test/bullet/TestIssue970.java b/jme3-examples/src/main/java/jme3test/bullet/TestIssue970.java new file mode 100644 index 000000000..c94d46c47 --- /dev/null +++ b/jme3-examples/src/main/java/jme3test/bullet/TestIssue970.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2018 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.bullet; + +import com.jme3.app.SimpleApplication; +import com.jme3.asset.AssetNotFoundException; +import com.jme3.asset.ModelKey; +import com.jme3.asset.plugins.FileLocator; +import com.jme3.bullet.collision.shapes.CollisionShape; +import com.jme3.bullet.collision.shapes.SphereCollisionShape; +import com.jme3.bullet.control.RigidBodyControl; +import com.jme3.bullet.objects.PhysicsRigidBody; +import com.jme3.export.JmeExporter; +import com.jme3.export.binary.BinaryExporter; +import com.jme3.math.Matrix3f; +import com.jme3.math.Vector3f; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import com.jme3.scene.control.Control; +import java.io.File; +import java.io.IOException; + +/** + * Test case for JME issue #970: RigidBodyControl doesn't read/write velocities. + * + * If successful, no AssertionError will be thrown. + * + * @author Stephen Gold sgold@sonic.net + */ +public class TestIssue970 extends SimpleApplication { + + private int fileIndex = 0; + + public static void main(String[] args) { + TestIssue970 app = new TestIssue970(); + app.start(); + } + + @Override + public void simpleInitApp() { + assetManager.registerLocator(".", FileLocator.class); + + CollisionShape shape = new SphereCollisionShape(1f); + RigidBodyControl rbc = new RigidBodyControl(shape, 1f); + setParameters(rbc); + verifyParameters(rbc); + RigidBodyControl rbcCopy = (RigidBodyControl) saveThenLoad(rbc); + verifyParameters(rbcCopy); + + stop(); + } + + /** + * Clone a body that implements Control by saving and then loading it. + * + * @param sgc the body/control to copy (not null, unaffected) + * @return a new body/control + */ + private PhysicsRigidBody saveThenLoad(PhysicsRigidBody body) { + Control sgc = (Control) body; + Node savedNode = new Node(); + /* + * Add the Control to the Node without altering its physics transform. + */ + Vector3f pl = body.getPhysicsLocation(null); + Matrix3f pr = body.getPhysicsRotationMatrix(null); + savedNode.addControl(sgc); + body.setPhysicsLocation(pl); + body.setPhysicsRotation(pr); + + String fileName = String.format("tmp%d.j3o", ++fileIndex); + File file = new File(fileName); + + JmeExporter exporter = BinaryExporter.getInstance(); + try { + exporter.save(savedNode, file); + } catch (IOException exception) { + assert false; + } + + ModelKey key = new ModelKey(fileName); + Spatial loadedNode = new Node(); + try { + loadedNode = assetManager.loadAsset(key); + } catch (AssetNotFoundException e) { + assert false; + } + file.delete(); + Control loadedSgc = loadedNode.getControl(0); + + return (PhysicsRigidBody) loadedSgc; + } + + private void setParameters(PhysicsRigidBody body) { + body.setAngularVelocity(new Vector3f(0.04f, 0.05f, 0.06f)); + body.setLinearVelocity(new Vector3f(0.26f, 0.27f, 0.28f)); + } + + private void verifyParameters(PhysicsRigidBody body) { + Vector3f w = body.getAngularVelocity(); + assert w.x == 0.04f : w; + assert w.y == 0.05f : w; + assert w.z == 0.06f : w; + + Vector3f v = body.getLinearVelocity(); + assert v.x == 0.26f : v; + assert v.y == 0.27f : v; + assert v.z == 0.28f : v; + } +} diff --git a/jme3-jbullet/src/main/java/com/jme3/bullet/objects/PhysicsRigidBody.java b/jme3-jbullet/src/main/java/com/jme3/bullet/objects/PhysicsRigidBody.java index e6ebeecd8..2d318e97c 100644 --- a/jme3-jbullet/src/main/java/com/jme3/bullet/objects/PhysicsRigidBody.java +++ b/jme3-jbullet/src/main/java/com/jme3/bullet/objects/PhysicsRigidBody.java @@ -634,6 +634,12 @@ public class PhysicsRigidBody extends PhysicsCollisionObject { rBody.destroy(); } + /** + * Serialize this body, for example when saving to a J3O file. + * + * @param e exporter (not null) + * @throws IOException from exporter + */ @Override public void write(JmeExporter e) throws IOException { super.write(e); @@ -657,10 +663,18 @@ public class PhysicsRigidBody extends PhysicsCollisionObject { capsule.write(getPhysicsLocation(new Vector3f()), "physicsLocation", new Vector3f()); capsule.write(getPhysicsRotationMatrix(new Matrix3f()), "physicsRotation", new Matrix3f()); + capsule.write(getLinearVelocity(), "linearVelocity", null); + capsule.write(getAngularVelocity(), "angularVelocity", null); capsule.writeSavableArrayList(joints, "joints", null); } + /** + * De-serialize this body, for example when loading from a J3O file. + * + * @param e importer (not null) + * @throws IOException from importer + */ @Override public void read(JmeImporter e) throws IOException { super.read(e); @@ -683,6 +697,8 @@ public class PhysicsRigidBody extends PhysicsCollisionObject { setPhysicsLocation((Vector3f) capsule.readSavable("physicsLocation", new Vector3f())); setPhysicsRotation((Matrix3f) capsule.readSavable("physicsRotation", new Matrix3f())); + setLinearVelocity((Vector3f) capsule.readSavable("linearVelocity", new Vector3f())); + setAngularVelocity((Vector3f) capsule.readSavable("angularVelocity", new Vector3f())); joints = capsule.readSavableArrayList("joints", null); }