
com.bulletphysics.collision.dispatch.ConvexConvexAlgorithm Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jbullet Show documentation
Show all versions of jbullet Show documentation
JBullet - Java port of Bullet Physics Library
The newest version!
/*
* Java port of Bullet (c) 2008 Martin Dvorak
*
* 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.util.ObjectPool;
import com.bulletphysics.collision.broadphase.CollisionAlgorithm;
import com.bulletphysics.collision.broadphase.CollisionAlgorithmConstructionInfo;
import com.bulletphysics.collision.broadphase.DispatcherInfo;
import com.bulletphysics.collision.narrowphase.ConvexCast;
import com.bulletphysics.collision.narrowphase.ConvexPenetrationDepthSolver;
import com.bulletphysics.collision.narrowphase.DiscreteCollisionDetectorInterface.ClosestPointInput;
import com.bulletphysics.collision.narrowphase.GjkConvexCast;
import com.bulletphysics.collision.narrowphase.GjkPairDetector;
import com.bulletphysics.collision.narrowphase.PersistentManifold;
import com.bulletphysics.collision.narrowphase.SimplexSolverInterface;
import com.bulletphysics.collision.narrowphase.VoronoiSimplexSolver;
import com.bulletphysics.collision.shapes.ConvexShape;
import com.bulletphysics.collision.shapes.SphereShape;
import com.bulletphysics.linearmath.Transform;
import com.bulletphysics.util.ObjectArrayList;
import cz.advel.stack.Stack;
import javax.vecmath.Vector3f;
/**
* ConvexConvexAlgorithm collision algorithm implements time of impact, convex
* closest points and penetration depth calculations.
*
* @author jezek2
*/
public class ConvexConvexAlgorithm extends CollisionAlgorithm {
protected final ObjectPool pointInputsPool = ObjectPool.get(ClosestPointInput.class);
private GjkPairDetector gjkPairDetector = new GjkPairDetector();
public boolean ownManifold;
public PersistentManifold manifoldPtr;
public boolean lowLevelOfDetail;
public void init(PersistentManifold mf, CollisionAlgorithmConstructionInfo ci, CollisionObject body0, CollisionObject body1, SimplexSolverInterface simplexSolver, ConvexPenetrationDepthSolver pdSolver) {
super.init(ci);
gjkPairDetector.init(null, null, simplexSolver, pdSolver);
this.manifoldPtr = mf;
this.ownManifold = false;
this.lowLevelOfDetail = false;
}
@Override
public void destroy() {
if (ownManifold) {
if (manifoldPtr != null) {
dispatcher.releaseManifold(manifoldPtr);
}
manifoldPtr = null;
}
}
public void setLowLevelOfDetail(boolean useLowLevel) {
this.lowLevelOfDetail = useLowLevel;
}
/**
* Convex-Convex collision algorithm.
*/
@Override
public void processCollision(CollisionObject body0, CollisionObject body1, DispatcherInfo dispatchInfo, ManifoldResult resultOut) {
if (manifoldPtr == null) {
// swapped?
manifoldPtr = dispatcher.getNewManifold(body0, body1);
ownManifold = true;
}
resultOut.setPersistentManifold(manifoldPtr);
// #ifdef USE_BT_GJKEPA
// btConvexShape* shape0(static_cast(body0->getCollisionShape()));
// btConvexShape* shape1(static_cast(body1->getCollisionShape()));
// const btScalar radialmargin(0/*shape0->getMargin()+shape1->getMargin()*/);
// btGjkEpaSolver::sResults results;
// if(btGjkEpaSolver::Collide( shape0,body0->getWorldTransform(),
// shape1,body1->getWorldTransform(),
// radialmargin,results))
// {
// dispatchInfo.m_debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0));
// resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth);
// }
// #else
ConvexShape min0 = (ConvexShape) body0.getCollisionShape();
ConvexShape min1 = (ConvexShape) body1.getCollisionShape();
ClosestPointInput input = pointInputsPool.get();
input.init();
// JAVA NOTE: original: TODO: if (dispatchInfo.m_useContinuous)
gjkPairDetector.setMinkowskiA(min0);
gjkPairDetector.setMinkowskiB(min1);
input.maximumDistanceSquared = min0.getMargin() + min1.getMargin() + manifoldPtr.getContactBreakingThreshold();
input.maximumDistanceSquared *= input.maximumDistanceSquared;
//input.m_stackAlloc = dispatchInfo.m_stackAllocator;
// input.m_maximumDistanceSquared = btScalar(1e30);
body0.getWorldTransform(input.transformA);
body1.getWorldTransform(input.transformB);
gjkPairDetector.getClosestPoints(input, resultOut, dispatchInfo.debugDraw);
pointInputsPool.release(input);
// #endif
if (ownManifold) {
resultOut.refreshContactPoints();
}
}
private static boolean disableCcd = false;
@Override
public float calculateTimeOfImpact(CollisionObject col0, CollisionObject col1, DispatcherInfo dispatchInfo, ManifoldResult resultOut) {
Vector3f tmp = Stack.alloc(Vector3f.class);
Transform tmpTrans1 = Stack.alloc(Transform.class);
Transform tmpTrans2 = Stack.alloc(Transform.class);
// Rather then checking ALL pairs, only calculate TOI when motion exceeds threshold
// Linear motion for one of objects needs to exceed m_ccdSquareMotionThreshold
// col0->m_worldTransform,
float resultFraction = 1f;
tmp.sub(col0.getInterpolationWorldTransform(tmpTrans1).origin, col0.getWorldTransform(tmpTrans2).origin);
float squareMot0 = tmp.lengthSquared();
tmp.sub(col1.getInterpolationWorldTransform(tmpTrans1).origin, col1.getWorldTransform(tmpTrans2).origin);
float squareMot1 = tmp.lengthSquared();
if (squareMot0 < col0.getCcdSquareMotionThreshold() &&
squareMot1 < col1.getCcdSquareMotionThreshold()) {
return resultFraction;
}
if (disableCcd) {
return 1f;
}
Transform tmpTrans3 = Stack.alloc(Transform.class);
Transform tmpTrans4 = Stack.alloc(Transform.class);
// An adhoc way of testing the Continuous Collision Detection algorithms
// One object is approximated as a sphere, to simplify things
// Starting in penetration should report no time of impact
// For proper CCD, better accuracy and handling of 'allowed' penetration should be added
// also the mainloop of the physics should have a kind of toi queue (something like Brian Mirtich's application of Timewarp for Rigidbodies)
// Convex0 against sphere for Convex1
{
ConvexShape convex0 = (ConvexShape) col0.getCollisionShape();
SphereShape sphere1 = new SphereShape(col1.getCcdSweptSphereRadius()); // todo: allow non-zero sphere sizes, for better approximation
ConvexCast.CastResult result = new ConvexCast.CastResult();
VoronoiSimplexSolver voronoiSimplex = new VoronoiSimplexSolver();
//SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
///Simplification, one object is simplified as a sphere
GjkConvexCast ccd1 = new GjkConvexCast(convex0, sphere1, voronoiSimplex);
//ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
if (ccd1.calcTimeOfImpact(col0.getWorldTransform(tmpTrans1), col0.getInterpolationWorldTransform(tmpTrans2),
col1.getWorldTransform(tmpTrans3), col1.getInterpolationWorldTransform(tmpTrans4), result)) {
// store result.m_fraction in both bodies
if (col0.getHitFraction() > result.fraction) {
col0.setHitFraction(result.fraction);
}
if (col1.getHitFraction() > result.fraction) {
col1.setHitFraction(result.fraction);
}
if (resultFraction > result.fraction) {
resultFraction = result.fraction;
}
}
}
// Sphere (for convex0) against Convex1
{
ConvexShape convex1 = (ConvexShape) col1.getCollisionShape();
SphereShape sphere0 = new SphereShape(col0.getCcdSweptSphereRadius()); // todo: allow non-zero sphere sizes, for better approximation
ConvexCast.CastResult result = new ConvexCast.CastResult();
VoronoiSimplexSolver voronoiSimplex = new VoronoiSimplexSolver();
//SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
///Simplification, one object is simplified as a sphere
GjkConvexCast ccd1 = new GjkConvexCast(sphere0, convex1, voronoiSimplex);
//ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
if (ccd1.calcTimeOfImpact(col0.getWorldTransform(tmpTrans1), col0.getInterpolationWorldTransform(tmpTrans2),
col1.getWorldTransform(tmpTrans3), col1.getInterpolationWorldTransform(tmpTrans4), result)) {
//store result.m_fraction in both bodies
if (col0.getHitFraction() > result.fraction) {
col0.setHitFraction(result.fraction);
}
if (col1.getHitFraction() > result.fraction) {
col1.setHitFraction(result.fraction);
}
if (resultFraction > result.fraction) {
resultFraction = result.fraction;
}
}
}
return resultFraction;
}
@Override
public void getAllContactManifolds(ObjectArrayList manifoldArray) {
// should we use ownManifold to avoid adding duplicates?
if (manifoldPtr != null && ownManifold) {
manifoldArray.add(manifoldPtr);
}
}
public PersistentManifold getManifold() {
return manifoldPtr;
}
////////////////////////////////////////////////////////////////////////////
public static class CreateFunc extends CollisionAlgorithmCreateFunc {
private final ObjectPool pool = ObjectPool.get(ConvexConvexAlgorithm.class);
public ConvexPenetrationDepthSolver pdSolver;
public SimplexSolverInterface simplexSolver;
public CreateFunc(SimplexSolverInterface simplexSolver, ConvexPenetrationDepthSolver pdSolver) {
this.simplexSolver = simplexSolver;
this.pdSolver = pdSolver;
}
@Override
public CollisionAlgorithm createCollisionAlgorithm(CollisionAlgorithmConstructionInfo ci, CollisionObject body0, CollisionObject body1) {
ConvexConvexAlgorithm algo = pool.get();
algo.init(ci.manifold, ci, body0, body1, simplexSolver, pdSolver);
return algo;
}
@Override
public void releaseCollisionAlgorithm(CollisionAlgorithm algo) {
pool.release((ConvexConvexAlgorithm)algo);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy