/* * Java port of Bullet (c) 2008 Martin Dvorak <jezek2@advel.cz> * * Bullet Continuous Collision Detection and Physics Library * Copyright (c) 2003-2008 Erwin Coumans http://www.bulletphysics.com/ * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ package com.bulletphysics.collision.shapes; import java.io.Serializable; /** * QuantizedBvhNodes is array of compressed AABB nodes, each of 16 bytes. * Node can be used for leaf node or internal node. Leaf nodes can point to 32-bit * triangle index (non-negative range).<p> * * <i>Implementation note:</i> the nodes are internally stored in int[] array * and bit packed. The actual structure is: * * <pre> * unsigned short quantizedAabbMin[3] * unsigned short quantizedAabbMax[3] * signed int escapeIndexOrTriangleIndex * </pre> * * @author jezek2 */ public class QuantizedBvhNodes implements Serializable { private static final long serialVersionUID = 1L; private static final int STRIDE = 4; // 16 bytes private int[] buf; private int size = 0; public QuantizedBvhNodes() { resize(16); } public int add() { while (size+1 >= capacity()) { resize(capacity()*2); } return size++; } public int size() { return size; } public int capacity() { return buf.length / STRIDE; } public void clear() { size = 0; } public void resize(int num) { int[] oldBuf = buf; buf = new int[num*STRIDE]; if (oldBuf != null) { System.arraycopy(oldBuf, 0, buf, 0, Math.min(oldBuf.length, buf.length)); } } public static int getNodeSize() { return STRIDE*4; } public void set(int destId, QuantizedBvhNodes srcNodes, int srcId) { assert (STRIDE == 4); // save field access: int[] buf = this.buf; int[] srcBuf = srcNodes.buf; buf[destId*STRIDE+0] = srcBuf[srcId*STRIDE+0]; buf[destId*STRIDE+1] = srcBuf[srcId*STRIDE+1]; buf[destId*STRIDE+2] = srcBuf[srcId*STRIDE+2]; buf[destId*STRIDE+3] = srcBuf[srcId*STRIDE+3]; } public void swap(int id1, int id2) { assert (STRIDE == 4); // save field access: int[] buf = this.buf; int temp0 = buf[id1*STRIDE+0]; int temp1 = buf[id1*STRIDE+1]; int temp2 = buf[id1*STRIDE+2]; int temp3 = buf[id1*STRIDE+3]; buf[id1*STRIDE+0] = buf[id2*STRIDE+0]; buf[id1*STRIDE+1] = buf[id2*STRIDE+1]; buf[id1*STRIDE+2] = buf[id2*STRIDE+2]; buf[id1*STRIDE+3] = buf[id2*STRIDE+3]; buf[id2*STRIDE+0] = temp0; buf[id2*STRIDE+1] = temp1; buf[id2*STRIDE+2] = temp2; buf[id2*STRIDE+3] = temp3; } public int getQuantizedAabbMin(int nodeId, int index) { switch (index) { default: case 0: return (buf[nodeId*STRIDE+0]) & 0xFFFF; case 1: return (buf[nodeId*STRIDE+0] >>> 16) & 0xFFFF; case 2: return (buf[nodeId*STRIDE+1]) & 0xFFFF; } } public long getQuantizedAabbMin(int nodeId) { return (buf[nodeId*STRIDE+0] & 0xFFFFFFFFL) | ((buf[nodeId*STRIDE+1] & 0xFFFFL) << 32); } public void setQuantizedAabbMin(int nodeId, long value) { buf[nodeId*STRIDE+0] = (int)value; setQuantizedAabbMin(nodeId, 2, (short)((value & 0xFFFF00000000L) >>> 32)); } public void setQuantizedAabbMax(int nodeId, long value) { setQuantizedAabbMax(nodeId, 0, (short)value); buf[nodeId*STRIDE+2] = (int)(value >>> 16); } public void setQuantizedAabbMin(int nodeId, int index, int value) { switch (index) { case 0: buf[nodeId*STRIDE+0] = (buf[nodeId*STRIDE+0] & 0xFFFF0000) | (value & 0xFFFF); break; case 1: buf[nodeId*STRIDE+0] = (buf[nodeId*STRIDE+0] & 0x0000FFFF) | ((value & 0xFFFF) << 16); break; case 2: buf[nodeId*STRIDE+1] = (buf[nodeId*STRIDE+1] & 0xFFFF0000) | (value & 0xFFFF); break; } } public int getQuantizedAabbMax(int nodeId, int index) { switch (index) { default: case 0: return (buf[nodeId*STRIDE+1] >>> 16) & 0xFFFF; case 1: return (buf[nodeId*STRIDE+2]) & 0xFFFF; case 2: return (buf[nodeId*STRIDE+2] >>> 16) & 0xFFFF; } } public long getQuantizedAabbMax(int nodeId) { return ((buf[nodeId*STRIDE+1] & 0xFFFF0000L) >>> 16) | ((buf[nodeId*STRIDE+2] & 0xFFFFFFFFL) << 16); } public void setQuantizedAabbMax(int nodeId, int index, int value) { switch (index) { case 0: buf[nodeId*STRIDE+1] = (buf[nodeId*STRIDE+1] & 0x0000FFFF) | ((value & 0xFFFF) << 16); break; case 1: buf[nodeId*STRIDE+2] = (buf[nodeId*STRIDE+2] & 0xFFFF0000) | (value & 0xFFFF); break; case 2: buf[nodeId*STRIDE+2] = (buf[nodeId*STRIDE+2] & 0x0000FFFF) | ((value & 0xFFFF) << 16); break; } } public int getEscapeIndexOrTriangleIndex(int nodeId) { return buf[nodeId*STRIDE+3]; } public void setEscapeIndexOrTriangleIndex(int nodeId, int value) { buf[nodeId*STRIDE+3] = value; } public boolean isLeafNode(int nodeId) { // skipindex is negative (internal node), triangleindex >=0 (leafnode) return (getEscapeIndexOrTriangleIndex(nodeId) >= 0); } public int getEscapeIndex(int nodeId) { assert (!isLeafNode(nodeId)); return -getEscapeIndexOrTriangleIndex(nodeId); } public int getTriangleIndex(int nodeId) { assert (isLeafNode(nodeId)); // Get only the lower bits where the triangle index is stored return (getEscapeIndexOrTriangleIndex(nodeId) & ~((~0) << (31 - OptimizedBvh.MAX_NUM_PARTS_IN_BITS))); } public int getPartId(int nodeId) { assert (isLeafNode(nodeId)); // Get only the highest bits where the part index is stored return (getEscapeIndexOrTriangleIndex(nodeId) >>> (31 - OptimizedBvh.MAX_NUM_PARTS_IN_BITS)); } public static int getCoord(long vec, int index) { switch (index) { default: case 0: return (int)((vec & 0x00000000FFFFL)) & 0xFFFF; case 1: return (int)((vec & 0x0000FFFF0000L) >>> 16) & 0xFFFF; case 2: return (int)((vec & 0xFFFF00000000L) >>> 32) & 0xFFFF; } } }