PageRenderTime 59ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/engine/src/core/com/jme3/scene/shape/Curve.java

http://jmonkeyengine.googlecode.com/
Java | 273 lines | 177 code | 21 blank | 75 comment | 14 complexity | c99f42138637ecf98681c3bf73d4675b MD5 | raw file
Possible License(s): LGPL-2.0, GPL-2.0, BSD-3-Clause
  1. /*
  2. * Copyright (c) 2009-2012 jMonkeyEngine
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are
  7. * met:
  8. *
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. *
  12. * * Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
  17. * may be used to endorse or promote products derived from this software
  18. * without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  22. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  23. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  24. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  26. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  27. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  28. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  29. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  30. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. */
  32. package com.jme3.scene.shape;
  33. import com.jme3.math.Spline;
  34. import com.jme3.math.Vector3f;
  35. import com.jme3.scene.Mesh;
  36. import com.jme3.scene.VertexBuffer;
  37. import java.util.Iterator;
  38. import java.util.List;
  39. /**
  40. * A
  41. * <code>Curve</code> is a visual, line-based representation of a {@link Spline}.
  42. * The underlying Spline will be sampled N times where N is the number of
  43. * segments as specified in the constructor. Each segment will represent one
  44. * line in the generated mesh.
  45. *
  46. * @author Nehon
  47. */
  48. public class Curve extends Mesh {
  49. private Spline spline;
  50. private Vector3f temp = new Vector3f();
  51. /**
  52. * Serialization only. Do not use.
  53. */
  54. public Curve() {
  55. }
  56. /**
  57. * Create a curve mesh. Use a CatmullRom spline model that does not cycle.
  58. *
  59. * @param controlPoints the control points to use to create this curve
  60. * @param nbSubSegments the number of subsegments between the control points
  61. */
  62. public Curve(Vector3f[] controlPoints, int nbSubSegments) {
  63. this(new Spline(Spline.SplineType.CatmullRom, controlPoints, 10, false), nbSubSegments);
  64. }
  65. /**
  66. * Create a curve mesh from a Spline
  67. *
  68. * @param spline the spline to use
  69. * @param nbSubSegments the number of subsegments between the control points
  70. */
  71. public Curve(Spline spline, int nbSubSegments) {
  72. super();
  73. this.spline = spline;
  74. switch (spline.getType()) {
  75. case CatmullRom:
  76. this.createCatmullRomMesh(nbSubSegments);
  77. break;
  78. case Bezier:
  79. this.createBezierMesh(nbSubSegments);
  80. break;
  81. case Nurb:
  82. this.createNurbMesh(nbSubSegments);
  83. break;
  84. case Linear:
  85. default:
  86. this.createLinearMesh();
  87. break;
  88. }
  89. }
  90. private void createCatmullRomMesh(int nbSubSegments) {
  91. float[] array = new float[((spline.getControlPoints().size() - 1) * nbSubSegments + 1) * 3];
  92. short[] indices = new short[(spline.getControlPoints().size() - 1) * nbSubSegments * 2];
  93. int i = 0;
  94. int cptCP = 0;
  95. for (Iterator<Vector3f> it = spline.getControlPoints().iterator(); it.hasNext();) {
  96. Vector3f vector3f = it.next();
  97. array[i] = vector3f.x;
  98. i++;
  99. array[i] = vector3f.y;
  100. i++;
  101. array[i] = vector3f.z;
  102. i++;
  103. if (it.hasNext()) {
  104. for (int j = 1; j < nbSubSegments; j++) {
  105. spline.interpolate((float) j / nbSubSegments, cptCP, temp);
  106. array[i] = temp.getX();
  107. i++;
  108. array[i] = temp.getY();
  109. i++;
  110. array[i] = temp.getZ();
  111. i++;
  112. }
  113. }
  114. cptCP++;
  115. }
  116. i = 0;
  117. int k;
  118. for (int j = 0; j < (spline.getControlPoints().size() - 1) * nbSubSegments; j++) {
  119. k = j;
  120. indices[i] = (short) k;
  121. i++;
  122. k++;
  123. indices[i] = (short) k;
  124. i++;
  125. }
  126. this.setMode(Mesh.Mode.Lines);
  127. this.setBuffer(VertexBuffer.Type.Position, 3, array);
  128. this.setBuffer(VertexBuffer.Type.Index, 2, indices);//(spline.getControlPoints().size() - 1) * nbSubSegments * 2
  129. this.updateBound();
  130. this.updateCounts();
  131. }
  132. /**
  133. * This method creates the Bezier path for this curve.
  134. *
  135. * @param nbSubSegments amount of subsegments between position control
  136. * points
  137. */
  138. private void createBezierMesh(int nbSubSegments) {
  139. if (nbSubSegments == 0) {
  140. nbSubSegments = 1;
  141. }
  142. int centerPointsAmount = (spline.getControlPoints().size() + 2) / 3;
  143. //calculating vertices
  144. float[] array = new float[((centerPointsAmount - 1) * nbSubSegments + 1) * 3];
  145. int currentControlPoint = 0;
  146. List<Vector3f> controlPoints = spline.getControlPoints();
  147. int lineIndex = 0;
  148. for (int i = 0; i < centerPointsAmount - 1; ++i) {
  149. Vector3f vector3f = controlPoints.get(currentControlPoint);
  150. array[lineIndex++] = vector3f.x;
  151. array[lineIndex++] = vector3f.y;
  152. array[lineIndex++] = vector3f.z;
  153. for (int j = 1; j < nbSubSegments; ++j) {
  154. spline.interpolate((float) j / nbSubSegments, currentControlPoint, temp);
  155. array[lineIndex++] = temp.getX();
  156. array[lineIndex++] = temp.getY();
  157. array[lineIndex++] = temp.getZ();
  158. }
  159. currentControlPoint += 3;
  160. }
  161. Vector3f vector3f = controlPoints.get(currentControlPoint);
  162. array[lineIndex++] = vector3f.x;
  163. array[lineIndex++] = vector3f.y;
  164. array[lineIndex++] = vector3f.z;
  165. //calculating indexes
  166. int i = 0, k;
  167. short[] indices = new short[(centerPointsAmount - 1) * nbSubSegments << 1];
  168. for (int j = 0; j < (centerPointsAmount - 1) * nbSubSegments; ++j) {
  169. k = j;
  170. indices[i++] = (short) k;
  171. ++k;
  172. indices[i++] = (short) k;
  173. }
  174. this.setMode(Mesh.Mode.Lines);
  175. this.setBuffer(VertexBuffer.Type.Position, 3, array);
  176. this.setBuffer(VertexBuffer.Type.Index, 2, indices);
  177. this.updateBound();
  178. this.updateCounts();
  179. }
  180. /**
  181. * This method creates the Nurb path for this curve.
  182. *
  183. * @param nbSubSegments amount of subsegments between position control
  184. * points
  185. */
  186. private void createNurbMesh(int nbSubSegments) {
  187. float minKnot = spline.getMinNurbKnot();
  188. float maxKnot = spline.getMaxNurbKnot();
  189. float deltaU = (maxKnot - minKnot) / nbSubSegments;
  190. float[] array = new float[(nbSubSegments + 1) * 3];
  191. float u = minKnot;
  192. Vector3f interpolationResult = new Vector3f();
  193. for (int i = 0; i < array.length; i += 3) {
  194. spline.interpolate(u, 0, interpolationResult);
  195. array[i] = interpolationResult.x;
  196. array[i + 1] = interpolationResult.y;
  197. array[i + 2] = interpolationResult.z;
  198. u += deltaU;
  199. }
  200. //calculating indexes
  201. int i = 0;
  202. short[] indices = new short[nbSubSegments << 1];
  203. for (int j = 0; j < nbSubSegments; ++j) {
  204. indices[i++] = (short) j;
  205. indices[i++] = (short) (j + 1);
  206. }
  207. this.setMode(Mesh.Mode.Lines);
  208. this.setBuffer(VertexBuffer.Type.Position, 3, array);
  209. this.setBuffer(VertexBuffer.Type.Index, 2, indices);
  210. this.updateBound();
  211. this.updateCounts();
  212. }
  213. private void createLinearMesh() {
  214. float[] array = new float[spline.getControlPoints().size() * 3];
  215. short[] indices = new short[(spline.getControlPoints().size() - 1) * 2];
  216. int i = 0;
  217. int cpt = 0;
  218. int k;
  219. int j = 0;
  220. for (Iterator<Vector3f> it = spline.getControlPoints().iterator(); it.hasNext();) {
  221. Vector3f vector3f = it.next();
  222. array[i] = vector3f.getX();
  223. i++;
  224. array[i] = vector3f.getY();
  225. i++;
  226. array[i] = vector3f.getZ();
  227. i++;
  228. if (it.hasNext()) {
  229. k = j;
  230. indices[cpt] = (short) k;
  231. cpt++;
  232. k++;
  233. indices[cpt] = (short) k;
  234. cpt++;
  235. j++;
  236. }
  237. }
  238. this.setMode(Mesh.Mode.Lines);
  239. this.setBuffer(VertexBuffer.Type.Position, 3, array);
  240. this.setBuffer(VertexBuffer.Type.Index, 2, indices);
  241. this.updateBound();
  242. this.updateCounts();
  243. }
  244. /**
  245. * This method returns the length of the curve.
  246. *
  247. * @return the length of the curve
  248. */
  249. public float getLength() {
  250. return spline.getTotalLength();
  251. }
  252. }