• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*******************************************************************************
2  * Copyright 2011 See AUTHORS file.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  ******************************************************************************/
16 
17 package com.badlogic.gdx.graphics.g3d.utils;
18 
19 import com.badlogic.gdx.graphics.Color;
20 import com.badlogic.gdx.graphics.GL20;
21 import com.badlogic.gdx.graphics.Mesh;
22 import com.badlogic.gdx.graphics.VertexAttribute;
23 import com.badlogic.gdx.graphics.VertexAttributes;
24 import com.badlogic.gdx.graphics.VertexAttributes.Usage;
25 import com.badlogic.gdx.graphics.g2d.TextureRegion;
26 import com.badlogic.gdx.graphics.g3d.model.MeshPart;
27 import com.badlogic.gdx.graphics.g3d.utils.shapebuilders.ArrowShapeBuilder;
28 import com.badlogic.gdx.graphics.g3d.utils.shapebuilders.BoxShapeBuilder;
29 import com.badlogic.gdx.graphics.g3d.utils.shapebuilders.CapsuleShapeBuilder;
30 import com.badlogic.gdx.graphics.g3d.utils.shapebuilders.ConeShapeBuilder;
31 import com.badlogic.gdx.graphics.g3d.utils.shapebuilders.CylinderShapeBuilder;
32 import com.badlogic.gdx.graphics.g3d.utils.shapebuilders.EllipseShapeBuilder;
33 import com.badlogic.gdx.graphics.g3d.utils.shapebuilders.PatchShapeBuilder;
34 import com.badlogic.gdx.graphics.g3d.utils.shapebuilders.SphereShapeBuilder;
35 import com.badlogic.gdx.graphics.glutils.ShaderProgram;
36 import com.badlogic.gdx.math.MathUtils;
37 import com.badlogic.gdx.math.Matrix3;
38 import com.badlogic.gdx.math.Matrix4;
39 import com.badlogic.gdx.math.Vector2;
40 import com.badlogic.gdx.math.Vector3;
41 import com.badlogic.gdx.math.collision.BoundingBox;
42 import com.badlogic.gdx.utils.Array;
43 import com.badlogic.gdx.utils.FloatArray;
44 import com.badlogic.gdx.utils.GdxRuntimeException;
45 import com.badlogic.gdx.utils.IntIntMap;
46 import com.badlogic.gdx.utils.NumberUtils;
47 import com.badlogic.gdx.utils.Pool;
48 import com.badlogic.gdx.utils.ShortArray;
49 
50 /** Class to construct a mesh, optionally splitting it into one or more mesh parts. Before you can call any other method you must
51  * call {@link #begin(VertexAttributes)} or {@link #begin(VertexAttributes, int)}. To use mesh parts you must call
52  * {@link #part(String, int)} before you start building the part. The MeshPart itself is only valid after the call to
53  * {@link #end()}.
54  * @author Xoppa */
55 public class MeshBuilder implements MeshPartBuilder {
56 	private final static ShortArray tmpIndices = new ShortArray();
57 	private final static FloatArray tmpVertices = new FloatArray();
58 
59 	private final VertexInfo vertTmp1 = new VertexInfo();
60 	private final VertexInfo vertTmp2 = new VertexInfo();
61 	private final VertexInfo vertTmp3 = new VertexInfo();
62 	private final VertexInfo vertTmp4 = new VertexInfo();
63 
64 	private final Color tempC1 = new Color();
65 
66 	/** The vertex attributes of the resulting mesh */
67 	private VertexAttributes attributes;
68 	/** The vertices to construct, no size checking is done */
69 	private FloatArray vertices = new FloatArray();
70 	/** The indices to construct, no size checking is done */
71 	private ShortArray indices = new ShortArray();
72 	/** The size (in number of floats) of each vertex */
73 	private int stride;
74 	/** The current vertex index, used for indexing */
75 	private short vindex;
76 	/** The offset in the indices array when begin() was called, used to define a meshpart. */
77 	private int istart;
78 	/** The offset within an vertex to position */
79 	private int posOffset;
80 	/** The size (in number of floats) of the position attribute */
81 	private int posSize;
82 	/** The offset within an vertex to normal, or -1 if not available */
83 	private int norOffset;
84 	/** The offset within a vertex to binormal, or -1 if not available */
85 	private int biNorOffset;
86 	/** The offset within a vertex to tangent, or -1 if not available */
87 	private int tangentOffset;
88 	/** The offset within an vertex to color, or -1 if not available */
89 	private int colOffset;
90 	/** The size (in number of floats) of the color attribute */
91 	private int colSize;
92 	/** The offset within an vertex to packed color, or -1 if not available */
93 	private int cpOffset;
94 	/** The offset within an vertex to texture coordinates, or -1 if not available */
95 	private int uvOffset;
96 	/** The meshpart currently being created */
97 	private MeshPart part;
98 	/** The parts created between begin and end */
99 	private Array<MeshPart> parts = new Array<MeshPart>();
100 	/** The color used if no vertex color is specified. */
101 	private final Color color = new Color(Color.WHITE);
102 	private boolean hasColor = false;
103 	/** The current primitiveType */
104 	private int primitiveType;
105 	/** The UV range used when building */
106 	private float uOffset = 0f, uScale = 1f, vOffset = 0f, vScale = 1f;
107 	private boolean hasUVTransform = false;
108 	private float[] vertex;
109 
110 	private boolean vertexTransformationEnabled = false;
111 	private final Matrix4 positionTransform = new Matrix4();
112 	private final Matrix3 normalTransform = new Matrix3();
113 	private final BoundingBox bounds = new BoundingBox();
114 
115 	/** @param usage bitwise mask of the {@link com.badlogic.gdx.graphics.VertexAttributes.Usage}, only Position, Color, Normal and
116 	 *           TextureCoordinates is supported. */
createAttributes(long usage)117 	public static VertexAttributes createAttributes (long usage) {
118 		final Array<VertexAttribute> attrs = new Array<VertexAttribute>();
119 		if ((usage & Usage.Position) == Usage.Position)
120 			attrs.add(new VertexAttribute(Usage.Position, 3, ShaderProgram.POSITION_ATTRIBUTE));
121 		if ((usage & Usage.ColorUnpacked) == Usage.ColorUnpacked)
122 			attrs.add(new VertexAttribute(Usage.ColorUnpacked, 4, ShaderProgram.COLOR_ATTRIBUTE));
123 		if ((usage & Usage.ColorPacked) == Usage.ColorPacked)
124 			attrs.add(new VertexAttribute(Usage.ColorPacked, 4, ShaderProgram.COLOR_ATTRIBUTE));
125 		if ((usage & Usage.Normal) == Usage.Normal)
126 			attrs.add(new VertexAttribute(Usage.Normal, 3, ShaderProgram.NORMAL_ATTRIBUTE));
127 		if ((usage & Usage.TextureCoordinates) == Usage.TextureCoordinates)
128 			attrs.add(new VertexAttribute(Usage.TextureCoordinates, 2, ShaderProgram.TEXCOORD_ATTRIBUTE + "0"));
129 		final VertexAttribute attributes[] = new VertexAttribute[attrs.size];
130 		for (int i = 0; i < attributes.length; i++)
131 			attributes[i] = attrs.get(i);
132 		return new VertexAttributes(attributes);
133 	}
134 
135 	/** Begin building a mesh. Call {@link #part(String, int)} to start a {@link MeshPart}.
136 	 * @param attributes bitwise mask of the {@link com.badlogic.gdx.graphics.VertexAttributes.Usage}, only Position, Color, Normal
137 	 *           and TextureCoordinates is supported. */
begin(final long attributes)138 	public void begin (final long attributes) {
139 		begin(createAttributes(attributes), -1);
140 	}
141 
142 	/** Begin building a mesh. Call {@link #part(String, int)} to start a {@link MeshPart}. */
begin(final VertexAttributes attributes)143 	public void begin (final VertexAttributes attributes) {
144 		begin(attributes, -1);
145 	}
146 
147 	/** Begin building a mesh.
148 	 * @param attributes bitwise mask of the {@link com.badlogic.gdx.graphics.VertexAttributes.Usage}, only Position, Color, Normal
149 	 *           and TextureCoordinates is supported. */
begin(final long attributes, int primitiveType)150 	public void begin (final long attributes, int primitiveType) {
151 		begin(createAttributes(attributes), primitiveType);
152 	}
153 
154 	/** Begin building a mesh */
begin(final VertexAttributes attributes, int primitiveType)155 	public void begin (final VertexAttributes attributes, int primitiveType) {
156 		if (this.attributes != null) throw new RuntimeException("Call end() first");
157 		this.attributes = attributes;
158 		this.vertices.clear();
159 		this.indices.clear();
160 		this.parts.clear();
161 		this.vindex = 0;
162 		this.lastIndex = -1;
163 		this.istart = 0;
164 		this.part = null;
165 		this.stride = attributes.vertexSize / 4;
166 		if (this.vertex == null || this.vertex.length < stride) this.vertex = new float[stride];
167 		VertexAttribute a = attributes.findByUsage(Usage.Position);
168 		if (a == null) throw new GdxRuntimeException("Cannot build mesh without position attribute");
169 		posOffset = a.offset / 4;
170 		posSize = a.numComponents;
171 		a = attributes.findByUsage(Usage.Normal);
172 		norOffset = a == null ? -1 : a.offset / 4;
173 		a = attributes.findByUsage(Usage.BiNormal);
174 		biNorOffset = a == null ? -1 : a.offset / 4;
175 		a = attributes.findByUsage(Usage.Tangent);
176 		tangentOffset = a == null ? -1 : a.offset / 4;
177 		a = attributes.findByUsage(Usage.ColorUnpacked);
178 		colOffset = a == null ? -1 : a.offset / 4;
179 		colSize = a == null ? 0 : a.numComponents;
180 		a = attributes.findByUsage(Usage.ColorPacked);
181 		cpOffset = a == null ? -1 : a.offset / 4;
182 		a = attributes.findByUsage(Usage.TextureCoordinates);
183 		uvOffset = a == null ? -1 : a.offset / 4;
184 		setColor(null);
185 		setVertexTransform(null);
186 		setUVRange(null);
187 		this.primitiveType = primitiveType;
188 		bounds.inf();
189 	}
190 
endpart()191 	private void endpart () {
192 		if (part != null) {
193 			bounds.getCenter(part.center);
194 			bounds.getDimensions(part.halfExtents).scl(0.5f);
195 			part.radius = part.halfExtents.len();
196 			bounds.inf();
197 			part.offset = istart;
198 			part.size = indices.size - istart;
199 			istart = indices.size;
200 			part = null;
201 		}
202 	}
203 
204 	/** Starts a new MeshPart. The mesh part is not usable until end() is called. This will reset the current color and vertex
205 	 * transformation.
206 	 * @see #part(String, int, MeshPart) */
part(final String id, int primitiveType)207 	public MeshPart part (final String id, int primitiveType) {
208 		return part(id, primitiveType, new MeshPart());
209 	}
210 
211 	/** Starts a new MeshPart. The mesh part is not usable until end() is called. This will reset the current color and vertex
212 	 * transformation.
213 	 * @param id The id (name) of the part
214 	 * @param primitiveType e.g. {@link GL20#GL_TRIANGLES} or {@link GL20#GL_LINES}
215 	 * @param meshPart The part to receive the result */
part(final String id, final int primitiveType, MeshPart meshPart)216 	public MeshPart part (final String id, final int primitiveType, MeshPart meshPart) {
217 		if (this.attributes == null) throw new RuntimeException("Call begin() first");
218 		endpart();
219 
220 		part = meshPart;
221 		part.id = id;
222 		this.primitiveType = part.primitiveType = primitiveType;
223 		parts.add(part);
224 
225 		setColor(null);
226 		setVertexTransform(null);
227 		setUVRange(null);
228 
229 		return part;
230 	}
231 
232 	/** End building the mesh and returns the mesh
233 	 * @param mesh The mesh to receive the built vertices and indices, must have the same attributes and must be big enough to hold
234 	 *           the data, any existing data will be overwritten. */
end(Mesh mesh)235 	public Mesh end (Mesh mesh) {
236 		endpart();
237 
238 		if (attributes == null) throw new GdxRuntimeException("Call begin() first");
239 		if (!attributes.equals(mesh.getVertexAttributes())) throw new GdxRuntimeException("Mesh attributes don't match");
240 		if ((mesh.getMaxVertices() * stride) < vertices.size)
241 			throw new GdxRuntimeException("Mesh can't hold enough vertices: " + mesh.getMaxVertices() + " * " + stride + " < "
242 				+ vertices.size);
243 		if (mesh.getMaxIndices() < indices.size)
244 			throw new GdxRuntimeException("Mesh can't hold enough indices: " + mesh.getMaxIndices() + " < " + indices.size);
245 
246 		mesh.setVertices(vertices.items, 0, vertices.size);
247 		mesh.setIndices(indices.items, 0, indices.size);
248 
249 		for (MeshPart p : parts)
250 			p.mesh = mesh;
251 		parts.clear();
252 
253 		attributes = null;
254 		vertices.clear();
255 		indices.clear();
256 
257 		return mesh;
258 	}
259 
260 	/** End building the mesh and returns the mesh */
end()261 	public Mesh end () {
262 		return end(new Mesh(true, vertices.size / stride, indices.size, attributes));
263 	}
264 
265 	/** Clears the data being built up until now, including the vertices, indices and all parts. Must be called in between the call
266 	 * to #begin and #end. Any builder calls made from the last call to #begin up until now are practically discarded. The state
267 	 * (e.g. UV region, color, vertex transform) will remain unchanged. */
clear()268 	public void clear () {
269 		this.vertices.clear();
270 		this.indices.clear();
271 		this.parts.clear();
272 		this.vindex = 0;
273 		this.lastIndex = -1;
274 		this.istart = 0;
275 		this.part = null;
276 	}
277 
278 	/** @return the size in number of floats of one vertex, multiply by four to get the size in bytes. */
getFloatsPerVertex()279 	public int getFloatsPerVertex () {
280 		return stride;
281 	}
282 
283 	/** @return The number of vertices built up until now, only valid in between the call to begin() and end(). */
getNumVertices()284 	public int getNumVertices () {
285 		return vertices.size / stride;
286 	}
287 
288 	/** Get a copy of the vertices built so far.
289 	 * @param out The float array to receive the copy of the vertices, must be at least `destOffset` + {@link #getNumVertices()} *
290 	 *           {@link #getFloatsPerVertex()} in size.
291 	 * @param destOffset The offset (number of floats) in the out array where to start copying */
getVertices(float[] out, int destOffset)292 	public void getVertices (float[] out, int destOffset) {
293 		if (attributes == null) throw new GdxRuntimeException("Must be called in between #begin and #end");
294 		if ((destOffset < 0) || (destOffset > out.length - vertices.size))
295 			throw new GdxRuntimeException("Array to small or offset out of range");
296 		System.arraycopy(vertices.items, 0, out, destOffset, vertices.size);
297 	}
298 
299 	/** Provides direct access to the vertices array being built, use with care. The size of the array might be bigger, do not rely
300 	 * on the length of the array. Instead use {@link #getFloatsPerVertex()} * {@link #getNumVertices()} to calculate the usable
301 	 * size of the array. Must be called in between the call to #begin and #end. */
getVertices()302 	protected float[] getVertices () {
303 		return vertices.items;
304 	}
305 
306 	/** @return The number of indices built up until now, only valid in between the call to begin() and end(). */
getNumIndices()307 	public int getNumIndices () {
308 		return indices.size;
309 	}
310 
311 	/** Get a copy of the indices built so far.
312 	 * @param out The short array to receive the copy of the indices, must be at least `destOffset` + {@link #getNumIndices()} in
313 	 *           size.
314 	 * @param destOffset The offset (number of shorts) in the out array where to start copying */
getIndices(short[] out, int destOffset)315 	public void getIndices (short[] out, int destOffset) {
316 		if (attributes == null) throw new GdxRuntimeException("Must be called in between #begin and #end");
317 		if ((destOffset < 0) || (destOffset > out.length - indices.size))
318 			throw new GdxRuntimeException("Array to small or offset out of range");
319 		System.arraycopy(indices.items, 0, out, destOffset, indices.size);
320 	}
321 
322 	/** Provides direct access to the indices array being built, use with care. The size of the array might be bigger, do not rely
323 	 * on the length of the array. Instead use {@link #getNumIndices()} to calculate the usable size of the array. Must be called
324 	 * in between the call to #begin and #end. */
getIndices()325 	protected short[] getIndices () {
326 		return indices.items;
327 	}
328 
329 	@Override
getAttributes()330 	public VertexAttributes getAttributes () {
331 		return attributes;
332 	}
333 
334 	@Override
getMeshPart()335 	public MeshPart getMeshPart () {
336 		return part;
337 	}
338 
339 	@Override
getPrimitiveType()340 	public int getPrimitiveType () {
341 		return primitiveType;
342 	}
343 
344 	@Override
setColor(float r, float g, float b, float a)345 	public void setColor (float r, float g, float b, float a) {
346 		color.set(r, g, b, a);
347 		hasColor = !color.equals(Color.WHITE);
348 	}
349 
350 	@Override
setColor(final Color color)351 	public void setColor (final Color color) {
352 		this.color.set(!(hasColor = (color != null)) ? Color.WHITE : color);
353 	}
354 
355 	@Override
setUVRange(float u1, float v1, float u2, float v2)356 	public void setUVRange (float u1, float v1, float u2, float v2) {
357 		uOffset = u1;
358 		vOffset = v1;
359 		uScale = u2 - u1;
360 		vScale = v2 - v1;
361 		hasUVTransform = !(MathUtils.isZero(u1) && MathUtils.isZero(v1) && MathUtils.isEqual(u2, 1f) && MathUtils.isEqual(v2, 1f));
362 	}
363 
364 	@Override
setUVRange(TextureRegion region)365 	public void setUVRange (TextureRegion region) {
366 		if (!(hasUVTransform = (region != null))) {
367 			uOffset = vOffset = 0f;
368 			uScale = vScale = 1f;
369 		} else
370 			setUVRange(region.getU(), region.getV(), region.getU2(), region.getV2());
371 	}
372 
373 	@Override
getVertexTransform(Matrix4 out)374 	public Matrix4 getVertexTransform (Matrix4 out) {
375 		return out.set(positionTransform);
376 	}
377 
378 	@Override
setVertexTransform(Matrix4 transform)379 	public void setVertexTransform (Matrix4 transform) {
380 		if ((vertexTransformationEnabled = (transform != null)) == true) {
381 			positionTransform.set(transform);
382 			normalTransform.set(transform).inv().transpose();
383 		} else {
384 			positionTransform.idt();
385 			normalTransform.idt();
386 		}
387 	}
388 
389 	@Override
isVertexTransformationEnabled()390 	public boolean isVertexTransformationEnabled () {
391 		return vertexTransformationEnabled;
392 	}
393 
394 	@Override
setVertexTransformationEnabled(boolean enabled)395 	public void setVertexTransformationEnabled (boolean enabled) {
396 		vertexTransformationEnabled = enabled;
397 	}
398 
399 	@Override
ensureVertices(int numVertices)400 	public void ensureVertices (int numVertices) {
401 		vertices.ensureCapacity(stride * numVertices);
402 	}
403 
404 	@Override
ensureIndices(int numIndices)405 	public void ensureIndices (int numIndices) {
406 		indices.ensureCapacity(numIndices);
407 	}
408 
409 	@Override
ensureCapacity(int numVertices, int numIndices)410 	public void ensureCapacity (int numVertices, int numIndices) {
411 		ensureVertices(numVertices);
412 		ensureIndices(numIndices);
413 	}
414 
415 	@Override
ensureTriangleIndices(int numTriangles)416 	public void ensureTriangleIndices (int numTriangles) {
417 		if (primitiveType == GL20.GL_LINES)
418 			ensureIndices(6 * numTriangles);
419 		else if (primitiveType == GL20.GL_TRIANGLES || primitiveType == GL20.GL_POINTS)
420 			ensureIndices(3 * numTriangles);
421 		else
422 			throw new GdxRuntimeException("Incorrect primtive type");
423 	}
424 
425 	/** @deprecated use {@link #ensureVertices(int)} followed by {@link #ensureTriangleIndices(int)} instead. */
426 	@Deprecated
ensureTriangles(int numVertices, int numTriangles)427 	public void ensureTriangles (int numVertices, int numTriangles) {
428 		ensureVertices(numVertices);
429 		ensureTriangleIndices(numTriangles);
430 	}
431 
432 	/** @deprecated use {@link #ensureVertices(int)} followed by {@link #ensureTriangleIndices(int)} instead. */
433 	@Deprecated
ensureTriangles(int numTriangles)434 	public void ensureTriangles (int numTriangles) {
435 		ensureVertices(3 * numTriangles);
436 		ensureTriangleIndices(numTriangles);
437 	}
438 
439 	@Override
ensureRectangleIndices(int numRectangles)440 	public void ensureRectangleIndices (int numRectangles) {
441 		if (primitiveType == GL20.GL_POINTS)
442 			ensureIndices(4 * numRectangles);
443 		else if (primitiveType == GL20.GL_LINES)
444 			ensureIndices(8 * numRectangles);
445 		else
446 			// GL_TRIANGLES
447 			ensureIndices(6 * numRectangles);
448 	}
449 
450 	/** @deprecated use {@link #ensureVertices(int)} followed by {@link #ensureRectangleIndices(int)} instead. */
451 	@Deprecated
ensureRectangles(int numVertices, int numRectangles)452 	public void ensureRectangles (int numVertices, int numRectangles) {
453 		ensureVertices(numVertices);
454 		ensureRectangleIndices(numRectangles);
455 	}
456 
457 	/** @deprecated use {@link #ensureVertices(int)} followed by {@link #ensureRectangleIndices(int)} instead. */
ensureRectangles(int numRectangles)458 	public void ensureRectangles (int numRectangles) {
459 		ensureVertices(4 * numRectangles);
460 		ensureRectangleIndices(numRectangles);
461 	}
462 
463 	private short lastIndex = -1;
464 
465 	@Override
lastIndex()466 	public short lastIndex () {
467 		return lastIndex;
468 	}
469 
470 	private final static Vector3 vTmp = new Vector3();
471 
transformPosition(final float[] values, final int offset, final int size, Matrix4 transform)472 	private final static void transformPosition (final float[] values, final int offset, final int size, Matrix4 transform) {
473 		if (size > 2) {
474 			vTmp.set(values[offset], values[offset + 1], values[offset + 2]).mul(transform);
475 			values[offset] = vTmp.x;
476 			values[offset + 1] = vTmp.y;
477 			values[offset + 2] = vTmp.z;
478 		} else if (size > 1) {
479 			vTmp.set(values[offset], values[offset + 1], 0).mul(transform);
480 			values[offset] = vTmp.x;
481 			values[offset + 1] = vTmp.y;
482 		} else
483 			values[offset] = vTmp.set(values[offset], 0, 0).mul(transform).x;
484 	}
485 
transformNormal(final float[] values, final int offset, final int size, Matrix3 transform)486 	private final static void transformNormal (final float[] values, final int offset, final int size, Matrix3 transform) {
487 		if (size > 2) {
488 			vTmp.set(values[offset], values[offset + 1], values[offset + 2]).mul(transform).nor();
489 			values[offset] = vTmp.x;
490 			values[offset + 1] = vTmp.y;
491 			values[offset + 2] = vTmp.z;
492 		} else if (size > 1) {
493 			vTmp.set(values[offset], values[offset + 1], 0).mul(transform).nor();
494 			values[offset] = vTmp.x;
495 			values[offset + 1] = vTmp.y;
496 		} else
497 			values[offset] = vTmp.set(values[offset], 0, 0).mul(transform).nor().x;
498 	}
499 
addVertex(final float[] values, final int offset)500 	private final void addVertex (final float[] values, final int offset) {
501 		final int o = vertices.size;
502 		vertices.addAll(values, offset, stride);
503 		lastIndex = (short)(vindex++);
504 
505 		if (vertexTransformationEnabled) {
506 			transformPosition(vertices.items, o + posOffset, posSize, positionTransform);
507 			if (norOffset >= 0) transformNormal(vertices.items, o + norOffset, 3, normalTransform);
508 			if (biNorOffset >= 0) transformNormal(vertices.items, o + biNorOffset, 3, normalTransform);
509 			if (tangentOffset >= 0) transformNormal(vertices.items, o + tangentOffset, 3, normalTransform);
510 		}
511 
512 		final float x = vertices.items[o + posOffset];
513 		final float y = (posSize > 1) ? vertices.items[o + posOffset + 1] : 0f;
514 		final float z = (posSize > 2) ? vertices.items[o + posOffset + 2] : 0f;
515 		bounds.ext(x, y, z);
516 
517 		if (hasColor) {
518 			if (colOffset >= 0) {
519 				vertices.items[o + colOffset] *= color.r;
520 				vertices.items[o + colOffset + 1] *= color.g;
521 				vertices.items[o + colOffset + 2] *= color.b;
522 				if (colSize > 3) vertices.items[o + colOffset + 3] *= color.a;
523 			} else if (cpOffset >= 0) {
524 				vertices.items[o + cpOffset] = tempC1.set(NumberUtils.floatToIntColor(vertices.items[o + cpOffset])).mul(color)
525 					.toFloatBits();
526 			}
527 		}
528 
529 		if (hasUVTransform && uvOffset >= 0) {
530 			vertices.items[o + uvOffset] = uOffset + uScale * vertices.items[o + uvOffset];
531 			vertices.items[o + uvOffset + 1] = vOffset + vScale * vertices.items[o + uvOffset + 1];
532 		}
533 	}
534 
535 	private final Vector3 tmpNormal = new Vector3();
536 
537 	@Override
vertex(Vector3 pos, Vector3 nor, Color col, Vector2 uv)538 	public short vertex (Vector3 pos, Vector3 nor, Color col, Vector2 uv) {
539 		if (vindex >= Short.MAX_VALUE) throw new GdxRuntimeException("Too many vertices used");
540 
541 		vertex[posOffset] = pos.x;
542 		if (posSize > 1) vertex[posOffset + 1] = pos.y;
543 		if (posSize > 2) vertex[posOffset + 2] = pos.z;
544 
545 		if (norOffset >= 0) {
546 			if (nor == null) nor = tmpNormal.set(pos).nor();
547 			vertex[norOffset] = nor.x;
548 			vertex[norOffset + 1] = nor.y;
549 			vertex[norOffset + 2] = nor.z;
550 		}
551 
552 		if (colOffset >= 0) {
553 			if (col == null) col = Color.WHITE;
554 			vertex[colOffset] = col.r;
555 			vertex[colOffset + 1] = col.g;
556 			vertex[colOffset + 2] = col.b;
557 			if (colSize > 3) vertex[colOffset + 3] = col.a;
558 		} else if (cpOffset > 0) {
559 			if (col == null) col = Color.WHITE;
560 			vertex[cpOffset] = col.toFloatBits(); // FIXME cache packed color?
561 		}
562 
563 		if (uv != null && uvOffset >= 0) {
564 			vertex[uvOffset] = uv.x;
565 			vertex[uvOffset + 1] = uv.y;
566 		}
567 
568 		addVertex(vertex, 0);
569 		return lastIndex;
570 	}
571 
572 	@Override
vertex(final float... values)573 	public short vertex (final float... values) {
574 		final int n = values.length - stride;
575 		for (int i = 0; i <= n; i += stride)
576 			addVertex(values, i);
577 		return lastIndex;
578 	}
579 
580 	@Override
vertex(final VertexInfo info)581 	public short vertex (final VertexInfo info) {
582 		return vertex(info.hasPosition ? info.position : null, info.hasNormal ? info.normal : null, info.hasColor ? info.color
583 			: null, info.hasUV ? info.uv : null);
584 	}
585 
586 	@Override
index(final short value)587 	public void index (final short value) {
588 		indices.add(value);
589 	}
590 
591 	@Override
index(final short value1, final short value2)592 	public void index (final short value1, final short value2) {
593 		ensureIndices(2);
594 		indices.add(value1);
595 		indices.add(value2);
596 	}
597 
598 	@Override
index(final short value1, final short value2, final short value3)599 	public void index (final short value1, final short value2, final short value3) {
600 		ensureIndices(3);
601 		indices.add(value1);
602 		indices.add(value2);
603 		indices.add(value3);
604 	}
605 
606 	@Override
index(final short value1, final short value2, final short value3, final short value4)607 	public void index (final short value1, final short value2, final short value3, final short value4) {
608 		ensureIndices(4);
609 		indices.add(value1);
610 		indices.add(value2);
611 		indices.add(value3);
612 		indices.add(value4);
613 	}
614 
615 	@Override
index(short value1, short value2, short value3, short value4, short value5, short value6)616 	public void index (short value1, short value2, short value3, short value4, short value5, short value6) {
617 		ensureIndices(6);
618 		indices.add(value1);
619 		indices.add(value2);
620 		indices.add(value3);
621 		indices.add(value4);
622 		indices.add(value5);
623 		indices.add(value6);
624 	}
625 
626 	@Override
index(short value1, short value2, short value3, short value4, short value5, short value6, short value7, short value8)627 	public void index (short value1, short value2, short value3, short value4, short value5, short value6, short value7,
628 		short value8) {
629 		ensureIndices(8);
630 		indices.add(value1);
631 		indices.add(value2);
632 		indices.add(value3);
633 		indices.add(value4);
634 		indices.add(value5);
635 		indices.add(value6);
636 		indices.add(value7);
637 		indices.add(value8);
638 	}
639 
640 	@Override
line(short index1, short index2)641 	public void line (short index1, short index2) {
642 		if (primitiveType != GL20.GL_LINES) throw new GdxRuntimeException("Incorrect primitive type");
643 		index(index1, index2);
644 	}
645 
646 	@Override
line(VertexInfo p1, VertexInfo p2)647 	public void line (VertexInfo p1, VertexInfo p2) {
648 		ensureVertices(2);
649 		line(vertex(p1), vertex(p2));
650 	}
651 
652 	@Override
line(Vector3 p1, Vector3 p2)653 	public void line (Vector3 p1, Vector3 p2) {
654 		line(vertTmp1.set(p1, null, null, null), vertTmp2.set(p2, null, null, null));
655 	}
656 
657 	@Override
line(float x1, float y1, float z1, float x2, float y2, float z2)658 	public void line (float x1, float y1, float z1, float x2, float y2, float z2) {
659 		line(vertTmp1.set(null, null, null, null).setPos(x1, y1, z1), vertTmp2.set(null, null, null, null).setPos(x2, y2, z2));
660 	}
661 
662 	@Override
line(Vector3 p1, Color c1, Vector3 p2, Color c2)663 	public void line (Vector3 p1, Color c1, Vector3 p2, Color c2) {
664 		line(vertTmp1.set(p1, null, c1, null), vertTmp2.set(p2, null, c2, null));
665 	}
666 
667 	@Override
triangle(short index1, short index2, short index3)668 	public void triangle (short index1, short index2, short index3) {
669 		if (primitiveType == GL20.GL_TRIANGLES || primitiveType == GL20.GL_POINTS) {
670 			index(index1, index2, index3);
671 		} else if (primitiveType == GL20.GL_LINES) {
672 			index(index1, index2, index2, index3, index3, index1);
673 		} else
674 			throw new GdxRuntimeException("Incorrect primitive type");
675 	}
676 
677 	@Override
triangle(VertexInfo p1, VertexInfo p2, VertexInfo p3)678 	public void triangle (VertexInfo p1, VertexInfo p2, VertexInfo p3) {
679 		ensureVertices(3);
680 		triangle(vertex(p1), vertex(p2), vertex(p3));
681 	}
682 
683 	@Override
triangle(Vector3 p1, Vector3 p2, Vector3 p3)684 	public void triangle (Vector3 p1, Vector3 p2, Vector3 p3) {
685 		triangle(vertTmp1.set(p1, null, null, null), vertTmp2.set(p2, null, null, null), vertTmp3.set(p3, null, null, null));
686 	}
687 
688 	@Override
triangle(Vector3 p1, Color c1, Vector3 p2, Color c2, Vector3 p3, Color c3)689 	public void triangle (Vector3 p1, Color c1, Vector3 p2, Color c2, Vector3 p3, Color c3) {
690 		triangle(vertTmp1.set(p1, null, c1, null), vertTmp2.set(p2, null, c2, null), vertTmp3.set(p3, null, c3, null));
691 	}
692 
693 	@Override
rect(short corner00, short corner10, short corner11, short corner01)694 	public void rect (short corner00, short corner10, short corner11, short corner01) {
695 		if (primitiveType == GL20.GL_TRIANGLES) {
696 			index(corner00, corner10, corner11, corner11, corner01, corner00);
697 		} else if (primitiveType == GL20.GL_LINES) {
698 			index(corner00, corner10, corner10, corner11, corner11, corner01, corner01, corner00);
699 		} else if (primitiveType == GL20.GL_POINTS) {
700 			index(corner00, corner10, corner11, corner01);
701 		} else
702 			throw new GdxRuntimeException("Incorrect primitive type");
703 	}
704 
705 	@Override
rect(VertexInfo corner00, VertexInfo corner10, VertexInfo corner11, VertexInfo corner01)706 	public void rect (VertexInfo corner00, VertexInfo corner10, VertexInfo corner11, VertexInfo corner01) {
707 		ensureVertices(4);
708 		rect(vertex(corner00), vertex(corner10), vertex(corner11), vertex(corner01));
709 	}
710 
711 	@Override
rect(Vector3 corner00, Vector3 corner10, Vector3 corner11, Vector3 corner01, Vector3 normal)712 	public void rect (Vector3 corner00, Vector3 corner10, Vector3 corner11, Vector3 corner01, Vector3 normal) {
713 		rect(vertTmp1.set(corner00, normal, null, null).setUV(0f, 1f), vertTmp2.set(corner10, normal, null, null).setUV(1f, 1f),
714 			vertTmp3.set(corner11, normal, null, null).setUV(1f, 0f), vertTmp4.set(corner01, normal, null, null).setUV(0f, 0f));
715 	}
716 
717 	@Override
rect(float x00, float y00, float z00, float x10, float y10, float z10, float x11, float y11, float z11, float x01, float y01, float z01, float normalX, float normalY, float normalZ)718 	public void rect (float x00, float y00, float z00, float x10, float y10, float z10, float x11, float y11, float z11,
719 		float x01, float y01, float z01, float normalX, float normalY, float normalZ) {
720 		rect(vertTmp1.set(null, null, null, null).setPos(x00, y00, z00).setNor(normalX, normalY, normalZ).setUV(0f, 1f), vertTmp2
721 			.set(null, null, null, null).setPos(x10, y10, z10).setNor(normalX, normalY, normalZ).setUV(1f, 1f),
722 			vertTmp3.set(null, null, null, null).setPos(x11, y11, z11).setNor(normalX, normalY, normalZ).setUV(1f, 0f), vertTmp4
723 				.set(null, null, null, null).setPos(x01, y01, z01).setNor(normalX, normalY, normalZ).setUV(0f, 0f));
724 	}
725 
726 	@Override
addMesh(Mesh mesh)727 	public void addMesh (Mesh mesh) {
728 		addMesh(mesh, 0, mesh.getNumIndices());
729 	}
730 
731 	@Override
addMesh(MeshPart meshpart)732 	public void addMesh (MeshPart meshpart) {
733 		if (meshpart.primitiveType != primitiveType) throw new GdxRuntimeException("Primitive type doesn't match");
734 		addMesh(meshpart.mesh, meshpart.offset, meshpart.size);
735 	}
736 
737 	@Override
addMesh(Mesh mesh, int indexOffset, int numIndices)738 	public void addMesh (Mesh mesh, int indexOffset, int numIndices) {
739 		if (!attributes.equals(mesh.getVertexAttributes())) throw new GdxRuntimeException("Vertex attributes do not match");
740 		if (numIndices <= 0) return; // silently ignore an empty mesh part
741 
742 		// FIXME don't triple copy, instead move the copy to jni
743 		int numFloats = mesh.getNumVertices() * stride;
744 		tmpVertices.clear();
745 		tmpVertices.ensureCapacity(numFloats);
746 		tmpVertices.size = numFloats;
747 		mesh.getVertices(tmpVertices.items);
748 
749 		tmpIndices.clear();
750 		tmpIndices.ensureCapacity(numIndices);
751 		tmpIndices.size = numIndices;
752 		mesh.getIndices(indexOffset, numIndices, tmpIndices.items, 0);
753 
754 		addMesh(tmpVertices.items, tmpIndices.items, 0, numIndices);
755 	}
756 
757 	private static IntIntMap indicesMap = null;
758 
759 	@Override
addMesh(float[] vertices, short[] indices, int indexOffset, int numIndices)760 	public void addMesh (float[] vertices, short[] indices, int indexOffset, int numIndices) {
761 		if (indicesMap == null)
762 			indicesMap = new IntIntMap(numIndices);
763 		else {
764 			indicesMap.clear();
765 			indicesMap.ensureCapacity(numIndices);
766 		}
767 		ensureIndices(numIndices);
768 		final int numVertices = vertices.length / stride;
769 		ensureVertices(numVertices < numIndices ? numVertices : numIndices);
770 		for (int i = 0; i < numIndices; i++) {
771 			final int sidx = indices[indexOffset + i];
772 			int didx = indicesMap.get(sidx, -1);
773 			if (didx < 0) {
774 				addVertex(vertices, sidx * stride);
775 				indicesMap.put(sidx, didx = lastIndex);
776 			}
777 			index((short)didx);
778 		}
779 	}
780 
781 	@Override
782 	public void addMesh (float[] vertices, short[] indices) {
783 		final short offset = (short)(lastIndex + 1);
784 
785 		final int numVertices = vertices.length / stride;
786 		ensureVertices(numVertices);
787 		for (int v = 0; v < vertices.length; v += stride)
788 			addVertex(vertices, v);
789 
790 		ensureIndices(indices.length);
791 		for (int i = 0; i < indices.length; ++i)
792 			index((short)(indices[i] + offset));
793 	}
794 
795 
796 	// TODO: The following methods are deprecated and will be removed in a future release
797 
798 	@Override
799 	@Deprecated
800 	public void patch (VertexInfo corner00, VertexInfo corner10, VertexInfo corner11, VertexInfo corner01, int divisionsU,
801 		int divisionsV) {
802 		PatchShapeBuilder.build(this, corner00, corner10, corner11, corner01, divisionsU, divisionsV);
803 	}
804 
805 	@Override
806 	@Deprecated
807 	public void patch (Vector3 corner00, Vector3 corner10, Vector3 corner11, Vector3 corner01, Vector3 normal, int divisionsU,
808 		int divisionsV) {
809 		PatchShapeBuilder.build(this, corner00, corner10, corner11, corner01, normal, divisionsU, divisionsV);
810 	}
811 
812 	@Override
813 	@Deprecated
814 	public void patch (float x00, float y00, float z00, float x10, float y10, float z10, float x11, float y11, float z11,
815 		float x01, float y01, float z01, float normalX, float normalY, float normalZ, int divisionsU, int divisionsV) {
816 		PatchShapeBuilder.build(this, x00, y00, z00, x10, y10, z10, x11, y11, z11, x01, y01, z01, normalX, normalY, normalZ, divisionsU, divisionsV);
817 	}
818 
819 	@Override
820 	@Deprecated
821 	public void box (VertexInfo corner000, VertexInfo corner010, VertexInfo corner100, VertexInfo corner110, VertexInfo corner001,
822 		VertexInfo corner011, VertexInfo corner101, VertexInfo corner111) {
823 		BoxShapeBuilder.build(this, corner000, corner010, corner100, corner110, corner001, corner011, corner101, corner111);
824 	}
825 
826 	@Override
827 	@Deprecated
828 	public void box (Vector3 corner000, Vector3 corner010, Vector3 corner100, Vector3 corner110, Vector3 corner001,
829 		Vector3 corner011, Vector3 corner101, Vector3 corner111) {
830 		BoxShapeBuilder.build(this, corner000, corner010, corner100, corner110, corner001, corner011, corner101, corner111);
831 	}
832 
833 	@Override
834 	@Deprecated
835 	public void box (Matrix4 transform) {
836 		BoxShapeBuilder.build(this, transform);
837 	}
838 
839 	@Override
840 	@Deprecated
841 	public void box (float width, float height, float depth) {
842 		BoxShapeBuilder.build(this, width, height, depth);
843 	}
844 
845 	@Override
846 	@Deprecated
847 	public void box (float x, float y, float z, float width, float height, float depth) {
848 		BoxShapeBuilder.build(this, x, y, z, width, height, depth);
849 	}
850 
851 	@Override
852 	@Deprecated
853 	public void circle (float radius, int divisions, float centerX, float centerY, float centerZ, float normalX, float normalY,
854 		float normalZ) {
855 		EllipseShapeBuilder.build(this, radius, divisions, centerX, centerY, centerZ, normalX, normalY, normalZ);
856 	}
857 
858 	@Override
859 	@Deprecated
860 	public void circle (float radius, int divisions, final Vector3 center, final Vector3 normal) {
861 		EllipseShapeBuilder.build(this, radius, divisions, center, normal);
862 	}
863 
864 	@Override
865 	@Deprecated
866 	public void circle (float radius, int divisions, final Vector3 center, final Vector3 normal, final Vector3 tangent,
867 		final Vector3 binormal) {
868 		EllipseShapeBuilder.build(this, radius, divisions, center, normal, tangent, binormal);
869 	}
870 
871 	@Override
872 	@Deprecated
873 	public void circle (float radius, int divisions, float centerX, float centerY, float centerZ, float normalX, float normalY,
874 		float normalZ, float tangentX, float tangentY, float tangentZ, float binormalX, float binormalY, float binormalZ) {
875 		EllipseShapeBuilder.build(this, radius, divisions, centerX, centerY, centerZ, normalX, normalY, normalZ, tangentX,
876 			tangentY, tangentZ, binormalX, binormalY, binormalZ);
877 	}
878 
879 	@Override
880 	@Deprecated
881 	public void circle (float radius, int divisions, float centerX, float centerY, float centerZ, float normalX, float normalY,
882 		float normalZ, float angleFrom, float angleTo) {
883 		EllipseShapeBuilder
884 			.build(this, radius, divisions, centerX, centerY, centerZ, normalX, normalY, normalZ, angleFrom, angleTo);
885 	}
886 
887 	@Override
888 	@Deprecated
889 	public void circle (float radius, int divisions, final Vector3 center, final Vector3 normal, float angleFrom, float angleTo) {
890 		EllipseShapeBuilder.build(this, radius, divisions, center, normal, angleFrom, angleTo);
891 	}
892 
893 	@Override
894 	@Deprecated
895 	public void circle (float radius, int divisions, final Vector3 center, final Vector3 normal, final Vector3 tangent,
896 		final Vector3 binormal, float angleFrom, float angleTo) {
897 		circle(radius, divisions, center.x, center.y, center.z, normal.x, normal.y, normal.z, tangent.x, tangent.y, tangent.z,
898 			binormal.x, binormal.y, binormal.z, angleFrom, angleTo);
899 	}
900 
901 	@Override
902 	@Deprecated
903 	public void circle (float radius, int divisions, float centerX, float centerY, float centerZ, float normalX, float normalY,
904 		float normalZ, float tangentX, float tangentY, float tangentZ, float binormalX, float binormalY, float binormalZ,
905 		float angleFrom, float angleTo) {
906 		EllipseShapeBuilder.build(this, radius, divisions, centerX, centerY, centerZ, normalX, normalY, normalZ, tangentX,
907 			tangentY, tangentZ, binormalX, binormalY, binormalZ, angleFrom, angleTo);
908 	}
909 
910 	@Override
911 	@Deprecated
912 	public void ellipse (float width, float height, int divisions, float centerX, float centerY, float centerZ, float normalX,
913 		float normalY, float normalZ) {
914 		EllipseShapeBuilder.build(this, width, height, divisions, centerX, centerY, centerZ, normalX, normalY, normalZ);
915 	}
916 
917 	@Override
918 	@Deprecated
919 	public void ellipse (float width, float height, int divisions, final Vector3 center, final Vector3 normal) {
920 		EllipseShapeBuilder.build(this, width, height, divisions, center, normal);
921 	}
922 
923 	@Override
924 	@Deprecated
925 	public void ellipse (float width, float height, int divisions, final Vector3 center, final Vector3 normal,
926 		final Vector3 tangent, final Vector3 binormal) {
927 		EllipseShapeBuilder.build(this, width, height, divisions, center, normal, tangent, binormal);
928 	}
929 
930 	@Override
931 	@Deprecated
932 	public void ellipse (float width, float height, int divisions, float centerX, float centerY, float centerZ, float normalX,
933 		float normalY, float normalZ, float tangentX, float tangentY, float tangentZ, float binormalX, float binormalY,
934 		float binormalZ) {
935 		EllipseShapeBuilder.build(this, width, height, divisions, centerX, centerY, centerZ, normalX, normalY, normalZ, tangentX,
936 			tangentY, tangentZ, binormalX, binormalY, binormalZ);
937 	}
938 
939 	@Override
940 	@Deprecated
941 	public void ellipse (float width, float height, int divisions, float centerX, float centerY, float centerZ, float normalX,
942 		float normalY, float normalZ, float angleFrom, float angleTo) {
943 		EllipseShapeBuilder.build(this, width, height, divisions, centerX, centerY, centerZ, normalX, normalY, normalZ, angleFrom,
944 			angleTo);
945 	}
946 
947 	@Override
948 	@Deprecated
949 	public void ellipse (float width, float height, int divisions, final Vector3 center, final Vector3 normal, float angleFrom,
950 		float angleTo) {
951 		EllipseShapeBuilder.build(this, width, height, divisions, center, normal, angleFrom, angleTo);
952 	}
953 
954 	@Override
955 	@Deprecated
956 	public void ellipse (float width, float height, int divisions, final Vector3 center, final Vector3 normal,
957 		final Vector3 tangent, final Vector3 binormal, float angleFrom, float angleTo) {
958 		EllipseShapeBuilder.build(this, width, height, divisions, center, normal, tangent, binormal, angleFrom, angleTo);
959 	}
960 
961 	@Override
962 	@Deprecated
963 	public void ellipse (float width, float height, int divisions, float centerX, float centerY, float centerZ, float normalX,
964 		float normalY, float normalZ, float tangentX, float tangentY, float tangentZ, float binormalX, float binormalY,
965 		float binormalZ, float angleFrom, float angleTo) {
966 		EllipseShapeBuilder.build(this, width, height, divisions, centerX, centerY, centerZ, normalX, normalY, normalZ, tangentX,
967 			tangentY, tangentZ, binormalX, binormalY, binormalZ, angleFrom, angleTo);
968 	}
969 
970 	@Override
971 	@Deprecated
972 	public void ellipse (float width, float height, float innerWidth, float innerHeight, int divisions, Vector3 center,
973 		Vector3 normal) {
974 		EllipseShapeBuilder.build(this, width, height, innerWidth, innerHeight, divisions, center, normal);
975 	}
976 
977 	@Override
978 	@Deprecated
979 	public void ellipse (float width, float height, float innerWidth, float innerHeight, int divisions, float centerX,
980 		float centerY, float centerZ, float normalX, float normalY, float normalZ) {
981 		EllipseShapeBuilder.build(this, width, height, innerWidth, innerHeight, divisions, centerX, centerY, centerZ, normalX,
982 			normalY, normalZ);
983 	}
984 
985 	@Override
986 	@Deprecated
987 	public void ellipse (float width, float height, float innerWidth, float innerHeight, int divisions, float centerX,
988 		float centerY, float centerZ, float normalX, float normalY, float normalZ, float angleFrom, float angleTo) {
989 		EllipseShapeBuilder.build(this, width, height, innerWidth, innerHeight, divisions, centerX, centerY, centerZ, normalX,
990 			normalY, normalZ, angleFrom, angleTo);
991 	}
992 
993 	@Override
994 	@Deprecated
995 	public void ellipse (float width, float height, float innerWidth, float innerHeight, int divisions, float centerX,
996 		float centerY, float centerZ, float normalX, float normalY, float normalZ, float tangentX, float tangentY, float tangentZ,
997 		float binormalX, float binormalY, float binormalZ, float angleFrom, float angleTo) {
998 		EllipseShapeBuilder.build(this, width, height, innerWidth, innerHeight, divisions, centerX, centerY, centerZ, normalX,
999 			normalY, normalZ, tangentX, tangentY, tangentZ, binormalX, binormalY, binormalZ, angleFrom, angleTo);
1000 	}
1001 
1002 	@Override
1003 	@Deprecated
1004 	public void cylinder (float width, float height, float depth, int divisions) {
1005 		CylinderShapeBuilder.build(this, width, height, depth, divisions);
1006 	}
1007 
1008 	@Override
1009 	@Deprecated
1010 	public void cylinder (float width, float height, float depth, int divisions, float angleFrom, float angleTo) {
1011 		CylinderShapeBuilder.build(this, width, height, depth, divisions, angleFrom, angleTo);
1012 	}
1013 
1014 	@Override
1015 	@Deprecated
1016 	public void cylinder (float width, float height, float depth, int divisions, float angleFrom, float angleTo, boolean close) {
1017 		CylinderShapeBuilder.build(this, width, height, depth, divisions, angleFrom, angleTo, close);
1018 	}
1019 
1020 	@Override
1021 	@Deprecated
1022 	public void cone (float width, float height, float depth, int divisions) {
1023 		cone(width, height, depth, divisions, 0, 360);
1024 	}
1025 
1026 	@Override
1027 	@Deprecated
1028 	public void cone (float width, float height, float depth, int divisions, float angleFrom, float angleTo) {
1029 		ConeShapeBuilder.build(this, width, height, depth, divisions, angleFrom, angleTo);
1030 	}
1031 
1032 	@Override
1033 	@Deprecated
1034 	public void sphere (float width, float height, float depth, int divisionsU, int divisionsV) {
1035 		SphereShapeBuilder.build(this, width, height, depth, divisionsU, divisionsV);
1036 	}
1037 
1038 	@Override
1039 	@Deprecated
1040 	public void sphere (final Matrix4 transform, float width, float height, float depth, int divisionsU, int divisionsV) {
1041 		SphereShapeBuilder.build(this, transform, width, height, depth, divisionsU, divisionsV);
1042 	}
1043 
1044 	@Override
1045 	@Deprecated
1046 	public void sphere (float width, float height, float depth, int divisionsU, int divisionsV, float angleUFrom, float angleUTo,
1047 		float angleVFrom, float angleVTo) {
1048 		SphereShapeBuilder.build(this, width, height, depth, divisionsU, divisionsV, angleUFrom, angleUTo, angleVFrom, angleVTo);
1049 	}
1050 
1051 	@Override
1052 	@Deprecated
1053 	public void sphere (final Matrix4 transform, float width, float height, float depth, int divisionsU, int divisionsV,
1054 		float angleUFrom, float angleUTo, float angleVFrom, float angleVTo) {
1055 		SphereShapeBuilder.build(this, transform, width, height, depth, divisionsU, divisionsV, angleUFrom, angleUTo, angleVFrom,
1056 			angleVTo);
1057 	}
1058 
1059 	@Override
1060 	@Deprecated
1061 	public void capsule (float radius, float height, int divisions) {
1062 		CapsuleShapeBuilder.build(this, radius, height, divisions);
1063 	}
1064 
1065 	@Override
1066 	@Deprecated
1067 	public void arrow (float x1, float y1, float z1, float x2, float y2, float z2, float capLength, float stemThickness,
1068 		int divisions) {
1069 		ArrowShapeBuilder.build(this, x1, y1, z1, x2, y2, z2, capLength, stemThickness, divisions);
1070 	}
1071 }
1072