/*
* 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.collision.broadphase.BroadphaseNativeType;
import com.bulletphysics.collision.dispatch.CollisionObject;
import com.bulletphysics.linearmath.Transform;
import com.bulletphysics.util.Stack;
import javax.vecmath.Vector3f;
/**
* CollisionShape class provides an interface for collision shapes that can be
* shared among {@link CollisionObject}s.
*
* @author jezek2
*/
public abstract class CollisionShape {
//protected final BulletStack stack = BulletStack.get();
protected Object userPointer;
///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t.
public abstract void getAabb(Transform t, Vector3f aabbMin, Vector3f aabbMax);
public float getBoundingSphere(Vector3f center) {
Stack stack = Stack.enter();
Vector3f tmp = stack.allocVector3f();
Transform tr = stack.allocTransform();
tr.setIdentity();
Vector3f aabbMin = stack.allocVector3f(), aabbMax = stack.allocVector3f();
getAabb(tr, aabbMin, aabbMax);
tmp.sub(aabbMax, aabbMin);
float radius = tmp.length() * 0.5f;
tmp.add(aabbMin, aabbMax);
center.scale(0.5f, tmp);
stack.leave();
return radius;
}
///getAngularMotionDisc returns the maximus radius needed for Conservative Advancement to handle time-of-impact with rotations.
public float getAngularMotionDisc() {
Stack stack = Stack.enter();
Vector3f center = stack.allocVector3f();
float disc = getBoundingSphere(center);
disc += center.length();
stack.leave();
return disc;
}
///calculateTemporalAabb calculates the enclosing aabb for the moving object over interval [0..timeStep)
///result is conservative
public void calculateTemporalAabb(Transform curTrans, Vector3f linvel, Vector3f angvel, float timeStep, Vector3f temporalAabbMin, Vector3f temporalAabbMax) {
//start with static aabb
getAabb(curTrans, temporalAabbMin, temporalAabbMax);
Stack stack = Stack.enter();
float temporalAabbMaxx = temporalAabbMax.x;
float temporalAabbMaxy = temporalAabbMax.y;
float temporalAabbMaxz = temporalAabbMax.z;
float temporalAabbMinx = temporalAabbMin.x;
float temporalAabbMiny = temporalAabbMin.y;
float temporalAabbMinz = temporalAabbMin.z;
// add linear motion
Vector3f linMotion = stack.alloc(linvel);
linMotion.scale(timeStep);
//todo: simd would have a vector max/min operation, instead of per-element access
if (linMotion.x > 0f) {
temporalAabbMaxx += linMotion.x;
}
else {
temporalAabbMinx += linMotion.x;
}
if (linMotion.y > 0f) {
temporalAabbMaxy += linMotion.y;
}
else {
temporalAabbMiny += linMotion.y;
}
if (linMotion.z > 0f) {
temporalAabbMaxz += linMotion.z;
}
else {
temporalAabbMinz += linMotion.z;
}
//add conservative angular motion
float angularMotion = angvel.length() * getAngularMotionDisc() * timeStep;
Vector3f angularMotion3d = stack.allocVector3f();
angularMotion3d.set(angularMotion, angularMotion, angularMotion);
temporalAabbMin.set(temporalAabbMinx, temporalAabbMiny, temporalAabbMinz);
temporalAabbMax.set(temporalAabbMaxx, temporalAabbMaxy, temporalAabbMaxz);
temporalAabbMin.sub(angularMotion3d);
temporalAabbMax.add(angularMotion3d);
stack.leave();
}
//#ifndef __SPU__
public boolean isPolyhedral() {
return getShapeType().isPolyhedral();
}
public boolean isConvex() {
return getShapeType().isConvex();
}
public boolean isConcave() {
return getShapeType().isConcave();
}
public boolean isCompound() {
return getShapeType().isCompound();
}
///isInfinite is used to catch simulation error (aabb check)
public boolean isInfinite() {
return getShapeType().isInfinite();
}
public abstract BroadphaseNativeType getShapeType();
public abstract void setLocalScaling(Vector3f scaling);
// TODO: returns const
public abstract Vector3f getLocalScaling(Vector3f out);
public abstract void calculateLocalInertia(float mass, Vector3f inertia);
//debugging support
public abstract String getName();
//#endif //__SPU__
public abstract void setMargin(float margin);
public abstract float getMargin();
// optional user data pointer
public void setUserPointer(Object userPtr) {
userPointer = userPtr;
}
public Object getUserPointer() {
return userPointer;
}
}