All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.badlogic.gdx.utils.BufferUtils Maven / Gradle / Ivy

/*******************************************************************************
 * Copyright 2011 See AUTHORS file.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/

package com.badlogic.gdx.utils;

import com.badlogic.gdx.math.Matrix3;
import com.badlogic.gdx.math.Matrix4;

import java.nio.*;

/** Class with static helper methods to increase the speed of array/direct buffer and direct buffer/direct buffer transfers
 * 
 * @author mzechner, xoppa */
public final class BufferUtils {
	static Array unsafeBuffers = new Array();
	static int allocatedUnsafe = 0;

	/** Copies numFloats floats from src starting at offset to dst. Dst is assumed to be a direct {@link Buffer}. The method will
	 * 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
	 * 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
	 * ByteBuffer and numFloats if it is a FloatBuffer. In case the Buffer is neither a ByteBuffer nor a FloatBuffer the limit is
	 * not set. This is an expert method, use at your own risk.
	 * 
	 * @param src the source array
	 * @param dst the destination buffer, has to be a direct Buffer
	 * @param numFloats the number of floats to copy
	 * @param offset the offset in src to start copying from */
	public static void copy (float[] src, Buffer dst, int numFloats, int offset) {
		if (dst instanceof ByteBuffer)
			dst.limit(numFloats << 2);
		else if (dst instanceof FloatBuffer) dst.limit(numFloats);

		copyJni(src, dst, numFloats, offset);
		dst.position(0);
	}

	/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
	 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit
	 * will be set to position + numElements. The Buffer must be a direct Buffer with native byte order. No error checking is
	 * performed.
	 * 
	 * @param src the source array.
	 * @param srcOffset the offset into the source array.
	 * @param dst the destination Buffer, its position is used as an offset.
	 * @param numElements the number of elements to copy. */
	public static void copy (byte[] src, int srcOffset, Buffer dst, int numElements) {
		dst.limit(dst.position() + bytesToElements(dst, numElements));
		copyJni(src, srcOffset, dst, positionInBytes(dst), numElements);
	}

