Add better support for btCollisionWorld::convexSweepTest for btStaticPlaneShape, now using the btContinuousConvexCollision directly.
Bugfix in btKinematicCharacterController, using an uninitialized variable
This commit is contained in:
@@ -662,68 +662,103 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
|
||||
triangleMesh->performConvexcast(&tccb,convexFromLocal,convexToLocal,boxMinLocal, boxMaxLocal);
|
||||
} else
|
||||
{
|
||||
//BT_PROFILE("convexSweepConcave");
|
||||
btConcaveShape* concaveShape = (btConcaveShape*)collisionShape;
|
||||
btTransform worldTocollisionObject = colObjWorldTransform.inverse();
|
||||
btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin();
|
||||
btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin();
|
||||
// rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
|
||||
btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
|
||||
|
||||
//ConvexCast::CastResult
|
||||
struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
|
||||
if (collisionShape->getShapeType()==STATIC_PLANE_PROXYTYPE)
|
||||
{
|
||||
btCollisionWorld::ConvexResultCallback* m_resultCallback;
|
||||
btCollisionObject* m_collisionObject;
|
||||
btConcaveShape* m_triangleMesh;
|
||||
btConvexCast::CastResult castResult;
|
||||
castResult.m_allowedPenetration = allowedPenetration;
|
||||
castResult.m_fraction = resultCallback.m_closestHitFraction;
|
||||
btStaticPlaneShape* planeShape = (btStaticPlaneShape*) collisionShape;
|
||||
btContinuousConvexCollision convexCaster1(castShape,planeShape);
|
||||
btConvexCast* castPtr = &convexCaster1;
|
||||
|
||||
BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to,
|
||||
btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btConcaveShape* triangleMesh, const btTransform& triangleToWorld):
|
||||
btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()),
|
||||
m_resultCallback(resultCallback),
|
||||
m_collisionObject(collisionObject),
|
||||
m_triangleMesh(triangleMesh)
|
||||
if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex )
|
||||
{
|
||||
btCollisionWorld::LocalShapeInfo shapeInfo;
|
||||
shapeInfo.m_shapePart = partId;
|
||||
shapeInfo.m_triangleIndex = triangleIndex;
|
||||
if (hitFraction <= m_resultCallback->m_closestHitFraction)
|
||||
//add hit
|
||||
if (castResult.m_normal.length2() > btScalar(0.0001))
|
||||
{
|
||||
if (castResult.m_fraction < resultCallback.m_closestHitFraction)
|
||||
{
|
||||
castResult.m_normal.normalize();
|
||||
btCollisionWorld::LocalConvexResult localConvexResult
|
||||
(
|
||||
collisionObject,
|
||||
0,
|
||||
castResult.m_normal,
|
||||
castResult.m_hitPoint,
|
||||
castResult.m_fraction
|
||||
);
|
||||
|
||||
btCollisionWorld::LocalConvexResult convexResult
|
||||
(m_collisionObject,
|
||||
&shapeInfo,
|
||||
hitNormalLocal,
|
||||
hitPointLocal,
|
||||
hitFraction);
|
||||
|
||||
bool normalInWorldSpace = false;
|
||||
|
||||
return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace);
|
||||
bool normalInWorldSpace = true;
|
||||
resultCallback.addSingleResult(localConvexResult, normalInWorldSpace);
|
||||
}
|
||||
}
|
||||
return hitFraction;
|
||||
}
|
||||
|
||||
};
|
||||
} else
|
||||
{
|
||||
//BT_PROFILE("convexSweepConcave");
|
||||
btConcaveShape* concaveShape = (btConcaveShape*)collisionShape;
|
||||
btTransform worldTocollisionObject = colObjWorldTransform.inverse();
|
||||
btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin();
|
||||
btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin();
|
||||
// rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
|
||||
btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
|
||||
|
||||
BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,concaveShape, colObjWorldTransform);
|
||||
tccb.m_hitFraction = resultCallback.m_closestHitFraction;
|
||||
tccb.m_allowedPenetration = allowedPenetration;
|
||||
btVector3 boxMinLocal, boxMaxLocal;
|
||||
castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
|
||||
//ConvexCast::CastResult
|
||||
struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
|
||||
{
|
||||
btCollisionWorld::ConvexResultCallback* m_resultCallback;
|
||||
btCollisionObject* m_collisionObject;
|
||||
btConcaveShape* m_triangleMesh;
|
||||
|
||||
btVector3 rayAabbMinLocal = convexFromLocal;
|
||||
rayAabbMinLocal.setMin(convexToLocal);
|
||||
btVector3 rayAabbMaxLocal = convexFromLocal;
|
||||
rayAabbMaxLocal.setMax(convexToLocal);
|
||||
rayAabbMinLocal += boxMinLocal;
|
||||
rayAabbMaxLocal += boxMaxLocal;
|
||||
concaveShape->processAllTriangles(&tccb,rayAabbMinLocal,rayAabbMaxLocal);
|
||||
BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to,
|
||||
btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btConcaveShape* triangleMesh, const btTransform& triangleToWorld):
|
||||
btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()),
|
||||
m_resultCallback(resultCallback),
|
||||
m_collisionObject(collisionObject),
|
||||
m_triangleMesh(triangleMesh)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex )
|
||||
{
|
||||
btCollisionWorld::LocalShapeInfo shapeInfo;
|
||||
shapeInfo.m_shapePart = partId;
|
||||
shapeInfo.m_triangleIndex = triangleIndex;
|
||||
if (hitFraction <= m_resultCallback->m_closestHitFraction)
|
||||
{
|
||||
|
||||
btCollisionWorld::LocalConvexResult convexResult
|
||||
(m_collisionObject,
|
||||
&shapeInfo,
|
||||
hitNormalLocal,
|
||||
hitPointLocal,
|
||||
hitFraction);
|
||||
|
||||
bool normalInWorldSpace = false;
|
||||
|
||||
return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace);
|
||||
}
|
||||
return hitFraction;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,concaveShape, colObjWorldTransform);
|
||||
tccb.m_hitFraction = resultCallback.m_closestHitFraction;
|
||||
tccb.m_allowedPenetration = allowedPenetration;
|
||||
btVector3 boxMinLocal, boxMaxLocal;
|
||||
castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
|
||||
|
||||
btVector3 rayAabbMinLocal = convexFromLocal;
|
||||
rayAabbMinLocal.setMin(convexToLocal);
|
||||
btVector3 rayAabbMaxLocal = convexFromLocal;
|
||||
rayAabbMaxLocal.setMax(convexToLocal);
|
||||
rayAabbMinLocal += boxMinLocal;
|
||||
rayAabbMaxLocal += boxMaxLocal;
|
||||
concaveShape->processAllTriangles(&tccb,rayAabbMinLocal,rayAabbMaxLocal);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
///@todo : use AABB tree or other BVH acceleration structure!
|
||||
|
||||
@@ -22,20 +22,72 @@ subject to the following restrictions:
|
||||
|
||||
#include "btGjkPairDetector.h"
|
||||
#include "btPointCollector.h"
|
||||
#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
|
||||
|
||||
|
||||
|
||||
btContinuousConvexCollision::btContinuousConvexCollision ( const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver)
|
||||
:m_simplexSolver(simplexSolver),
|
||||
m_penetrationDepthSolver(penetrationDepthSolver),
|
||||
m_convexA(convexA),m_convexB(convexB)
|
||||
m_convexA(convexA),m_convexB1(convexB),m_planeShape(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
btContinuousConvexCollision::btContinuousConvexCollision( const btConvexShape* convexA,const btStaticPlaneShape* plane)
|
||||
:m_simplexSolver(0),
|
||||
m_penetrationDepthSolver(0),
|
||||
m_convexA(convexA),m_convexB1(0),m_planeShape(plane)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// This maximum should not be necessary. It allows for untested/degenerate cases in production code.
|
||||
/// You don't want your game ever to lock-up.
|
||||
#define MAX_ITERATIONS 64
|
||||
|
||||
void btContinuousConvexCollision::computeClosestPoints( const btTransform& transA, const btTransform& transB,btPointCollector& pointCollector)
|
||||
{
|
||||
if (m_convexB1)
|
||||
{
|
||||
m_simplexSolver->reset();
|
||||
btGjkPairDetector gjk(m_convexA,m_convexB1,m_convexA->getShapeType(),m_convexB1->getShapeType(),m_convexA->getMargin(),m_convexB1->getMargin(),m_simplexSolver,m_penetrationDepthSolver);
|
||||
btGjkPairDetector::ClosestPointInput input;
|
||||
input.m_transformA = transA;
|
||||
input.m_transformB = transB;
|
||||
gjk.getClosestPoints(input,pointCollector,0);
|
||||
} else
|
||||
{
|
||||
//convex versus plane
|
||||
const btConvexShape* convexShape = m_convexA;
|
||||
const btStaticPlaneShape* planeShape = m_planeShape;
|
||||
|
||||
bool hasCollision = false;
|
||||
const btVector3& planeNormal = planeShape->getPlaneNormal();
|
||||
const btScalar& planeConstant = planeShape->getPlaneConstant();
|
||||
|
||||
btTransform convexWorldTransform = transA;
|
||||
btTransform convexInPlaneTrans;
|
||||
convexInPlaneTrans= transB.inverse() * convexWorldTransform;
|
||||
btTransform planeInConvex;
|
||||
planeInConvex= convexWorldTransform.inverse() * transB;
|
||||
|
||||
btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal);
|
||||
|
||||
btVector3 vtxInPlane = convexInPlaneTrans(vtx);
|
||||
btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
|
||||
|
||||
btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal;
|
||||
btVector3 vtxInPlaneWorld = transB * vtxInPlaneProjected;
|
||||
btVector3 normalOnSurfaceB = transB.getBasis() * planeNormal;
|
||||
|
||||
pointCollector.addContactPoint(
|
||||
normalOnSurfaceB,
|
||||
vtxInPlaneWorld,
|
||||
distance);
|
||||
}
|
||||
}
|
||||
|
||||
bool btContinuousConvexCollision::calcTimeOfImpact(
|
||||
const btTransform& fromA,
|
||||
const btTransform& toA,
|
||||
@@ -44,7 +96,6 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
|
||||
CastResult& result)
|
||||
{
|
||||
|
||||
m_simplexSolver->reset();
|
||||
|
||||
/// compute linear and angular velocity for this interval, to interpolate
|
||||
btVector3 linVelA,angVelA,linVelB,angVelB;
|
||||
@@ -53,7 +104,7 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
|
||||
|
||||
|
||||
btScalar boundingRadiusA = m_convexA->getAngularMotionDisc();
|
||||
btScalar boundingRadiusB = m_convexB->getAngularMotionDisc();
|
||||
btScalar boundingRadiusB = m_convexB1?m_convexB1->getAngularMotionDisc():0.f;
|
||||
|
||||
btScalar maxAngularProjectedVelocity = angVelA.length() * boundingRadiusA + angVelB.length() * boundingRadiusB;
|
||||
btVector3 relLinVel = (linVelB-linVelA);
|
||||
@@ -81,11 +132,6 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
|
||||
int numIter = 0;
|
||||
//first solution, using GJK
|
||||
|
||||
btTransform identityTrans;
|
||||
identityTrans.setIdentity();
|
||||
|
||||
btSphereShape raySphere(btScalar(0.0));
|
||||
raySphere.setMargin(btScalar(0.));
|
||||
|
||||
btScalar radius = 0.001f;
|
||||
// result.drawCoordSystem(sphereTr);
|
||||
@@ -93,14 +139,8 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
|
||||
btPointCollector pointCollector1;
|
||||
|
||||
{
|
||||
|
||||
btGjkPairDetector gjk(m_convexA,m_convexB,m_convexA->getShapeType(),m_convexB->getShapeType(),m_convexA->getMargin(),m_convexB->getMargin(),m_simplexSolver,m_penetrationDepthSolver);
|
||||
btGjkPairDetector::ClosestPointInput input;
|
||||
|
||||
|
||||
input.m_transformA = fromA;
|
||||
input.m_transformB = fromB;
|
||||
gjk.getClosestPoints(input,pointCollector1,0);
|
||||
computeClosestPoints(fromA,fromB,pointCollector1);
|
||||
|
||||
hasResult = pointCollector1.m_hasResult;
|
||||
c = pointCollector1.m_pointInWorld;
|
||||
@@ -170,11 +210,8 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
|
||||
result.DebugDraw( lambda );
|
||||
|
||||
btPointCollector pointCollector;
|
||||
btGjkPairDetector gjk(m_convexA,m_convexB,m_simplexSolver,m_penetrationDepthSolver);
|
||||
btGjkPairDetector::ClosestPointInput input;
|
||||
input.m_transformA = interpolatedTransA;
|
||||
input.m_transformB = interpolatedTransB;
|
||||
gjk.getClosestPoints(input,pointCollector,0);
|
||||
computeClosestPoints(interpolatedTransA,interpolatedTransB,pointCollector);
|
||||
|
||||
if (pointCollector.m_hasResult)
|
||||
{
|
||||
dist = pointCollector.m_distance+result.m_allowedPenetration;
|
||||
@@ -203,3 +240,4 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ subject to the following restrictions:
|
||||
#include "btSimplexSolverInterface.h"
|
||||
class btConvexPenetrationDepthSolver;
|
||||
class btConvexShape;
|
||||
class btStaticPlaneShape;
|
||||
|
||||
/// btContinuousConvexCollision implements angular and linear time of impact for convex objects.
|
||||
/// Based on Brian Mirtich's Conservative Advancement idea (PhD thesis).
|
||||
@@ -31,13 +32,18 @@ class btContinuousConvexCollision : public btConvexCast
|
||||
btSimplexSolverInterface* m_simplexSolver;
|
||||
btConvexPenetrationDepthSolver* m_penetrationDepthSolver;
|
||||
const btConvexShape* m_convexA;
|
||||
const btConvexShape* m_convexB;
|
||||
//second object is either a convex or a plane (code sharing)
|
||||
const btConvexShape* m_convexB1;
|
||||
const btStaticPlaneShape* m_planeShape;
|
||||
|
||||
void computeClosestPoints( const btTransform& transA, const btTransform& transB,struct btPointCollector& pointCollector);
|
||||
|
||||
public:
|
||||
|
||||
btContinuousConvexCollision (const btConvexShape* shapeA,const btConvexShape* shapeB ,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver);
|
||||
|
||||
btContinuousConvexCollision(const btConvexShape* shapeA,const btStaticPlaneShape* plane );
|
||||
|
||||
virtual bool calcTimeOfImpact(
|
||||
const btTransform& fromA,
|
||||
const btTransform& toA,
|
||||
@@ -48,5 +54,6 @@ public:
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif //CONTINUOUS_COLLISION_CONVEX_CAST_H
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
} else
|
||||
{
|
||||
///need to transform normal into worldspace
|
||||
hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal;
|
||||
hitNormalWorld = convexResult.m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal;
|
||||
}
|
||||
|
||||
btScalar dotUp = m_up.dot(hitNormalWorld);
|
||||
|
||||
Reference in New Issue
Block a user