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);
|
triangleMesh->performConvexcast(&tccb,convexFromLocal,convexToLocal,boxMinLocal, boxMaxLocal);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
//BT_PROFILE("convexSweepConcave");
|
if (collisionShape->getShapeType()==STATIC_PLANE_PROXYTYPE)
|
||||||
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
|
|
||||||
{
|
{
|
||||||
btCollisionWorld::ConvexResultCallback* m_resultCallback;
|
btConvexCast::CastResult castResult;
|
||||||
btCollisionObject* m_collisionObject;
|
castResult.m_allowedPenetration = allowedPenetration;
|
||||||
btConcaveShape* m_triangleMesh;
|
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,
|
if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
}
|
//add hit
|
||||||
|
if (castResult.m_normal.length2() > btScalar(0.0001))
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
|
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
|
bool normalInWorldSpace = true;
|
||||||
(m_collisionObject,
|
resultCallback.addSingleResult(localConvexResult, normalInWorldSpace);
|
||||||
&shapeInfo,
|
}
|
||||||
hitNormalLocal,
|
|
||||||
hitPointLocal,
|
|
||||||
hitFraction);
|
|
||||||
|
|
||||||
bool normalInWorldSpace = false;
|
|
||||||
|
|
||||||
return m_resultCallback->addSingleResult(convexResult,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);
|
//ConvexCast::CastResult
|
||||||
tccb.m_hitFraction = resultCallback.m_closestHitFraction;
|
struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
|
||||||
tccb.m_allowedPenetration = allowedPenetration;
|
{
|
||||||
btVector3 boxMinLocal, boxMaxLocal;
|
btCollisionWorld::ConvexResultCallback* m_resultCallback;
|
||||||
castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
|
btCollisionObject* m_collisionObject;
|
||||||
|
btConcaveShape* m_triangleMesh;
|
||||||
|
|
||||||
btVector3 rayAabbMinLocal = convexFromLocal;
|
BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to,
|
||||||
rayAabbMinLocal.setMin(convexToLocal);
|
btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btConcaveShape* triangleMesh, const btTransform& triangleToWorld):
|
||||||
btVector3 rayAabbMaxLocal = convexFromLocal;
|
btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()),
|
||||||
rayAabbMaxLocal.setMax(convexToLocal);
|
m_resultCallback(resultCallback),
|
||||||
rayAabbMinLocal += boxMinLocal;
|
m_collisionObject(collisionObject),
|
||||||
rayAabbMaxLocal += boxMaxLocal;
|
m_triangleMesh(triangleMesh)
|
||||||
concaveShape->processAllTriangles(&tccb,rayAabbMinLocal,rayAabbMaxLocal);
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 {
|
} else {
|
||||||
///@todo : use AABB tree or other BVH acceleration structure!
|
///@todo : use AABB tree or other BVH acceleration structure!
|
||||||
|
|||||||
@@ -22,20 +22,72 @@ subject to the following restrictions:
|
|||||||
|
|
||||||
#include "btGjkPairDetector.h"
|
#include "btGjkPairDetector.h"
|
||||||
#include "btPointCollector.h"
|
#include "btPointCollector.h"
|
||||||
|
#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
btContinuousConvexCollision::btContinuousConvexCollision ( const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver)
|
btContinuousConvexCollision::btContinuousConvexCollision ( const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver)
|
||||||
:m_simplexSolver(simplexSolver),
|
:m_simplexSolver(simplexSolver),
|
||||||
m_penetrationDepthSolver(penetrationDepthSolver),
|
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.
|
/// 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.
|
/// You don't want your game ever to lock-up.
|
||||||
#define MAX_ITERATIONS 64
|
#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(
|
bool btContinuousConvexCollision::calcTimeOfImpact(
|
||||||
const btTransform& fromA,
|
const btTransform& fromA,
|
||||||
const btTransform& toA,
|
const btTransform& toA,
|
||||||
@@ -44,7 +96,6 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
|
|||||||
CastResult& result)
|
CastResult& result)
|
||||||
{
|
{
|
||||||
|
|
||||||
m_simplexSolver->reset();
|
|
||||||
|
|
||||||
/// compute linear and angular velocity for this interval, to interpolate
|
/// compute linear and angular velocity for this interval, to interpolate
|
||||||
btVector3 linVelA,angVelA,linVelB,angVelB;
|
btVector3 linVelA,angVelA,linVelB,angVelB;
|
||||||
@@ -53,7 +104,7 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
|
|||||||
|
|
||||||
|
|
||||||
btScalar boundingRadiusA = m_convexA->getAngularMotionDisc();
|
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;
|
btScalar maxAngularProjectedVelocity = angVelA.length() * boundingRadiusA + angVelB.length() * boundingRadiusB;
|
||||||
btVector3 relLinVel = (linVelB-linVelA);
|
btVector3 relLinVel = (linVelB-linVelA);
|
||||||
@@ -81,11 +132,6 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
|
|||||||
int numIter = 0;
|
int numIter = 0;
|
||||||
//first solution, using GJK
|
//first solution, using GJK
|
||||||
|
|
||||||
btTransform identityTrans;
|
|
||||||
identityTrans.setIdentity();
|
|
||||||
|
|
||||||
btSphereShape raySphere(btScalar(0.0));
|
|
||||||
raySphere.setMargin(btScalar(0.));
|
|
||||||
|
|
||||||
btScalar radius = 0.001f;
|
btScalar radius = 0.001f;
|
||||||
// result.drawCoordSystem(sphereTr);
|
// result.drawCoordSystem(sphereTr);
|
||||||
@@ -94,13 +140,7 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
|
|||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
btGjkPairDetector gjk(m_convexA,m_convexB,m_convexA->getShapeType(),m_convexB->getShapeType(),m_convexA->getMargin(),m_convexB->getMargin(),m_simplexSolver,m_penetrationDepthSolver);
|
computeClosestPoints(fromA,fromB,pointCollector1);
|
||||||
btGjkPairDetector::ClosestPointInput input;
|
|
||||||
|
|
||||||
|
|
||||||
input.m_transformA = fromA;
|
|
||||||
input.m_transformB = fromB;
|
|
||||||
gjk.getClosestPoints(input,pointCollector1,0);
|
|
||||||
|
|
||||||
hasResult = pointCollector1.m_hasResult;
|
hasResult = pointCollector1.m_hasResult;
|
||||||
c = pointCollector1.m_pointInWorld;
|
c = pointCollector1.m_pointInWorld;
|
||||||
@@ -170,11 +210,8 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
|
|||||||
result.DebugDraw( lambda );
|
result.DebugDraw( lambda );
|
||||||
|
|
||||||
btPointCollector pointCollector;
|
btPointCollector pointCollector;
|
||||||
btGjkPairDetector gjk(m_convexA,m_convexB,m_simplexSolver,m_penetrationDepthSolver);
|
computeClosestPoints(interpolatedTransA,interpolatedTransB,pointCollector);
|
||||||
btGjkPairDetector::ClosestPointInput input;
|
|
||||||
input.m_transformA = interpolatedTransA;
|
|
||||||
input.m_transformB = interpolatedTransB;
|
|
||||||
gjk.getClosestPoints(input,pointCollector,0);
|
|
||||||
if (pointCollector.m_hasResult)
|
if (pointCollector.m_hasResult)
|
||||||
{
|
{
|
||||||
dist = pointCollector.m_distance+result.m_allowedPenetration;
|
dist = pointCollector.m_distance+result.m_allowedPenetration;
|
||||||
@@ -203,3 +240,4 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ subject to the following restrictions:
|
|||||||
#include "btSimplexSolverInterface.h"
|
#include "btSimplexSolverInterface.h"
|
||||||
class btConvexPenetrationDepthSolver;
|
class btConvexPenetrationDepthSolver;
|
||||||
class btConvexShape;
|
class btConvexShape;
|
||||||
|
class btStaticPlaneShape;
|
||||||
|
|
||||||
/// btContinuousConvexCollision implements angular and linear time of impact for convex objects.
|
/// btContinuousConvexCollision implements angular and linear time of impact for convex objects.
|
||||||
/// Based on Brian Mirtich's Conservative Advancement idea (PhD thesis).
|
/// Based on Brian Mirtich's Conservative Advancement idea (PhD thesis).
|
||||||
@@ -31,13 +32,18 @@ class btContinuousConvexCollision : public btConvexCast
|
|||||||
btSimplexSolverInterface* m_simplexSolver;
|
btSimplexSolverInterface* m_simplexSolver;
|
||||||
btConvexPenetrationDepthSolver* m_penetrationDepthSolver;
|
btConvexPenetrationDepthSolver* m_penetrationDepthSolver;
|
||||||
const btConvexShape* m_convexA;
|
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:
|
public:
|
||||||
|
|
||||||
btContinuousConvexCollision (const btConvexShape* shapeA,const btConvexShape* shapeB ,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver);
|
btContinuousConvexCollision (const btConvexShape* shapeA,const btConvexShape* shapeB ,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver);
|
||||||
|
|
||||||
|
btContinuousConvexCollision(const btConvexShape* shapeA,const btStaticPlaneShape* plane );
|
||||||
|
|
||||||
virtual bool calcTimeOfImpact(
|
virtual bool calcTimeOfImpact(
|
||||||
const btTransform& fromA,
|
const btTransform& fromA,
|
||||||
const btTransform& toA,
|
const btTransform& toA,
|
||||||
@@ -48,5 +54,6 @@ public:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif //CONTINUOUS_COLLISION_CONVEX_CAST_H
|
#endif //CONTINUOUS_COLLISION_CONVEX_CAST_H
|
||||||
|
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ public:
|
|||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
///need to transform normal into worldspace
|
///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);
|
btScalar dotUp = m_up.dot(hitNormalWorld);
|
||||||
|
|||||||
Reference in New Issue
Block a user