/*
|
* 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.linearmath;
|
|
import cz.advel.stack.Stack;
|
import javax.vecmath.Matrix3f;
|
import javax.vecmath.Vector3f;
|
|
/**
|
* Utility functions for axis aligned bounding boxes (AABB).
|
*
|
* @author jezek2
|
*/
|
public class AabbUtil2 {
|
|
public static void aabbExpand(Vector3f aabbMin, Vector3f aabbMax, Vector3f expansionMin, Vector3f expansionMax) {
|
aabbMin.add(expansionMin);
|
aabbMax.add(expansionMax);
|
}
|
|
public static int outcode(Vector3f p, Vector3f halfExtent) {
|
return (p.x < -halfExtent.x ? 0x01 : 0x0) |
|
(p.x > halfExtent.x ? 0x08 : 0x0) |
|
(p.y < -halfExtent.y ? 0x02 : 0x0) |
|
(p.y > halfExtent.y ? 0x10 : 0x0) |
|
(p.z < -halfExtent.z ? 0x4 : 0x0) |
|
(p.z > halfExtent.z ? 0x20 : 0x0);
|
}
|
|
public static boolean rayAabb(Vector3f rayFrom, Vector3f rayTo, Vector3f aabbMin, Vector3f aabbMax, float[] param, Vector3f normal) {
|
Vector3f aabbHalfExtent = Stack.alloc(Vector3f.class);
|
Vector3f aabbCenter = Stack.alloc(Vector3f.class);
|
Vector3f source = Stack.alloc(Vector3f.class);
|
Vector3f target = Stack.alloc(Vector3f.class);
|
Vector3f r = Stack.alloc(Vector3f.class);
|
Vector3f hitNormal = Stack.alloc(Vector3f.class);
|
|
aabbHalfExtent.sub(aabbMax, aabbMin);
|
aabbHalfExtent.scale(0.5f);
|
|
aabbCenter.add(aabbMax, aabbMin);
|
aabbCenter.scale(0.5f);
|
|
source.sub(rayFrom, aabbCenter);
|
target.sub(rayTo, aabbCenter);
|
|
int sourceOutcode = outcode(source, aabbHalfExtent);
|
int targetOutcode = outcode(target, aabbHalfExtent);
|
if ((sourceOutcode & targetOutcode) == 0x0) {
|
float lambda_enter = 0f;
|
float lambda_exit = param[0];
|
r.sub(target, source);
|
|
float normSign = 1f;
|
hitNormal.set(0f, 0f, 0f);
|
int bit = 1;
|
|
for (int j = 0; j < 2; j++) {
|
for (int i = 0; i != 3; ++i) {
|
if ((sourceOutcode & bit) != 0) {
|
float lambda = (-VectorUtil.getCoord(source, i) - VectorUtil.getCoord(aabbHalfExtent, i) * normSign) / VectorUtil.getCoord(r, i);
|
if (lambda_enter <= lambda) {
|
lambda_enter = lambda;
|
hitNormal.set(0f, 0f, 0f);
|
VectorUtil.setCoord(hitNormal, i, normSign);
|
}
|
}
|
else if ((targetOutcode & bit) != 0) {
|
float lambda = (-VectorUtil.getCoord(source, i) - VectorUtil.getCoord(aabbHalfExtent, i) * normSign) / VectorUtil.getCoord(r, i);
|
//btSetMin(lambda_exit, lambda);
|
lambda_exit = Math.min(lambda_exit, lambda);
|
}
|
bit <<= 1;
|
}
|
normSign = -1f;
|
}
|
if (lambda_enter <= lambda_exit) {
|
param[0] = lambda_enter;
|
normal.set(hitNormal);
|
return true;
|
}
|
}
|
return false;
|
}
|
|
/**
|
* Conservative test for overlap between two AABBs.
|
*/
|
public static boolean testAabbAgainstAabb2(Vector3f aabbMin1, Vector3f aabbMax1, Vector3f aabbMin2, Vector3f aabbMax2) {
|
boolean overlap = true;
|
overlap = (aabbMin1.x > aabbMax2.x || aabbMax1.x < aabbMin2.x) ? false : overlap;
|
overlap = (aabbMin1.z > aabbMax2.z || aabbMax1.z < aabbMin2.z) ? false : overlap;
|
overlap = (aabbMin1.y > aabbMax2.y || aabbMax1.y < aabbMin2.y) ? false : overlap;
|
return overlap;
|
}
|
|
/**
|
* Conservative test for overlap between triangle and AABB.
|
*/
|
public static boolean testTriangleAgainstAabb2(Vector3f[] vertices, Vector3f aabbMin, Vector3f aabbMax) {
|
Vector3f p1 = vertices[0];
|
Vector3f p2 = vertices[1];
|
Vector3f p3 = vertices[2];
|
|
if (Math.min(Math.min(p1.x, p2.x), p3.x) > aabbMax.x) return false;
|
if (Math.max(Math.max(p1.x, p2.x), p3.x) < aabbMin.x) return false;
|
|
if (Math.min(Math.min(p1.z, p2.z), p3.z) > aabbMax.z) return false;
|
if (Math.max(Math.max(p1.z, p2.z), p3.z) < aabbMin.z) return false;
|
|
if (Math.min(Math.min(p1.y, p2.y), p3.y) > aabbMax.y) return false;
|
if (Math.max(Math.max(p1.y, p2.y), p3.y) < aabbMin.y) return false;
|
|
return true;
|
}
|
|
public static void transformAabb(Vector3f halfExtents, float margin, Transform t, Vector3f aabbMinOut, Vector3f aabbMaxOut) {
|
Vector3f halfExtentsWithMargin = Stack.alloc(Vector3f.class);
|
halfExtentsWithMargin.x = halfExtents.x + margin;
|
halfExtentsWithMargin.y = halfExtents.y + margin;
|
halfExtentsWithMargin.z = halfExtents.z + margin;
|
|
Matrix3f abs_b = (Matrix3f) Stack.alloc(t.basis);
|
MatrixUtil.absolute(abs_b);
|
|
Vector3f tmp = Stack.alloc(Vector3f.class);
|
|
Vector3f center = (Vector3f) Stack.alloc(t.origin);
|
Vector3f extent = Stack.alloc(Vector3f.class);
|
abs_b.getRow(0, tmp);
|
extent.x = tmp.dot(halfExtentsWithMargin);
|
abs_b.getRow(1, tmp);
|
extent.y = tmp.dot(halfExtentsWithMargin);
|
abs_b.getRow(2, tmp);
|
extent.z = tmp.dot(halfExtentsWithMargin);
|
|
aabbMinOut.sub(center, extent);
|
aabbMaxOut.add(center, extent);
|
}
|
|
public static void transformAabb(Vector3f localAabbMin, Vector3f localAabbMax, float margin, Transform trans, Vector3f aabbMinOut, Vector3f aabbMaxOut) {
|
assert (localAabbMin.x <= localAabbMax.x);
|
assert (localAabbMin.y <= localAabbMax.y);
|
assert (localAabbMin.z <= localAabbMax.z);
|
|
Vector3f localHalfExtents = Stack.alloc(Vector3f.class);
|
localHalfExtents.sub(localAabbMax, localAabbMin);
|
localHalfExtents.scale(0.5f);
|
|
localHalfExtents.x += margin;
|
localHalfExtents.y += margin;
|
localHalfExtents.z += margin;
|
|
Vector3f localCenter = Stack.alloc(Vector3f.class);
|
localCenter.add(localAabbMax, localAabbMin);
|
localCenter.scale(0.5f);
|
|
Matrix3f abs_b = (Matrix3f) Stack.alloc(trans.basis);
|
MatrixUtil.absolute(abs_b);
|
|
Vector3f center = (Vector3f) Stack.alloc(localCenter);
|
trans.transform(center);
|
|
Vector3f extent = Stack.alloc(Vector3f.class);
|
Vector3f tmp = Stack.alloc(Vector3f.class);
|
|
abs_b.getRow(0, tmp);
|
extent.x = tmp.dot(localHalfExtents);
|
abs_b.getRow(1, tmp);
|
extent.y = tmp.dot(localHalfExtents);
|
abs_b.getRow(2, tmp);
|
extent.z = tmp.dot(localHalfExtents);
|
|
aabbMinOut.sub(center, extent);
|
aabbMaxOut.add(center, extent);
|
}
|
|
}
|