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.utils;
     18 
     19 import java.nio.Buffer;
     20 import java.nio.ByteBuffer;
     21 import java.nio.ByteOrder;
     22 import java.nio.CharBuffer;
     23 import java.nio.DoubleBuffer;
     24 import java.nio.FloatBuffer;
     25 import java.nio.IntBuffer;
     26 import java.nio.LongBuffer;
     27 import java.nio.ShortBuffer;
     28 
     29 import com.badlogic.gdx.math.Matrix3;
     30 import com.badlogic.gdx.math.Matrix4;
     31 
     32 /** Class with static helper methods to increase the speed of array/direct buffer and direct buffer/direct buffer transfers
     33  *
     34  * @author mzechner, xoppa */
     35 public final class BufferUtils {
     36 	static Array<ByteBuffer> unsafeBuffers = new Array<ByteBuffer>();
     37 	static int allocatedUnsafe = 0;
     38 
     39 	/** Copies numFloats floats from src starting at offset to dst. Dst is assumed to be a direct {@link Buffer}. The method will
     40 	 * crash if that is not the case. The position and limit of the buffer are ignored, the copy is placed at position 0 in the
     41 	 * buffer. After the copying process the position of the buffer is set to 0 and its limit is set to numFloats * 4 if it is a
     42 	 * ByteBuffer and numFloats if it is a FloatBuffer. In case the Buffer is neither a ByteBuffer nor a FloatBuffer the limit is
     43 	 * not set. This is an expert method, use at your own risk.
     44 	 *
     45 	 * @param src the source array
     46 	 * @param dst the destination buffer, has to be a direct Buffer
     47 	 * @param numFloats the number of floats to copy
     48 	 * @param offset the offset in src to start copying from */
     49 	public static void copy (float[] src, Buffer dst, int numFloats, int offset) {
     50 		if (dst instanceof ByteBuffer)
     51 			dst.limit(numFloats << 2);
     52 		else if (dst instanceof FloatBuffer) dst.limit(numFloats);
     53 
     54 		copyJni(src, dst, numFloats, offset);
     55 		dst.position(0);
     56 	}
     57 
     58 	/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
     59 	 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit
     60 	 * will be set to position + numElements. <b>The Buffer must be a direct Buffer with native byte order. No error checking is
     61 	 * performed</b>.
     62 	 *
     63 	 * @param src the source array.
     64 	 * @param srcOffset the offset into the source array.
     65 	 * @param dst the destination Buffer, its position is used as an offset.
     66 	 * @param numElements the number of elements to copy. */
     67 	public static void copy (byte[] src, int srcOffset, Buffer dst, int numElements) {
     68 		dst.limit(dst.position() + bytesToElements(dst, numElements));
     69 		copyJni(src, srcOffset, dst, positionInBytes(dst), numElements);
     70 	}
     71 
     72 	/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
     73 	 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit
     74 	 * will be set to position + numElements. <b>The Buffer must be a direct Buffer with native byte order. No error checking is
     75 	 * performed</b>.
     76 	 *
     77 	 * @param src the source array.
     78 	 * @param srcOffset the offset into the source array.
     79 	 * @param dst the destination Buffer, its position is used as an offset.
     80 	 * @param numElements the number of elements to copy. */
     81 	public static void copy (short[] src, int srcOffset, Buffer dst, int numElements) {
     82 		dst.limit(dst.position() + bytesToElements(dst, numElements << 1));
     83 		copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 1);
     84 	}
     85 
     86 	/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
     87 	 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position and limit will stay the same.
     88 	 * <b>The Buffer must be a direct Buffer with native byte order. No error checking is performed</b>.
     89 	 *
     90 	 * @param src the source array.
     91 	 * @param srcOffset the offset into the source array.
     92 	 * @param numElements the number of elements to copy.
     93 	 * @param dst the destination Buffer, its position is used as an offset. */
     94 	public static void copy (char[] src, int srcOffset, int numElements, Buffer dst) {
     95 		copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 1);
     96 	}
     97 
     98 	/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
     99 	 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position and limit will stay the same.
    100 	 * <b>The Buffer must be a direct Buffer with native byte order. No error checking is performed</b>.
    101 	 *
    102 	 * @param src the source array.
    103 	 * @param srcOffset the offset into the source array.
    104 	 * @param numElements the number of elements to copy.
    105 	 * @param dst the destination Buffer, its position is used as an offset. */
    106 	public static void copy (int[] src, int srcOffset, int numElements, Buffer dst) {
    107 		copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 2);
    108 	}
    109 
    110 	/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
    111 	 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position and limit will stay the same.
    112 	 * <b>The Buffer must be a direct Buffer with native byte order. No error checking is performed</b>.
    113 	 *
    114 	 * @param src the source array.
    115 	 * @param srcOffset the offset into the source array.
    116 	 * @param numElements the number of elements to copy.
    117 	 * @param dst the destination Buffer, its position is used as an offset. */
    118 	public static void copy (long[] src, int srcOffset, int numElements, Buffer dst) {
    119 		copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 3);
    120 	}
    121 
    122 	/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
    123 	 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position and limit will stay the same.
    124 	 * <b>The Buffer must be a direct Buffer with native byte order. No error checking is performed</b>.
    125 	 *
    126 	 * @param src the source array.
    127 	 * @param srcOffset the offset into the source array.
    128 	 * @param numElements the number of elements to copy.
    129 	 * @param dst the destination Buffer, its position is used as an offset. */
    130 	public static void copy (float[] src, int srcOffset, int numElements, Buffer dst) {
    131 		copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 2);
    132 	}
    133 
    134 	/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
    135 	 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position and limit will stay the same.
    136 	 * <b>The Buffer must be a direct Buffer with native byte order. No error checking is performed</b>.
    137 	 *
    138 	 * @param src the source array.
    139 	 * @param srcOffset the offset into the source array.
    140 	 * @param numElements the number of elements to copy.
    141 	 * @param dst the destination Buffer, its position is used as an offset. */
    142 	public static void copy (double[] src, int srcOffset, int numElements, Buffer dst) {
    143 		copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 3);
    144 	}
    145 
    146 	/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
    147 	 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit
    148 	 * will be set to position + numElements. <b>The Buffer must be a direct Buffer with native byte order. No error checking is
    149 	 * performed</b>.
    150 	 *
    151 	 * @param src the source array.
    152 	 * @param srcOffset the offset into the source array.
    153 	 * @param dst the destination Buffer, its position is used as an offset.
    154 	 * @param numElements the number of elements to copy. */
    155 	public static void copy (char[] src, int srcOffset, Buffer dst, int numElements) {
    156 		dst.limit(dst.position() + bytesToElements(dst, numElements << 1));
    157 		copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 1);
    158 	}
    159 
    160 	/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
    161 	 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit
    162 	 * will be set to position + numElements. <b>The Buffer must be a direct Buffer with native byte order. No error checking is
    163 	 * performed</b>.
    164 	 *
    165 	 * @param src the source array.
    166 	 * @param srcOffset the offset into the source array.
    167 	 * @param dst the destination Buffer, its position is used as an offset.
    168 	 * @param numElements the number of elements to copy. */
    169 	public static void copy (int[] src, int srcOffset, Buffer dst, int numElements) {
    170 		dst.limit(dst.position() + bytesToElements(dst, numElements << 2));
    171 		copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 2);
    172 	}
    173 
    174 	/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
    175 	 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit
    176 	 * will be set to position + numElements. <b>The Buffer must be a direct Buffer with native byte order. No error checking is
    177 	 * performed</b>.
    178 	 *
    179 	 * @param src the source array.
    180 	 * @param srcOffset the offset into the source array.
    181 	 * @param dst the destination Buffer, its position is used as an offset.
    182 	 * @param numElements the number of elements to copy. */
    183 	public static void copy (long[] src, int srcOffset, Buffer dst, int numElements) {
    184 		dst.limit(dst.position() + bytesToElements(dst, numElements << 3));
    185 		copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 3);
    186 	}
    187 
    188 	/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
    189 	 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit
    190 	 * will be set to position + numElements. <b>The Buffer must be a direct Buffer with native byte order. No error checking is
    191 	 * performed</b>.
    192 	 *
    193 	 * @param src the source array.
    194 	 * @param srcOffset the offset into the source array.
    195 	 * @param dst the destination Buffer, its position is used as an offset.
    196 	 * @param numElements the number of elements to copy. */
    197 	public static void copy (float[] src, int srcOffset, Buffer dst, int numElements) {
    198 		dst.limit(dst.position() + bytesToElements(dst, numElements << 2));
    199 		copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 2);
    200 	}
    201 
    202 	/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
    203 	 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit
    204 	 * will be set to position + numElements. <b>The Buffer must be a direct Buffer with native byte order. No error checking is
    205 	 * performed</b>.
    206 	 *
    207 	 * @param src the source array.
    208 	 * @param srcOffset the offset into the source array.
    209 	 * @param dst the destination Buffer, its position is used as an offset.
    210 	 * @param numElements the number of elements to copy. */
    211 	public static void copy (double[] src, int srcOffset, Buffer dst, int numElements) {
    212 		dst.limit(dst.position() + bytesToElements(dst, numElements << 3));
    213 		copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 3);
    214 	}
    215 
    216 	/** Copies the contents of src to dst, starting from the current position of src, copying numElements elements (using the data
    217 	 * type of src, no matter the datatype of dst). The dst {@link Buffer#position()} is used as the writing offset. The position
    218 	 * of both Buffers will stay the same. The limit of the src Buffer will stay the same. The limit of the dst Buffer will be set
    219 	 * to dst.position() + numElements, where numElements are translated to the number of elements appropriate for the dst Buffer
    220 	 * data type. <b>The Buffers must be direct Buffers with native byte order. No error checking is performed</b>.
    221 	 *
    222 	 * @param src the source Buffer.
    223 	 * @param dst the destination Buffer.
    224 	 * @param numElements the number of elements to copy. */
    225 	public static void copy (Buffer src, Buffer dst, int numElements) {
    226 		int numBytes = elementsToBytes(src, numElements);
    227 		dst.limit(dst.position() + bytesToElements(dst, numBytes));
    228 		copyJni(src, positionInBytes(src), dst, positionInBytes(dst), numBytes);
    229 	}
    230 
    231 	/** Multiply float vector components within the buffer with the specified matrix. The {@link Buffer#position()} is used as the
    232 	 * offset.
    233 	 * @param data The buffer to transform.
    234 	 * @param dimensions The number of components of the vector (2 for xy, 3 for xyz or 4 for xyzw)
    235 	 * @param strideInBytes The offset between the first and the second vector to transform
    236 	 * @param count The number of vectors to transform
    237 	 * @param matrix The matrix to multiply the vector with */
    238 	public static void transform (Buffer data, int dimensions, int strideInBytes, int count, Matrix4 matrix) {
    239 		transform(data, dimensions, strideInBytes, count, matrix, 0);
    240 	}
    241 
    242 	/** Multiply float vector components within the buffer with the specified matrix. The {@link Buffer#position()} is used as the
    243 	 * offset.
    244 	 * @param data The buffer to transform.
    245 	 * @param dimensions The number of components of the vector (2 for xy, 3 for xyz or 4 for xyzw)
    246 	 * @param strideInBytes The offset between the first and the second vector to transform
    247 	 * @param count The number of vectors to transform
    248 	 * @param matrix The matrix to multiply the vector with */
    249 	public static void transform (float[] data, int dimensions, int strideInBytes, int count, Matrix4 matrix) {
    250 		transform(data, dimensions, strideInBytes, count, matrix, 0);
    251 	}
    252 
    253 	/** Multiply float vector components within the buffer with the specified matrix. The specified offset value is added to the
    254 	 * {@link Buffer#position()} and used as the offset.
    255 	 * @param data The buffer to transform.
    256 	 * @param dimensions The number of components of the vector (2 for xy, 3 for xyz or 4 for xyzw)
    257 	 * @param strideInBytes The offset between the first and the second vector to transform
    258 	 * @param count The number of vectors to transform
    259 	 * @param matrix The matrix to multiply the vector with
    260 	 * @param offset The offset within the buffer (in bytes relative to the current position) to the vector */
    261 	public static void transform (Buffer data, int dimensions, int strideInBytes, int count, Matrix4 matrix, int offset) {
    262 		switch (dimensions) {
    263 		case 4:
    264 			transformV4M4Jni(data, strideInBytes, count, matrix.val, positionInBytes(data) + offset);
    265 			break;
    266 		case 3:
    267 			transformV3M4Jni(data, strideInBytes, count, matrix.val, positionInBytes(data) + offset);
    268 			break;
    269 		case 2:
    270 			transformV2M4Jni(data, strideInBytes, count, matrix.val, positionInBytes(data) + offset);
    271 			break;
    272 		default:
    273 			throw new IllegalArgumentException();
    274 		}
    275 	}
    276 
    277 	/** Multiply float vector components within the buffer with the specified matrix. The specified offset value is added to the
    278 	 * {@link Buffer#position()} and used as the offset.
    279 	 * @param data The buffer to transform.
    280 	 * @param dimensions The number of components of the vector (2 for xy, 3 for xyz or 4 for xyzw)
    281 	 * @param strideInBytes The offset between the first and the second vector to transform
    282 	 * @param count The number of vectors to transform
    283 	 * @param matrix The matrix to multiply the vector with
    284 	 * @param offset The offset within the buffer (in bytes relative to the current position) to the vector */
    285 	public static void transform (float[] data, int dimensions, int strideInBytes, int count, Matrix4 matrix, int offset) {
    286 		switch (dimensions) {
    287 		case 4:
    288 			transformV4M4Jni(data, strideInBytes, count, matrix.val, offset);
    289 			break;
    290 		case 3:
    291 			transformV3M4Jni(data, strideInBytes, count, matrix.val, offset);
    292 			break;
    293 		case 2:
    294 			transformV2M4Jni(data, strideInBytes, count, matrix.val, offset);
    295 			break;
    296 		default:
    297 			throw new IllegalArgumentException();
    298 		}
    299 	}
    300 
    301 	/** Multiply float vector components within the buffer with the specified matrix. The {@link Buffer#position()} is used as the
    302 	 * offset.
    303 	 * @param data The buffer to transform.
    304 	 * @param dimensions The number of components (x, y, z) of the vector (2 for xy or 3 for xyz)
    305 	 * @param strideInBytes The offset between the first and the second vector to transform
    306 	 * @param count The number of vectors to transform
    307 	 * @param matrix The matrix to multiply the vector with */
    308 	public static void transform (Buffer data, int dimensions, int strideInBytes, int count, Matrix3 matrix) {
    309 		transform(data, dimensions, strideInBytes, count, matrix, 0);
    310 	}
    311 
    312 	/** Multiply float vector components within the buffer with the specified matrix. The {@link Buffer#position()} is used as the
    313 	 * offset.
    314 	 * @param data The buffer to transform.
    315 	 * @param dimensions The number of components (x, y, z) of the vector (2 for xy or 3 for xyz)
    316 	 * @param strideInBytes The offset between the first and the second vector to transform
    317 	 * @param count The number of vectors to transform
    318 	 * @param matrix The matrix to multiply the vector with */
    319 	public static void transform (float[] data, int dimensions, int strideInBytes, int count, Matrix3 matrix) {
    320 		transform(data, dimensions, strideInBytes, count, matrix, 0);
    321 	}
    322 
    323 	/** Multiply float vector components within the buffer with the specified matrix. The specified offset value is added to the
    324 	 * {@link Buffer#position()} and used as the offset.
    325 	 * @param data The buffer to transform.
    326 	 * @param dimensions The number of components (x, y, z) of the vector (2 for xy or 3 for xyz)
    327 	 * @param strideInBytes The offset between the first and the second vector to transform
    328 	 * @param count The number of vectors to transform
    329 	 * @param matrix The matrix to multiply the vector with,
    330 	 * @param offset The offset within the buffer (in bytes relative to the current position) to the vector */
    331 	public static void transform (Buffer data, int dimensions, int strideInBytes, int count, Matrix3 matrix, int offset) {
    332 		switch (dimensions) {
    333 		case 3:
    334 			transformV3M3Jni(data, strideInBytes, count, matrix.val, positionInBytes(data) + offset);
    335 			break;
    336 		case 2:
    337 			transformV2M3Jni(data, strideInBytes, count, matrix.val, positionInBytes(data) + offset);
    338 			break;
    339 		default:
    340 			throw new IllegalArgumentException();
    341 		}
    342 	}
    343 
    344 	/** Multiply float vector components within the buffer with the specified matrix. The specified offset value is added to the
    345 	 * {@link Buffer#position()} and used as the offset.
    346 	 * @param data The buffer to transform.
    347 	 * @param dimensions The number of components (x, y, z) of the vector (2 for xy or 3 for xyz)
    348 	 * @param strideInBytes The offset between the first and the second vector to transform
    349 	 * @param count The number of vectors to transform
    350 	 * @param matrix The matrix to multiply the vector with,
    351 	 * @param offset The offset within the buffer (in bytes relative to the current position) to the vector */
    352 	public static void transform (float[] data, int dimensions, int strideInBytes, int count, Matrix3 matrix, int offset) {
    353 		switch (dimensions) {
    354 		case 3:
    355 			transformV3M3Jni(data, strideInBytes, count, matrix.val, offset);
    356 			break;
    357 		case 2:
    358 			transformV2M3Jni(data, strideInBytes, count, matrix.val, offset);
    359 			break;
    360 		default:
    361 			throw new IllegalArgumentException();
    362 		}
    363 	}
    364 
    365 	public static long findFloats (Buffer vertex, int strideInBytes, Buffer vertices, int numVertices) {
    366 		return find(vertex, positionInBytes(vertex), strideInBytes, vertices, positionInBytes(vertices), numVertices);
    367 	}
    368 
    369 	public static long findFloats (float[] vertex, int strideInBytes, Buffer vertices, int numVertices) {
    370 		return find(vertex, 0, strideInBytes, vertices, positionInBytes(vertices), numVertices);
    371 	}
    372 
    373 	public static long findFloats (Buffer vertex, int strideInBytes, float[] vertices, int numVertices) {
    374 		return find(vertex, positionInBytes(vertex), strideInBytes, vertices, 0, numVertices);
    375 	}
    376 
    377 	public static long findFloats (float[] vertex, int strideInBytes, float[] vertices, int numVertices) {
    378 		return find(vertex, 0, strideInBytes, vertices, 0, numVertices);
    379 	}
    380 
    381 	public static long findFloats (Buffer vertex, int strideInBytes, Buffer vertices, int numVertices, float epsilon) {
    382 		return find(vertex, positionInBytes(vertex), strideInBytes, vertices, positionInBytes(vertices), numVertices, epsilon);
    383 	}
    384 
    385 	public static long findFloats (float[] vertex, int strideInBytes, Buffer vertices, int numVertices, float epsilon) {
    386 		return find(vertex, 0, strideInBytes, vertices, positionInBytes(vertices), numVertices, epsilon);
    387 	}
    388 
    389 	public static long findFloats (Buffer vertex, int strideInBytes, float[] vertices, int numVertices, float epsilon) {
    390 		return find(vertex, positionInBytes(vertex), strideInBytes, vertices, 0, numVertices, epsilon);
    391 	}
    392 
    393 	public static long findFloats (float[] vertex, int strideInBytes, float[] vertices, int numVertices, float epsilon) {
    394 		return find(vertex, 0, strideInBytes, vertices, 0, numVertices, epsilon);
    395 	}
    396 
    397 	private static int positionInBytes (Buffer dst) {
    398 		if (dst instanceof ByteBuffer)
    399 			return dst.position();
    400 		else if (dst instanceof ShortBuffer)
    401 			return dst.position() << 1;
    402 		else if (dst instanceof CharBuffer)
    403 			return dst.position() << 1;
    404 		else if (dst instanceof IntBuffer)
    405 			return dst.position() << 2;
    406 		else if (dst instanceof LongBuffer)
    407 			return dst.position() << 3;
    408 		else if (dst instanceof FloatBuffer)
    409 			return dst.position() << 2;
    410 		else if (dst instanceof DoubleBuffer)
    411 			return dst.position() << 3;
    412 		else
    413 			throw new GdxRuntimeException("Can't copy to a " + dst.getClass().getName() + " instance");
    414 	}
    415 
    416 	private static int bytesToElements (Buffer dst, int bytes) {
    417 		if (dst instanceof ByteBuffer)
    418 			return bytes;
    419 		else if (dst instanceof ShortBuffer)
    420 			return bytes >>> 1;
    421 		else if (dst instanceof CharBuffer)
    422 			return bytes >>> 1;
    423 		else if (dst instanceof IntBuffer)
    424 			return bytes >>> 2;
    425 		else if (dst instanceof LongBuffer)
    426 			return bytes >>> 3;
    427 		else if (dst instanceof FloatBuffer)
    428 			return bytes >>> 2;
    429 		else if (dst instanceof DoubleBuffer)
    430 			return bytes >>> 3;
    431 		else
    432 			throw new GdxRuntimeException("Can't copy to a " + dst.getClass().getName() + " instance");
    433 	}
    434 
    435 	private static int elementsToBytes (Buffer dst, int elements) {
    436 		if (dst instanceof ByteBuffer)
    437 			return elements;
    438 		else if (dst instanceof ShortBuffer)
    439 			return elements << 1;
    440 		else if (dst instanceof CharBuffer)
    441 			return elements << 1;
    442 		else if (dst instanceof IntBuffer)
    443 			return elements << 2;
    444 		else if (dst instanceof LongBuffer)
    445 			return elements << 3;
    446 		else if (dst instanceof FloatBuffer)
    447 			return elements << 2;
    448 		else if (dst instanceof DoubleBuffer)
    449 			return elements << 3;
    450 		else
    451 			throw new GdxRuntimeException("Can't copy to a " + dst.getClass().getName() + " instance");
    452 	}
    453 
    454 	public static FloatBuffer newFloatBuffer (int numFloats) {
    455 		ByteBuffer buffer = ByteBuffer.allocateDirect(numFloats * 4);
    456 		buffer.order(ByteOrder.nativeOrder());
    457 		return buffer.asFloatBuffer();
    458 	}
    459 
    460 	public static DoubleBuffer newDoubleBuffer (int numDoubles) {
    461 		ByteBuffer buffer = ByteBuffer.allocateDirect(numDoubles * 8);
    462 		buffer.order(ByteOrder.nativeOrder());
    463 		return buffer.asDoubleBuffer();
    464 	}
    465 
    466 	public static ByteBuffer newByteBuffer (int numBytes) {
    467 		ByteBuffer buffer = ByteBuffer.allocateDirect(numBytes);
    468 		buffer.order(ByteOrder.nativeOrder());
    469 		return buffer;
    470 	}
    471 
    472 	public static ShortBuffer newShortBuffer (int numShorts) {
    473 		ByteBuffer buffer = ByteBuffer.allocateDirect(numShorts * 2);
    474 		buffer.order(ByteOrder.nativeOrder());
    475 		return buffer.asShortBuffer();
    476 	}
    477 
    478 	public static CharBuffer newCharBuffer (int numChars) {
    479 		ByteBuffer buffer = ByteBuffer.allocateDirect(numChars * 2);
    480 		buffer.order(ByteOrder.nativeOrder());
    481 		return buffer.asCharBuffer();
    482 	}
    483 
    484 	public static IntBuffer newIntBuffer (int numInts) {
    485 		ByteBuffer buffer = ByteBuffer.allocateDirect(numInts * 4);
    486 		buffer.order(ByteOrder.nativeOrder());
    487 		return buffer.asIntBuffer();
    488 	}
    489 
    490 	public static LongBuffer newLongBuffer (int numLongs) {
    491 		ByteBuffer buffer = ByteBuffer.allocateDirect(numLongs * 8);
    492 		buffer.order(ByteOrder.nativeOrder());
    493 		return buffer.asLongBuffer();
    494 	}
    495 
    496 	// @off
    497 	/*JNI
    498 	#include <stdio.h>
    499 	#include <stdlib.h>
    500 	#include <string.h>
    501 	*/
    502 
    503 	public static void disposeUnsafeByteBuffer(ByteBuffer buffer) {
    504 		int size = buffer.capacity();
    505 		synchronized(unsafeBuffers) {
    506 			if(!unsafeBuffers.removeValue(buffer, true))
    507 				throw new IllegalArgumentException("buffer not allocated with newUnsafeByteBuffer or already disposed");
    508 		}
    509 		allocatedUnsafe -= size;
    510 		freeMemory(buffer);
    511 	}
    512 
    513 	/** Allocates a new direct ByteBuffer from native heap memory using the native byte order. Needs to be disposed with
    514 	 * {@link #freeMemory(ByteBuffer)}.
    515 	 * @param numBytes */
    516 	public static ByteBuffer newUnsafeByteBuffer (int numBytes) {
    517 		ByteBuffer buffer = newDisposableByteBuffer(numBytes);
    518 		buffer.order(ByteOrder.nativeOrder());
    519 		allocatedUnsafe += numBytes;
    520 		synchronized(unsafeBuffers) {
    521 			unsafeBuffers.add(buffer);
    522 		}
    523 		return buffer;
    524 	}
    525 
    526 	/**
    527 	 * Returns the address of the Buffer, it assumes it is an unsafe buffer.
    528 	 * @param buffer The Buffer to ask the address for.
    529 	 * @return the address of the Buffer.
    530 	 */
    531 	public static long getUnsafeBufferAddress(Buffer buffer) {
    532 		return getBufferAddress(buffer) + buffer.position();
    533 	}
    534 
    535 	/**
    536 	 * Registers the given ByteBuffer as an unsafe ByteBuffer. The ByteBuffer must have been
    537 	 * allocated in native code, pointing to a memory region allocated via malloc. Needs to
    538 	 * be disposed with {@link #freeMemory(ByteBuffer)}.
    539 	 * @param buffer the {@link ByteBuffer} to register
    540 	 * @return the ByteBuffer passed to the method
    541 	 */
    542 	public static ByteBuffer newUnsafeByteBuffer(ByteBuffer buffer) {
    543 		allocatedUnsafe += buffer.capacity();
    544 		synchronized(unsafeBuffers) {
    545 			unsafeBuffers.add(buffer);
    546 		}
    547 		return buffer;
    548 	}
    549 
    550 	/**
    551 	 * @return the number of bytes allocated with {@link #newUnsafeByteBuffer(int)}
    552 	 */
    553 	public static int getAllocatedBytesUnsafe() {
    554 		return allocatedUnsafe;
    555 	}
    556 
    557 	/** Frees the memory allocated for the ByteBuffer. DO NOT USE THIS ON BYTEBUFFERS ALLOCATEd VIA METHODS IN THIS CLASS OR
    558 	 * ByteBuffer.allocateDirect()! IT WILL EXPLODE! */
    559 	private static native void freeMemory (ByteBuffer buffer); /*
    560 		free(buffer);
    561 	 */
    562 
    563 	private static native ByteBuffer newDisposableByteBuffer (int numBytes); /*
    564 		return env->NewDirectByteBuffer((char*)malloc(numBytes), numBytes);
    565 	*/
    566 
    567 	private static native long getBufferAddress (Buffer buffer); /*
    568 	    return (jlong) buffer;
    569 	*/
    570 
    571 	/** Writes the specified number of zeros to the buffer. This is generally faster than reallocating a new buffer. */
    572 	public static native void clear (ByteBuffer buffer, int numBytes); /*
    573 		memset(buffer, 0, numBytes);
    574 	*/
    575 
    576 	private native static void copyJni (float[] src, Buffer dst, int numFloats, int offset); /*
    577 		memcpy(dst, src + offset, numFloats << 2 );
    578 	*/
    579 
    580 	private native static void copyJni (byte[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /*
    581 		memcpy(dst + dstOffset, src + srcOffset, numBytes);
    582 	*/
    583 
    584 	private native static void copyJni (char[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /*
    585 		memcpy(dst + dstOffset, src + srcOffset, numBytes);
    586 	*/
    587 
    588 	private native static void copyJni (short[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /*
    589 		memcpy(dst + dstOffset, src + srcOffset, numBytes);
    590 	 */
    591 
    592 	private native static void copyJni (int[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /*
    593 		memcpy(dst + dstOffset, src + srcOffset, numBytes);
    594 	*/
    595 
    596 	private native static void copyJni (long[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /*
    597 		memcpy(dst + dstOffset, src + srcOffset, numBytes);
    598 	*/
    599 
    600 	private native static void copyJni (float[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /*
    601 		memcpy(dst + dstOffset, src + srcOffset, numBytes);
    602 	*/
    603 
    604 	private native static void copyJni (double[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /*
    605 		memcpy(dst + dstOffset, src + srcOffset, numBytes);
    606 	*/
    607 
    608 	private native static void copyJni (Buffer src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /*
    609 		memcpy(dst + dstOffset, src + srcOffset, numBytes);
    610 	*/
    611 
    612 	/*JNI
    613 	template<size_t n1, size_t n2> void transform(float * const &src, float * const &m, float * const &dst) {}
    614 
    615 	template<> inline void transform<4, 4>(float * const &src, float * const &m, float * const &dst) {
    616 		const float x = src[0], y = src[1], z = src[2], w = src[3];
    617 		dst[0] = x * m[ 0] + y * m[ 4] + z * m[ 8] + w * m[12];
    618 		dst[1] = x * m[ 1] + y * m[ 5] + z * m[ 9] + w * m[13];
    619 		dst[2] = x * m[ 2] + y * m[ 6] + z * m[10] + w * m[14];
    620 		dst[3] = x * m[ 3] + y * m[ 7] + z * m[11] + w * m[15];
    621 	}
    622 
    623 	template<> inline void transform<3, 4>(float * const &src, float * const &m, float * const &dst) {
    624 		const float x = src[0], y = src[1], z = src[2];
    625 		dst[0] = x * m[ 0] + y * m[ 4] + z * m[ 8] + m[12];
    626 		dst[1] = x * m[ 1] + y * m[ 5] + z * m[ 9] + m[13];
    627 		dst[2] = x * m[ 2] + y * m[ 6] + z * m[10] + m[14];
    628 	}
    629 
    630 	template<> inline void transform<2, 4>(float * const &src, float * const &m, float * const &dst) {
    631 		const float x = src[0], y = src[1];
    632 		dst[0] = x * m[ 0] + y * m[ 4] + m[12];
    633 		dst[1] = x * m[ 1] + y * m[ 5] + m[13];
    634 	}
    635 
    636 	template<> inline void transform<3, 3>(float * const &src, float * const &m, float * const &dst) {
    637 		const float x = src[0], y = src[1], z = src[2];
    638 		dst[0] = x * m[0] + y * m[3] + z * m[6];
    639 		dst[1] = x * m[1] + y * m[4] + z * m[7];
    640 		dst[2] = x * m[2] + y * m[5] + z * m[8];
    641 	}
    642 
    643 	template<> inline void transform<2, 3>(float * const &src, float * const &m, float * const &dst) {
    644 		const float x = src[0], y = src[1];
    645 		dst[0] = x * m[0] + y * m[3] + m[6];
    646 		dst[1] = x * m[1] + y * m[4] + m[7];
    647 	}
    648 
    649 	template<size_t n1, size_t n2> void transform(float * const &v, int const &stride, int const &count, float * const &m, int offset) {
    650 		for (int i = 0; i < count; i++) {
    651 			transform<n1, n2>(&v[offset], m, &v[offset]);
    652 			offset += stride;
    653 		}
    654 	}
    655 
    656 	template<size_t n1, size_t n2> void transform(float * const &v, int const &stride, unsigned short * const &indices, int const &count, float * const &m, int offset) {
    657 		for (int i = 0; i < count; i++) {
    658 			transform<n1, n2>(&v[offset], m, &v[offset]);
    659 			offset += stride;
    660 		}
    661 	}
    662 
    663 	inline bool compare(float * const &lhs, float * const & rhs, const unsigned int &size, const float &epsilon) {
    664    	for (unsigned int i = 0; i < size; i++)
    665    		if ((*(unsigned int*)&lhs[i] != *(unsigned int*)&rhs[i]) && ((lhs[i] > rhs[i] ? lhs[i] - rhs[i] : rhs[i] - lhs[i]) > epsilon))
    666          	return false;
    667 		return true;
    668 	}
    669 
    670 	long find(float * const &vertex, const unsigned int &size, float * const &vertices, const unsigned int &count, const float &epsilon) {
    671 		for (unsigned int i = 0; i < count; i++)
    672 			if (compare(&vertices[i*size], vertex, size, epsilon))
    673 				return (long)i;
    674 		return -1;
    675 	}
    676 
    677 	inline bool compare(float * const &lhs, float * const & rhs, const unsigned int &size) {
    678    	for (unsigned int i = 0; i < size; i++)
    679       	if ((*(unsigned int*)&lhs[i] != *(unsigned int*)&rhs[i]) && lhs[i] != rhs[i])
    680          	return false;
    681 		return true;
    682 	}
    683 
    684 	long find(float * const &vertex, const unsigned int &size, float * const &vertices, const unsigned int &count) {
    685 		for (unsigned int i = 0; i < count; i++)
    686 			if (compare(&vertices[i*size], vertex, size))
    687 				return (long)i;
    688 		return -1;
    689 	}
    690 
    691 	inline unsigned int calcHash(float * const &vertex, const unsigned int &size) {
    692 		unsigned int result = 0;
    693 		for (unsigned int i = 0; i < size; ++i)
    694 			result += ((*((unsigned int *)&vertex[i])) & 0xffffff80) >> (i & 0x7);
    695 		return result & 0x7fffffff;
    696 	}
    697 
    698 	long find(float * const &vertex, const unsigned int &size, float * const &vertices, unsigned int * const &hashes, const unsigned int &count) {
    699 		const unsigned int hash = calcHash(vertex, size);
    700 		for (unsigned int i = 0; i < count; i++)
    701 			if (hashes[i] == hash && compare(&vertices[i*size], vertex, size))
    702 				return (long)i;
    703 		return -1;
    704 	}
    705 	*/
    706 
    707 	private native static void transformV4M4Jni (Buffer data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /*
    708 		transform<4, 4>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4);
    709 	*/
    710 
    711 	private native static void transformV4M4Jni (float[] data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /*
    712 		transform<4, 4>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4);
    713 	*/
    714 
    715 	private native static void transformV3M4Jni (Buffer data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /*
    716 		transform<3, 4>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4);
    717 	*/
    718 
    719 	private native static void transformV3M4Jni (float[] data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /*
    720 		transform<3, 4>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4);
    721 	*/
    722 
    723 	private native static void transformV2M4Jni (Buffer data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /*
    724 		transform<2, 4>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4);
    725 	*/
    726 
    727 	private native static void transformV2M4Jni (float[] data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /*
    728 		transform<2, 4>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4);
    729 	*/
    730 
    731 	private native static void transformV3M3Jni (Buffer data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /*
    732 		transform<3, 3>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4);
    733 	*/
    734 
    735 	private native static void transformV3M3Jni (float[] data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /*
    736 		transform<3, 3>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4);
    737 	*/
    738 
    739 	private native static void transformV2M3Jni (Buffer data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /*
    740 		transform<2, 3>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4);
    741 	*/
    742 
    743 	private native static void transformV2M3Jni (float[] data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /*
    744 		transform<2, 3>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4);
    745 	*/
    746 
    747 	private native static long find(Buffer vertex, int vertexOffsetInBytes, int strideInBytes, Buffer vertices, int verticesOffsetInBytes, int numVertices); /*
    748 		return find((float *)&vertex[vertexOffsetInBytes / 4], (unsigned int)(strideInBytes / 4), (float*)&vertices[verticesOffsetInBytes / 4], (unsigned int)numVertices);
    749 	*/
    750 
    751 	private native static long find(float[] vertex, int vertexOffsetInBytes, int strideInBytes, Buffer vertices, int verticesOffsetInBytes, int numVertices); /*
    752 		return find((float *)&vertex[vertexOffsetInBytes / 4], (unsigned int)(strideInBytes / 4), (float*)&vertices[verticesOffsetInBytes / 4], (unsigned int)numVertices);
    753 	*/
    754 
    755 	private native static long find(Buffer vertex, int vertexOffsetInBytes, int strideInBytes, float[] vertices, int verticesOffsetInBytes, int numVertices); /*
    756 		return find((float *)&vertex[vertexOffsetInBytes / 4], (unsigned int)(strideInBytes / 4), (float*)&vertices[verticesOffsetInBytes / 4], (unsigned int)numVertices);
    757 	*/
    758 
    759 	private native static long find(float[] vertex, int vertexOffsetInBytes, int strideInBytes, float[] vertices, int verticesOffsetInBytes, int numVertices); /*
    760 		return find((float *)&vertex[vertexOffsetInBytes / 4], (unsigned int)(strideInBytes / 4), (float*)&vertices[verticesOffsetInBytes / 4], (unsigned int)numVertices);
    761 	*/
    762 
    763 	private native static long find(Buffer vertex, int vertexOffsetInBytes, int strideInBytes, Buffer vertices, int verticesOffsetInBytes, int numVertices, float epsilon); /*
    764 		return find((float *)&vertex[vertexOffsetInBytes / 4], (unsigned int)(strideInBytes / 4), (float*)&vertices[verticesOffsetInBytes / 4], (unsigned int)numVertices, epsilon);
    765 	*/
    766 
    767 	private native static long find(float[] vertex, int vertexOffsetInBytes, int strideInBytes, Buffer vertices, int verticesOffsetInBytes, int numVertices, float epsilon); /*
    768 		return find((float *)&vertex[vertexOffsetInBytes / 4], (unsigned int)(strideInBytes / 4), (float*)&vertices[verticesOffsetInBytes / 4], (unsigned int)numVertices, epsilon);
    769 	*/
    770 
    771 	private native static long find(Buffer vertex, int vertexOffsetInBytes, int strideInBytes, float[] vertices, int verticesOffsetInBytes, int numVertices, float epsilon); /*
    772 		return find((float *)&vertex[vertexOffsetInBytes / 4], (unsigned int)(strideInBytes / 4), (float*)&vertices[verticesOffsetInBytes / 4], (unsigned int)numVertices, epsilon);
    773 	*/
    774 
    775 	private native static long find(float[] vertex, int vertexOffsetInBytes, int strideInBytes, float[] vertices, int verticesOffsetInBytes, int numVertices, float epsilon); /*
    776 		return find((float *)&vertex[vertexOffsetInBytes / 4], (unsigned int)(strideInBytes / 4), (float*)&vertices[verticesOffsetInBytes / 4], (unsigned int)numVertices, epsilon);
    777 	*/
    778 }
    779