/*
|
* 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.dispatch;
|
|
import com.bulletphysics.BulletGlobals;
|
import com.bulletphysics.util.ObjectPool;
|
import com.bulletphysics.collision.narrowphase.DiscreteCollisionDetectorInterface;
|
import com.bulletphysics.collision.narrowphase.ManifoldPoint;
|
import com.bulletphysics.collision.narrowphase.PersistentManifold;
|
import com.bulletphysics.linearmath.Transform;
|
import cz.advel.stack.Stack;
|
import javax.vecmath.Vector3f;
|
|
/**
|
* ManifoldResult is helper class to manage contact results.
|
*
|
* @author jezek2
|
*/
|
public class ManifoldResult extends DiscreteCollisionDetectorInterface.Result {
|
|
//protected final BulletStack stack = BulletStack.get();
|
protected final ObjectPool<ManifoldPoint> pointsPool = ObjectPool.get(ManifoldPoint.class);
|
|
private PersistentManifold manifoldPtr;
|
|
// we need this for compounds
|
private final Transform rootTransA = new Transform();
|
private final Transform rootTransB = new Transform();
|
private CollisionObject body0;
|
private CollisionObject body1;
|
private int partId0;
|
private int partId1;
|
private int index0;
|
private int index1;
|
|
public ManifoldResult() {
|
}
|
|
public ManifoldResult(CollisionObject body0, CollisionObject body1) {
|
init(body0, body1);
|
}
|
|
public void init(CollisionObject body0, CollisionObject body1) {
|
this.body0 = body0;
|
this.body1 = body1;
|
body0.getWorldTransform(this.rootTransA);
|
body1.getWorldTransform(this.rootTransB);
|
}
|
|
public PersistentManifold getPersistentManifold() {
|
return manifoldPtr;
|
}
|
|
public void setPersistentManifold(PersistentManifold manifoldPtr) {
|
this.manifoldPtr = manifoldPtr;
|
}
|
|
public void setShapeIdentifiers(int partId0, int index0, int partId1, int index1) {
|
this.partId0 = partId0;
|
this.partId1 = partId1;
|
this.index0 = index0;
|
this.index1 = index1;
|
}
|
|
public void addContactPoint(Vector3f normalOnBInWorld, Vector3f pointInWorld, float depth) {
|
assert (manifoldPtr != null);
|
//order in manifold needs to match
|
|
if (depth > manifoldPtr.getContactBreakingThreshold()) {
|
return;
|
}
|
|
boolean isSwapped = manifoldPtr.getBody0() != body0;
|
|
Vector3f pointA = Stack.alloc(Vector3f.class);
|
pointA.scaleAdd(depth, normalOnBInWorld, pointInWorld);
|
|
Vector3f localA = Stack.alloc(Vector3f.class);
|
Vector3f localB = Stack.alloc(Vector3f.class);
|
|
if (isSwapped) {
|
rootTransB.invXform(pointA, localA);
|
rootTransA.invXform(pointInWorld, localB);
|
}
|
else {
|
rootTransA.invXform(pointA, localA);
|
rootTransB.invXform(pointInWorld, localB);
|
}
|
|
ManifoldPoint newPt = pointsPool.get();
|
newPt.init(localA, localB, normalOnBInWorld, depth);
|
|
newPt.positionWorldOnA.set(pointA);
|
newPt.positionWorldOnB.set(pointInWorld);
|
|
int insertIndex = manifoldPtr.getCacheEntry(newPt);
|
|
newPt.combinedFriction = calculateCombinedFriction(body0, body1);
|
newPt.combinedRestitution = calculateCombinedRestitution(body0, body1);
|
|
// BP mod, store contact triangles.
|
newPt.partId0 = partId0;
|
newPt.partId1 = partId1;
|
newPt.index0 = index0;
|
newPt.index1 = index1;
|
|
/// todo, check this for any side effects
|
if (insertIndex >= 0) {
|
//const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex);
|
manifoldPtr.replaceContactPoint(newPt, insertIndex);
|
}
|
else {
|
insertIndex = manifoldPtr.addManifoldPoint(newPt);
|
}
|
|
// User can override friction and/or restitution
|
if (BulletGlobals.getContactAddedCallback() != null &&
|
// and if either of the two bodies requires custom material
|
((body0.getCollisionFlags() & CollisionFlags.CUSTOM_MATERIAL_CALLBACK) != 0 ||
|
(body1.getCollisionFlags() & CollisionFlags.CUSTOM_MATERIAL_CALLBACK) != 0)) {
|
//experimental feature info, for per-triangle material etc.
|
CollisionObject obj0 = isSwapped ? body1 : body0;
|
CollisionObject obj1 = isSwapped ? body0 : body1;
|
BulletGlobals.getContactAddedCallback().contactAdded(manifoldPtr.getContactPoint(insertIndex), obj0, partId0, index0, obj1, partId1, index1);
|
}
|
|
pointsPool.release(newPt);
|
}
|
|
///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback;
|
private static float calculateCombinedFriction(CollisionObject body0, CollisionObject body1) {
|
float friction = body0.getFriction() * body1.getFriction();
|
|
float MAX_FRICTION = 10f;
|
if (friction < -MAX_FRICTION) {
|
friction = -MAX_FRICTION;
|
}
|
if (friction > MAX_FRICTION) {
|
friction = MAX_FRICTION;
|
}
|
return friction;
|
}
|
|
private static float calculateCombinedRestitution(CollisionObject body0, CollisionObject body1) {
|
return body0.getRestitution() * body1.getRestitution();
|
}
|
|
public void refreshContactPoints() {
|
assert (manifoldPtr != null);
|
if (manifoldPtr.getNumContacts() == 0) {
|
return;
|
}
|
|
boolean isSwapped = manifoldPtr.getBody0() != body0;
|
|
if (isSwapped) {
|
manifoldPtr.refreshContactPoints(rootTransB, rootTransA);
|
}
|
else {
|
manifoldPtr.refreshContactPoints(rootTransA, rootTransB);
|
}
|
}
|
}
|