Hey guys,
I needed another Curve, so i implemented the PolylineCurve, which is a polyline (a chain of N lines) and can be used like a Curve (CurveController, …)
I also created a suiting testcase.
Here's the patch:
Index: src/com/jme/curve/PolylineCurve.java
===================================================================
--- src/com/jme/curve/PolylineCurve.java (revision 0)
+++ src/com/jme/curve/PolylineCurve.java (revision 0)
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2003-2009 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 com.jme.curve;
+
+import com.jme.intersection.CollisionResults;
+import com.jme.intersection.PickResults;
+import com.jme.math.Matrix3f;
+import com.jme.math.Ray;
+import com.jme.math.Vector3f;
+import com.jme.scene.Spatial;
+import com.jme.util.geom.BufferUtils;
+
+
+public class PolylineCurve extends Curve {
+
+ private Vector3f prev = new Vector3f();
+
+ private Vector3f next = new Vector3f();
+
+ private Vector3f temp = new Vector3f();
+
+ private static final long serialVersionUID = -1650585082935112089L;
+
+ private float[] percents;
+
+ private final Vector3f[] controlPoints;
+
+ private float totalLength;
+
+
+ /**
+ * Constructor instantiates a new <code>PolylineCurve</code> object. The control points that define the curve are
+ * supplied.
+ *
+ * @param name the name of the scene element. This is required for identification and comparision purposes.
+ * @param controlPoints the points that define the curve.
+ */
+ public PolylineCurve(String name, Vector3f[] controlPoints) {
+ super(name, controlPoints);
+ this.controlPoints = controlPoints;
+
+ float[] cummLengths = new float[controlPoints.length];
+ percents = new float[controlPoints.length];
+
+ // calculate length of curve up to control points
+ for (int i = 1; i < controlPoints.length; i++) {
+ cummLengths[i] = cummLengths[i - 1] + controlPoints[i].subtract(controlPoints[i - 1]).length();
+ } // for
+
+ // calculate place in percent on curve of all control points
+ totalLength = cummLengths[cummLengths.length - 1];
+ for (int i = 1; i < controlPoints.length; i++) {
+ percents[i] = (1f / totalLength) * cummLengths[i];
+ } // for
+ } // PolylineCurve
+
+
+ /**
+ * <code>getOrientation</code> calculates the rotation matrix for any given point along to the line to still be facing
+ * in the direction of the line.
+ *
+ * @param time the current time (between 0 and 1)
+ * @param precision how accurate to (i.e. the next time) to check against.
+ * @return the rotation matrix.
+ * @see com.jme.curve.Curve#getOrientation(float, float)
+ */
+ public Matrix3f getOrientation(float time, float precision) {
+ Matrix3f rotation = new Matrix3f();
+
+ // calculate tangent
+ Vector3f point = getPoint(time);
+ Vector3f tangent = point.subtract(getPoint(time + precision)).normalizeLocal();
+ // calculate normal
+ Vector3f tangent2 = getPoint(time - precision).subtract(point);
+ Vector3f normal = tangent.cross(tangent2).normalizeLocal();
+ // calculate binormal
+ Vector3f binormal = tangent.cross(normal).normalizeLocal();
+ // set columns
+ rotation.setColumn(0, tangent);
+ rotation.setColumn(1, normal);
+ rotation.setColumn(2, binormal);
+ return rotation;
+ }
+
+
+ /**
+ * <code>getOrientation</code> calculates the rotation matrix for any given point along to the line to still be facing
+ * in the direction of the line. A up vector is supplied, this keep the rotation matrix following the line, but
+ * insures the object's up vector is not drastically changed.
+ *
+ * @param time the current time (between 0 and 1)
+ * @param precision how accurate to (i.e. the next time) to check against.
+ * @return the rotation matrix.
+ * @see com.jme.curve.Curve#getOrientation(float, float)
+ */
+ public Matrix3f getOrientation(float time, float precision, Vector3f up) {
+ if (up == null) {
+ return getOrientation(time, precision);
+ }
+ Matrix3f rotation = new Matrix3f();
+ // calculate tangent
+ Vector3f tangent = getPoint(time).subtract(getPoint(time + precision)).normalizeLocal();
+ // calculate binormal
+ Vector3f binormal = tangent.cross(up).normalizeLocal();
+ // calculate normal
+ Vector3f normal = binormal.cross(tangent).normalizeLocal();
+ // set columns
+ rotation.setColumn(0, tangent);
+ rotation.setColumn(1, normal);
+ rotation.setColumn(2, binormal);
+ return rotation;
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.jme.curve.Curve#getPoint(float)
+ */
+ @Override
+ public Vector3f getPoint(float time) {
+ return getPoint(time, new Vector3f());
+ }
+
+
+ @Override
+ public Vector3f getPoint(float time, Vector3f store) {
+ // first point
+ if (time <= 0 || controlPoints.length <= 1) {
+ BufferUtils.populateFromBuffer(store, getVertexBuffer(), 0);
+ return store;
+ } // if
+ // last point.
+ if (time >= 1) {
+ BufferUtils.populateFromBuffer(store, getVertexBuffer(), getVertexCount() - 1);
+ return store;
+ } // if
+
+ int i = 0;
+ while (time > percents[i]) {
+ i++;
+ } // while
+
+ // get the next and previous control point on the curve
+ BufferUtils.populateFromBuffer(next, getVertexBuffer(), i);
+ BufferUtils.populateFromBuffer(prev, getVertexBuffer(), i - 1);
+
+ temp.set(next);
+ temp.subtractLocal(prev);
+ store.set(prev);
+ store.addLocal(temp.normalizeLocal().multLocal(totalLength * (time - percents[i - 1])));
+
+ return store;
+ }
+
+
+ @Override
+ public void findCollisions(Spatial scene, CollisionResults results) {
+ // TODO Auto-generated method stub
+ }
+
+
+ @Override
+ public boolean hasCollision(Spatial scene, boolean checkTriangles) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.jme.scene.Spatial#doPick(com.jme.math.Ray, com.jme.intersection.PickResults)
+ */
+ public void findPick(Ray toTest, PickResults results) {
+ // TODO Auto-generated method stub
+
+ }
+
+}
Index: src/jmetest/curve/TestPolylineCurve.java
===================================================================
--- src/jmetest/curve/TestPolylineCurve.java (revision 0)
+++ src/jmetest/curve/TestPolylineCurve.java (revision 0)
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2003-2009 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 jmetest.curve;
+
+import com.jme.app.SimpleGame;
+import com.jme.bounding.BoundingSphere;
+import com.jme.curve.CurveController;
+import com.jme.curve.PolylineCurve;
+import com.jme.image.Texture;
+import com.jme.input.MouseInput;
+import com.jme.math.Vector3f;
+import com.jme.renderer.ColorRGBA;
+import com.jme.scene.Controller;
+import com.jme.scene.TriMesh;
+import com.jme.scene.shape.Box;
+import com.jme.scene.state.TextureState;
+import com.jme.scene.state.ZBufferState;
+import com.jme.util.TextureManager;
+import com.jme.util.geom.BufferUtils;
+
+/**
+ * <code>TestPolyCurve</code>
+ * @author Mark Powell
+ * @version $Id: TestBezierCurve.java 4130 2009-03-19 20:04:51Z blaine.dev $
+ */
+public class TestPolylineCurve extends SimpleGame {
+
+ private Vector3f up = new Vector3f(0, 1, 0);
+
+ public static void main(String[] args) {
+ TestPolylineCurve app = new TestPolylineCurve();
+ app.setConfigShowMode(ConfigShowMode.AlwaysShow);
+ app.start();
+ }
+
+ /* (non-Javadoc)
+ * @see com.jme.app.SimpleGame#initGame()
+ */
+ protected void simpleInitGame() {
+ MouseInput.get().setCursorVisible(true);
+ lightState.setEnabled(false); // by default for this demo
+ display.setTitle("Polyline Curve Test");
+
+ //create control Points
+ Vector3f[] points = new Vector3f[4];
+ points[0] = new Vector3f( -4, 0, 0);
+ points[1] = new Vector3f( -2, 3, 2);
+ points[2] = new Vector3f(2, -3, -2);
+ points[3] = new Vector3f(4, 0, 0);
+
+ PolylineCurve curve = new PolylineCurve("Curve", points);
+ curve.setSteps(256);
+ ColorRGBA[] colors = new ColorRGBA[4];
+ colors[0] = new ColorRGBA(0, 1, 0, 1);
+ colors[1] = new ColorRGBA(1, 0, 0, 1);
+ colors[2] = new ColorRGBA(1, 1, 0, 1);
+ colors[3] = new ColorRGBA(0, 0, 1, 1);
+ curve.setColorBuffer(BufferUtils.createFloatBuffer(colors));
+
+ Vector3f min = new Vector3f( -0.1f, -0.1f, -0.1f);
+ Vector3f max = new Vector3f(0.1f, 0.1f, 0.1f);
+
+ ZBufferState buf = display.getRenderer().createZBufferState();
+ buf.setEnabled(true);
+ buf.setFunction(ZBufferState.TestFunction.LessThanOrEqualTo);
+
+ TriMesh t = new Box("Control 1", min, max);
+ t.setModelBound(new BoundingSphere());
+ t.updateModelBound();
+
+ t.setLocalTranslation(new Vector3f(points[0]));
+
+ TriMesh t2 = new Box("Control 2", min, max);
+ t2.setModelBound(new BoundingSphere());
+ t2.updateModelBound();
+
+ t2.setLocalTranslation(new Vector3f(points[1]));
+
+ TriMesh t3 = new Box("Control 3", min, max);
+ t3.setModelBound(new BoundingSphere());
+ t3.updateModelBound();
+
+ t3.setLocalTranslation(new Vector3f(points[2]));
+
+ TriMesh t4 = new Box("Control 4", min, max);
+ t4.setModelBound(new BoundingSphere());
+ t4.updateModelBound();
+
+ t4.setLocalTranslation(new Vector3f(points[3]));
+
+ TriMesh box = new Box("Controlled Box", min.mult(5), max.mult(5));
+ box.setModelBound(new BoundingSphere());
+ box.updateModelBound();
+
+ box.setLocalTranslation(new Vector3f(points[0]));
+
+ CurveController cc = new CurveController(curve, box);
+ box.addController(cc);
+ cc.setRepeatType(Controller.RT_CYCLE);
+ cc.setUpVector(up);
+ cc.setSpeed(0.5f);
+
+ TextureState ts = display.getRenderer().createTextureState();
+ ts.setEnabled(true);
+ ts.setTexture(
+ TextureManager.loadTexture(
+ TestPolylineCurve.class.getClassLoader().getResource(
+ "jmetest/data/images/Monkey.jpg"),
+ Texture.MinificationFilter.BilinearNearestMipMap,
+ Texture.MagnificationFilter.Bilinear));
+ box.setRenderState(ts);
+
+ rootNode.setRenderState(buf);
+ rootNode.attachChild(t);
+ rootNode.attachChild(t2);
+ rootNode.attachChild(t3);
+ rootNode.attachChild(t4);
+ rootNode.attachChild(box);
+ rootNode.attachChild(curve);
+
+ }
+}