	/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
	 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit
	 * will be set to position + numElements. The Buffer must be a direct Buffer with native byte order. No error checking is
	 * performed.
	 * 
	 * @param src the source array.
	 * @param srcOffset the offset into the source array.
	 * @param dst the destination Buffer, its position is used as an offset.
	 * @param numElements the number of elements to copy. */
	public static void copy (short[] src, int srcOffset, Buffer dst, int numElements) {
		dst.limit(dst.position() + bytesToElements(dst, numElements << 1));
		copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 1);
	}

	/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
	 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position and limit will stay the same.
	 * The Buffer must be a direct Buffer with native byte order. No error checking is performed.
	 * 
	 * @param src the source array.
	 * @param srcOffset the offset into the source array.
	 * @param numElements the number of elements to copy.
	 * @param dst the destination Buffer, its position is used as an offset. */
	public static void copy (char[] src, int srcOffset, int numElements, Buffer dst) {
		copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 1);
	}

	/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
	 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position and limit will stay the same.
	 * The Buffer must be a direct Buffer with native byte order. No error checking is performed.
	 * 
	 * @param src the source array.
	 * @param srcOffset the offset into the source array.
	 * @param numElements the number of elements to copy.
	 * @param dst the destination Buffer, its position is used as an offset. */
	public static void copy (int[] src, int srcOffset, int numElements, Buffer dst) {
		copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 2);
	}

	/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
	 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position and limit will stay the same.
	 * The Buffer must be a direct Buffer with native byte order. No error checking is performed.
	 * 
	 * @param src the source array.
	 * @param srcOffset the offset into the source array.
	 * @param numElements the number of elements to copy.
	 * @param dst the destination Buffer, its position is used as an offset. */
	public static void copy (long[] src, int srcOffset, int numElements, Buffer dst) {
		copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 3);
	}

	/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
	 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position and limit will stay the same.
	 * The Buffer must be a direct Buffer with native byte order. No error checking is performed.
	 * 
	 * @param src the source array.
	 * @param srcOffset the offset into the source array.
	 * @param numElements the number of elements to copy.
	 * @param dst the destination Buffer, its position is used as an offset. */
	public static void copy (float[] src, int srcOffset, int numElements, Buffer dst) {
		copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 2);
	}

	/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
	 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position and limit will stay the same.
	 * The Buffer must be a direct Buffer with native byte order. No error checking is performed.
	 * 
	 * @param src the source array.
	 * @param srcOffset the offset into the source array.
	 * @param numElements the number of elements to copy.
	 * @param dst the destination Buffer, its position is used as an offset. */
	public static void copy (double[] src, int srcOffset, int numElements, Buffer dst) {
		copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 3);
	}

	/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
	 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit
	 * will be set to position + numElements. The Buffer must be a direct Buffer with native byte order. No error checking is
	 * performed.
	 * 
	 * @param src the source array.
	 * @param srcOffset the offset into the source array.
	 * @param dst the destination Buffer, its position is used as an offset.
	 * @param numElements the number of elements to copy. */
	public static void copy (char[] src, int srcOffset, Buffer dst, int numElements) {
		dst.limit(dst.position() + bytesToElements(dst, numElements << 1));
		copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 1);
	}

	/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
	 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit
	 * will be set to position + numElements. The Buffer must be a direct Buffer with native byte order. No error checking is
	 * performed.
	 * 
	 * @param src the source array.
	 * @param srcOffset the offset into the source array.
	 * @param dst the destination Buffer, its position is used as an offset.
	 * @param numElements the number of elements to copy. */
	public static void copy (int[] src, int srcOffset, Buffer dst, int numElements) {
		dst.limit(dst.position() + bytesToElements(dst, numElements << 2));
		copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 2);
	}

	/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
	 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit
	 * will be set to position + numElements. The Buffer must be a direct Buffer with native byte order. No error checking is
	 * performed.
	 * 
	 * @param src the source array.
	 * @param srcOffset the offset into the source array.
	 * @param dst the destination Buffer, its position is used as an offset.
	 * @param numElements the number of elements to copy. */
	public static void copy (long[] src, int srcOffset, Buffer dst, int numElements) {
		dst.limit(dst.position() + bytesToElements(dst, numElements << 3));
		copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 3);
	}

	/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
	 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit
	 * will be set to position + numElements. The Buffer must be a direct Buffer with native byte order. No error checking is
	 * performed.
	 * 
	 * @param src the source array.
	 * @param srcOffset the offset into the source array.
	 * @param dst the destination Buffer, its position is used as an offset.
	 * @param numElements the number of elements to copy. */
	public static void copy (float[] src, int srcOffset, Buffer dst, int numElements) {
		dst.limit(dst.position() + bytesToElements(dst, numElements << 2));
		copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 2);
	}

	/** Copies the contents of src to dst, starting from src[srcOffset], copying numElements elements. The {@link Buffer} instance's
	 * {@link Buffer#position()} is used to define the offset into the Buffer itself. The position will stay the same, the limit
	 * will be set to position + numElements. The Buffer must be a direct Buffer with native byte order. No error checking is
	 * performed.
	 * 
	 * @param src the source array.
	 * @param srcOffset the offset into the source array.
	 * @param dst the destination Buffer, its position is used as an offset.
	 * @param numElements the number of elements to copy. */
	public static void copy (double[] src, int srcOffset, Buffer dst, int numElements) {
		dst.limit(dst.position() + bytesToElements(dst, numElements << 3));
		copyJni(src, srcOffset, dst, positionInBytes(dst), numElements << 3);
	}

	/** Copies the contents of src to dst, starting from the current position of src, copying numElements elements (using the data
	 * type of src, no matter the datatype of dst). The dst {@link Buffer#position()} is used as the writing offset. The position
	 * 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
	 * to dst.position() + numElements, where numElements are translated to the number of elements appropriate for the dst Buffer
	 * data type. The Buffers must be direct Buffers with native byte order. No error checking is performed.
	 * 
	 * @param src the source Buffer.
	 * @param dst the destination Buffer.
	 * @param numElements the number of elements to copy. */
	public static void copy (Buffer src, Buffer dst, int numElements) {
		int numBytes = elementsToBytes(src, numElements);
		dst.limit(dst.position() + bytesToElements(dst, numBytes));
		copyJni(src, positionInBytes(src), dst, positionInBytes(dst), numBytes);
	}

	/** Multiply float vector components within the buffer with the specified matrix. The {@link Buffer#position()} is used as the
	 * offset.
	 * @param data The buffer to transform.
	 * @param dimensions The number of components of the vector (2 for xy, 3 for xyz or 4 for xyzw)
	 * @param strideInBytes The offset between the first and the second vector to transform
	 * @param count The number of vectors to transform
	 * @param matrix The matrix to multiply the vector with */
	public static void transform (Buffer data, int dimensions, int strideInBytes, int count, Matrix4 matrix) {
		transform(data, dimensions, strideInBytes, count, matrix, 0);
	}

	/** Multiply float vector components within the buffer with the specified matrix. The {@link Buffer#position()} is used as the
	 * offset.
	 * @param data The buffer to transform.
	 * @param dimensions The number of components of the vector (2 for xy, 3 for xyz or 4 for xyzw)
	 * @param strideInBytes The offset between the first and the second vector to transform
	 * @param count The number of vectors to transform
	 * @param matrix The matrix to multiply the vector with */
	public static void transform (float[] data, int dimensions, int strideInBytes, int count, Matrix4 matrix) {
		transform(data, dimensions, strideInBytes, count, matrix, 0);
	}

	/** Multiply float vector components within the buffer with the specified matrix. The specified offset value is added to the
	 * {@link Buffer#position()} and used as the offset.
	 * @param data The buffer to transform.
	 * @param dimensions The number of components of the vector (2 for xy, 3 for xyz or 4 for xyzw)
	 * @param strideInBytes The offset between the first and the second vector to transform
	 * @param count The number of vectors to transform
	 * @param matrix The matrix to multiply the vector with
	 * @param offset The offset within the buffer (in bytes relative to the current position) to the vector */
	public static void transform (Buffer data, int dimensions, int strideInBytes, int count, Matrix4 matrix, int offset) {
		switch (dimensions) {
		case 4:
			transformV4M4Jni(data, strideInBytes, count, matrix.val, positionInBytes(data) + offset);
			break;
		case 3:
			transformV3M4Jni(data, strideInBytes, count, matrix.val, positionInBytes(data) + offset);
			break;
		case 2:
			transformV2M4Jni(data, strideInBytes, count, matrix.val, positionInBytes(data) + offset);
			break;
		default:
			throw new IllegalArgumentException();
		}
	}

	/** Multiply float vector components within the buffer with the specified matrix. The specified offset value is added to the
	 * {@link Buffer#position()} and used as the offset.
	 * @param data The buffer to transform.
	 * @param dimensions The number of components of the vector (2 for xy, 3 for xyz or 4 for xyzw)
	 * @param strideInBytes The offset between the first and the second vector to transform
	 * @param count The number of vectors to transform
	 * @param matrix The matrix to multiply the vector with
	 * @param offset The offset within the buffer (in bytes relative to the current position) to the vector */
	public static void transform (float[] data, int dimensions, int strideInBytes, int count, Matrix4 matrix, int offset) {
		switch (dimensions) {
		case 4:
			transformV4M4Jni(data, strideInBytes, count, matrix.val, offset);
			break;
		case 3:
			transformV3M4Jni(data, strideInBytes, count, matrix.val, offset);
			break;
		case 2:
			transformV2M4Jni(data, strideInBytes, count, matrix.val, offset);
			break;
		default:
			throw new IllegalArgumentException();
		}
	}

	/** Multiply float vector components within the buffer with the specified matrix. The {@link Buffer#position()} is used as the
	 * offset.
	 * @param data The buffer to transform.
	 * @param dimensions The number of components (x, y, z) of the vector (2 for xy or 3 for xyz)
	 * @param strideInBytes The offset between the first and the second vector to transform
	 * @param count The number of vectors to transform
	 * @param matrix The matrix to multiply the vector with */
	public static void transform (Buffer data, int dimensions, int strideInBytes, int count, Matrix3 matrix) {
		transform(data, dimensions, strideInBytes, count, matrix, 0);
	}

	/** Multiply float vector components within the buffer with the specified matrix. The {@link Buffer#position()} is used as the
	 * offset.
	 * @param data The buffer to transform.
	 * @param dimensions The number of components (x, y, z) of the vector (2 for xy or 3 for xyz)
	 * @param strideInBytes The offset between the first and the second vector to transform
	 * @param count The number of vectors to transform
	 * @param matrix The matrix to multiply the vector with */
	public static void transform (float[] data, int dimensions, int strideInBytes, int count, Matrix3 matrix) {
		transform(data, dimensions, strideInBytes, count, matrix, 0);
	}

	/** Multiply float vector components within the buffer with the specified matrix. The specified offset value is added to the
	 * {@link Buffer#position()} and used as the offset.
	 * @param data The buffer to transform.
	 * @param dimensions The number of components (x, y, z) of the vector (2 for xy or 3 for xyz)
	 * @param strideInBytes The offset between the first and the second vector to transform
	 * @param count The number of vectors to transform
	 * @param matrix The matrix to multiply the vector with,
	 * @param offset The offset within the buffer (in bytes relative to the current position) to the vector */
	public static void transform (Buffer data, int dimensions, int strideInBytes, int count, Matrix3 matrix, int offset) {
		switch (dimensions) {
		case 3:
			transformV3M3Jni(data, strideInBytes, count, matrix.val, positionInBytes(data) + offset);
			break;
		case 2:
			transformV2M3Jni(data, strideInBytes, count, matrix.val, positionInBytes(data) + offset);
			break;
		default:
			throw new IllegalArgumentException();
		}
	}

	/** Multiply float vector components within the buffer with the specified matrix. The specified offset value is added to the
	 * {@link Buffer#position()} and used as the offset.
	 * @param data The buffer to transform.
	 * @param dimensions The number of components (x, y, z) of the vector (2 for xy or 3 for xyz)
	 * @param strideInBytes The offset between the first and the second vector to transform
	 * @param count The number of vectors to transform
	 * @param matrix The matrix to multiply the vector with,
	 * @param offset The offset within the buffer (in bytes relative to the current position) to the vector */
	public static void transform (float[] data, int dimensions, int strideInBytes, int count, Matrix3 matrix, int offset) {
		switch (dimensions) {
		case 3:
			transformV3M3Jni(data, strideInBytes, count, matrix.val, offset);
			break;
		case 2:
			transformV2M3Jni(data, strideInBytes, count, matrix.val, offset);
			break;
		default:
			throw new IllegalArgumentException();
		}
	}

	public static long findFloats (Buffer vertex, int strideInBytes, Buffer vertices, int numVertices) {
		return find(vertex, positionInBytes(vertex), strideInBytes, vertices, positionInBytes(vertices), numVertices);
	}

	public static long findFloats (float[] vertex, int strideInBytes, Buffer vertices, int numVertices) {
		return find(vertex, 0, strideInBytes, vertices, positionInBytes(vertices), numVertices);
	}

	public static long findFloats (Buffer vertex, int strideInBytes, float[] vertices, int numVertices) {
		return find(vertex, positionInBytes(vertex), strideInBytes, vertices, 0, numVertices);
	}

	public static long findFloats (float[] vertex, int strideInBytes, float[] vertices, int numVertices) {
		return find(vertex, 0, strideInBytes, vertices, 0, numVertices);
	}

	public static long findFloats (Buffer vertex, int strideInBytes, Buffer vertices, int numVertices, float epsilon) {
		return find(vertex, positionInBytes(vertex), strideInBytes, vertices, positionInBytes(vertices), numVertices, epsilon);
	}

	public static long findFloats (float[] vertex, int strideInBytes, Buffer vertices, int numVertices, float epsilon) {
		return find(vertex, 0, strideInBytes, vertices, positionInBytes(vertices), numVertices, epsilon);
	}

	public static long findFloats (Buffer vertex, int strideInBytes, float[] vertices, int numVertices, float epsilon) {
		return find(vertex, positionInBytes(vertex), strideInBytes, vertices, 0, numVertices, epsilon);
	}

	public static long findFloats (float[] vertex, int strideInBytes, float[] vertices, int numVertices, float epsilon) {
		return find(vertex, 0, strideInBytes, vertices, 0, numVertices, epsilon);
	}

	private static int positionInBytes (Buffer dst) {
		if (dst instanceof ByteBuffer)
			return dst.position();
		else if (dst instanceof ShortBuffer)
			return dst.position() << 1;
		else if (dst instanceof CharBuffer)
			return dst.position() << 1;
		else if (dst instanceof IntBuffer)
			return dst.position() << 2;
		else if (dst instanceof LongBuffer)
			return dst.position() << 3;
		else if (dst instanceof FloatBuffer)
			return dst.position() << 2;
		else if (dst instanceof DoubleBuffer)
			return dst.position() << 3;
		else
			throw new GdxRuntimeException("Can't copy to a " + dst.getClass().getName() + " instance");
	}

	private static int bytesToElements (Buffer dst, int bytes) {
		if (dst instanceof ByteBuffer)
			return bytes;
		else if (dst instanceof ShortBuffer)
			return bytes >>> 1;
		else if (dst instanceof CharBuffer)
			return bytes >>> 1;
		else if (dst instanceof IntBuffer)
			return bytes >>> 2;
		else if (dst instanceof LongBuffer)
			return bytes >>> 3;
		else if (dst instanceof FloatBuffer)
			return bytes >>> 2;
		else if (dst instanceof DoubleBuffer)
			return bytes >>> 3;
		else
			throw new GdxRuntimeException("Can't copy to a " + dst.getClass().getName() + " instance");
	}

	private static int elementsToBytes (Buffer dst, int elements) {
		if (dst instanceof ByteBuffer)
			return elements;
		else if (dst instanceof ShortBuffer)
			return elements << 1;
		else if (dst instanceof CharBuffer)
			return elements << 1;
		else if (dst instanceof IntBuffer)
			return elements << 2;
		else if (dst instanceof LongBuffer)
			return elements << 3;
		else if (dst instanceof FloatBuffer)
			return elements << 2;
		else if (dst instanceof DoubleBuffer)
			return elements << 3;
		else
			throw new GdxRuntimeException("Can't copy to a " + dst.getClass().getName() + " instance");
	}

	public static FloatBuffer newFloatBuffer (int numFloats) {
		ByteBuffer buffer = ByteBuffer.allocateDirect(numFloats * 4);
		buffer.order(ByteOrder.nativeOrder());
		return buffer.asFloatBuffer();
	}

	public static DoubleBuffer newDoubleBuffer (int numDoubles) {
		ByteBuffer buffer = ByteBuffer.allocateDirect(numDoubles * 8);
		buffer.order(ByteOrder.nativeOrder());
		return buffer.asDoubleBuffer();
	}

	public static ByteBuffer newByteBuffer (int numBytes) {
		ByteBuffer buffer = ByteBuffer.allocateDirect(numBytes);
		buffer.order(ByteOrder.nativeOrder());
		return buffer;
	}

	public static ShortBuffer newShortBuffer (int numShorts) {
		ByteBuffer buffer = ByteBuffer.allocateDirect(numShorts * 2);
		buffer.order(ByteOrder.nativeOrder());
		return buffer.asShortBuffer();
	}

	public static CharBuffer newCharBuffer (int numChars) {
		ByteBuffer buffer = ByteBuffer.allocateDirect(numChars * 2);
		buffer.order(ByteOrder.nativeOrder());
		return buffer.asCharBuffer();
	}

	public static IntBuffer newIntBuffer (int numInts) {
		ByteBuffer buffer = ByteBuffer.allocateDirect(numInts * 4);
		buffer.order(ByteOrder.nativeOrder());
		return buffer.asIntBuffer();
	}

	public static LongBuffer newLongBuffer (int numLongs) {
		ByteBuffer buffer = ByteBuffer.allocateDirect(numLongs * 8);
		buffer.order(ByteOrder.nativeOrder());
		return buffer.asLongBuffer();
	}

	// @off
	/*JNI 
	#include 
	#include 
	#include 
	*/
	
	public static void disposeUnsafeByteBuffer(ByteBuffer buffer) {
		int size = buffer.capacity(); 
		synchronized(unsafeBuffers) {
			if(!unsafeBuffers.removeValue(buffer, true))
				throw new IllegalArgumentException("buffer not allocated with newUnsafeByteBuffer or already disposed");
		}
		allocatedUnsafe -= size;
		freeMemory(buffer);
	}

	/** Allocates a new direct ByteBuffer from native heap memory using the native byte order. Needs to be disposed with
	 * {@link #freeMemory(ByteBuffer)}.
	 * @param numBytes */
	public static ByteBuffer newUnsafeByteBuffer (int numBytes) {
		ByteBuffer buffer = newDisposableByteBuffer(numBytes);
		buffer.order(ByteOrder.nativeOrder());
		allocatedUnsafe += numBytes;
		synchronized(unsafeBuffers) {
			unsafeBuffers.add(buffer);
		}
		return buffer;
	}
	
	/**
	 * Returns the address of the Buffer, it assumes it is an unsafe buffer.
	 * @param buffer The Buffer to ask the address for.
	 * @return the address of the Buffer.
	 */
	public static long getUnsafeBufferAddress(Buffer buffer) {
		return getBufferAddress(buffer) + buffer.position();
	}
	
	/**
	 * Registers the given ByteBuffer as an unsafe ByteBuffer. The ByteBuffer must have been 
	 * allocated in native code, pointing to a memory region allocated via malloc. Needs to 
	 * be disposed with {@link #freeMemory(ByteBuffer)}.
	 * @param buffer the {@link ByteBuffer} to register
	 * @return the ByteBuffer passed to the method
	 */
	public static ByteBuffer newUnsafeByteBuffer(ByteBuffer buffer) {
		allocatedUnsafe += buffer.capacity();
		synchronized(unsafeBuffers) {
			unsafeBuffers.add(buffer);
		}
		return buffer;
	}

	/**
	 * @return the number of bytes allocated with {@link #newUnsafeByteBuffer(int)}
	 */
	public static int getAllocatedBytesUnsafe() {
		return allocatedUnsafe;
	}
	
	/** Frees the memory allocated for the ByteBuffer. DO NOT USE THIS ON BYTEBUFFERS ALLOCATEd VIA METHODS IN THIS CLASS OR
	 * ByteBuffer.allocateDirect()! IT WILL EXPLODE! */
	private static native void freeMemory (ByteBuffer buffer); /*
		free(buffer);
	 */
	
	private static native ByteBuffer newDisposableByteBuffer (int numBytes); /*
		return env->NewDirectByteBuffer((char*)malloc(numBytes), numBytes);
	*/
	
	private static native long getBufferAddress (Buffer buffer); /*
	    return (jlong) buffer;
	*/
	
	/** Writes the specified number of zeros to the buffer. This is generally faster than reallocating a new buffer. */
	public static native void clear (ByteBuffer buffer, int numBytes); /*
		memset(buffer, 0, numBytes);
	*/
	
	private native static void copyJni (float[] src, Buffer dst, int numFloats, int offset); /*
		memcpy(dst, src + offset, numFloats << 2 );
	*/

	private native static void copyJni (byte[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /*
		memcpy(dst + dstOffset, src + srcOffset, numBytes);
	*/

	private native static void copyJni (char[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /*
		memcpy(dst + dstOffset, src + srcOffset, numBytes);
	*/

	private native static void copyJni (short[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /*
		memcpy(dst + dstOffset, src + srcOffset, numBytes);
	 */

	private native static void copyJni (int[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /*
		memcpy(dst + dstOffset, src + srcOffset, numBytes);
	*/
	
	private native static void copyJni (long[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /*
		memcpy(dst + dstOffset, src + srcOffset, numBytes);
	*/

	private native static void copyJni (float[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /*
		memcpy(dst + dstOffset, src + srcOffset, numBytes);
	*/
	
	private native static void copyJni (double[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /*
		memcpy(dst + dstOffset, src + srcOffset, numBytes);
	*/

	private native static void copyJni (Buffer src, int srcOffset, Buffer dst, int dstOffset, int numBytes); /*
		memcpy(dst + dstOffset, src + srcOffset, numBytes);
	*/
	
	/*JNI
	template void transform(float * const &src, float * const &m, float * const &dst) {}
	
	template<> inline void transform<4, 4>(float * const &src, float * const &m, float * const &dst) {
		const float x = src[0], y = src[1], z = src[2], w = src[3];
		dst[0] = x * m[ 0] + y * m[ 4] + z * m[ 8] + w * m[12]; 
		dst[1] = x * m[ 1] + y * m[ 5] + z * m[ 9] + w * m[13];
		dst[2] = x * m[ 2] + y * m[ 6] + z * m[10] + w * m[14];
		dst[3] = x * m[ 3] + y * m[ 7] + z * m[11] + w * m[15]; 
	}
	
	template<> inline void transform<3, 4>(float * const &src, float * const &m, float * const &dst) {
		const float x = src[0], y = src[1], z = src[2];
		dst[0] = x * m[ 0] + y * m[ 4] + z * m[ 8] + m[12]; 
		dst[1] = x * m[ 1] + y * m[ 5] + z * m[ 9] + m[13];
		dst[2] = x * m[ 2] + y * m[ 6] + z * m[10] + m[14]; 
	}
	
	template<> inline void transform<2, 4>(float * const &src, float * const &m, float * const &dst) {
		const float x = src[0], y = src[1];
		dst[0] = x * m[ 0] + y * m[ 4] + m[12]; 
		dst[1] = x * m[ 1] + y * m[ 5] + m[13]; 
	}
	
	template<> inline void transform<3, 3>(float * const &src, float * const &m, float * const &dst) {
		const float x = src[0], y = src[1], z = src[2];
		dst[0] = x * m[0] + y * m[3] + z * m[6]; 
		dst[1] = x * m[1] + y * m[4] + z * m[7];
		dst[2] = x * m[2] + y * m[5] + z * m[8]; 
	}
	
	template<> inline void transform<2, 3>(float * const &src, float * const &m, float * const &dst) {
		const float x = src[0], y = src[1];
		dst[0] = x * m[0] + y * m[3] + m[6]; 
		dst[1] = x * m[1] + y * m[4] + m[7]; 
	}
	
	template void transform(float * const &v, int const &stride, int const &count, float * const &m, int offset) {
		for (int i = 0; i < count; i++) {
			transform(&v[offset], m, &v[offset]);
			offset += stride;
		}
	}
	
	template void transform(float * const &v, int const &stride, unsigned short * const &indices, int const &count, float * const &m, int offset) {
		for (int i = 0; i < count; i++) {
			transform(&v[offset], m, &v[offset]);
			offset += stride;
		}
	}
	
	inline bool compare(float * const &lhs, float * const & rhs, const unsigned int &size, const float &epsilon) {
   	for (unsigned int i = 0; i < size; i++)
   		if ((*(unsigned int*)&lhs[i] != *(unsigned int*)&rhs[i]) && ((lhs[i] > rhs[i] ? lhs[i] - rhs[i] : rhs[i] - lhs[i]) > epsilon))
         	return false;
		return true;
	}
	
	long find(float * const &vertex, const unsigned int &size, float * const &vertices, const unsigned int &count, const float &epsilon) {
		for (unsigned int i = 0; i < count; i++)
			if (compare(&vertices[i*size], vertex, size, epsilon))
				return (long)i;
		return -1;
	}

	inline bool compare(float * const &lhs, float * const & rhs, const unsigned int &size) {
   	for (unsigned int i = 0; i < size; i++)
      	if ((*(unsigned int*)&lhs[i] != *(unsigned int*)&rhs[i]) && lhs[i] != rhs[i])
         	return false;
		return true;
	}
	
	long find(float * const &vertex, const unsigned int &size, float * const &vertices, const unsigned int &count) {
		for (unsigned int i = 0; i < count; i++)
			if (compare(&vertices[i*size], vertex, size))
				return (long)i;
		return -1;
	}

	inline unsigned int calcHash(float * const &vertex, const unsigned int &size) {
		unsigned int result = 0;
		for (unsigned int i = 0; i < size; ++i)
			result += ((*((unsigned int *)&vertex[i])) & 0xffffff80) >> (i & 0x7);
		return result & 0x7fffffff;
	}
	
	long find(float * const &vertex, const unsigned int &size, float * const &vertices, unsigned int * const &hashes, const unsigned int &count) {
		const unsigned int hash = calcHash(vertex, size);
		for (unsigned int i = 0; i < count; i++)
			if (hashes[i] == hash && compare(&vertices[i*size], vertex, size))
				return (long)i;
		return -1;
	}
	*/
	
	private native static void transformV4M4Jni (Buffer data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /*
		transform<4, 4>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4);  
	*/
	
	private native static void transformV4M4Jni (float[] data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /*
		transform<4, 4>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4);  
	*/
	
	private native static void transformV3M4Jni (Buffer data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /*
		transform<3, 4>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4);
	*/
	
	private native static void transformV3M4Jni (float[] data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /*
		transform<3, 4>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4);
	*/
	
	private native static void transformV2M4Jni (Buffer data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /*
		transform<2, 4>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4);
	*/
	
	private native static void transformV2M4Jni (float[] data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /*
		transform<2, 4>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4);
	*/

	private native static void transformV3M3Jni (Buffer data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /*
		transform<3, 3>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4);
	*/
	
	private native static void transformV3M3Jni (float[] data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /*
		transform<3, 3>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4);
	*/
	
	private native static void transformV2M3Jni (Buffer data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /*
		transform<2, 3>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4);
	*/
	
	private native static void transformV2M3Jni (float[] data, int strideInBytes, int count, float[] matrix, int offsetInBytes); /*
		transform<2, 3>((float*)data, strideInBytes / 4, count, (float*)matrix, offsetInBytes / 4);
	*/
	
	private native static long find(Buffer vertex, int vertexOffsetInBytes, int strideInBytes, Buffer vertices, int verticesOffsetInBytes, int numVertices); /*
		return find((float *)&vertex[vertexOffsetInBytes / 4], (unsigned int)(strideInBytes / 4), (float*)&vertices[verticesOffsetInBytes / 4], (unsigned int)numVertices);
	*/
	
	private native static long find(float[] vertex, int vertexOffsetInBytes, int strideInBytes, Buffer vertices, int verticesOffsetInBytes, int numVertices); /*
		return find((float *)&vertex[vertexOffsetInBytes / 4], (unsigned int)(strideInBytes / 4), (float*)&vertices[verticesOffsetInBytes / 4], (unsigned int)numVertices);
	*/
	
	private native static long find(Buffer vertex, int vertexOffsetInBytes, int strideInBytes, float[] vertices, int verticesOffsetInBytes, int numVertices); /*
		return find((float *)&vertex[vertexOffsetInBytes / 4], (unsigned int)(strideInBytes / 4), (float*)&vertices[verticesOffsetInBytes / 4], (unsigned int)numVertices);
	*/
	
	private native static long find(float[] vertex, int vertexOffsetInBytes, int strideInBytes, float[] vertices, int verticesOffsetInBytes, int numVertices); /*
		return find((float *)&vertex[vertexOffsetInBytes / 4], (unsigned int)(strideInBytes / 4), (float*)&vertices[verticesOffsetInBytes / 4], (unsigned int)numVertices);
	*/
	
	private native static long find(Buffer vertex, int vertexOffsetInBytes, int strideInBytes, Buffer vertices, int verticesOffsetInBytes, int numVertices, float epsilon); /*
		return find((float *)&vertex[vertexOffsetInBytes / 4], (unsigned int)(strideInBytes / 4), (float*)&vertices[verticesOffsetInBytes / 4], (unsigned int)numVertices, epsilon);
	*/
	
	private native static long find(float[] vertex, int vertexOffsetInBytes, int strideInBytes, Buffer vertices, int verticesOffsetInBytes, int numVertices, float epsilon); /*
		return find((float *)&vertex[vertexOffsetInBytes / 4], (unsigned int)(strideInBytes / 4), (float*)&vertices[verticesOffsetInBytes / 4], (unsigned int)numVertices, epsilon);
	*/
	
	private native static long find(Buffer vertex, int vertexOffsetInBytes, int strideInBytes, float[] vertices, int verticesOffsetInBytes, int numVertices, float epsilon); /*
		return find((float *)&vertex[vertexOffsetInBytes / 4], (unsigned int)(strideInBytes / 4), (float*)&vertices[verticesOffsetInBytes / 4], (unsigned int)numVertices, epsilon);
	*/
	
	private native static long find(float[] vertex, int vertexOffsetInBytes, int strideInBytes, float[] vertices, int verticesOffsetInBytes, int numVertices, float epsilon); /*
		return find((float *)&vertex[vertexOffsetInBytes / 4], (unsigned int)(strideInBytes / 4), (float*)&vertices[verticesOffsetInBytes / 4], (unsigned int)numVertices, epsilon);
	*/
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy