• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2009-2010 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 
34 import com.jme3.math.Spline;
35 import com.jme3.math.Vector3f;
36 import com.jme3.scene.Mesh;
37 import com.jme3.scene.VertexBuffer;
38 import java.util.Iterator;
39 import java.util.List;
40 
41 /**
42  * A <code>Curve</code> is a visual, line-based representation of a {@link Spline}.
43  * The underlying Spline will be sampled N times where N is the number of
44  * segments as specified in the constructor. Each segment will represent
45  * one line in the generated mesh.
46  *
47  * @author Nehon
48  */
49 public class Curve extends Mesh {
50 
51     private Spline spline;
52     private Vector3f temp = new Vector3f();
53 
54     /**
55      * Serialization only. Do not use.
56      */
Curve()57     public Curve(){
58     }
59 
60     /**
61      * Create a curve mesh.
62      * Use a CatmullRom spline model that does not cycle.
63      *
64      * @param controlPoints the control points to use to create this curve
65      * @param nbSubSegments the number of subsegments between the control points
66      */
Curve(Vector3f[] controlPoints, int nbSubSegments)67     public Curve(Vector3f[] controlPoints, int nbSubSegments) {
68         this(new Spline(Spline.SplineType.CatmullRom, controlPoints, 10, false), nbSubSegments);
69     }
70 
71     /**
72      * Create a curve mesh from a Spline
73      *
74      * @param spline the spline to use
75      * @param nbSubSegments the number of subsegments between the control points
76      */
Curve(Spline spline, int nbSubSegments)77     public Curve(Spline spline, int nbSubSegments) {
78         super();
79         this.spline = spline;
80         switch (spline.getType()) {
81             case CatmullRom:
82             	this.createCatmullRomMesh(nbSubSegments);
83                 break;
84             case Bezier:
85             	this.createBezierMesh(nbSubSegments);
86             	break;
87             case Nurb:
88             	this.createNurbMesh(nbSubSegments);
89             	break;
90             case Linear:
91             default:
92             	this.createLinearMesh();
93                 break;
94         }
95     }
96 
createCatmullRomMesh(int nbSubSegments)97     private void createCatmullRomMesh(int nbSubSegments) {
98         float[] array = new float[((spline.getControlPoints().size() - 1) * nbSubSegments + 1) * 3];
99         short[] indices = new short[(spline.getControlPoints().size() - 1) * nbSubSegments * 2];
100         int i = 0;
101         int cptCP = 0;
102         for (Iterator<Vector3f> it = spline.getControlPoints().iterator(); it.hasNext();) {
103             Vector3f vector3f = it.next();
104             array[i] = vector3f.x;
105             i++;
106             array[i] = vector3f.y;
107             i++;
108             array[i] = vector3f.z;
109             i++;
110             if (it.hasNext()) {
111                 for (int j = 1; j < nbSubSegments; j++) {
112                     spline.interpolate((float) j / nbSubSegments, cptCP, temp);
113                     array[i] = temp.getX();
114                     i++;
115                     array[i] = temp.getY();
116                     i++;
117                     array[i] = temp.getZ();
118                     i++;
119                 }
120             }
121             cptCP++;
122         }
123 
124         i = 0;
125         int k = 0;
126         for (int j = 0; j < (spline.getControlPoints().size() - 1) * nbSubSegments; j++) {
127             k = j;
128             indices[i] = (short) k;
129             i++;
130             k++;
131             indices[i] = (short) k;
132             i++;
133         }
134 
135         this.setMode(Mesh.Mode.Lines);
136         this.setBuffer(VertexBuffer.Type.Position, 3, array);
137         this.setBuffer(VertexBuffer.Type.Index, 2, indices);//(spline.getControlPoints().size() - 1) * nbSubSegments * 2
138         this.updateBound();
139         this.updateCounts();
140     }
141 
142     /**
143 	 * This method creates the Bezier path for this curve.
144 	 *
145 	 * @param nbSubSegments
146 	 *            amount of subsegments between position control points
147 	 */
createBezierMesh(int nbSubSegments)148 	private void createBezierMesh(int nbSubSegments) {
149 		if(nbSubSegments==0) {
150 			nbSubSegments = 1;
151 		}
152 		int centerPointsAmount = (spline.getControlPoints().size() + 2) / 3;
153 
154 		//calculating vertices
155 		float[] array = new float[((centerPointsAmount - 1) * nbSubSegments + 1) * 3];
156 		int currentControlPoint = 0;
157 		List<Vector3f> controlPoints = spline.getControlPoints();
158 		int lineIndex = 0;
159 		for (int i = 0; i < centerPointsAmount - 1; ++i) {
160 			Vector3f vector3f = controlPoints.get(currentControlPoint);
161 			array[lineIndex++] = vector3f.x;
162 			array[lineIndex++] = vector3f.y;
163 			array[lineIndex++] = vector3f.z;
164 			for (int j = 1; j < nbSubSegments; ++j) {
165 				spline.interpolate((float) j / nbSubSegments, currentControlPoint, temp);
166 				array[lineIndex++] = temp.getX();
167 				array[lineIndex++] = temp.getY();
168 				array[lineIndex++] = temp.getZ();
169 			}
170 			currentControlPoint += 3;
171 		}
172 		Vector3f vector3f = controlPoints.get(currentControlPoint);
173 		array[lineIndex++] = vector3f.x;
174 		array[lineIndex++] = vector3f.y;
175 		array[lineIndex++] = vector3f.z;
176 
177 		//calculating indexes
178 		int i = 0, k = 0;
179 		short[] indices = new short[(centerPointsAmount - 1) * nbSubSegments << 1];
180 		for (int j = 0; j < (centerPointsAmount - 1) * nbSubSegments; ++j) {
181 			k = j;
182 			indices[i++] = (short) k;
183 			++k;
184 			indices[i++] = (short) k;
185 		}
186 
187 		this.setMode(Mesh.Mode.Lines);
188 		this.setBuffer(VertexBuffer.Type.Position, 3, array);
189 		this.setBuffer(VertexBuffer.Type.Index, 2, indices);
190 		this.updateBound();
191 		this.updateCounts();
192 	}
193 
194 	/**
195 	 * This method creates the Nurb path for this curve.
196 	 * @param nbSubSegments
197 	 *            amount of subsegments between position control points
198 	 */
createNurbMesh(int nbSubSegments)199 	private void createNurbMesh(int nbSubSegments) {
200 		float minKnot = spline.getMinNurbKnot();
201 		float maxKnot = spline.getMaxNurbKnot();
202 		float deltaU = (maxKnot - minKnot)/nbSubSegments;
203 
204 		float[] array = new float[(nbSubSegments + 1) * 3];
205 
206 		float u = minKnot;
207 		Vector3f interpolationResult = new Vector3f();
208 		for(int i=0;i<array.length;i+=3) {
209 			spline.interpolate(u, 0, interpolationResult);
210 			array[i] = interpolationResult.x;
211 			array[i + 1] = interpolationResult.y;
212 			array[i + 2] = interpolationResult.z;
213 			u += deltaU;
214 		}
215 
216 		//calculating indexes
217 		int i = 0;
218 		short[] indices = new short[nbSubSegments << 1];
219 		for (int j = 0; j < nbSubSegments; ++j) {
220 			indices[i++] = (short) j;
221 			indices[i++] = (short) (j + 1);
222 		}
223 
224 		this.setMode(Mesh.Mode.Lines);
225 		this.setBuffer(VertexBuffer.Type.Position, 3, array);
226 		this.setBuffer(VertexBuffer.Type.Index, 2, indices);
227 		this.updateBound();
228 		this.updateCounts();
229 	}
230 
createLinearMesh()231     private void createLinearMesh() {
232         float[] array = new float[spline.getControlPoints().size() * 3];
233         short[] indices = new short[(spline.getControlPoints().size() - 1) * 2];
234         int i = 0;
235         int cpt = 0;
236         int k = 0;
237         int j = 0;
238         for (Iterator<Vector3f> it = spline.getControlPoints().iterator(); it.hasNext();) {
239             Vector3f vector3f = it.next();
240             array[i] = vector3f.getX();
241             i++;
242             array[i] = vector3f.getY();
243             i++;
244             array[i] = vector3f.getZ();
245             i++;
246             if (it.hasNext()) {
247                 k = j;
248                 indices[cpt] = (short) k;
249                 cpt++;
250                 k++;
251                 indices[cpt] = (short) k;
252                 cpt++;
253                 j++;
254             }
255         }
256 
257         this.setMode(Mesh.Mode.Lines);
258         this.setBuffer(VertexBuffer.Type.Position, 3, array);
259         this.setBuffer(VertexBuffer.Type.Index, 2, indices);
260         this.updateBound();
261         this.updateCounts();
262     }
263 
264     /**
265      * This method returns the length of the curve.
266      * @return the length of the curve
267      */
getLength()268     public float getLength() {
269     	return spline.getTotalLength();
270     }
271 }
272