From 2bf5936317a37f0dfdd889b73fbe9ce270464c96 Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Thu, 23 Jun 2005 03:49:18 +0000 Subject: [PATCH] Fixed the orienting ballistic path, though it doesn't properly handle arbitrarily oriented sprites. They currently have to "point" toward (1, 0, 0) as that is the direction that will be aligned with the velocity. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@3619 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../threerings/jme/sprite/BallisticPath.java | 3 ++ .../jme/sprite/OrientingBallisticPath.java | 49 +++++++++--------- .../com/threerings/jme/sprite/PathTest.java | 50 ++++++++++++++----- 3 files changed, 64 insertions(+), 38 deletions(-) diff --git a/src/java/com/threerings/jme/sprite/BallisticPath.java b/src/java/com/threerings/jme/sprite/BallisticPath.java index 996afdf2d..51ad7b83a 100644 --- a/src/java/com/threerings/jme/sprite/BallisticPath.java +++ b/src/java/com/threerings/jme/sprite/BallisticPath.java @@ -29,6 +29,9 @@ import com.jme.math.Vector3f; */ public class BallisticPath extends Path { + /** Gravity: it's the law. */ + public static final float G = -9.8f; + /** * Moves the supplied sprite from the starting coordinate (which will * be modified) using the starting velocity, under the specified diff --git a/src/java/com/threerings/jme/sprite/OrientingBallisticPath.java b/src/java/com/threerings/jme/sprite/OrientingBallisticPath.java index a5eeb1cde..da5d6526b 100644 --- a/src/java/com/threerings/jme/sprite/OrientingBallisticPath.java +++ b/src/java/com/threerings/jme/sprite/OrientingBallisticPath.java @@ -21,8 +21,6 @@ package com.threerings.jme.sprite; -import com.jme.math.FastMath; -import com.jme.math.Matrix3f; import com.jme.math.Quaternion; import com.jme.math.Vector3f; @@ -45,42 +43,41 @@ public class OrientingBallisticPath extends BallisticPath { super(sprite, start, velocity, accel, duration); - // rotate the sprite to start - rotate(orient, velocity); + // TODO: handle orient that is not (1, 0, 0) + _orient = orient; + + // compute the up vector (opposite of acceleration) + _up = accel.negate(); + _up.normalizeLocal(); + + computeRotation(velocity); + _sprite.getLocalRotation().set(_rotate); } // documentation inherited public void update (float time) { - // keep track of the old velocity before we update - _ovelocity.set(_velocity); - // do the normal update super.update(time); - // rotate the sprite accordingly - rotate(_ovelocity, _velocity); + computeRotation(_velocity); + _sprite.getLocalRotation().set(_rotate); } - protected void rotate (Vector3f oorient, Vector3f norient) + protected void computeRotation (Vector3f velocity) { - // compute the cross product to get the normal to the plane - // defined by the velocity vectors - oorient.cross(norient, _normal); - - // compute the angle between the two vectors - float angle = FastMath.acos( - oorient.dot(norient) / (norient.length() * oorient.length())); - - // now use that to compute a rotation matrix from the old to the - // new vector - _rotate.fromAngleAxis(angle, _normal); - - // finally rotate the sprite accordingly - _sprite.getLocalRotation().multLocal(_rotate); + _axes[0].set(velocity); + _axes[0].normalizeLocal(); + _axes[0].cross(_up, _axes[1]); + _axes[1].normalizeLocal(); + _axes[1].cross(_axes[0], _axes[2]); + _axes[2].cross(_axes[0], _axes[1]); + _rotate.fromAxes(_axes); } - protected Vector3f _ovelocity = new Vector3f(); - protected Vector3f _normal = new Vector3f(); + protected Vector3f _orient; + protected Vector3f _up; + protected Vector3f[] _axes = { + new Vector3f(), new Vector3f(), new Vector3f() }; protected Quaternion _rotate = new Quaternion(); } diff --git a/tests/src/java/com/threerings/jme/sprite/PathTest.java b/tests/src/java/com/threerings/jme/sprite/PathTest.java index 62ca3296c..ecb320012 100644 --- a/tests/src/java/com/threerings/jme/sprite/PathTest.java +++ b/tests/src/java/com/threerings/jme/sprite/PathTest.java @@ -9,9 +9,12 @@ import com.jme.math.FastMath; import com.jme.math.Matrix3f; import com.jme.math.Quaternion; import com.jme.math.Vector3f; -import com.jme.util.LoggingSystem; +import com.jme.renderer.ColorRGBA; import com.jme.scene.shape.Box; +import com.jme.scene.shape.Quad; import com.jme.scene.shape.Sphere; +import com.jme.scene.state.LightState; +import com.jme.util.LoggingSystem; import com.threerings.jme.JmeApp; @@ -24,25 +27,37 @@ public class PathTest extends JmeApp { super.initRoot(); - float range = 56, muzvel = 24; + float dist = 10; // set up the camera - Vector3f loc = new Vector3f(range/2, -range*2, 0); + Vector3f loc = new Vector3f(0, -dist, 10); _camera.setLocation(loc); Matrix3f rotm = new Matrix3f(); - rotm.fromAngleAxis(-FastMath.PI/2, _camera.getLeft()); + rotm.fromAngleAxis(-FastMath.PI/4, _camera.getLeft()); rotm.multLocal(_camera.getDirection()); rotm.multLocal(_camera.getUp()); rotm.multLocal(_camera.getLeft()); _camera.update(); - Box box = new Box("box", new Vector3f(-1, -1, -1), - new Vector3f(1, 1, 1)); + for (int yy = -1; yy < 1; yy++) { + for (int xx = -1; xx < 1; xx++) { + Quad quad = new Quad("ground", 10, 10); + quad.setLightCombineMode(LightState.OFF); + int index = (yy+1)*2 + (xx+1); + quad.setSolidColor(COLORS[index]); + quad.setLocalTranslation( + new Vector3f(xx * 10 + 5, yy * 10 + 5, -1)); + _geom.attachChild(quad); + } + } + + Box box = new Box("box", new Vector3f(-1, -0.5f, -0.25f), + new Vector3f(1, 0.5f, 0.25f)); _geom.attachChild(box); - Box box2 = new Box("box2", new Vector3f(-1, -1, -1), - new Vector3f(1, 1, 1)); - box2.setLocalTranslation(new Vector3f(range, 0, 0)); + Box box2 = new Box("box2", new Vector3f(-.1f, -.1f, -.1f), + new Vector3f(.1f, .1f, .1f)); + box2.setLocalTranslation(new Vector3f(dist, dist, 0)); _geom.attachChild(box2); Sprite shot = new Sprite(); @@ -52,15 +67,22 @@ public class PathTest extends JmeApp Vector3f start = new Vector3f(0, 0, 0); // start with the "cannon" pointed along the x axis - Vector3f vel = new Vector3f(1, 0, 0); + Vector3f diff = box2.getLocalTranslation().subtract( + box.getLocalTranslation()); + Vector3f vel = diff.normalize(); + float range = diff.length(), angle = -FastMath.PI/4; + + Vector3f axis = UP.cross(vel); + axis.normalizeLocal(); // rotate it up (around the y axis) the necessary elevation Quaternion rot = new Quaternion(); - float angle = BallisticPath.computeElevation(range, muzvel, -9.8f); - rot.fromAngleAxis(angle, new Vector3f(0, 1, 0)); + rot.fromAngleAxis(angle, axis); rot.multLocal(vel); // give the cannon its muzzle velocity + float muzvel = FastMath.sqrt(range * BallisticPath.G / + FastMath.sin(2*angle)); vel.multLocal(muzvel); float time = BallisticPath.computeFlightTime(range, muzvel, angle); @@ -69,6 +91,7 @@ public class PathTest extends JmeApp System.out.println("Range: " + range); System.out.println("Muzzle velocity: " + muzvel); + System.out.println("Rotation axis: " + axis); System.out.println("Angle: " + angle + " (" + (angle * 180 / FastMath.PI) + ")"); System.out.println("Flight time: " + time); @@ -86,4 +109,7 @@ public class PathTest extends JmeApp } protected static final Vector3f GRAVITY = new Vector3f(0, 0, -9.8f); + protected static final Vector3f UP = new Vector3f(0, 0, 1); + protected static final ColorRGBA[] COLORS = { + ColorRGBA.red, ColorRGBA.green, ColorRGBA.blue, ColorRGBA.gray }; }