Home | History | Annotate | Download | only in utils
      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. */
    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. */
    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}. */
    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. */
    150 	public void begin (final long attributes, int primitiveType) {
    151 		begin(createAttributes(attributes), primitiveType);
    152 	}
    153 
    154 	/** Begin building a mesh */
    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 
    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) */
    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 */
    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. */
    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 */
    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. */
    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. */
    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(). */
    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 */
    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. */
    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(). */
    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 */
    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. */
    325 	protected short[] getIndices () {
    326 		return indices.items;
    327 	}
    328 
    329 	@Override
    330 	public VertexAttributes getAttributes () {
    331 		return attributes;
    332 	}
    333 
    334 	@Override
    335 	public MeshPart getMeshPart () {
    336 		return part;
    337 	}
    338 
    339 	@Override
    340 	public int getPrimitiveType () {
    341 		return primitiveType;
    342 	}
    343 
    344 	@Override
    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
    351 	public void setColor (final Color color) {
    352 		this.color.set(!(hasColor = (color != null)) ? Color.WHITE : color);
    353 	}
    354 
    355 	@Override
    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
    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
    374 	public Matrix4 getVertexTransform (Matrix4 out) {
    375 		return out.set(positionTransform);
    376 	}
    377 
    378 	@Override
    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
    390 	public boolean isVertexTransformationEnabled () {
    391 		return vertexTransformationEnabled;
    392 	}
    393 
    394 	@Override
    395 	public void setVertexTransformationEnabled (boolean enabled) {
    396 		vertexTransformationEnabled = enabled;
    397 	}
    398 
    399 	@Override
    400 	public void ensureVertices (int numVertices) {
    401 		vertices.ensureCapacity(stride * numVertices);
    402 	}
    403 
    404 	@Override
    405 	public void ensureIndices (int numIndices) {
    406 		indices.ensureCapacity(numIndices);
    407 	}
    408 
    409 	@Override
    410 	public void ensureCapacity (int numVertices, int numIndices) {
    411 		ensureVertices(numVertices);
    412 		ensureIndices(numIndices);
    413 	}
    414 
    415 	@Override
    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
    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
    434 	public void ensureTriangles (int numTriangles) {
    435 		ensureVertices(3 * numTriangles);
    436 		ensureTriangleIndices(numTriangles);
    437 	}
    438 
    439 	@Override
    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
    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. */
    458 	public void ensureRectangles (int numRectangles) {
    459 		ensureVertices(4 * numRectangles);
    460 		ensureRectangleIndices(numRectangles);
    461 	}
    462 
    463 	private short lastIndex = -1;
    464 
    465 	@Override
    466 	public short lastIndex () {
    467 		return lastIndex;
    468 	}
    469 
    470 	private final static Vector3 vTmp = new Vector3();
    471 
    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 
    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 
    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
    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
    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
    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
    587 	public void index (final short value) {
    588 		indices.add(value);
    589 	}
    590 
    591 	@Override
    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
    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
    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
    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
    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
    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
    647 	public void line (VertexInfo p1, VertexInfo p2) {
    648 		ensureVertices(2);
    649 		line(vertex(p1), vertex(p2));
    650 	}
    651 
    652 	@Override
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    727 	public void addMesh (Mesh mesh) {
    728 		addMesh(mesh, 0, mesh.getNumIndices());
    729 	}
    730 
    731 	@Override
    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
    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
    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