/*
* 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 com.bulletphysics.linearmath.AabbUtil2;
import com.bulletphysics.linearmath.Transform;
import com.bulletphysics.linearmath.VectorUtil;
import cz.advel.stack.Stack;
import javax.vecmath.Vector3f;
/**
* PolyhedralConvexShape is an internal interface class for polyhedral convex shapes.
*
* @author jezek2
*/
public abstract class PolyhedralConvexShape extends ConvexInternalShape {
private static Vector3f[] _directions = new Vector3f[] {
new Vector3f( 1f, 0f, 0f),
new Vector3f( 0f, 1f, 0f),
new Vector3f( 0f, 0f, 1f),
new Vector3f(-1f, 0f, 0f),
new Vector3f( 0f, -1f, 0f),
new Vector3f( 0f, 0f, -1f)
};
private static Vector3f[] _supporting = new Vector3f[] {
new Vector3f(0f, 0f, 0f),
new Vector3f(0f, 0f, 0f),
new Vector3f(0f, 0f, 0f),
new Vector3f(0f, 0f, 0f),
new Vector3f(0f, 0f, 0f),
new Vector3f(0f, 0f, 0f)
};
protected final Vector3f localAabbMin = new Vector3f(1f, 1f, 1f);
protected final Vector3f localAabbMax = new Vector3f(-1f, -1f, -1f);
protected boolean isLocalAabbValid = false;
// /** optional Hull is for optional Separating Axis Test Hull collision detection, see Hull.cpp */
// public Hull optionalHull = null;
@Override
public Vector3f localGetSupportingVertexWithoutMargin(Vector3f vec0, Vector3f out) {
int i;
Vector3f supVec = out;
supVec.set(0f, 0f, 0f);
float maxDot = -1e30f;
Vector3f vec = Stack.alloc(vec0);
float lenSqr = vec.lengthSquared();
if (lenSqr < 0.0001f) {
vec.set(1f, 0f, 0f);
}
else {
float rlen = 1f / (float) Math.sqrt(lenSqr);
vec.scale(rlen);
}
Vector3f vtx = Stack.alloc(Vector3f.class);
float newDot;
for (i = 0; i < getNumVertices(); i++) {
getVertex(i, vtx);
newDot = vec.dot(vtx);
if (newDot > maxDot) {
maxDot = newDot;
supVec = vtx;
}
}
return out;
}
@Override
public void batchedUnitVectorGetSupportingVertexWithoutMargin(Vector3f[] vectors, Vector3f[] supportVerticesOut, int numVectors) {
int i;
Vector3f vtx = Stack.alloc(Vector3f.class);
float newDot;
// JAVA NOTE: rewritten as code used W coord for temporary usage in Vector3
// TODO: optimize it
float[] wcoords = new float[numVectors];
for (i = 0; i < numVectors; i++) {
// TODO: used w in vector3:
//supportVerticesOut[i].w = -1e30f;
wcoords[i] = -1e30f;
}
for (int j = 0; j < numVectors; j++) {
Vector3f vec = vectors[j];
for (i = 0; i < getNumVertices(); i++) {
getVertex(i, vtx);
newDot = vec.dot(vtx);
//if (newDot > supportVerticesOut[j].w)
if (newDot > wcoords[j]) {
//WARNING: don't swap next lines, the w component would get overwritten!
supportVerticesOut[j].set(vtx);
//supportVerticesOut[j].w = newDot;
wcoords[j] = newDot;
}
}
}
}
@Override
public void calculateLocalInertia(float mass, Vector3f inertia) {
// not yet, return box inertia
float margin = getMargin();
Transform ident = Stack.alloc(Transform.class);
ident.setIdentity();
Vector3f aabbMin = Stack.alloc(Vector3f.class), aabbMax = Stack.alloc(Vector3f.class);
getAabb(ident, aabbMin, aabbMax);
Vector3f halfExtents = Stack.alloc(Vector3f.class);
halfExtents.sub(aabbMax, aabbMin);
halfExtents.scale(0.5f);
float lx = 2f * (halfExtents.x + margin);
float ly = 2f * (halfExtents.y + margin);
float lz = 2f * (halfExtents.z + margin);
float x2 = lx * lx;
float y2 = ly * ly;
float z2 = lz * lz;
float scaledmass = mass * 0.08333333f;
inertia.set(y2 + z2, x2 + z2, x2 + y2);
inertia.scale(scaledmass);
}
private void getNonvirtualAabb(Transform trans, Vector3f aabbMin, Vector3f aabbMax, float margin) {
// lazy evaluation of local aabb
assert (isLocalAabbValid);
AabbUtil2.transformAabb(localAabbMin, localAabbMax, margin, trans, aabbMin, aabbMax);
}
@Override
public void getAabb(Transform trans, Vector3f aabbMin, Vector3f aabbMax) {
getNonvirtualAabb(trans, aabbMin, aabbMax, getMargin());
}
protected final void _PolyhedralConvexShape_getAabb(Transform trans, Vector3f aabbMin, Vector3f aabbMax) {
getNonvirtualAabb(trans, aabbMin, aabbMax, getMargin());
}
public void recalcLocalAabb() {
isLocalAabbValid = true;
//#if 1
batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6);
for (int i=0; i<3; i++) {
VectorUtil.setCoord(localAabbMax, i, VectorUtil.getCoord(_supporting[i], i) + collisionMargin);
VectorUtil.setCoord(localAabbMin, i, VectorUtil.getCoord(_supporting[i + 3], i) - collisionMargin);
}
//#else
//for (int i=0; i<3; i++) {
// Vector3f vec = Stack.alloc(Vector3f.class);
// vec.set(0f, 0f, 0f);
// VectorUtil.setCoord(vec, i, 1f);
// Vector3f tmp = localGetSupportingVertex(vec, Stack.alloc(Vector3f.class));
// VectorUtil.setCoord(localAabbMax, i, VectorUtil.getCoord(tmp, i) + collisionMargin);
// VectorUtil.setCoord(vec, i, -1f);
// localGetSupportingVertex(vec, tmp);
// VectorUtil.setCoord(localAabbMin, i, VectorUtil.getCoord(tmp, i) - collisionMargin);
//}
//#endif
}
@Override
public void setLocalScaling(Vector3f scaling) {
super.setLocalScaling(scaling);
recalcLocalAabb();
}
public abstract int getNumVertices();
public abstract int getNumEdges();
public abstract void getEdge(int i, Vector3f pa, Vector3f pb);
public abstract void getVertex(int i, Vector3f vtx);
public abstract int getNumPlanes();
public abstract void getPlane(Vector3f planeNormal, Vector3f planeSupport, int i);
// public abstract int getIndex(int i) const = 0 ;
public abstract boolean isInside(Vector3f pt, float tolerance);
}