/*
|
* 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;
|
}
|
}
|
|
}
|