OSDN Git Service

Replace CatmullRomSpline, reuse SplineTest by renaming PathTest to SplineTest.
authorXoppa <contact@xoppa.nl>
Thu, 14 Feb 2013 17:15:08 +0000 (18:15 +0100)
committerXoppa <contact@xoppa.nl>
Thu, 14 Feb 2013 17:15:08 +0000 (18:15 +0100)
gdx/src/com/badlogic/gdx/math/CatmullRomSpline.java
tests/gdx-tests/src/com/badlogic/gdx/tests/PathTest.java [deleted file]
tests/gdx-tests/src/com/badlogic/gdx/tests/SplineTest.java

index 0f660c8..1537ad1 100644 (file)
 \r
 package com.badlogic.gdx.math;\r
 \r
-import java.io.Serializable;\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-\r
-/** Encapsulates a catmull rom spline with n control points, n >= 4. For more information on this type of spline see\r
- * http://www.mvps.org/directx/articles/catmull/.\r
- * \r
- * @author badlogicgames@gmail.com */\r
-public class CatmullRomSpline implements Serializable {\r
-       private static final long serialVersionUID = -3290464799289771451L;\r
-       private List<Vector3> controlPoints = new ArrayList<Vector3>();\r
-       Vector3 T1 = new Vector3();\r
-       Vector3 T2 = new Vector3();\r
-\r
-       /** Adds a new control point\r
-        * \r
-        * @param point the point */\r
-       public void add (Vector3 point) {\r
-               controlPoints.add(point);\r
+import com.badlogic.gdx.utils.Array;\r
+\r
+/** @author Xoppa */\r
+public class CatmullRomSpline<T extends Vector<T>> implements Path<T> {\r
+       /** Calculates the catmullrom value for the given position (t).\r
+        * @param out The Vector to set to the result.\r
+        * @param t The position (0<=t<=1) on the spline\r
+        * @param points The control points\r
+        * @param continuous If true the b-spline restarts at 0 when reaching 1\r
+        * @param tmp A temporary vector used for the calculation\r
+        * @return The value of out */\r
+       public static <T extends Vector<T>> T calculate(final T out, final float t, final T[] points, final boolean continuous, final T tmp) {\r
+               final int n = continuous ? points.length : points.length - 3;\r
+               float u = t * n;\r
+               int i = (t >= 1f) ? (n - 1) : (int)u;\r
+               u -= (float)i;\r
+               return calculate(out, i, u, points, continuous, tmp);\r
        }\r
-\r
-       /** @return all control points */\r
-       public List<Vector3> getControlPoints () {\r
-               return controlPoints;\r
+       \r
+       /** Calculates the catmullrom value for the given span (i) at the given position (u).\r
+        * @param out The Vector to set to the result.\r
+        * @param i The span (0<=i<spanCount) spanCount = continuous ? points.length : points.length - degree\r
+        * @param u The position (0<=u<=1) on the span\r
+        * @param points The control points\r
+        * @param continuous If true the b-spline restarts at 0 when reaching 1\r
+        * @param tmp A temporary vector used for the calculation\r
+        * @return The value of out */\r
+       public static <T extends Vector<T>> T calculate(final T out, final int i, final float u, final T[] points, final boolean continuous, final T tmp) {\r
+               final int n = points.length;\r
+               final float u2 = u * u;\r
+               final float u3 = u2 * u;\r
+               out.set(points[i]).mul(1.5f * u3 - 2.5f * u2 + 1.0f);\r
+               if (continuous || i > 0) out.add(tmp.set(points[(n+i-1)%n]).mul(-0.5f * u3 + u2 - 0.5f * u));\r
+               if (continuous || i < (n - 1)) out.add(tmp.set(points[(i + 1)%n]).mul(-1.5f * u3 + 2f * u2 + 0.5f * u));\r
+               if (continuous || i < (n - 2)) out.add(tmp.set(points[(i + 2)%n]).mul(0.5f * u3 - 0.5f * u2));\r
+               return out;\r
        }\r
-\r
-       /** Returns a path, between every two control points numPoints are generated and the control points themselves are added too.\r
-        * The first and the last controlpoint are omitted. if there's less than 4 controlpoints an empty path is returned.\r
-        * \r
-        * @param numPoints number of points returned for a segment\r
-        * @return the path */\r
-       public List<Vector3> getPath (int numPoints) {\r
-               ArrayList<Vector3> points = new ArrayList<Vector3>();\r
-\r
-               if (controlPoints.size() < 4) return points;\r
-\r
-               Vector3 T1 = new Vector3();\r
-               Vector3 T2 = new Vector3();\r
-\r
-               for (int i = 1; i <= controlPoints.size() - 3; i++) {\r
-                       points.add(controlPoints.get(i));\r
-                       float increment = 1.0f / (numPoints + 1);\r
-                       float t = increment;\r
-\r
-                       T1.set(controlPoints.get(i + 1)).sub(controlPoints.get(i - 1)).mul(0.5f);\r
-                       T2.set(controlPoints.get(i + 2)).sub(controlPoints.get(i)).mul(0.5f);\r
-\r
-                       for (int j = 0; j < numPoints; j++) {\r
-                               float h1 = 2 * t * t * t - 3 * t * t + 1; // calculate basis\r
-                               // function 1\r
-                               float h2 = -2 * t * t * t + 3 * t * t; // calculate basis\r
-                               // function 2\r
-                               float h3 = t * t * t - 2 * t * t + t; // calculate basis\r
-                               // function 3\r
-                               float h4 = t * t * t - t * t; // calculate basis function 4\r
-\r
-                               Vector3 point = new Vector3(controlPoints.get(i)).mul(h1);\r
-                               point.add(controlPoints.get(i + 1).tmp().mul(h2));\r
-                               point.add(T1.tmp().mul(h3));\r
-                               point.add(T2.tmp().mul(h4));\r
-                               points.add(point);\r
-                               t += increment;\r
-                       }\r
-               }\r
-\r
-               if (controlPoints.size() >= 4) points.add(controlPoints.get(controlPoints.size() - 2));\r
-\r
-               return points;\r
+       \r
+       public T[] controlPoints;\r
+       public boolean continuous;\r
+       public int spanCount;\r
+       private T tmp;\r
+       \r
+       public CatmullRomSpline() { }\r
+       public CatmullRomSpline(final T[] controlPoints, final boolean continuous) {\r
+               set(controlPoints, continuous);\r
        }\r
-\r
-       /** Returns a path, between every two control points numPoints are generated and the control points themselves are added too.\r
-        * The first and the last controlpoint are omitted. if there's less than 4 controlpoints an empty path is returned.\r
-        * \r
-        * @param points the array of Vector3 instances to store the path in\r
-        * @param numPoints number of points returned for a segment */\r
-       public void getPath (Vector3[] points, int numPoints) {\r
-               int idx = 0;\r
-               if (controlPoints.size() < 4) return;\r
-\r
-               for (int i = 1; i <= controlPoints.size() - 3; i++) {\r
-                       points[idx++].set(controlPoints.get(i));\r
-                       float increment = 1.0f / (numPoints + 1);\r
-                       float t = increment;\r
-\r
-                       T1.set(controlPoints.get(i + 1)).sub(controlPoints.get(i - 1)).mul(0.5f);\r
-                       T2.set(controlPoints.get(i + 2)).sub(controlPoints.get(i)).mul(0.5f);\r
-\r
-                       for (int j = 0; j < numPoints; j++) {\r
-                               float h1 = 2 * t * t * t - 3 * t * t + 1; // calculate basis\r
-                               // function 1\r
-                               float h2 = -2 * t * t * t + 3 * t * t; // calculate basis\r
-                               // function 2\r
-                               float h3 = t * t * t - 2 * t * t + t; // calculate basis\r
-                               // function 3\r
-                               float h4 = t * t * t - t * t; // calculate basis function 4\r
-\r
-                               Vector3 point = points[idx++].set(controlPoints.get(i)).mul(h1);\r
-                               point.add(controlPoints.get(i + 1).tmp().mul(h2));\r
-                               point.add(T1.tmp().mul(h3));\r
-                               point.add(T2.tmp().mul(h4));\r
-                               t += increment;\r
-                       }\r
-               }\r
-\r
-               points[idx].set(controlPoints.get(controlPoints.size() - 2));\r
+       \r
+       public CatmullRomSpline set(final T[] controlPoints, final boolean continuous) {\r
+               if (tmp == null)\r
+                       tmp = controlPoints[0].cpy();\r
+               this.controlPoints = controlPoints;\r
+               this.continuous = continuous;\r
+               this.spanCount = continuous ? controlPoints.length : controlPoints.length - 3;\r
+               return this;\r
        }\r
 \r
-       /** Returns all tangents for the points in a path. Same semantics as getPath.\r
-        * \r
-        * @param numPoints number of points returned for a segment\r
-        * @return the tangents of the points in the path */\r
-       public List<Vector3> getTangents (int numPoints) {\r
-               ArrayList<Vector3> tangents = new ArrayList<Vector3>();\r
-\r
-               if (controlPoints.size() < 4) return tangents;\r
-\r
-               Vector3 T1 = new Vector3();\r
-               Vector3 T2 = new Vector3();\r
-\r
-               for (int i = 1; i <= controlPoints.size() - 3; i++) {\r
-                       float increment = 1.0f / (numPoints + 1);\r
-                       float t = increment;\r
-\r
-                       T1.set(controlPoints.get(i + 1)).sub(controlPoints.get(i - 1)).mul(0.5f);\r
-                       T2.set(controlPoints.get(i + 2)).sub(controlPoints.get(i)).mul(0.5f);\r
-\r
-                       tangents.add(new Vector3(T1).nor());\r
-\r
-                       for (int j = 0; j < numPoints; j++) {\r
-                               float h1 = 6 * t * t - 6 * t; // calculate basis function 1\r
-                               float h2 = -6 * t * t + 6 * t; // calculate basis function 2\r
-                               float h3 = 3 * t * t - 4 * t + 1; // calculate basis function 3\r
-                               float h4 = 3 * t * t - 2 * t; // calculate basis function 4\r
-\r
-                               Vector3 point = new Vector3(controlPoints.get(i)).mul(h1);\r
-                               point.add(controlPoints.get(i + 1).tmp().mul(h2));\r
-                               point.add(T1.tmp().mul(h3));\r
-                               point.add(T2.tmp().mul(h4));\r
-                               tangents.add(point.nor());\r
-                               t += increment;\r
-                       }\r
-               }\r
-\r
-               if (controlPoints.size() >= 4)\r
-                       tangents.add(T1.set(controlPoints.get(controlPoints.size() - 1)).sub(controlPoints.get(controlPoints.size() - 3))\r
-                               .mul(0.5f).cpy().nor());\r
-\r
-               return tangents;\r
+       @Override\r
+       public T valueAt (T out, float t) {\r
+               final int n = spanCount;\r
+               float u = t * n;\r
+               int i = (t >= 1f) ? (n - 1) : (int)u;\r
+               u -= (float)i;\r
+               return valueAt(out, i, u);\r
        }\r
-\r
-       /** Returns all tangent's normals in 2D space for the points in a path. The controlpoints have to lie in the x/y plane for this\r
-        * to work. Same semantics as getPath.\r
-        * \r
-        * @param numPoints number of points returned for a segment\r
-        * @return the tangents of the points in the path */\r
-       public List<Vector3> getTangentNormals2D (int numPoints) {\r
-               ArrayList<Vector3> tangents = new ArrayList<Vector3>();\r
-\r
-               if (controlPoints.size() < 4) return tangents;\r
-\r
-               Vector3 T1 = new Vector3();\r
-               Vector3 T2 = new Vector3();\r
-\r
-               for (int i = 1; i <= controlPoints.size() - 3; i++) {\r
-                       float increment = 1.0f / (numPoints + 1);\r
-                       float t = increment;\r
-\r
-                       T1.set(controlPoints.get(i + 1)).sub(controlPoints.get(i - 1)).mul(0.5f);\r
-                       T2.set(controlPoints.get(i + 2)).sub(controlPoints.get(i)).mul(0.5f);\r
-\r
-                       Vector3 normal = new Vector3(T1).nor();\r
-                       float x = normal.x;\r
-                       normal.x = normal.y;\r
-                       normal.y = -x;\r
-                       tangents.add(normal);\r
-\r
-                       for (int j = 0; j < numPoints; j++) {\r
-                               float h1 = 6 * t * t - 6 * t; // calculate basis function 1\r
-                               float h2 = -6 * t * t + 6 * t; // calculate basis function 2\r
-                               float h3 = 3 * t * t - 4 * t + 1; // calculate basis function 3\r
-                               float h4 = 3 * t * t - 2 * t; // calculate basis function 4\r
-\r
-                               Vector3 point = new Vector3(controlPoints.get(i)).mul(h1);\r
-                               point.add(controlPoints.get(i + 1).tmp().mul(h2));\r
-                               point.add(T1.tmp().mul(h3));\r
-                               point.add(T2.tmp().mul(h4));\r
-                               point.nor();\r
-                               x = point.x;\r
-                               point.x = point.y;\r
-                               point.y = -x;\r
-                               tangents.add(point);\r
-                               t += increment;\r
+       \r
+       /** @return The value of the spline at position u of the specified span */ \r
+       public T valueAt(final T out, final int span, final float u) {\r
+               return calculate(out, continuous ? span : (span + 1), u, controlPoints, continuous, tmp);\r
+       }\r
+       \r
+       /** @return The span closest to the specified value */ \r
+       public int nearest(final T in) {\r
+               return nearest(in, 0, spanCount);\r
+       }\r
+       \r
+       /** @return The span closest to the specified value, restricting to the specified spans. */\r
+       public int nearest(final T in, int start, final int count) {\r
+               while (start < 0) start += spanCount;\r
+               int result = start % spanCount;\r
+               float dst = in.dst2(controlPoints[result]);\r
+               for (int i = 1; i < count; i++) {\r
+                       final int idx = (start + i) % spanCount;\r
+                       final float d = in.dst2(controlPoints[idx]);\r
+                       if (d < dst) {\r
+                               dst = d;\r
+                               result = idx;\r
                        }\r
                }\r
-\r
-               return tangents;\r
+               return result;\r
        }\r
-\r
-       /** Returns the tangent's normals using the tangent and provided up vector doing a cross product.\r
-        * \r
-        * @param numPoints number of points per segment\r
-        * @param up up vector\r
-        * @return a list of tangent normals */\r
-       public List<Vector3> getTangentNormals (int numPoints, Vector3 up) {\r
-               List<Vector3> tangents = getTangents(numPoints);\r
-               ArrayList<Vector3> normals = new ArrayList<Vector3>();\r
-\r
-               for (Vector3 tangent : tangents)\r
-                       normals.add(new Vector3(tangent).crs(up).nor());\r
-\r
-               return normals;\r
+       \r
+       @Override\r
+       public float approximate (T v) {\r
+               return approximate(v, nearest(v));\r
        }\r
-\r
-       public List<Vector3> getTangentNormals (int numPoints, List<Vector3> up) {\r
-               List<Vector3> tangents = getTangents(numPoints);\r
-               ArrayList<Vector3> normals = new ArrayList<Vector3>();\r
-\r
-               int i = 0;\r
-               for (Vector3 tangent : tangents)\r
-                       normals.add(new Vector3(tangent).crs(up.get(i++)).nor());\r
-\r
-               return normals;\r
+       \r
+       public float approximate(final T in, int start, final int count) {\r
+               return approximate(in, nearest(in, start, count));\r
+       }\r
+       \r
+       public float approximate(final T in, final int near) {\r
+               int n = near;\r
+               final T nearest = controlPoints[n];\r
+               final T previous = controlPoints[n>0?n-1:spanCount-1];\r
+               final T next = controlPoints[(n+1)%spanCount];\r
+               final float dstPrev2 = in.dst2(previous);\r
+               final float dstNext2 = in.dst2(next);\r
+               T P1, P2, P3;\r
+               if (dstNext2 < dstPrev2) {\r
+                       P1 = nearest;\r
+                       P2 = next;\r
+                       P3 = in;\r
+               } else {\r
+                       P1 = previous;\r
+                       P2 = nearest;\r
+                       P3 = in;\r
+                       n = n>0?n-1:spanCount-1;\r
+               }\r
+               float L1 = P1.dst(P2);\r
+               float L2 = P3.dst(P2);\r
+               float L3 = P3.dst(P1);\r
+               float s = (L2*L2 + L1*L1 - L3*L3) / (2*L1);\r
+               float u = MathUtils.clamp((L1-s)/L1, 0f, 1f);\r
+               return ((float)n + u) / spanCount;\r
        }\r
 }\r
diff --git a/tests/gdx-tests/src/com/badlogic/gdx/tests/PathTest.java b/tests/gdx-tests/src/com/badlogic/gdx/tests/PathTest.java
deleted file mode 100644 (file)
index 25d32ff..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/*******************************************************************************
- * Copyright 2011 See AUTHORS file.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- ******************************************************************************/
-
-package com.badlogic.gdx.tests;
-
-import com.badlogic.gdx.Gdx;
-import com.badlogic.gdx.InputProcessor;
-import com.badlogic.gdx.graphics.GL10;
-import com.badlogic.gdx.graphics.Texture;
-import com.badlogic.gdx.graphics.g2d.Sprite;
-import com.badlogic.gdx.graphics.g2d.SpriteBatch;
-import com.badlogic.gdx.graphics.glutils.ImmediateModeRenderer10;
-import com.badlogic.gdx.math.BSpline;
-import com.badlogic.gdx.math.Bezier;
-import com.badlogic.gdx.math.Path;
-import com.badlogic.gdx.math.Vector2;
-import com.badlogic.gdx.tests.utils.GdxTest;
-import com.badlogic.gdx.utils.Array;
-
-/** @author Xoppa */
-public class PathTest extends GdxTest {
-       int SAMPLE_POINTS = 50;
-       float SAMPLE_POINT_DISTANCE = 1f/SAMPLE_POINTS;
-       
-       SpriteBatch spriteBatch;
-       ImmediateModeRenderer10 renderer;
-       Sprite obj;
-       Array<Path<Vector2>> paths = new Array<Path<Vector2>>();
-       int currentPath = 0;
-       float t;
-       float speed = 0.3f;
-       float wait = 0f;
-
-       @Override
-       public boolean needsGL20 () {
-               return false;
-       }
-       
-       @Override
-       public void create () {
-               renderer = new ImmediateModeRenderer10();
-               spriteBatch = new SpriteBatch();
-               obj = new Sprite(new Texture(Gdx.files.internal("data/badlogicsmall.jpg")));
-               
-               float w = Gdx.graphics.getWidth() - obj.getWidth();
-               float h = Gdx.graphics.getHeight() - obj.getHeight();
-               
-               paths.add(new Bezier<Vector2>(new Vector2(0,0), new Vector2(w, h)));
-               paths.add(new Bezier<Vector2>(new Vector2(0,0), new Vector2(0, h), new Vector2(w, h)));
-               paths.add(new Bezier<Vector2>(new Vector2(0,0), new Vector2(w, 0), new Vector2(0, h), new Vector2(w, h)));
-               
-               Vector2 cp[] = new Vector2[]{
-                       new Vector2(0, 0), new Vector2(w * 0.25f, h * 0.5f), new Vector2(0, h), new Vector2(w*0.5f, h*0.75f),
-                       new Vector2(w, h), new Vector2(w * 0.75f, h * 0.5f), new Vector2(w, 0), new Vector2(w*0.5f, h*0.25f)
-               };
-               paths.add(new BSpline<Vector2>(cp, 3, true));
-               
-               Gdx.input.setInputProcessor(this);
-       }
-       
-       final Vector2 tmpV = new Vector2();
-       @Override
-       public void render () {
-               GL10 gl = Gdx.graphics.getGL10();
-               gl.glClearColor(0.7f, 0.7f, 0.7f, 1);
-               gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
-               
-               if (wait > 0)
-                       wait -= Gdx.graphics.getDeltaTime();
-               else {
-                       t += speed * Gdx.graphics.getDeltaTime();
-                       while (t >= 1f) {
-                               currentPath = (currentPath + 1) % paths.size;
-                               t -= 1f;
-                       }
-                       
-                       paths.get(currentPath).valueAt(tmpV, t);
-                       obj.setPosition(tmpV.x, tmpV.y);
-               }
-                       
-               spriteBatch.begin();
-               
-               renderer.begin(GL10.GL_LINE_STRIP);
-               float val = 0f;
-               while (val <= 1f) {
-                       renderer.color(0f, 0f, 0f, 1f);
-                       paths.get(currentPath).valueAt(Vector2.tmp, val);
-                       renderer.vertex(Vector2.tmp.x, Vector2.tmp.y, 0);
-                       val += SAMPLE_POINT_DISTANCE;
-               }
-               renderer.end();
-               
-               obj.draw(spriteBatch);
-               spriteBatch.end();
-       }
-       
-       private void touch(int x, int y) {
-               t = paths.get(currentPath).approximate(tmpV.set(x, Gdx.graphics.getHeight()-y));
-               paths.get(currentPath).valueAt(tmpV, t);
-               obj.setPosition(tmpV.x, tmpV.y);
-               wait = 0.2f;            
-       }
-       
-       @Override
-       public boolean touchUp (int screenX, int screenY, int pointer, int button) {
-               touch(screenX, screenY);
-               return super.touchUp(screenX, screenY, pointer, button);
-       }
-       
-       @Override
-       public boolean touchDragged (int screenX, int screenY, int pointer) {
-               touch(screenX, screenY);
-               return super.touchDragged(screenX, screenY, pointer);
-       }
-}
index afde2e3..cf86bd5 100644 (file)
 package com.badlogic.gdx.tests;\r
 \r
 import com.badlogic.gdx.Gdx;\r
+import com.badlogic.gdx.InputProcessor;\r
 import com.badlogic.gdx.graphics.GL10;\r
-import com.badlogic.gdx.graphics.OrthographicCamera;\r
+import com.badlogic.gdx.graphics.Texture;\r
+import com.badlogic.gdx.graphics.g2d.Sprite;\r
+import com.badlogic.gdx.graphics.g2d.SpriteBatch;\r
 import com.badlogic.gdx.graphics.glutils.ImmediateModeRenderer10;\r
+import com.badlogic.gdx.math.BSpline;\r
+import com.badlogic.gdx.math.Bezier;\r
 import com.badlogic.gdx.math.CatmullRomSpline;\r
-import com.badlogic.gdx.math.Vector3;\r
+import com.badlogic.gdx.math.Path;\r
+import com.badlogic.gdx.math.Vector2;\r
 import com.badlogic.gdx.tests.utils.GdxTest;\r
+import com.badlogic.gdx.utils.Array;\r
 \r
+/** @author Xoppa */\r
 public class SplineTest extends GdxTest {\r
+       int SAMPLE_POINTS = 100;\r
+       float SAMPLE_POINT_DISTANCE = 1f/SAMPLE_POINTS;\r
+       \r
+       SpriteBatch spriteBatch;\r
+       ImmediateModeRenderer10 renderer;\r
+       Sprite obj;\r
+       Array<Path<Vector2>> paths = new Array<Path<Vector2>>();\r
+       int currentPath = 0;\r
+       float t;\r
+       float speed = 0.3f;\r
+       float wait = 0f;\r
 \r
        @Override\r
        public boolean needsGL20 () {\r
                return false;\r
        }\r
-\r
-       final int CONTROL_POINTS = 10;\r
-       OrthographicCamera cam;\r
-       ImmediateModeRenderer10 renderer;\r
-       CatmullRomSpline spline;\r
-       Vector3[] path;\r
-\r
+       \r
        @Override\r
        public void create () {\r
-               cam = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());\r
-               cam.position.set(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2, 0);\r
                renderer = new ImmediateModeRenderer10();\r
-               spline = new CatmullRomSpline();\r
-               float x = 0;\r
-               float y = Gdx.graphics.getHeight() / 2;\r
-               spline.add(new Vector3(x - 50, y, 0));\r
-               for (int i = 0; i < CONTROL_POINTS; i++) {\r
-                       spline.add(new Vector3(x, y, 0));\r
-                       x += Gdx.graphics.getWidth() / (CONTROL_POINTS - 2);\r
-               }\r
-               spline.add(new Vector3(Gdx.graphics.getWidth() + 50, y, 0));\r
-               path = new Vector3[(CONTROL_POINTS - 2) * 7 - 1];\r
-               for (int i = 0; i < path.length; i++)\r
-                       path[i] = new Vector3();\r
-               spline.getPath(path, 5);\r
+               spriteBatch = new SpriteBatch();\r
+               obj = new Sprite(new Texture(Gdx.files.internal("data/badlogicsmall.jpg")));\r
+               \r
+               float w = Gdx.graphics.getWidth() - obj.getWidth();\r
+               float h = Gdx.graphics.getHeight() - obj.getHeight();\r
+               \r
+               paths.add(new Bezier<Vector2>(new Vector2(0,0), new Vector2(w, h)));\r
+               paths.add(new Bezier<Vector2>(new Vector2(0,0), new Vector2(0, h), new Vector2(w, h)));\r
+               paths.add(new Bezier<Vector2>(new Vector2(0,0), new Vector2(w, 0), new Vector2(0, h), new Vector2(w, h)));\r
+               \r
+               Vector2 cp[] = new Vector2[]{\r
+                       new Vector2(0, 0), new Vector2(w * 0.25f, h * 0.5f), new Vector2(0, h), new Vector2(w*0.5f, h*0.75f),\r
+                       new Vector2(w, h), new Vector2(w * 0.75f, h * 0.5f), new Vector2(w, 0), new Vector2(w*0.5f, h*0.25f)\r
+               };\r
+               paths.add(new BSpline<Vector2>(cp, 3, true));\r
+               \r
+               paths.add(new CatmullRomSpline<Vector2>(cp, true));\r
+               \r
+               Gdx.input.setInputProcessor(this);\r
        }\r
-\r
+       \r
+       final Vector2 tmpV = new Vector2();\r
        @Override\r
        public void render () {\r
-               Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);\r
-               cam.update();\r
-               Gdx.gl10.glMatrixMode(GL10.GL_PROJECTION);\r
-               Gdx.gl10.glLoadMatrixf(cam.projection.val, 0);\r
-               Gdx.gl10.glMatrixMode(GL10.GL_MODELVIEW);\r
-               Gdx.gl10.glLoadMatrixf(cam.view.val, 0);\r
-\r
-               renderer.begin(GL10.GL_TRIANGLES);\r
-               for (int i = 0; i < path.length - 1; i++) {\r
-                       Vector3 point1 = path[i];\r
-                       Vector3 point2 = path[i + 1];\r
-                       renderer.color(1, 1, 1, 1);\r
-                       renderer.vertex(point1.x, point1.y, 0);\r
-                       renderer.color(1, 1, 1, 1);\r
-                       renderer.vertex(point1.x, 0, 0);\r
-                       renderer.color(1, 1, 1, 1);\r
-                       renderer.vertex(point2.x, point2.y, 0);\r
-\r
-                       renderer.color(1, 1, 1, 1);\r
-                       renderer.vertex(point2.x, point2.y, 0);\r
-                       renderer.color(1, 1, 1, 1);\r
-                       renderer.vertex(point1.x, 0, 0);\r
-                       renderer.color(1, 1, 1, 1);\r
-                       renderer.vertex(point2.x, 0, 0);\r
+               GL10 gl = Gdx.graphics.getGL10();\r
+               gl.glClearColor(0.7f, 0.7f, 0.7f, 1);\r
+               gl.glClear(GL10.GL_COLOR_BUFFER_BIT);\r
+               \r
+               if (wait > 0)\r
+                       wait -= Gdx.graphics.getDeltaTime();\r
+               else {\r
+                       t += speed * Gdx.graphics.getDeltaTime();\r
+                       while (t >= 1f) {\r
+                               currentPath = (currentPath + 1) % paths.size;\r
+                               t -= 1f;\r
+                       }\r
+                       \r
+                       paths.get(currentPath).valueAt(tmpV, t);\r
+                       obj.setPosition(tmpV.x, tmpV.y);\r
                }\r
-               renderer.end();\r
-\r
-               Gdx.gl10.glPointSize(4);\r
-               renderer.begin(GL10.GL_POINTS);\r
-               for (int i = 0; i < spline.getControlPoints().size(); i++) {\r
-                       Vector3 point = spline.getControlPoints().get(i);\r
-                       renderer.color(1, 0, 0, 1);\r
-                       renderer.vertex(point.x, point.y, 0);\r
+                       \r
+               spriteBatch.begin();\r
+               \r
+               renderer.begin(GL10.GL_LINE_STRIP);\r
+               float val = 0f;\r
+               while (val <= 1f) {\r
+                       renderer.color(0f, 0f, 0f, 1f);\r
+                       paths.get(currentPath).valueAt(Vector2.tmp, val);\r
+                       renderer.vertex(Vector2.tmp.x, Vector2.tmp.y, 0);\r
+                       val += SAMPLE_POINT_DISTANCE;\r
                }\r
                renderer.end();\r
-               Gdx.gl10.glPointSize(1);\r
-\r
-               processInput();\r
+               \r
+               obj.draw(spriteBatch);\r
+               spriteBatch.end();\r
        }\r
-\r
-       Vector3 point = new Vector3();\r
-\r
-       private void processInput () {\r
-// if(Gdx.input.isTouched()) {\r
-// Vector3 nearest = null;\r
-// float nearestDist = Float.MAX_VALUE;\r
-// point.set(cam.getScreenToWorldX(Gdx.input.getX()),\r
-// cam.getScreenToWorldY(Gdx.input.getY()),\r
-// 0);\r
-//\r
-// for(int i = 0; i < spline.getControlPoints().size(); i++) {\r
-// Vector3 controlPoint = spline.getControlPoints().get(i);\r
-// float dist = Math.abs(point.x - controlPoint.x);\r
-// if(dist < nearestDist) {\r
-// nearest = controlPoint;\r
-// nearestDist = dist;\r
-// }\r
-// }\r
-//\r
-// nearest.y += (point.y - nearest.y) * Gdx.graphics.getDeltaTime();\r
-// spline.getPath(path, 5);\r
-// }\r
+       \r
+       private void touch(int x, int y) {\r
+               t = paths.get(currentPath).approximate(tmpV.set(x, Gdx.graphics.getHeight()-y));\r
+               paths.get(currentPath).valueAt(tmpV, t);\r
+               obj.setPosition(tmpV.x, tmpV.y);\r
+               wait = 0.2f;            \r
+       }\r
+       \r
+       @Override\r
+       public boolean touchUp (int screenX, int screenY, int pointer, int button) {\r
+               touch(screenX, screenY);\r
+               return super.touchUp(screenX, screenY, pointer, button);\r
+       }\r
+       \r
+       @Override\r
+       public boolean touchDragged (int screenX, int screenY, int pointer) {\r
+               touch(screenX, screenY);\r
+               return super.touchDragged(screenX, screenY, pointer);\r
        }\r
 }\r