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