Code-style consistency improvement:
Apply clang-format-all.sh using the _clang-format file through all the cpp/.h files. make sure not to apply it to certain serialization structures, since some parser expects the * as part of the name, instead of type. This commit contains no other changes aside from adding and applying clang-format-all.sh
This commit is contained in:
@@ -16,163 +16,153 @@ subject to the following restrictions:
|
||||
#ifndef BT_GJK_EPA_PENETATION_CONVEX_COLLISION_H
|
||||
#define BT_GJK_EPA_PENETATION_CONVEX_COLLISION_H
|
||||
|
||||
#include "LinearMath/btTransform.h" // Note that btVector3 might be double precision...
|
||||
#include "LinearMath/btTransform.h" // Note that btVector3 might be double precision...
|
||||
#include "btGjkEpa3.h"
|
||||
#include "btGjkCollisionDescription.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename btConvexTemplate>
|
||||
bool btGjkEpaCalcPenDepth(const btConvexTemplate& a, const btConvexTemplate& b,
|
||||
const btGjkCollisionDescription& colDesc,
|
||||
btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB)
|
||||
const btGjkCollisionDescription& colDesc,
|
||||
btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB)
|
||||
{
|
||||
(void)v;
|
||||
|
||||
// const btScalar radialmargin(btScalar(0.));
|
||||
|
||||
btVector3 guessVector(b.getWorldTransform().getOrigin()-a.getWorldTransform().getOrigin());//?? why not use the GJK input?
|
||||
|
||||
btGjkEpaSolver3::sResults results;
|
||||
(void)v;
|
||||
|
||||
|
||||
if(btGjkEpaSolver3_Penetration(a,b,guessVector,results))
|
||||
|
||||
{
|
||||
// debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0));
|
||||
//resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth);
|
||||
wWitnessOnA = results.witnesses[0];
|
||||
wWitnessOnB = results.witnesses[1];
|
||||
v = results.normal;
|
||||
return true;
|
||||
} else
|
||||
{
|
||||
if(btGjkEpaSolver3_Distance(a,b,guessVector,results))
|
||||
{
|
||||
wWitnessOnA = results.witnesses[0];
|
||||
wWitnessOnB = results.witnesses[1];
|
||||
v = results.normal;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
// const btScalar radialmargin(btScalar(0.));
|
||||
|
||||
btVector3 guessVector(b.getWorldTransform().getOrigin() - a.getWorldTransform().getOrigin()); //?? why not use the GJK input?
|
||||
|
||||
btGjkEpaSolver3::sResults results;
|
||||
|
||||
if (btGjkEpaSolver3_Penetration(a, b, guessVector, results))
|
||||
|
||||
{
|
||||
// debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0));
|
||||
//resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth);
|
||||
wWitnessOnA = results.witnesses[0];
|
||||
wWitnessOnB = results.witnesses[1];
|
||||
v = results.normal;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (btGjkEpaSolver3_Distance(a, b, guessVector, results))
|
||||
{
|
||||
wWitnessOnA = results.witnesses[0];
|
||||
wWitnessOnB = results.witnesses[1];
|
||||
v = results.normal;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename btConvexTemplate, typename btGjkDistanceTemplate>
|
||||
int btComputeGjkEpaPenetration(const btConvexTemplate& a, const btConvexTemplate& b, const btGjkCollisionDescription& colDesc, btVoronoiSimplexSolver& simplexSolver, btGjkDistanceTemplate* distInfo)
|
||||
int btComputeGjkEpaPenetration(const btConvexTemplate& a, const btConvexTemplate& b, const btGjkCollisionDescription& colDesc, btVoronoiSimplexSolver& simplexSolver, btGjkDistanceTemplate* distInfo)
|
||||
{
|
||||
|
||||
bool m_catchDegeneracies = true;
|
||||
btScalar m_cachedSeparatingDistance = 0.f;
|
||||
|
||||
btScalar distance=btScalar(0.);
|
||||
btVector3 normalInB(btScalar(0.),btScalar(0.),btScalar(0.));
|
||||
|
||||
btVector3 pointOnA,pointOnB;
|
||||
btTransform localTransA = a.getWorldTransform();
|
||||
btTransform localTransB = b.getWorldTransform();
|
||||
|
||||
btScalar marginA = a.getMargin();
|
||||
btScalar marginB = b.getMargin();
|
||||
|
||||
int m_curIter = 0;
|
||||
int gGjkMaxIter = colDesc.m_maxGjkIterations;//this is to catch invalid input, perhaps check for #NaN?
|
||||
btVector3 m_cachedSeparatingAxis = colDesc.m_firstDir;
|
||||
|
||||
bool isValid = false;
|
||||
bool checkSimplex = false;
|
||||
bool checkPenetration = true;
|
||||
int m_degenerateSimplex = 0;
|
||||
|
||||
int m_lastUsedMethod = -1;
|
||||
|
||||
{
|
||||
btScalar squaredDistance = BT_LARGE_FLOAT;
|
||||
btScalar delta = btScalar(0.);
|
||||
|
||||
btScalar margin = marginA + marginB;
|
||||
|
||||
|
||||
|
||||
simplexSolver.reset();
|
||||
|
||||
for ( ; ; )
|
||||
//while (true)
|
||||
{
|
||||
|
||||
btVector3 seperatingAxisInA = (-m_cachedSeparatingAxis)* localTransA.getBasis();
|
||||
btVector3 seperatingAxisInB = m_cachedSeparatingAxis* localTransB.getBasis();
|
||||
|
||||
btVector3 pInA = a.getLocalSupportWithoutMargin(seperatingAxisInA);
|
||||
btVector3 qInB = b.getLocalSupportWithoutMargin(seperatingAxisInB);
|
||||
|
||||
btVector3 pWorld = localTransA(pInA);
|
||||
btVector3 qWorld = localTransB(qInB);
|
||||
|
||||
|
||||
|
||||
btVector3 w = pWorld - qWorld;
|
||||
delta = m_cachedSeparatingAxis.dot(w);
|
||||
|
||||
// potential exit, they don't overlap
|
||||
if ((delta > btScalar(0.0)) && (delta * delta > squaredDistance * colDesc.m_maximumDistanceSquared))
|
||||
{
|
||||
m_degenerateSimplex = 10;
|
||||
checkSimplex=true;
|
||||
//checkPenetration = false;
|
||||
break;
|
||||
}
|
||||
|
||||
//exit 0: the new point is already in the simplex, or we didn't come any closer
|
||||
if (simplexSolver.inSimplex(w))
|
||||
{
|
||||
m_degenerateSimplex = 1;
|
||||
checkSimplex = true;
|
||||
break;
|
||||
}
|
||||
// are we getting any closer ?
|
||||
btScalar f0 = squaredDistance - delta;
|
||||
btScalar f1 = squaredDistance * colDesc.m_gjkRelError2;
|
||||
|
||||
if (f0 <= f1)
|
||||
{
|
||||
if (f0 <= btScalar(0.))
|
||||
{
|
||||
m_degenerateSimplex = 2;
|
||||
} else
|
||||
{
|
||||
m_degenerateSimplex = 11;
|
||||
}
|
||||
checkSimplex = true;
|
||||
break;
|
||||
}
|
||||
|
||||
//add current vertex to simplex
|
||||
simplexSolver.addVertex(w, pWorld, qWorld);
|
||||
btVector3 newCachedSeparatingAxis;
|
||||
|
||||
//calculate the closest point to the origin (update vector v)
|
||||
if (!simplexSolver.closest(newCachedSeparatingAxis))
|
||||
{
|
||||
m_degenerateSimplex = 3;
|
||||
checkSimplex = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if(newCachedSeparatingAxis.length2()<colDesc.m_gjkRelError2)
|
||||
{
|
||||
m_cachedSeparatingAxis = newCachedSeparatingAxis;
|
||||
m_degenerateSimplex = 6;
|
||||
checkSimplex = true;
|
||||
break;
|
||||
}
|
||||
|
||||
btScalar previousSquaredDistance = squaredDistance;
|
||||
squaredDistance = newCachedSeparatingAxis.length2();
|
||||
bool m_catchDegeneracies = true;
|
||||
btScalar m_cachedSeparatingDistance = 0.f;
|
||||
|
||||
btScalar distance = btScalar(0.);
|
||||
btVector3 normalInB(btScalar(0.), btScalar(0.), btScalar(0.));
|
||||
|
||||
btVector3 pointOnA, pointOnB;
|
||||
btTransform localTransA = a.getWorldTransform();
|
||||
btTransform localTransB = b.getWorldTransform();
|
||||
|
||||
btScalar marginA = a.getMargin();
|
||||
btScalar marginB = b.getMargin();
|
||||
|
||||
int m_curIter = 0;
|
||||
int gGjkMaxIter = colDesc.m_maxGjkIterations; //this is to catch invalid input, perhaps check for #NaN?
|
||||
btVector3 m_cachedSeparatingAxis = colDesc.m_firstDir;
|
||||
|
||||
bool isValid = false;
|
||||
bool checkSimplex = false;
|
||||
bool checkPenetration = true;
|
||||
int m_degenerateSimplex = 0;
|
||||
|
||||
int m_lastUsedMethod = -1;
|
||||
|
||||
{
|
||||
btScalar squaredDistance = BT_LARGE_FLOAT;
|
||||
btScalar delta = btScalar(0.);
|
||||
|
||||
btScalar margin = marginA + marginB;
|
||||
|
||||
simplexSolver.reset();
|
||||
|
||||
for (;;)
|
||||
//while (true)
|
||||
{
|
||||
btVector3 seperatingAxisInA = (-m_cachedSeparatingAxis) * localTransA.getBasis();
|
||||
btVector3 seperatingAxisInB = m_cachedSeparatingAxis * localTransB.getBasis();
|
||||
|
||||
btVector3 pInA = a.getLocalSupportWithoutMargin(seperatingAxisInA);
|
||||
btVector3 qInB = b.getLocalSupportWithoutMargin(seperatingAxisInB);
|
||||
|
||||
btVector3 pWorld = localTransA(pInA);
|
||||
btVector3 qWorld = localTransB(qInB);
|
||||
|
||||
btVector3 w = pWorld - qWorld;
|
||||
delta = m_cachedSeparatingAxis.dot(w);
|
||||
|
||||
// potential exit, they don't overlap
|
||||
if ((delta > btScalar(0.0)) && (delta * delta > squaredDistance * colDesc.m_maximumDistanceSquared))
|
||||
{
|
||||
m_degenerateSimplex = 10;
|
||||
checkSimplex = true;
|
||||
//checkPenetration = false;
|
||||
break;
|
||||
}
|
||||
|
||||
//exit 0: the new point is already in the simplex, or we didn't come any closer
|
||||
if (simplexSolver.inSimplex(w))
|
||||
{
|
||||
m_degenerateSimplex = 1;
|
||||
checkSimplex = true;
|
||||
break;
|
||||
}
|
||||
// are we getting any closer ?
|
||||
btScalar f0 = squaredDistance - delta;
|
||||
btScalar f1 = squaredDistance * colDesc.m_gjkRelError2;
|
||||
|
||||
if (f0 <= f1)
|
||||
{
|
||||
if (f0 <= btScalar(0.))
|
||||
{
|
||||
m_degenerateSimplex = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_degenerateSimplex = 11;
|
||||
}
|
||||
checkSimplex = true;
|
||||
break;
|
||||
}
|
||||
|
||||
//add current vertex to simplex
|
||||
simplexSolver.addVertex(w, pWorld, qWorld);
|
||||
btVector3 newCachedSeparatingAxis;
|
||||
|
||||
//calculate the closest point to the origin (update vector v)
|
||||
if (!simplexSolver.closest(newCachedSeparatingAxis))
|
||||
{
|
||||
m_degenerateSimplex = 3;
|
||||
checkSimplex = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (newCachedSeparatingAxis.length2() < colDesc.m_gjkRelError2)
|
||||
{
|
||||
m_cachedSeparatingAxis = newCachedSeparatingAxis;
|
||||
m_degenerateSimplex = 6;
|
||||
checkSimplex = true;
|
||||
break;
|
||||
}
|
||||
|
||||
btScalar previousSquaredDistance = squaredDistance;
|
||||
squaredDistance = newCachedSeparatingAxis.length2();
|
||||
#if 0
|
||||
///warning: this termination condition leads to some problems in 2d test case see Bullet/Demos/Box2dDemo
|
||||
if (squaredDistance>previousSquaredDistance)
|
||||
@@ -182,188 +172,183 @@ int btComputeGjkEpaPenetration(const btConvexTemplate& a, const btConvexTemplate
|
||||
checkSimplex = false;
|
||||
break;
|
||||
}
|
||||
#endif //
|
||||
|
||||
|
||||
//redundant m_simplexSolver->compute_points(pointOnA, pointOnB);
|
||||
|
||||
//are we getting any closer ?
|
||||
if (previousSquaredDistance - squaredDistance <= SIMD_EPSILON * previousSquaredDistance)
|
||||
{
|
||||
// m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
|
||||
checkSimplex = true;
|
||||
m_degenerateSimplex = 12;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
m_cachedSeparatingAxis = newCachedSeparatingAxis;
|
||||
|
||||
//degeneracy, this is typically due to invalid/uninitialized worldtransforms for a btCollisionObject
|
||||
if (m_curIter++ > gGjkMaxIter)
|
||||
{
|
||||
#if defined(DEBUG) || defined (_DEBUG)
|
||||
|
||||
printf("btGjkPairDetector maxIter exceeded:%i\n",m_curIter);
|
||||
printf("sepAxis=(%f,%f,%f), squaredDistance = %f\n",
|
||||
m_cachedSeparatingAxis.getX(),
|
||||
m_cachedSeparatingAxis.getY(),
|
||||
m_cachedSeparatingAxis.getZ(),
|
||||
squaredDistance);
|
||||
#endif //
|
||||
|
||||
//redundant m_simplexSolver->compute_points(pointOnA, pointOnB);
|
||||
|
||||
//are we getting any closer ?
|
||||
if (previousSquaredDistance - squaredDistance <= SIMD_EPSILON * previousSquaredDistance)
|
||||
{
|
||||
// m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
|
||||
checkSimplex = true;
|
||||
m_degenerateSimplex = 12;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
m_cachedSeparatingAxis = newCachedSeparatingAxis;
|
||||
|
||||
//degeneracy, this is typically due to invalid/uninitialized worldtransforms for a btCollisionObject
|
||||
if (m_curIter++ > gGjkMaxIter)
|
||||
{
|
||||
#if defined(DEBUG) || defined(_DEBUG)
|
||||
|
||||
printf("btGjkPairDetector maxIter exceeded:%i\n", m_curIter);
|
||||
printf("sepAxis=(%f,%f,%f), squaredDistance = %f\n",
|
||||
m_cachedSeparatingAxis.getX(),
|
||||
m_cachedSeparatingAxis.getY(),
|
||||
m_cachedSeparatingAxis.getZ(),
|
||||
squaredDistance);
|
||||
#endif
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool check = (!simplexSolver.fullSimplex());
|
||||
//bool check = (!m_simplexSolver->fullSimplex() && squaredDistance > SIMD_EPSILON * m_simplexSolver->maxVertex());
|
||||
|
||||
if (!check)
|
||||
{
|
||||
//do we need this backup_closest here ?
|
||||
// m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
|
||||
m_degenerateSimplex = 13;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (checkSimplex)
|
||||
{
|
||||
simplexSolver.compute_points(pointOnA, pointOnB);
|
||||
normalInB = m_cachedSeparatingAxis;
|
||||
|
||||
btScalar lenSqr =m_cachedSeparatingAxis.length2();
|
||||
|
||||
//valid normal
|
||||
if (lenSqr < 0.0001)
|
||||
{
|
||||
m_degenerateSimplex = 5;
|
||||
}
|
||||
if (lenSqr > SIMD_EPSILON*SIMD_EPSILON)
|
||||
{
|
||||
btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
|
||||
normalInB *= rlen; //normalize
|
||||
|
||||
btScalar s = btSqrt(squaredDistance);
|
||||
|
||||
btAssert(s > btScalar(0.0));
|
||||
pointOnA -= m_cachedSeparatingAxis * (marginA / s);
|
||||
pointOnB += m_cachedSeparatingAxis * (marginB / s);
|
||||
distance = ((btScalar(1.)/rlen) - margin);
|
||||
isValid = true;
|
||||
|
||||
m_lastUsedMethod = 1;
|
||||
} else
|
||||
{
|
||||
m_lastUsedMethod = 2;
|
||||
}
|
||||
}
|
||||
|
||||
bool catchDegeneratePenetrationCase =
|
||||
(m_catchDegeneracies && m_degenerateSimplex && ((distance+margin) < 0.01));
|
||||
|
||||
//if (checkPenetration && !isValid)
|
||||
if (checkPenetration && (!isValid || catchDegeneratePenetrationCase ))
|
||||
{
|
||||
//penetration case
|
||||
|
||||
//if there is no way to handle penetrations, bail out
|
||||
|
||||
// Penetration depth case.
|
||||
btVector3 tmpPointOnA,tmpPointOnB;
|
||||
|
||||
m_cachedSeparatingAxis.setZero();
|
||||
|
||||
bool isValid2 = btGjkEpaCalcPenDepth(a,b,
|
||||
colDesc,
|
||||
m_cachedSeparatingAxis, tmpPointOnA, tmpPointOnB);
|
||||
|
||||
if (isValid2)
|
||||
{
|
||||
btVector3 tmpNormalInB = tmpPointOnB-tmpPointOnA;
|
||||
btScalar lenSqr = tmpNormalInB.length2();
|
||||
if (lenSqr <= (SIMD_EPSILON*SIMD_EPSILON))
|
||||
{
|
||||
tmpNormalInB = m_cachedSeparatingAxis;
|
||||
lenSqr = m_cachedSeparatingAxis.length2();
|
||||
}
|
||||
|
||||
if (lenSqr > (SIMD_EPSILON*SIMD_EPSILON))
|
||||
{
|
||||
tmpNormalInB /= btSqrt(lenSqr);
|
||||
btScalar distance2 = -(tmpPointOnA-tmpPointOnB).length();
|
||||
//only replace valid penetrations when the result is deeper (check)
|
||||
if (!isValid || (distance2 < distance))
|
||||
{
|
||||
distance = distance2;
|
||||
pointOnA = tmpPointOnA;
|
||||
pointOnB = tmpPointOnB;
|
||||
normalInB = tmpNormalInB;
|
||||
|
||||
isValid = true;
|
||||
m_lastUsedMethod = 3;
|
||||
} else
|
||||
{
|
||||
m_lastUsedMethod = 8;
|
||||
}
|
||||
} else
|
||||
{
|
||||
m_lastUsedMethod = 9;
|
||||
}
|
||||
} else
|
||||
|
||||
{
|
||||
///this is another degenerate case, where the initial GJK calculation reports a degenerate case
|
||||
///EPA reports no penetration, and the second GJK (using the supporting vector without margin)
|
||||
///reports a valid positive distance. Use the results of the second GJK instead of failing.
|
||||
///thanks to Jacob.Langford for the reproduction case
|
||||
///http://code.google.com/p/bullet/issues/detail?id=250
|
||||
|
||||
|
||||
if (m_cachedSeparatingAxis.length2() > btScalar(0.))
|
||||
{
|
||||
btScalar distance2 = (tmpPointOnA-tmpPointOnB).length()-margin;
|
||||
//only replace valid distances when the distance is less
|
||||
if (!isValid || (distance2 < distance))
|
||||
{
|
||||
distance = distance2;
|
||||
pointOnA = tmpPointOnA;
|
||||
pointOnB = tmpPointOnB;
|
||||
pointOnA -= m_cachedSeparatingAxis * marginA ;
|
||||
pointOnB += m_cachedSeparatingAxis * marginB ;
|
||||
normalInB = m_cachedSeparatingAxis;
|
||||
normalInB.normalize();
|
||||
|
||||
isValid = true;
|
||||
m_lastUsedMethod = 6;
|
||||
} else
|
||||
{
|
||||
m_lastUsedMethod = 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (isValid && ((distance < 0) || (distance*distance < colDesc.m_maximumDistanceSquared)))
|
||||
{
|
||||
|
||||
m_cachedSeparatingAxis = normalInB;
|
||||
m_cachedSeparatingDistance = distance;
|
||||
distInfo->m_distance = distance;
|
||||
distInfo->m_normalBtoA = normalInB;
|
||||
distInfo->m_pointOnB = pointOnB;
|
||||
distInfo->m_pointOnA = pointOnB+normalInB*distance;
|
||||
return 0;
|
||||
}
|
||||
return -m_lastUsedMethod;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
bool check = (!simplexSolver.fullSimplex());
|
||||
//bool check = (!m_simplexSolver->fullSimplex() && squaredDistance > SIMD_EPSILON * m_simplexSolver->maxVertex());
|
||||
|
||||
if (!check)
|
||||
{
|
||||
//do we need this backup_closest here ?
|
||||
// m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
|
||||
m_degenerateSimplex = 13;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (checkSimplex)
|
||||
{
|
||||
simplexSolver.compute_points(pointOnA, pointOnB);
|
||||
normalInB = m_cachedSeparatingAxis;
|
||||
|
||||
btScalar lenSqr = m_cachedSeparatingAxis.length2();
|
||||
|
||||
//valid normal
|
||||
if (lenSqr < 0.0001)
|
||||
{
|
||||
m_degenerateSimplex = 5;
|
||||
}
|
||||
if (lenSqr > SIMD_EPSILON * SIMD_EPSILON)
|
||||
{
|
||||
btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
|
||||
normalInB *= rlen; //normalize
|
||||
|
||||
btScalar s = btSqrt(squaredDistance);
|
||||
|
||||
btAssert(s > btScalar(0.0));
|
||||
pointOnA -= m_cachedSeparatingAxis * (marginA / s);
|
||||
pointOnB += m_cachedSeparatingAxis * (marginB / s);
|
||||
distance = ((btScalar(1.) / rlen) - margin);
|
||||
isValid = true;
|
||||
|
||||
m_lastUsedMethod = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_lastUsedMethod = 2;
|
||||
}
|
||||
}
|
||||
|
||||
bool catchDegeneratePenetrationCase =
|
||||
(m_catchDegeneracies && m_degenerateSimplex && ((distance + margin) < 0.01));
|
||||
|
||||
//if (checkPenetration && !isValid)
|
||||
if (checkPenetration && (!isValid || catchDegeneratePenetrationCase))
|
||||
{
|
||||
//penetration case
|
||||
|
||||
//if there is no way to handle penetrations, bail out
|
||||
|
||||
// Penetration depth case.
|
||||
btVector3 tmpPointOnA, tmpPointOnB;
|
||||
|
||||
m_cachedSeparatingAxis.setZero();
|
||||
|
||||
bool isValid2 = btGjkEpaCalcPenDepth(a, b,
|
||||
colDesc,
|
||||
m_cachedSeparatingAxis, tmpPointOnA, tmpPointOnB);
|
||||
|
||||
if (isValid2)
|
||||
{
|
||||
btVector3 tmpNormalInB = tmpPointOnB - tmpPointOnA;
|
||||
btScalar lenSqr = tmpNormalInB.length2();
|
||||
if (lenSqr <= (SIMD_EPSILON * SIMD_EPSILON))
|
||||
{
|
||||
tmpNormalInB = m_cachedSeparatingAxis;
|
||||
lenSqr = m_cachedSeparatingAxis.length2();
|
||||
}
|
||||
|
||||
if (lenSqr > (SIMD_EPSILON * SIMD_EPSILON))
|
||||
{
|
||||
tmpNormalInB /= btSqrt(lenSqr);
|
||||
btScalar distance2 = -(tmpPointOnA - tmpPointOnB).length();
|
||||
//only replace valid penetrations when the result is deeper (check)
|
||||
if (!isValid || (distance2 < distance))
|
||||
{
|
||||
distance = distance2;
|
||||
pointOnA = tmpPointOnA;
|
||||
pointOnB = tmpPointOnB;
|
||||
normalInB = tmpNormalInB;
|
||||
|
||||
isValid = true;
|
||||
m_lastUsedMethod = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_lastUsedMethod = 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_lastUsedMethod = 9;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
{
|
||||
///this is another degenerate case, where the initial GJK calculation reports a degenerate case
|
||||
///EPA reports no penetration, and the second GJK (using the supporting vector without margin)
|
||||
///reports a valid positive distance. Use the results of the second GJK instead of failing.
|
||||
///thanks to Jacob.Langford for the reproduction case
|
||||
///http://code.google.com/p/bullet/issues/detail?id=250
|
||||
|
||||
if (m_cachedSeparatingAxis.length2() > btScalar(0.))
|
||||
{
|
||||
btScalar distance2 = (tmpPointOnA - tmpPointOnB).length() - margin;
|
||||
//only replace valid distances when the distance is less
|
||||
if (!isValid || (distance2 < distance))
|
||||
{
|
||||
distance = distance2;
|
||||
pointOnA = tmpPointOnA;
|
||||
pointOnB = tmpPointOnB;
|
||||
pointOnA -= m_cachedSeparatingAxis * marginA;
|
||||
pointOnB += m_cachedSeparatingAxis * marginB;
|
||||
normalInB = m_cachedSeparatingAxis;
|
||||
normalInB.normalize();
|
||||
|
||||
isValid = true;
|
||||
m_lastUsedMethod = 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_lastUsedMethod = 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isValid && ((distance < 0) || (distance * distance < colDesc.m_maximumDistanceSquared)))
|
||||
{
|
||||
m_cachedSeparatingAxis = normalInB;
|
||||
m_cachedSeparatingDistance = distance;
|
||||
distInfo->m_distance = distance;
|
||||
distInfo->m_normalBtoA = normalInB;
|
||||
distInfo->m_pointOnB = pointOnB;
|
||||
distInfo->m_pointOnA = pointOnB + normalInB * distance;
|
||||
return 0;
|
||||
}
|
||||
return -m_lastUsedMethod;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif //BT_GJK_EPA_PENETATION_CONVEX_COLLISION_H
|
||||
#endif //BT_GJK_EPA_PENETATION_CONVEX_COLLISION_H
|
||||
|
||||
@@ -13,7 +13,6 @@ subject to the following restrictions:
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "btContinuousConvexCollision.h"
|
||||
#include "BulletCollision/CollisionShapes/btConvexShape.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
|
||||
@@ -24,59 +23,60 @@ subject to the following restrictions:
|
||||
#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_convexB1(convexB),m_planeShape(0)
|
||||
btContinuousConvexCollision::btContinuousConvexCollision(const btConvexShape* convexA, const btConvexShape* convexB, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver)
|
||||
: m_simplexSolver(simplexSolver),
|
||||
m_penetrationDepthSolver(penetrationDepthSolver),
|
||||
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)
|
||||
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)
|
||||
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 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
|
||||
gjk.getClosestPoints(input, pointCollector, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
//convex versus plane
|
||||
const btConvexShape* convexShape = m_convexA;
|
||||
const btStaticPlaneShape* planeShape = m_planeShape;
|
||||
|
||||
|
||||
const btVector3& planeNormal = planeShape->getPlaneNormal();
|
||||
const btScalar& planeConstant = planeShape->getPlaneConstant();
|
||||
|
||||
|
||||
btTransform convexWorldTransform = transA;
|
||||
btTransform convexInPlaneTrans;
|
||||
convexInPlaneTrans= transB.inverse() * convexWorldTransform;
|
||||
convexInPlaneTrans = transB.inverse() * convexWorldTransform;
|
||||
btTransform planeInConvex;
|
||||
planeInConvex= convexWorldTransform.inverse() * transB;
|
||||
|
||||
btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal);
|
||||
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 vtxInPlaneProjected = vtxInPlane - distance * planeNormal;
|
||||
btVector3 vtxInPlaneWorld = transB * vtxInPlaneProjected;
|
||||
btVector3 normalOnSurfaceB = transB.getBasis() * planeNormal;
|
||||
|
||||
@@ -87,36 +87,33 @@ void btContinuousConvexCollision::computeClosestPoints( const btTransform& trans
|
||||
}
|
||||
}
|
||||
|
||||
bool btContinuousConvexCollision::calcTimeOfImpact(
|
||||
const btTransform& fromA,
|
||||
const btTransform& toA,
|
||||
const btTransform& fromB,
|
||||
const btTransform& toB,
|
||||
CastResult& result)
|
||||
bool btContinuousConvexCollision::calcTimeOfImpact(
|
||||
const btTransform& fromA,
|
||||
const btTransform& toA,
|
||||
const btTransform& fromB,
|
||||
const btTransform& toB,
|
||||
CastResult& result)
|
||||
{
|
||||
|
||||
|
||||
/// compute linear and angular velocity for this interval, to interpolate
|
||||
btVector3 linVelA,angVelA,linVelB,angVelB;
|
||||
btTransformUtil::calculateVelocity(fromA,toA,btScalar(1.),linVelA,angVelA);
|
||||
btTransformUtil::calculateVelocity(fromB,toB,btScalar(1.),linVelB,angVelB);
|
||||
|
||||
btVector3 linVelA, angVelA, linVelB, angVelB;
|
||||
btTransformUtil::calculateVelocity(fromA, toA, btScalar(1.), linVelA, angVelA);
|
||||
btTransformUtil::calculateVelocity(fromB, toB, btScalar(1.), linVelB, angVelB);
|
||||
|
||||
btScalar boundingRadiusA = m_convexA->getAngularMotionDisc();
|
||||
btScalar boundingRadiusB = m_convexB1?m_convexB1->getAngularMotionDisc():0.f;
|
||||
btScalar boundingRadiusB = m_convexB1 ? m_convexB1->getAngularMotionDisc() : 0.f;
|
||||
|
||||
btScalar maxAngularProjectedVelocity = angVelA.length() * boundingRadiusA + angVelB.length() * boundingRadiusB;
|
||||
btVector3 relLinVel = (linVelB-linVelA);
|
||||
btVector3 relLinVel = (linVelB - linVelA);
|
||||
|
||||
btScalar relLinVelocLength = (linVelB-linVelA).length();
|
||||
|
||||
if ((relLinVelocLength+maxAngularProjectedVelocity) == 0.f)
|
||||
btScalar relLinVelocLength = (linVelB - linVelA).length();
|
||||
|
||||
if ((relLinVelocLength + maxAngularProjectedVelocity) == 0.f)
|
||||
return false;
|
||||
|
||||
btScalar lambda = btScalar(0.);
|
||||
|
||||
btVector3 n;
|
||||
n.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
|
||||
n.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
|
||||
bool hasResult = false;
|
||||
btVector3 c;
|
||||
|
||||
@@ -126,14 +123,13 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
|
||||
int numIter = 0;
|
||||
//first solution, using GJK
|
||||
|
||||
|
||||
btScalar radius = 0.001f;
|
||||
// result.drawCoordSystem(sphereTr);
|
||||
// result.drawCoordSystem(sphereTr);
|
||||
|
||||
btPointCollector pointCollector1;
|
||||
btPointCollector pointCollector1;
|
||||
|
||||
{
|
||||
computeClosestPoints(fromA,fromB,pointCollector1);
|
||||
{
|
||||
computeClosestPoints(fromA, fromB, pointCollector1);
|
||||
|
||||
hasResult = pointCollector1.m_hasResult;
|
||||
c = pointCollector1.m_pointInWorld;
|
||||
@@ -145,7 +141,7 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
|
||||
dist = pointCollector1.m_distance + result.m_allowedPenetration;
|
||||
n = pointCollector1.m_normalOnBInWorld;
|
||||
btScalar projectedLinearVelocity = relLinVel.dot(n);
|
||||
if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=SIMD_EPSILON)
|
||||
if ((projectedLinearVelocity + maxAngularProjectedVelocity) <= SIMD_EPSILON)
|
||||
return false;
|
||||
|
||||
//not close enough
|
||||
@@ -153,18 +149,17 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
|
||||
{
|
||||
if (result.m_debugDrawer)
|
||||
{
|
||||
result.m_debugDrawer->drawSphere(c,0.2f,btVector3(1,1,1));
|
||||
result.m_debugDrawer->drawSphere(c, 0.2f, btVector3(1, 1, 1));
|
||||
}
|
||||
btScalar dLambda = btScalar(0.);
|
||||
|
||||
projectedLinearVelocity = relLinVel.dot(n);
|
||||
|
||||
|
||||
//don't report time of impact for motion away from the contact normal (or causes minor penetration)
|
||||
if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=SIMD_EPSILON)
|
||||
if ((projectedLinearVelocity + maxAngularProjectedVelocity) <= SIMD_EPSILON)
|
||||
return false;
|
||||
|
||||
dLambda = dist / (projectedLinearVelocity+ maxAngularProjectedVelocity);
|
||||
|
||||
dLambda = dist / (projectedLinearVelocity + maxAngularProjectedVelocity);
|
||||
|
||||
lambda += dLambda;
|
||||
|
||||
@@ -181,28 +176,29 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
|
||||
lastLambda = lambda;
|
||||
|
||||
//interpolate to next lambda
|
||||
btTransform interpolatedTransA,interpolatedTransB,relativeTrans;
|
||||
btTransform interpolatedTransA, interpolatedTransB, relativeTrans;
|
||||
|
||||
btTransformUtil::integrateTransform(fromA,linVelA,angVelA,lambda,interpolatedTransA);
|
||||
btTransformUtil::integrateTransform(fromB,linVelB,angVelB,lambda,interpolatedTransB);
|
||||
btTransformUtil::integrateTransform(fromA, linVelA, angVelA, lambda, interpolatedTransA);
|
||||
btTransformUtil::integrateTransform(fromB, linVelB, angVelB, lambda, interpolatedTransB);
|
||||
relativeTrans = interpolatedTransB.inverseTimes(interpolatedTransA);
|
||||
|
||||
if (result.m_debugDrawer)
|
||||
{
|
||||
result.m_debugDrawer->drawSphere(interpolatedTransA.getOrigin(),0.2f,btVector3(1,0,0));
|
||||
result.m_debugDrawer->drawSphere(interpolatedTransA.getOrigin(), 0.2f, btVector3(1, 0, 0));
|
||||
}
|
||||
|
||||
result.DebugDraw( lambda );
|
||||
result.DebugDraw(lambda);
|
||||
|
||||
btPointCollector pointCollector;
|
||||
computeClosestPoints(interpolatedTransA,interpolatedTransB,pointCollector);
|
||||
btPointCollector pointCollector;
|
||||
computeClosestPoints(interpolatedTransA, interpolatedTransB, pointCollector);
|
||||
|
||||
if (pointCollector.m_hasResult)
|
||||
{
|
||||
dist = pointCollector.m_distance+result.m_allowedPenetration;
|
||||
c = pointCollector.m_pointInWorld;
|
||||
dist = pointCollector.m_distance + result.m_allowedPenetration;
|
||||
c = pointCollector.m_pointInWorld;
|
||||
n = pointCollector.m_normalOnBInWorld;
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
result.reportFailure(-1, numIter);
|
||||
return false;
|
||||
@@ -215,7 +211,7 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
result.m_fraction = lambda;
|
||||
result.m_normal = n;
|
||||
result.m_hitPoint = c;
|
||||
@@ -224,4 +220,3 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ subject to the following restrictions:
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BT_CONTINUOUS_COLLISION_CONVEX_CAST_H
|
||||
#define BT_CONTINUOUS_COLLISION_CONVEX_CAST_H
|
||||
|
||||
@@ -30,30 +29,25 @@ class btStaticPlaneShape;
|
||||
class btContinuousConvexCollision : public btConvexCast
|
||||
{
|
||||
btSimplexSolverInterface* m_simplexSolver;
|
||||
btConvexPenetrationDepthSolver* m_penetrationDepthSolver;
|
||||
const btConvexShape* m_convexA;
|
||||
btConvexPenetrationDepthSolver* m_penetrationDepthSolver;
|
||||
const btConvexShape* m_convexA;
|
||||
//second object is either a convex or a plane (code sharing)
|
||||
const btConvexShape* m_convexB1;
|
||||
const btStaticPlaneShape* m_planeShape;
|
||||
const btConvexShape* m_convexB1;
|
||||
const btStaticPlaneShape* m_planeShape;
|
||||
|
||||
void computeClosestPoints( const btTransform& transA, const btTransform& transB,struct btPointCollector& pointCollector);
|
||||
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 btConvexShape* shapeB ,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver);
|
||||
|
||||
btContinuousConvexCollision(const btConvexShape* shapeA,const btStaticPlaneShape* plane );
|
||||
|
||||
virtual bool calcTimeOfImpact(
|
||||
const btTransform& fromA,
|
||||
const btTransform& toA,
|
||||
const btTransform& fromB,
|
||||
const btTransform& toB,
|
||||
CastResult& result);
|
||||
|
||||
btContinuousConvexCollision(const btConvexShape* shapeA, const btStaticPlaneShape* plane);
|
||||
|
||||
virtual bool calcTimeOfImpact(
|
||||
const btTransform& fromA,
|
||||
const btTransform& toA,
|
||||
const btTransform& fromB,
|
||||
const btTransform& toB,
|
||||
CastResult& result);
|
||||
};
|
||||
|
||||
|
||||
#endif //BT_CONTINUOUS_COLLISION_CONVEX_CAST_H
|
||||
|
||||
#endif //BT_CONTINUOUS_COLLISION_CONVEX_CAST_H
|
||||
|
||||
@@ -13,7 +13,6 @@ subject to the following restrictions:
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BT_CONVEX_CAST_H
|
||||
#define BT_CONVEX_CAST_H
|
||||
|
||||
@@ -27,47 +26,46 @@ class btMinkowskiSumShape;
|
||||
class btConvexCast
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
virtual ~btConvexCast();
|
||||
|
||||
///RayResult stores the closest result
|
||||
/// alternatively, add a callback method to decide about closest/all results
|
||||
struct CastResult
|
||||
struct CastResult
|
||||
{
|
||||
//virtual bool addRayResult(const btVector3& normal,btScalar fraction) = 0;
|
||||
|
||||
virtual void DebugDraw(btScalar fraction) {(void)fraction;}
|
||||
virtual void drawCoordSystem(const btTransform& trans) {(void)trans;}
|
||||
virtual void reportFailure(int errNo, int numIterations) {(void)errNo;(void)numIterations;}
|
||||
|
||||
virtual void DebugDraw(btScalar fraction) { (void)fraction; }
|
||||
virtual void drawCoordSystem(const btTransform& trans) { (void)trans; }
|
||||
virtual void reportFailure(int errNo, int numIterations)
|
||||
{
|
||||
(void)errNo;
|
||||
(void)numIterations;
|
||||
}
|
||||
CastResult()
|
||||
:m_fraction(btScalar(BT_LARGE_FLOAT)),
|
||||
m_debugDrawer(0),
|
||||
m_allowedPenetration(btScalar(0))
|
||||
: m_fraction(btScalar(BT_LARGE_FLOAT)),
|
||||
m_debugDrawer(0),
|
||||
m_allowedPenetration(btScalar(0))
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~CastResult(){};
|
||||
|
||||
virtual ~CastResult() {};
|
||||
|
||||
btTransform m_hitTransformA;
|
||||
btTransform m_hitTransformB;
|
||||
btVector3 m_normal;
|
||||
btVector3 m_hitPoint;
|
||||
btScalar m_fraction; //input and output
|
||||
btTransform m_hitTransformA;
|
||||
btTransform m_hitTransformB;
|
||||
btVector3 m_normal;
|
||||
btVector3 m_hitPoint;
|
||||
btScalar m_fraction; //input and output
|
||||
btIDebugDraw* m_debugDrawer;
|
||||
btScalar m_allowedPenetration;
|
||||
|
||||
btScalar m_allowedPenetration;
|
||||
};
|
||||
|
||||
|
||||
/// cast a convex against another convex object
|
||||
virtual bool calcTimeOfImpact(
|
||||
const btTransform& fromA,
|
||||
const btTransform& toA,
|
||||
const btTransform& fromB,
|
||||
const btTransform& toB,
|
||||
CastResult& result) = 0;
|
||||
virtual bool calcTimeOfImpact(
|
||||
const btTransform& fromA,
|
||||
const btTransform& toA,
|
||||
const btTransform& fromB,
|
||||
const btTransform& toB,
|
||||
CastResult& result) = 0;
|
||||
};
|
||||
|
||||
#endif //BT_CONVEX_CAST_H
|
||||
#endif //BT_CONVEX_CAST_H
|
||||
|
||||
@@ -13,7 +13,6 @@ subject to the following restrictions:
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BT_CONVEX_PENETRATION_DEPTH_H
|
||||
#define BT_CONVEX_PENETRATION_DEPTH_H
|
||||
|
||||
@@ -25,16 +24,12 @@ class btTransform;
|
||||
///ConvexPenetrationDepthSolver provides an interface for penetration depth calculation.
|
||||
class btConvexPenetrationDepthSolver
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~btConvexPenetrationDepthSolver() {};
|
||||
virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver,
|
||||
const btConvexShape* convexA,const btConvexShape* convexB,
|
||||
const btTransform& transA,const btTransform& transB,
|
||||
btVector3& v, btVector3& pa, btVector3& pb,
|
||||
class btIDebugDraw* debugDraw) = 0;
|
||||
|
||||
|
||||
public:
|
||||
virtual ~btConvexPenetrationDepthSolver(){};
|
||||
virtual bool calcPenDepth(btSimplexSolverInterface& simplexSolver,
|
||||
const btConvexShape* convexA, const btConvexShape* convexB,
|
||||
const btTransform& transA, const btTransform& transB,
|
||||
btVector3& v, btVector3& pa, btVector3& pb,
|
||||
class btIDebugDraw* debugDraw) = 0;
|
||||
};
|
||||
#endif //BT_CONVEX_PENETRATION_DEPTH_H
|
||||
|
||||
#endif //BT_CONVEX_PENETRATION_DEPTH_H
|
||||
|
||||
@@ -13,7 +13,6 @@ subject to the following restrictions:
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H
|
||||
#define BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H
|
||||
|
||||
@@ -27,64 +26,60 @@ subject to the following restrictions:
|
||||
/// by taking closestPointInA = closestPointInB + m_distance * m_normalOnSurfaceB
|
||||
struct btDiscreteCollisionDetectorInterface
|
||||
{
|
||||
|
||||
struct Result
|
||||
{
|
||||
|
||||
virtual ~Result(){}
|
||||
virtual ~Result() {}
|
||||
|
||||
///setShapeIdentifiersA/B provides experimental support for per-triangle material / custom material combiner
|
||||
virtual void setShapeIdentifiersA(int partId0,int index0)=0;
|
||||
virtual void setShapeIdentifiersB(int partId1,int index1)=0;
|
||||
virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)=0;
|
||||
virtual void setShapeIdentifiersA(int partId0, int index0) = 0;
|
||||
virtual void setShapeIdentifiersB(int partId1, int index1) = 0;
|
||||
virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth) = 0;
|
||||
};
|
||||
|
||||
struct ClosestPointInput
|
||||
{
|
||||
ClosestPointInput()
|
||||
:m_maximumDistanceSquared(btScalar(BT_LARGE_FLOAT))
|
||||
: m_maximumDistanceSquared(btScalar(BT_LARGE_FLOAT))
|
||||
{
|
||||
}
|
||||
|
||||
btTransform m_transformA;
|
||||
btTransform m_transformB;
|
||||
btScalar m_maximumDistanceSquared;
|
||||
btScalar m_maximumDistanceSquared;
|
||||
};
|
||||
|
||||
virtual ~btDiscreteCollisionDetectorInterface() {};
|
||||
virtual ~btDiscreteCollisionDetectorInterface(){};
|
||||
|
||||
//
|
||||
// give either closest points (distance > 0) or penetration (distance)
|
||||
// the normal always points from B towards A
|
||||
//
|
||||
virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false) = 0;
|
||||
|
||||
virtual void getClosestPoints(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw, bool swapResults = false) = 0;
|
||||
};
|
||||
|
||||
struct btStorageResult : public btDiscreteCollisionDetectorInterface::Result
|
||||
{
|
||||
btVector3 m_normalOnSurfaceB;
|
||||
btVector3 m_closestPointInB;
|
||||
btScalar m_distance; //negative means penetration !
|
||||
btVector3 m_normalOnSurfaceB;
|
||||
btVector3 m_closestPointInB;
|
||||
btScalar m_distance; //negative means penetration !
|
||||
|
||||
protected:
|
||||
btStorageResult() : m_distance(btScalar(BT_LARGE_FLOAT))
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual ~btStorageResult() {};
|
||||
protected:
|
||||
btStorageResult() : m_distance(btScalar(BT_LARGE_FLOAT))
|
||||
{
|
||||
}
|
||||
|
||||
virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
|
||||
public:
|
||||
virtual ~btStorageResult(){};
|
||||
|
||||
virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
|
||||
{
|
||||
if (depth < m_distance)
|
||||
{
|
||||
if (depth < m_distance)
|
||||
{
|
||||
m_normalOnSurfaceB = normalOnBInWorld;
|
||||
m_closestPointInB = pointInWorld;
|
||||
m_distance = depth;
|
||||
}
|
||||
m_normalOnSurfaceB = normalOnBInWorld;
|
||||
m_closestPointInB = pointInWorld;
|
||||
m_distance = depth;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif //BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H
|
||||
|
||||
#endif //BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H
|
||||
|
||||
@@ -13,7 +13,6 @@ subject to the following restrictions:
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef GJK_COLLISION_DESCRIPTION_H
|
||||
#define GJK_COLLISION_DESCRIPTION_H
|
||||
|
||||
@@ -21,21 +20,20 @@ subject to the following restrictions:
|
||||
|
||||
struct btGjkCollisionDescription
|
||||
{
|
||||
btVector3 m_firstDir;
|
||||
int m_maxGjkIterations;
|
||||
btScalar m_maximumDistanceSquared;
|
||||
btScalar m_gjkRelError2;
|
||||
btGjkCollisionDescription()
|
||||
:m_firstDir(0,1,0),
|
||||
m_maxGjkIterations(1000),
|
||||
m_maximumDistanceSquared(1e30f),
|
||||
m_gjkRelError2(1.0e-6)
|
||||
{
|
||||
}
|
||||
virtual ~btGjkCollisionDescription()
|
||||
{
|
||||
}
|
||||
btVector3 m_firstDir;
|
||||
int m_maxGjkIterations;
|
||||
btScalar m_maximumDistanceSquared;
|
||||
btScalar m_gjkRelError2;
|
||||
btGjkCollisionDescription()
|
||||
: m_firstDir(0, 1, 0),
|
||||
m_maxGjkIterations(1000),
|
||||
m_maximumDistanceSquared(1e30f),
|
||||
m_gjkRelError2(1.0e-6)
|
||||
{
|
||||
}
|
||||
virtual ~btGjkCollisionDescription()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#endif //GJK_COLLISION_DESCRIPTION_H
|
||||
|
||||
#endif //GJK_COLLISION_DESCRIPTION_H
|
||||
|
||||
@@ -13,8 +13,6 @@ subject to the following restrictions:
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "btGjkConvexCast.h"
|
||||
#include "BulletCollision/CollisionShapes/btSphereShape.h"
|
||||
#include "btGjkPairDetector.h"
|
||||
@@ -27,41 +25,39 @@ subject to the following restrictions:
|
||||
#define MAX_ITERATIONS 32
|
||||
#endif
|
||||
|
||||
btGjkConvexCast::btGjkConvexCast(const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver)
|
||||
:m_simplexSolver(simplexSolver),
|
||||
m_convexA(convexA),
|
||||
m_convexB(convexB)
|
||||
btGjkConvexCast::btGjkConvexCast(const btConvexShape* convexA, const btConvexShape* convexB, btSimplexSolverInterface* simplexSolver)
|
||||
: m_simplexSolver(simplexSolver),
|
||||
m_convexA(convexA),
|
||||
m_convexB(convexB)
|
||||
{
|
||||
}
|
||||
|
||||
bool btGjkConvexCast::calcTimeOfImpact(
|
||||
const btTransform& fromA,
|
||||
const btTransform& toA,
|
||||
const btTransform& fromB,
|
||||
const btTransform& toB,
|
||||
CastResult& result)
|
||||
bool btGjkConvexCast::calcTimeOfImpact(
|
||||
const btTransform& fromA,
|
||||
const btTransform& toA,
|
||||
const btTransform& fromB,
|
||||
const btTransform& toB,
|
||||
CastResult& result)
|
||||
{
|
||||
|
||||
|
||||
m_simplexSolver->reset();
|
||||
|
||||
/// compute linear velocity for this interval, to interpolate
|
||||
//assume no rotation/angular velocity, assert here?
|
||||
btVector3 linVelA,linVelB;
|
||||
linVelA = toA.getOrigin()-fromA.getOrigin();
|
||||
linVelB = toB.getOrigin()-fromB.getOrigin();
|
||||
btVector3 linVelA, linVelB;
|
||||
linVelA = toA.getOrigin() - fromA.getOrigin();
|
||||
linVelB = toB.getOrigin() - fromB.getOrigin();
|
||||
|
||||
btScalar radius = btScalar(0.001);
|
||||
btScalar lambda = btScalar(0.);
|
||||
btVector3 v(1,0,0);
|
||||
btVector3 v(1, 0, 0);
|
||||
|
||||
int maxIter = MAX_ITERATIONS;
|
||||
|
||||
btVector3 n;
|
||||
n.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
|
||||
n.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
|
||||
bool hasResult = false;
|
||||
btVector3 c;
|
||||
btVector3 r = (linVelA-linVelB);
|
||||
btVector3 r = (linVelA - linVelB);
|
||||
|
||||
btScalar lastLambda = lambda;
|
||||
//btScalar epsilon = btScalar(0.001);
|
||||
@@ -69,17 +65,14 @@ bool btGjkConvexCast::calcTimeOfImpact(
|
||||
int numIter = 0;
|
||||
//first solution, using GJK
|
||||
|
||||
|
||||
btTransform identityTrans;
|
||||
identityTrans.setIdentity();
|
||||
|
||||
// result.drawCoordSystem(sphereTr);
|
||||
|
||||
// result.drawCoordSystem(sphereTr);
|
||||
btPointCollector pointCollector;
|
||||
|
||||
btPointCollector pointCollector;
|
||||
|
||||
|
||||
btGjkPairDetector gjk(m_convexA,m_convexB,m_simplexSolver,0);//m_penetrationDepthSolver);
|
||||
btGjkPairDetector gjk(m_convexA, m_convexB, m_simplexSolver, 0); //m_penetrationDepthSolver);
|
||||
btGjkPairDetector::ClosestPointInput input;
|
||||
|
||||
//we don't use margins during CCD
|
||||
@@ -87,7 +80,7 @@ bool btGjkConvexCast::calcTimeOfImpact(
|
||||
|
||||
input.m_transformA = fromA;
|
||||
input.m_transformB = fromB;
|
||||
gjk.getClosestPoints(input,pointCollector,0);
|
||||
gjk.getClosestPoints(input, pointCollector, 0);
|
||||
|
||||
hasResult = pointCollector.m_hasResult;
|
||||
c = pointCollector.m_pointInWorld;
|
||||
@@ -98,20 +91,18 @@ bool btGjkConvexCast::calcTimeOfImpact(
|
||||
dist = pointCollector.m_distance;
|
||||
n = pointCollector.m_normalOnBInWorld;
|
||||
|
||||
|
||||
|
||||
//not close enough
|
||||
while (dist > radius)
|
||||
{
|
||||
numIter++;
|
||||
if (numIter > maxIter)
|
||||
{
|
||||
return false; //todo: report a failure
|
||||
return false; //todo: report a failure
|
||||
}
|
||||
btScalar dLambda = btScalar(0.);
|
||||
|
||||
btScalar projectedLinearVelocity = r.dot(n);
|
||||
|
||||
|
||||
dLambda = dist / (projectedLinearVelocity);
|
||||
|
||||
lambda = lambda - dLambda;
|
||||
@@ -132,35 +123,35 @@ bool btGjkConvexCast::calcTimeOfImpact(
|
||||
lastLambda = lambda;
|
||||
|
||||
//interpolate to next lambda
|
||||
result.DebugDraw( lambda );
|
||||
input.m_transformA.getOrigin().setInterpolate3(fromA.getOrigin(),toA.getOrigin(),lambda);
|
||||
input.m_transformB.getOrigin().setInterpolate3(fromB.getOrigin(),toB.getOrigin(),lambda);
|
||||
|
||||
gjk.getClosestPoints(input,pointCollector,0);
|
||||
result.DebugDraw(lambda);
|
||||
input.m_transformA.getOrigin().setInterpolate3(fromA.getOrigin(), toA.getOrigin(), lambda);
|
||||
input.m_transformB.getOrigin().setInterpolate3(fromB.getOrigin(), toB.getOrigin(), lambda);
|
||||
|
||||
gjk.getClosestPoints(input, pointCollector, 0);
|
||||
if (pointCollector.m_hasResult)
|
||||
{
|
||||
if (pointCollector.m_distance < btScalar(0.))
|
||||
{
|
||||
result.m_fraction = lastLambda;
|
||||
n = pointCollector.m_normalOnBInWorld;
|
||||
result.m_normal=n;
|
||||
result.m_normal = n;
|
||||
result.m_hitPoint = pointCollector.m_pointInWorld;
|
||||
return true;
|
||||
}
|
||||
c = pointCollector.m_pointInWorld;
|
||||
c = pointCollector.m_pointInWorld;
|
||||
n = pointCollector.m_normalOnBInWorld;
|
||||
dist = pointCollector.m_distance;
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
//??
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//is n normalized?
|
||||
//don't report time of impact for motion away from the contact normal (or causes minor penetration)
|
||||
if (n.dot(r)>=-result.m_allowedPenetration)
|
||||
if (n.dot(r) >= -result.m_allowedPenetration)
|
||||
return false;
|
||||
|
||||
result.m_fraction = lambda;
|
||||
@@ -170,7 +161,4 @@ bool btGjkConvexCast::calcTimeOfImpact(
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -13,8 +13,6 @@ subject to the following restrictions:
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef BT_GJK_CONVEX_CAST_H
|
||||
#define BT_GJK_CONVEX_CAST_H
|
||||
|
||||
@@ -29,22 +27,20 @@ class btMinkowskiSumShape;
|
||||
///GjkConvexCast performs a raycast on a convex object using support mapping.
|
||||
class btGjkConvexCast : public btConvexCast
|
||||
{
|
||||
btSimplexSolverInterface* m_simplexSolver;
|
||||
const btConvexShape* m_convexA;
|
||||
const btConvexShape* m_convexB;
|
||||
btSimplexSolverInterface* m_simplexSolver;
|
||||
const btConvexShape* m_convexA;
|
||||
const btConvexShape* m_convexB;
|
||||
|
||||
public:
|
||||
|
||||
btGjkConvexCast(const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver);
|
||||
btGjkConvexCast(const btConvexShape* convexA, const btConvexShape* convexB, btSimplexSolverInterface* simplexSolver);
|
||||
|
||||
/// cast a convex against another convex object
|
||||
virtual bool calcTimeOfImpact(
|
||||
const btTransform& fromA,
|
||||
const btTransform& toA,
|
||||
const btTransform& fromB,
|
||||
const btTransform& toB,
|
||||
CastResult& result);
|
||||
|
||||
virtual bool calcTimeOfImpact(
|
||||
const btTransform& fromA,
|
||||
const btTransform& toA,
|
||||
const btTransform& fromB,
|
||||
const btTransform& toB,
|
||||
CastResult& result);
|
||||
};
|
||||
|
||||
#endif //BT_GJK_CONVEX_CAST_H
|
||||
#endif //BT_GJK_CONVEX_CAST_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -28,48 +28,46 @@ GJK-EPA collision solver by Nathanael Presson, 2008
|
||||
#include "BulletCollision/CollisionShapes/btConvexShape.h"
|
||||
|
||||
///btGjkEpaSolver contributed under zlib by Nathanael Presson
|
||||
struct btGjkEpaSolver2
|
||||
struct btGjkEpaSolver2
|
||||
{
|
||||
struct sResults
|
||||
struct sResults
|
||||
{
|
||||
enum eStatus
|
||||
enum eStatus
|
||||
{
|
||||
Separated, /* Shapes doesnt penetrate */
|
||||
Penetrating, /* Shapes are penetrating */
|
||||
GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */
|
||||
EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */
|
||||
} status;
|
||||
btVector3 witnesses[2];
|
||||
btVector3 normal;
|
||||
btScalar distance;
|
||||
Separated, /* Shapes doesnt penetrate */
|
||||
Penetrating, /* Shapes are penetrating */
|
||||
GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */
|
||||
EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */
|
||||
} status;
|
||||
btVector3 witnesses[2];
|
||||
btVector3 normal;
|
||||
btScalar distance;
|
||||
};
|
||||
|
||||
static int StackSizeRequirement();
|
||||
static int StackSizeRequirement();
|
||||
|
||||
static bool Distance( const btConvexShape* shape0,const btTransform& wtrs0,
|
||||
const btConvexShape* shape1,const btTransform& wtrs1,
|
||||
const btVector3& guess,
|
||||
sResults& results);
|
||||
static bool Distance(const btConvexShape* shape0, const btTransform& wtrs0,
|
||||
const btConvexShape* shape1, const btTransform& wtrs1,
|
||||
const btVector3& guess,
|
||||
sResults& results);
|
||||
|
||||
static bool Penetration(const btConvexShape* shape0,const btTransform& wtrs0,
|
||||
const btConvexShape* shape1,const btTransform& wtrs1,
|
||||
static bool Penetration(const btConvexShape* shape0, const btTransform& wtrs0,
|
||||
const btConvexShape* shape1, const btTransform& wtrs1,
|
||||
const btVector3& guess,
|
||||
sResults& results,
|
||||
bool usemargins=true);
|
||||
bool usemargins = true);
|
||||
#ifndef __SPU__
|
||||
static btScalar SignedDistance( const btVector3& position,
|
||||
btScalar margin,
|
||||
const btConvexShape* shape,
|
||||
const btTransform& wtrs,
|
||||
sResults& results);
|
||||
|
||||
static bool SignedDistance( const btConvexShape* shape0,const btTransform& wtrs0,
|
||||
const btConvexShape* shape1,const btTransform& wtrs1,
|
||||
const btVector3& guess,
|
||||
sResults& results);
|
||||
#endif //__SPU__
|
||||
static btScalar SignedDistance(const btVector3& position,
|
||||
btScalar margin,
|
||||
const btConvexShape* shape,
|
||||
const btTransform& wtrs,
|
||||
sResults& results);
|
||||
|
||||
static bool SignedDistance(const btConvexShape* shape0, const btTransform& wtrs0,
|
||||
const btConvexShape* shape1, const btTransform& wtrs1,
|
||||
const btVector3& guess,
|
||||
sResults& results);
|
||||
#endif //__SPU__
|
||||
};
|
||||
|
||||
#endif //BT_GJK_EPA2_H
|
||||
|
||||
#endif //BT_GJK_EPA2_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,16 +18,14 @@ subject to the following restrictions:
|
||||
#include "BulletCollision/CollisionShapes/btConvexShape.h"
|
||||
#include "btGjkEpaPenetrationDepthSolver.h"
|
||||
|
||||
|
||||
#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
|
||||
|
||||
bool btGjkEpaPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& simplexSolver,
|
||||
const btConvexShape* pConvexA, const btConvexShape* pConvexB,
|
||||
const btTransform& transformA, const btTransform& transformB,
|
||||
btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB,
|
||||
class btIDebugDraw* debugDraw)
|
||||
const btConvexShape* pConvexA, const btConvexShape* pConvexB,
|
||||
const btTransform& transformA, const btTransform& transformB,
|
||||
btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB,
|
||||
class btIDebugDraw* debugDraw)
|
||||
{
|
||||
|
||||
(void)debugDraw;
|
||||
(void)v;
|
||||
(void)simplexSolver;
|
||||
@@ -49,13 +47,13 @@ bool btGjkEpaPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& simp
|
||||
for (int i = 0; i < numVectors; i++)
|
||||
{
|
||||
simplexSolver.reset();
|
||||
btVector3 guessVector = guessVectors[i];
|
||||
btVector3 guessVector = guessVectors[i];
|
||||
|
||||
btGjkEpaSolver2::sResults results;
|
||||
btGjkEpaSolver2::sResults results;
|
||||
|
||||
if (btGjkEpaSolver2::Penetration(pConvexA, transformA,
|
||||
pConvexB, transformB,
|
||||
guessVector, results))
|
||||
pConvexB, transformB,
|
||||
guessVector, results))
|
||||
|
||||
{
|
||||
wWitnessOnA = results.witnesses[0];
|
||||
@@ -81,4 +79,3 @@ bool btGjkEpaPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& simp
|
||||
v.setValue(0, 0, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,21 +23,18 @@ subject to the following restrictions:
|
||||
///calculate the penetration depth between two convex shapes.
|
||||
class btGjkEpaPenetrationDepthSolver : public btConvexPenetrationDepthSolver
|
||||
{
|
||||
public :
|
||||
public:
|
||||
btGjkEpaPenetrationDepthSolver()
|
||||
{
|
||||
}
|
||||
|
||||
btGjkEpaPenetrationDepthSolver()
|
||||
{
|
||||
}
|
||||
|
||||
bool calcPenDepth( btSimplexSolverInterface& simplexSolver,
|
||||
const btConvexShape* pConvexA, const btConvexShape* pConvexB,
|
||||
const btTransform& transformA, const btTransform& transformB,
|
||||
btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB,
|
||||
class btIDebugDraw* debugDraw);
|
||||
|
||||
private :
|
||||
bool calcPenDepth(btSimplexSolverInterface& simplexSolver,
|
||||
const btConvexShape* pConvexA, const btConvexShape* pConvexB,
|
||||
const btTransform& transformA, const btTransform& transformB,
|
||||
btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB,
|
||||
class btIDebugDraw* debugDraw);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // BT_GJP_EPA_PENETRATION_DEPTH_H
|
||||
|
||||
#endif // BT_GJP_EPA_PENETRATION_DEPTH_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -13,9 +13,6 @@ subject to the following restrictions:
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef BT_GJK_PAIR_DETECTOR_H
|
||||
#define BT_GJK_PAIR_DETECTOR_H
|
||||
|
||||
@@ -29,39 +26,34 @@ class btConvexPenetrationDepthSolver;
|
||||
/// btGjkPairDetector uses GJK to implement the btDiscreteCollisionDetectorInterface
|
||||
class btGjkPairDetector : public btDiscreteCollisionDetectorInterface
|
||||
{
|
||||
|
||||
|
||||
btVector3 m_cachedSeparatingAxis;
|
||||
btConvexPenetrationDepthSolver* m_penetrationDepthSolver;
|
||||
btVector3 m_cachedSeparatingAxis;
|
||||
btConvexPenetrationDepthSolver* m_penetrationDepthSolver;
|
||||
btSimplexSolverInterface* m_simplexSolver;
|
||||
const btConvexShape* m_minkowskiA;
|
||||
const btConvexShape* m_minkowskiB;
|
||||
int m_shapeTypeA;
|
||||
int m_shapeTypeA;
|
||||
int m_shapeTypeB;
|
||||
btScalar m_marginA;
|
||||
btScalar m_marginB;
|
||||
btScalar m_marginA;
|
||||
btScalar m_marginB;
|
||||
|
||||
bool m_ignoreMargin;
|
||||
btScalar m_cachedSeparatingDistance;
|
||||
|
||||
bool m_ignoreMargin;
|
||||
btScalar m_cachedSeparatingDistance;
|
||||
|
||||
public:
|
||||
|
||||
//some debugging to fix degeneracy problems
|
||||
int m_lastUsedMethod;
|
||||
int m_curIter;
|
||||
int m_degenerateSimplex;
|
||||
int m_catchDegeneracies;
|
||||
int m_fixContactNormalDirection;
|
||||
int m_lastUsedMethod;
|
||||
int m_curIter;
|
||||
int m_degenerateSimplex;
|
||||
int m_catchDegeneracies;
|
||||
int m_fixContactNormalDirection;
|
||||
|
||||
btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver);
|
||||
btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,int shapeTypeA,int shapeTypeB,btScalar marginA, btScalar marginB, btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver);
|
||||
virtual ~btGjkPairDetector() {};
|
||||
btGjkPairDetector(const btConvexShape* objectA, const btConvexShape* objectB, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver);
|
||||
btGjkPairDetector(const btConvexShape* objectA, const btConvexShape* objectB, int shapeTypeA, int shapeTypeB, btScalar marginA, btScalar marginB, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver);
|
||||
virtual ~btGjkPairDetector(){};
|
||||
|
||||
virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
|
||||
virtual void getClosestPoints(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw, bool swapResults = false);
|
||||
|
||||
void getClosestPointsNonVirtual(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw);
|
||||
|
||||
void getClosestPointsNonVirtual(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw);
|
||||
|
||||
void setMinkowskiA(const btConvexShape* minkA)
|
||||
{
|
||||
@@ -81,23 +73,21 @@ public:
|
||||
{
|
||||
return m_cachedSeparatingAxis;
|
||||
}
|
||||
btScalar getCachedSeparatingDistance() const
|
||||
btScalar getCachedSeparatingDistance() const
|
||||
{
|
||||
return m_cachedSeparatingDistance;
|
||||
}
|
||||
|
||||
void setPenetrationDepthSolver(btConvexPenetrationDepthSolver* penetrationDepthSolver)
|
||||
void setPenetrationDepthSolver(btConvexPenetrationDepthSolver* penetrationDepthSolver)
|
||||
{
|
||||
m_penetrationDepthSolver = penetrationDepthSolver;
|
||||
}
|
||||
|
||||
///don't use setIgnoreMargin, it's for Bullet's internal use
|
||||
void setIgnoreMargin(bool ignoreMargin)
|
||||
void setIgnoreMargin(bool ignoreMargin)
|
||||
{
|
||||
m_ignoreMargin = ignoreMargin;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif //BT_GJK_PAIR_DETECTOR_H
|
||||
#endif //BT_GJK_PAIR_DETECTOR_H
|
||||
|
||||
@@ -20,161 +20,152 @@ subject to the following restrictions:
|
||||
#include "LinearMath/btTransformUtil.h"
|
||||
|
||||
#ifdef PFX_USE_FREE_VECTORMATH
|
||||
#include "physics_effects/base_level/solver/pfx_constraint_row.h"
|
||||
#include "physics_effects/base_level/solver/pfx_constraint_row.h"
|
||||
typedef sce::PhysicsEffects::PfxConstraintRow btConstraintRow;
|
||||
#else
|
||||
// Don't change following order of parameters
|
||||
ATTRIBUTE_ALIGNED16(struct) btConstraintRow {
|
||||
btScalar m_normal[3];
|
||||
btScalar m_rhs;
|
||||
btScalar m_jacDiagInv;
|
||||
btScalar m_lowerLimit;
|
||||
btScalar m_upperLimit;
|
||||
btScalar m_accumImpulse;
|
||||
};
|
||||
typedef btConstraintRow PfxConstraintRow;
|
||||
#endif //PFX_USE_FREE_VECTORMATH
|
||||
// Don't change following order of parameters
|
||||
ATTRIBUTE_ALIGNED16(struct)
|
||||
btConstraintRow
|
||||
{
|
||||
btScalar m_normal[3];
|
||||
btScalar m_rhs;
|
||||
btScalar m_jacDiagInv;
|
||||
btScalar m_lowerLimit;
|
||||
btScalar m_upperLimit;
|
||||
btScalar m_accumImpulse;
|
||||
};
|
||||
typedef btConstraintRow PfxConstraintRow;
|
||||
#endif //PFX_USE_FREE_VECTORMATH
|
||||
|
||||
enum btContactPointFlags
|
||||
{
|
||||
BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED=1,
|
||||
BT_CONTACT_FLAG_HAS_CONTACT_CFM=2,
|
||||
BT_CONTACT_FLAG_HAS_CONTACT_ERP=4,
|
||||
BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING = 8,
|
||||
BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED = 1,
|
||||
BT_CONTACT_FLAG_HAS_CONTACT_CFM = 2,
|
||||
BT_CONTACT_FLAG_HAS_CONTACT_ERP = 4,
|
||||
BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING = 8,
|
||||
BT_CONTACT_FLAG_FRICTION_ANCHOR = 16,
|
||||
};
|
||||
|
||||
/// ManifoldContactPoint collects and maintains persistent contactpoints.
|
||||
/// used to improve stability and performance of rigidbody dynamics response.
|
||||
class btManifoldPoint
|
||||
{
|
||||
public:
|
||||
btManifoldPoint()
|
||||
: m_userPersistentData(0),
|
||||
m_contactPointFlags(0),
|
||||
m_appliedImpulse(0.f),
|
||||
m_appliedImpulseLateral1(0.f),
|
||||
m_appliedImpulseLateral2(0.f),
|
||||
m_contactMotion1(0.f),
|
||||
m_contactMotion2(0.f),
|
||||
m_contactCFM(0.f),
|
||||
m_contactERP(0.f),
|
||||
m_frictionCFM(0.f),
|
||||
m_lifeTime(0)
|
||||
{
|
||||
public:
|
||||
btManifoldPoint()
|
||||
:m_userPersistentData(0),
|
||||
m_contactPointFlags(0),
|
||||
m_appliedImpulse(0.f),
|
||||
m_appliedImpulseLateral1(0.f),
|
||||
m_appliedImpulseLateral2(0.f),
|
||||
m_contactMotion1(0.f),
|
||||
m_contactMotion2(0.f),
|
||||
m_contactCFM(0.f),
|
||||
m_contactERP(0.f),
|
||||
m_frictionCFM(0.f),
|
||||
m_lifeTime(0)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
btManifoldPoint( const btVector3 &pointA, const btVector3 &pointB,
|
||||
const btVector3 &normal,
|
||||
btScalar distance ) :
|
||||
m_localPointA( pointA ),
|
||||
m_localPointB( pointB ),
|
||||
m_normalWorldOnB( normal ),
|
||||
m_distance1( distance ),
|
||||
m_combinedFriction(btScalar(0.)),
|
||||
m_combinedRollingFriction(btScalar(0.)),
|
||||
m_combinedSpinningFriction(btScalar(0.)),
|
||||
m_combinedRestitution(btScalar(0.)),
|
||||
m_userPersistentData(0),
|
||||
m_contactPointFlags(0),
|
||||
m_appliedImpulse(0.f),
|
||||
m_appliedImpulseLateral1(0.f),
|
||||
m_appliedImpulseLateral2(0.f),
|
||||
m_contactMotion1(0.f),
|
||||
m_contactMotion2(0.f),
|
||||
m_contactCFM(0.f),
|
||||
m_contactERP(0.f),
|
||||
m_frictionCFM(0.f),
|
||||
m_lifeTime(0)
|
||||
{
|
||||
|
||||
}
|
||||
btManifoldPoint(const btVector3& pointA, const btVector3& pointB,
|
||||
const btVector3& normal,
|
||||
btScalar distance) : m_localPointA(pointA),
|
||||
m_localPointB(pointB),
|
||||
m_normalWorldOnB(normal),
|
||||
m_distance1(distance),
|
||||
m_combinedFriction(btScalar(0.)),
|
||||
m_combinedRollingFriction(btScalar(0.)),
|
||||
m_combinedSpinningFriction(btScalar(0.)),
|
||||
m_combinedRestitution(btScalar(0.)),
|
||||
m_userPersistentData(0),
|
||||
m_contactPointFlags(0),
|
||||
m_appliedImpulse(0.f),
|
||||
m_appliedImpulseLateral1(0.f),
|
||||
m_appliedImpulseLateral2(0.f),
|
||||
m_contactMotion1(0.f),
|
||||
m_contactMotion2(0.f),
|
||||
m_contactCFM(0.f),
|
||||
m_contactERP(0.f),
|
||||
m_frictionCFM(0.f),
|
||||
m_lifeTime(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
btVector3 m_localPointA;
|
||||
btVector3 m_localPointB;
|
||||
btVector3 m_positionWorldOnB;
|
||||
///m_positionWorldOnA is redundant information, see getPositionWorldOnA(), but for clarity
|
||||
btVector3 m_positionWorldOnA;
|
||||
btVector3 m_normalWorldOnB;
|
||||
|
||||
btVector3 m_localPointA;
|
||||
btVector3 m_localPointB;
|
||||
btVector3 m_positionWorldOnB;
|
||||
///m_positionWorldOnA is redundant information, see getPositionWorldOnA(), but for clarity
|
||||
btVector3 m_positionWorldOnA;
|
||||
btVector3 m_normalWorldOnB;
|
||||
|
||||
btScalar m_distance1;
|
||||
btScalar m_combinedFriction;
|
||||
btScalar m_combinedRollingFriction;//torsional friction orthogonal to contact normal, useful to make spheres stop rolling forever
|
||||
btScalar m_combinedSpinningFriction;//torsional friction around contact normal, useful for grasping objects
|
||||
btScalar m_combinedRestitution;
|
||||
btScalar m_distance1;
|
||||
btScalar m_combinedFriction;
|
||||
btScalar m_combinedRollingFriction; //torsional friction orthogonal to contact normal, useful to make spheres stop rolling forever
|
||||
btScalar m_combinedSpinningFriction; //torsional friction around contact normal, useful for grasping objects
|
||||
btScalar m_combinedRestitution;
|
||||
|
||||
//BP mod, store contact triangles.
|
||||
int m_partId0;
|
||||
int m_partId1;
|
||||
int m_index0;
|
||||
int m_index1;
|
||||
|
||||
mutable void* m_userPersistentData;
|
||||
//bool m_lateralFrictionInitialized;
|
||||
int m_contactPointFlags;
|
||||
|
||||
btScalar m_appliedImpulse;
|
||||
btScalar m_appliedImpulseLateral1;
|
||||
btScalar m_appliedImpulseLateral2;
|
||||
btScalar m_contactMotion1;
|
||||
btScalar m_contactMotion2;
|
||||
|
||||
union
|
||||
{
|
||||
btScalar m_contactCFM;
|
||||
btScalar m_combinedContactStiffness1;
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
btScalar m_contactERP;
|
||||
btScalar m_combinedContactDamping1;
|
||||
};
|
||||
//BP mod, store contact triangles.
|
||||
int m_partId0;
|
||||
int m_partId1;
|
||||
int m_index0;
|
||||
int m_index1;
|
||||
|
||||
btScalar m_frictionCFM;
|
||||
mutable void* m_userPersistentData;
|
||||
//bool m_lateralFrictionInitialized;
|
||||
int m_contactPointFlags;
|
||||
|
||||
int m_lifeTime;//lifetime of the contactpoint in frames
|
||||
|
||||
btVector3 m_lateralFrictionDir1;
|
||||
btVector3 m_lateralFrictionDir2;
|
||||
|
||||
|
||||
|
||||
|
||||
btScalar getDistance() const
|
||||
{
|
||||
return m_distance1;
|
||||
}
|
||||
int getLifeTime() const
|
||||
{
|
||||
return m_lifeTime;
|
||||
}
|
||||
|
||||
const btVector3& getPositionWorldOnA() const {
|
||||
return m_positionWorldOnA;
|
||||
// return m_positionWorldOnB + m_normalWorldOnB * m_distance1;
|
||||
}
|
||||
|
||||
const btVector3& getPositionWorldOnB() const
|
||||
{
|
||||
return m_positionWorldOnB;
|
||||
}
|
||||
|
||||
void setDistance(btScalar dist)
|
||||
{
|
||||
m_distance1 = dist;
|
||||
}
|
||||
|
||||
///this returns the most recent applied impulse, to satisfy contact constraints by the constraint solver
|
||||
btScalar getAppliedImpulse() const
|
||||
{
|
||||
return m_appliedImpulse;
|
||||
}
|
||||
|
||||
|
||||
btScalar m_appliedImpulse;
|
||||
btScalar m_appliedImpulseLateral1;
|
||||
btScalar m_appliedImpulseLateral2;
|
||||
btScalar m_contactMotion1;
|
||||
btScalar m_contactMotion2;
|
||||
|
||||
union {
|
||||
btScalar m_contactCFM;
|
||||
btScalar m_combinedContactStiffness1;
|
||||
};
|
||||
|
||||
#endif //BT_MANIFOLD_CONTACT_POINT_H
|
||||
union {
|
||||
btScalar m_contactERP;
|
||||
btScalar m_combinedContactDamping1;
|
||||
};
|
||||
|
||||
btScalar m_frictionCFM;
|
||||
|
||||
int m_lifeTime; //lifetime of the contactpoint in frames
|
||||
|
||||
btVector3 m_lateralFrictionDir1;
|
||||
btVector3 m_lateralFrictionDir2;
|
||||
|
||||
btScalar getDistance() const
|
||||
{
|
||||
return m_distance1;
|
||||
}
|
||||
int getLifeTime() const
|
||||
{
|
||||
return m_lifeTime;
|
||||
}
|
||||
|
||||
const btVector3& getPositionWorldOnA() const
|
||||
{
|
||||
return m_positionWorldOnA;
|
||||
// return m_positionWorldOnB + m_normalWorldOnB * m_distance1;
|
||||
}
|
||||
|
||||
const btVector3& getPositionWorldOnB() const
|
||||
{
|
||||
return m_positionWorldOnB;
|
||||
}
|
||||
|
||||
void setDistance(btScalar dist)
|
||||
{
|
||||
m_distance1 = dist;
|
||||
}
|
||||
|
||||
///this returns the most recent applied impulse, to satisfy contact constraints by the constraint solver
|
||||
btScalar getAppliedImpulse() const
|
||||
{
|
||||
return m_appliedImpulse;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //BT_MANIFOLD_CONTACT_POINT_H
|
||||
|
||||
@@ -21,42 +21,38 @@ subject to the following restrictions:
|
||||
|
||||
#define NUM_UNITSPHERE_POINTS 42
|
||||
|
||||
|
||||
bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& simplexSolver,
|
||||
const btConvexShape* convexA,const btConvexShape* convexB,
|
||||
const btTransform& transA,const btTransform& transB,
|
||||
btVector3& v, btVector3& pa, btVector3& pb,
|
||||
class btIDebugDraw* debugDraw
|
||||
)
|
||||
const btConvexShape* convexA, const btConvexShape* convexB,
|
||||
const btTransform& transA, const btTransform& transB,
|
||||
btVector3& v, btVector3& pa, btVector3& pb,
|
||||
class btIDebugDraw* debugDraw)
|
||||
{
|
||||
|
||||
(void)v;
|
||||
|
||||
bool check2d= convexA->isConvex2d() && convexB->isConvex2d();
|
||||
|
||||
bool check2d = convexA->isConvex2d() && convexB->isConvex2d();
|
||||
|
||||
struct btIntermediateResult : public btDiscreteCollisionDetectorInterface::Result
|
||||
{
|
||||
|
||||
btIntermediateResult():m_hasResult(false)
|
||||
btIntermediateResult() : m_hasResult(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
btVector3 m_normalOnBInWorld;
|
||||
btVector3 m_pointInWorld;
|
||||
btScalar m_depth;
|
||||
bool m_hasResult;
|
||||
bool m_hasResult;
|
||||
|
||||
virtual void setShapeIdentifiersA(int partId0,int index0)
|
||||
virtual void setShapeIdentifiersA(int partId0, int index0)
|
||||
{
|
||||
(void)partId0;
|
||||
(void)index0;
|
||||
}
|
||||
virtual void setShapeIdentifiersB(int partId1,int index1)
|
||||
virtual void setShapeIdentifiersB(int partId1, int index1)
|
||||
{
|
||||
(void)partId1;
|
||||
(void)index1;
|
||||
}
|
||||
void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
|
||||
void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
|
||||
{
|
||||
m_normalOnBInWorld = normalOnBInWorld;
|
||||
m_pointInWorld = pointInWorld;
|
||||
@@ -68,39 +64,39 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
|
||||
//just take fixed number of orientation, and sample the penetration depth in that direction
|
||||
btScalar minProj = btScalar(BT_LARGE_FLOAT);
|
||||
btVector3 minNorm(btScalar(0.), btScalar(0.), btScalar(0.));
|
||||
btVector3 minA,minB;
|
||||
btVector3 seperatingAxisInA,seperatingAxisInB;
|
||||
btVector3 pInA,qInB,pWorld,qWorld,w;
|
||||
btVector3 minA, minB;
|
||||
btVector3 seperatingAxisInA, seperatingAxisInB;
|
||||
btVector3 pInA, qInB, pWorld, qWorld, w;
|
||||
|
||||
#ifndef __SPU__
|
||||
#define USE_BATCHED_SUPPORT 1
|
||||
#endif
|
||||
#ifdef USE_BATCHED_SUPPORT
|
||||
|
||||
btVector3 supportVerticesABatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
|
||||
btVector3 supportVerticesBBatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
|
||||
btVector3 seperatingAxisInABatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
|
||||
btVector3 seperatingAxisInBBatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
|
||||
btVector3 supportVerticesABatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
|
||||
btVector3 supportVerticesBBatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
|
||||
btVector3 seperatingAxisInABatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
|
||||
btVector3 seperatingAxisInBBatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
|
||||
int i;
|
||||
|
||||
int numSampleDirections = NUM_UNITSPHERE_POINTS;
|
||||
|
||||
for (i=0;i<numSampleDirections;i++)
|
||||
for (i = 0; i < numSampleDirections; i++)
|
||||
{
|
||||
btVector3 norm = getPenetrationDirections()[i];
|
||||
seperatingAxisInABatch[i] = (-norm) * transA.getBasis() ;
|
||||
seperatingAxisInBBatch[i] = norm * transB.getBasis() ;
|
||||
seperatingAxisInABatch[i] = (-norm) * transA.getBasis();
|
||||
seperatingAxisInBBatch[i] = norm * transB.getBasis();
|
||||
}
|
||||
|
||||
{
|
||||
int numPDA = convexA->getNumPreferredPenetrationDirections();
|
||||
if (numPDA)
|
||||
{
|
||||
for (int i=0;i<numPDA;i++)
|
||||
for (int i = 0; i < numPDA; i++)
|
||||
{
|
||||
btVector3 norm;
|
||||
convexA->getPreferredPenetrationDirection(i,norm);
|
||||
norm = transA.getBasis() * norm;
|
||||
convexA->getPreferredPenetrationDirection(i, norm);
|
||||
norm = transA.getBasis() * norm;
|
||||
getPenetrationDirections()[numSampleDirections] = norm;
|
||||
seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis();
|
||||
seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis();
|
||||
@@ -113,11 +109,11 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
|
||||
int numPDB = convexB->getNumPreferredPenetrationDirections();
|
||||
if (numPDB)
|
||||
{
|
||||
for (int i=0;i<numPDB;i++)
|
||||
for (int i = 0; i < numPDB; i++)
|
||||
{
|
||||
btVector3 norm;
|
||||
convexB->getPreferredPenetrationDirection(i,norm);
|
||||
norm = transB.getBasis() * norm;
|
||||
convexB->getPreferredPenetrationDirection(i, norm);
|
||||
norm = transB.getBasis() * norm;
|
||||
getPenetrationDirections()[numSampleDirections] = norm;
|
||||
seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis();
|
||||
seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis();
|
||||
@@ -126,29 +122,25 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
|
||||
}
|
||||
}
|
||||
|
||||
convexA->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInABatch, supportVerticesABatch, numSampleDirections);
|
||||
convexB->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInBBatch, supportVerticesBBatch, numSampleDirections);
|
||||
|
||||
|
||||
|
||||
convexA->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInABatch,supportVerticesABatch,numSampleDirections);
|
||||
convexB->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInBBatch,supportVerticesBBatch,numSampleDirections);
|
||||
|
||||
for (i=0;i<numSampleDirections;i++)
|
||||
for (i = 0; i < numSampleDirections; i++)
|
||||
{
|
||||
btVector3 norm = getPenetrationDirections()[i];
|
||||
if (check2d)
|
||||
{
|
||||
norm[2] = 0.f;
|
||||
}
|
||||
if (norm.length2()>0.01)
|
||||
if (norm.length2() > 0.01)
|
||||
{
|
||||
|
||||
seperatingAxisInA = seperatingAxisInABatch[i];
|
||||
seperatingAxisInB = seperatingAxisInBBatch[i];
|
||||
|
||||
pInA = supportVerticesABatch[i];
|
||||
qInB = supportVerticesBBatch[i];
|
||||
|
||||
pWorld = transA(pInA);
|
||||
pWorld = transA(pInA);
|
||||
qWorld = transB(qInB);
|
||||
if (check2d)
|
||||
{
|
||||
@@ -156,7 +148,7 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
|
||||
qWorld[2] = 0.f;
|
||||
}
|
||||
|
||||
w = qWorld - pWorld;
|
||||
w = qWorld - pWorld;
|
||||
btScalar delta = norm.dot(w);
|
||||
//find smallest delta
|
||||
if (delta < minProj)
|
||||
@@ -167,7 +159,7 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
|
||||
minB = qWorld;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
int numSampleDirections = NUM_UNITSPHERE_POINTS;
|
||||
@@ -177,11 +169,11 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
|
||||
int numPDA = convexA->getNumPreferredPenetrationDirections();
|
||||
if (numPDA)
|
||||
{
|
||||
for (int i=0;i<numPDA;i++)
|
||||
for (int i = 0; i < numPDA; i++)
|
||||
{
|
||||
btVector3 norm;
|
||||
convexA->getPreferredPenetrationDirection(i,norm);
|
||||
norm = transA.getBasis() * norm;
|
||||
convexA->getPreferredPenetrationDirection(i, norm);
|
||||
norm = transA.getBasis() * norm;
|
||||
getPenetrationDirections()[numSampleDirections] = norm;
|
||||
numSampleDirections++;
|
||||
}
|
||||
@@ -192,28 +184,28 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
|
||||
int numPDB = convexB->getNumPreferredPenetrationDirections();
|
||||
if (numPDB)
|
||||
{
|
||||
for (int i=0;i<numPDB;i++)
|
||||
for (int i = 0; i < numPDB; i++)
|
||||
{
|
||||
btVector3 norm;
|
||||
convexB->getPreferredPenetrationDirection(i,norm);
|
||||
norm = transB.getBasis() * norm;
|
||||
convexB->getPreferredPenetrationDirection(i, norm);
|
||||
norm = transB.getBasis() * norm;
|
||||
getPenetrationDirections()[numSampleDirections] = norm;
|
||||
numSampleDirections++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // __SPU__
|
||||
#endif // __SPU__
|
||||
|
||||
for (int i=0;i<numSampleDirections;i++)
|
||||
for (int i = 0; i < numSampleDirections; i++)
|
||||
{
|
||||
const btVector3& norm = getPenetrationDirections()[i];
|
||||
seperatingAxisInA = (-norm)* transA.getBasis();
|
||||
seperatingAxisInB = norm* transB.getBasis();
|
||||
seperatingAxisInA = (-norm) * transA.getBasis();
|
||||
seperatingAxisInB = norm * transB.getBasis();
|
||||
pInA = convexA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
|
||||
qInB = convexB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
|
||||
pWorld = transA(pInA);
|
||||
pWorld = transA(pInA);
|
||||
qWorld = transB(qInB);
|
||||
w = qWorld - pWorld;
|
||||
w = qWorld - pWorld;
|
||||
btScalar delta = norm.dot(w);
|
||||
//find smallest delta
|
||||
if (delta < minProj)
|
||||
@@ -224,48 +216,39 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
|
||||
minB = qWorld;
|
||||
}
|
||||
}
|
||||
#endif //USE_BATCHED_SUPPORT
|
||||
#endif //USE_BATCHED_SUPPORT
|
||||
|
||||
//add the margins
|
||||
|
||||
minA += minNorm*convexA->getMarginNonVirtual();
|
||||
minB -= minNorm*convexB->getMarginNonVirtual();
|
||||
minA += minNorm * convexA->getMarginNonVirtual();
|
||||
minB -= minNorm * convexB->getMarginNonVirtual();
|
||||
//no penetration
|
||||
if (minProj < btScalar(0.))
|
||||
return false;
|
||||
|
||||
btScalar extraSeparation = 0.5f;///scale dependent
|
||||
minProj += extraSeparation+(convexA->getMarginNonVirtual() + convexB->getMarginNonVirtual());
|
||||
|
||||
|
||||
|
||||
|
||||
btScalar extraSeparation = 0.5f; ///scale dependent
|
||||
minProj += extraSeparation + (convexA->getMarginNonVirtual() + convexB->getMarginNonVirtual());
|
||||
|
||||
//#define DEBUG_DRAW 1
|
||||
#ifdef DEBUG_DRAW
|
||||
if (debugDraw)
|
||||
{
|
||||
btVector3 color(0,1,0);
|
||||
debugDraw->drawLine(minA,minB,color);
|
||||
color = btVector3 (1,1,1);
|
||||
btVector3 vec = minB-minA;
|
||||
btVector3 color(0, 1, 0);
|
||||
debugDraw->drawLine(minA, minB, color);
|
||||
color = btVector3(1, 1, 1);
|
||||
btVector3 vec = minB - minA;
|
||||
btScalar prj2 = minNorm.dot(vec);
|
||||
debugDraw->drawLine(minA,minA+(minNorm*minProj),color);
|
||||
|
||||
debugDraw->drawLine(minA, minA + (minNorm * minProj), color);
|
||||
}
|
||||
#endif //DEBUG_DRAW
|
||||
#endif //DEBUG_DRAW
|
||||
|
||||
|
||||
|
||||
btGjkPairDetector gjkdet(convexA,convexB,&simplexSolver,0);
|
||||
btGjkPairDetector gjkdet(convexA, convexB, &simplexSolver, 0);
|
||||
|
||||
btScalar offsetDist = minProj;
|
||||
btVector3 offset = minNorm * offsetDist;
|
||||
|
||||
|
||||
|
||||
btGjkPairDetector::ClosestPointInput input;
|
||||
|
||||
|
||||
btVector3 newOrg = transA.getOrigin() + offset;
|
||||
|
||||
btTransform displacedTrans = transA;
|
||||
@@ -273,89 +256,81 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s
|
||||
|
||||
input.m_transformA = displacedTrans;
|
||||
input.m_transformB = transB;
|
||||
input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT);//minProj;
|
||||
|
||||
input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT); //minProj;
|
||||
|
||||
btIntermediateResult res;
|
||||
gjkdet.setCachedSeperatingAxis(-minNorm);
|
||||
gjkdet.getClosestPoints(input,res,debugDraw);
|
||||
gjkdet.getClosestPoints(input, res, debugDraw);
|
||||
|
||||
btScalar correctedMinNorm = minProj - res.m_depth;
|
||||
|
||||
|
||||
//the penetration depth is over-estimated, relax it
|
||||
btScalar penetration_relaxation= btScalar(1.);
|
||||
minNorm*=penetration_relaxation;
|
||||
|
||||
btScalar penetration_relaxation = btScalar(1.);
|
||||
minNorm *= penetration_relaxation;
|
||||
|
||||
if (res.m_hasResult)
|
||||
{
|
||||
|
||||
pa = res.m_pointInWorld - minNorm * correctedMinNorm;
|
||||
pb = res.m_pointInWorld;
|
||||
v = minNorm;
|
||||
|
||||
|
||||
#ifdef DEBUG_DRAW
|
||||
if (debugDraw)
|
||||
{
|
||||
btVector3 color(1,0,0);
|
||||
debugDraw->drawLine(pa,pb,color);
|
||||
btVector3 color(1, 0, 0);
|
||||
debugDraw->drawLine(pa, pb, color);
|
||||
}
|
||||
#endif//DEBUG_DRAW
|
||||
|
||||
|
||||
#endif //DEBUG_DRAW
|
||||
}
|
||||
return res.m_hasResult;
|
||||
}
|
||||
|
||||
btVector3* btMinkowskiPenetrationDepthSolver::getPenetrationDirections()
|
||||
btVector3* btMinkowskiPenetrationDepthSolver::getPenetrationDirections()
|
||||
{
|
||||
static btVector3 sPenetrationDirections[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2] =
|
||||
{
|
||||
btVector3(btScalar(0.000000) , btScalar(-0.000000),btScalar(-1.000000)),
|
||||
btVector3(btScalar(0.723608) , btScalar(-0.525725),btScalar(-0.447219)),
|
||||
btVector3(btScalar(-0.276388) , btScalar(-0.850649),btScalar(-0.447219)),
|
||||
btVector3(btScalar(-0.894426) , btScalar(-0.000000),btScalar(-0.447216)),
|
||||
btVector3(btScalar(-0.276388) , btScalar(0.850649),btScalar(-0.447220)),
|
||||
btVector3(btScalar(0.723608) , btScalar(0.525725),btScalar(-0.447219)),
|
||||
btVector3(btScalar(0.276388) , btScalar(-0.850649),btScalar(0.447220)),
|
||||
btVector3(btScalar(-0.723608) , btScalar(-0.525725),btScalar(0.447219)),
|
||||
btVector3(btScalar(-0.723608) , btScalar(0.525725),btScalar(0.447219)),
|
||||
btVector3(btScalar(0.276388) , btScalar(0.850649),btScalar(0.447219)),
|
||||
btVector3(btScalar(0.894426) , btScalar(0.000000),btScalar(0.447216)),
|
||||
btVector3(btScalar(-0.000000) , btScalar(0.000000),btScalar(1.000000)),
|
||||
btVector3(btScalar(0.425323) , btScalar(-0.309011),btScalar(-0.850654)),
|
||||
btVector3(btScalar(-0.162456) , btScalar(-0.499995),btScalar(-0.850654)),
|
||||
btVector3(btScalar(0.262869) , btScalar(-0.809012),btScalar(-0.525738)),
|
||||
btVector3(btScalar(0.425323) , btScalar(0.309011),btScalar(-0.850654)),
|
||||
btVector3(btScalar(0.850648) , btScalar(-0.000000),btScalar(-0.525736)),
|
||||
btVector3(btScalar(-0.525730) , btScalar(-0.000000),btScalar(-0.850652)),
|
||||
btVector3(btScalar(-0.688190) , btScalar(-0.499997),btScalar(-0.525736)),
|
||||
btVector3(btScalar(-0.162456) , btScalar(0.499995),btScalar(-0.850654)),
|
||||
btVector3(btScalar(-0.688190) , btScalar(0.499997),btScalar(-0.525736)),
|
||||
btVector3(btScalar(0.262869) , btScalar(0.809012),btScalar(-0.525738)),
|
||||
btVector3(btScalar(0.951058) , btScalar(0.309013),btScalar(0.000000)),
|
||||
btVector3(btScalar(0.951058) , btScalar(-0.309013),btScalar(0.000000)),
|
||||
btVector3(btScalar(0.587786) , btScalar(-0.809017),btScalar(0.000000)),
|
||||
btVector3(btScalar(0.000000) , btScalar(-1.000000),btScalar(0.000000)),
|
||||
btVector3(btScalar(-0.587786) , btScalar(-0.809017),btScalar(0.000000)),
|
||||
btVector3(btScalar(-0.951058) , btScalar(-0.309013),btScalar(-0.000000)),
|
||||
btVector3(btScalar(-0.951058) , btScalar(0.309013),btScalar(-0.000000)),
|
||||
btVector3(btScalar(-0.587786) , btScalar(0.809017),btScalar(-0.000000)),
|
||||
btVector3(btScalar(-0.000000) , btScalar(1.000000),btScalar(-0.000000)),
|
||||
btVector3(btScalar(0.587786) , btScalar(0.809017),btScalar(-0.000000)),
|
||||
btVector3(btScalar(0.688190) , btScalar(-0.499997),btScalar(0.525736)),
|
||||
btVector3(btScalar(-0.262869) , btScalar(-0.809012),btScalar(0.525738)),
|
||||
btVector3(btScalar(-0.850648) , btScalar(0.000000),btScalar(0.525736)),
|
||||
btVector3(btScalar(-0.262869) , btScalar(0.809012),btScalar(0.525738)),
|
||||
btVector3(btScalar(0.688190) , btScalar(0.499997),btScalar(0.525736)),
|
||||
btVector3(btScalar(0.525730) , btScalar(0.000000),btScalar(0.850652)),
|
||||
btVector3(btScalar(0.162456) , btScalar(-0.499995),btScalar(0.850654)),
|
||||
btVector3(btScalar(-0.425323) , btScalar(-0.309011),btScalar(0.850654)),
|
||||
btVector3(btScalar(-0.425323) , btScalar(0.309011),btScalar(0.850654)),
|
||||
btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654))
|
||||
};
|
||||
static btVector3 sPenetrationDirections[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2] =
|
||||
{
|
||||
btVector3(btScalar(0.000000), btScalar(-0.000000), btScalar(-1.000000)),
|
||||
btVector3(btScalar(0.723608), btScalar(-0.525725), btScalar(-0.447219)),
|
||||
btVector3(btScalar(-0.276388), btScalar(-0.850649), btScalar(-0.447219)),
|
||||
btVector3(btScalar(-0.894426), btScalar(-0.000000), btScalar(-0.447216)),
|
||||
btVector3(btScalar(-0.276388), btScalar(0.850649), btScalar(-0.447220)),
|
||||
btVector3(btScalar(0.723608), btScalar(0.525725), btScalar(-0.447219)),
|
||||
btVector3(btScalar(0.276388), btScalar(-0.850649), btScalar(0.447220)),
|
||||
btVector3(btScalar(-0.723608), btScalar(-0.525725), btScalar(0.447219)),
|
||||
btVector3(btScalar(-0.723608), btScalar(0.525725), btScalar(0.447219)),
|
||||
btVector3(btScalar(0.276388), btScalar(0.850649), btScalar(0.447219)),
|
||||
btVector3(btScalar(0.894426), btScalar(0.000000), btScalar(0.447216)),
|
||||
btVector3(btScalar(-0.000000), btScalar(0.000000), btScalar(1.000000)),
|
||||
btVector3(btScalar(0.425323), btScalar(-0.309011), btScalar(-0.850654)),
|
||||
btVector3(btScalar(-0.162456), btScalar(-0.499995), btScalar(-0.850654)),
|
||||
btVector3(btScalar(0.262869), btScalar(-0.809012), btScalar(-0.525738)),
|
||||
btVector3(btScalar(0.425323), btScalar(0.309011), btScalar(-0.850654)),
|
||||
btVector3(btScalar(0.850648), btScalar(-0.000000), btScalar(-0.525736)),
|
||||
btVector3(btScalar(-0.525730), btScalar(-0.000000), btScalar(-0.850652)),
|
||||
btVector3(btScalar(-0.688190), btScalar(-0.499997), btScalar(-0.525736)),
|
||||
btVector3(btScalar(-0.162456), btScalar(0.499995), btScalar(-0.850654)),
|
||||
btVector3(btScalar(-0.688190), btScalar(0.499997), btScalar(-0.525736)),
|
||||
btVector3(btScalar(0.262869), btScalar(0.809012), btScalar(-0.525738)),
|
||||
btVector3(btScalar(0.951058), btScalar(0.309013), btScalar(0.000000)),
|
||||
btVector3(btScalar(0.951058), btScalar(-0.309013), btScalar(0.000000)),
|
||||
btVector3(btScalar(0.587786), btScalar(-0.809017), btScalar(0.000000)),
|
||||
btVector3(btScalar(0.000000), btScalar(-1.000000), btScalar(0.000000)),
|
||||
btVector3(btScalar(-0.587786), btScalar(-0.809017), btScalar(0.000000)),
|
||||
btVector3(btScalar(-0.951058), btScalar(-0.309013), btScalar(-0.000000)),
|
||||
btVector3(btScalar(-0.951058), btScalar(0.309013), btScalar(-0.000000)),
|
||||
btVector3(btScalar(-0.587786), btScalar(0.809017), btScalar(-0.000000)),
|
||||
btVector3(btScalar(-0.000000), btScalar(1.000000), btScalar(-0.000000)),
|
||||
btVector3(btScalar(0.587786), btScalar(0.809017), btScalar(-0.000000)),
|
||||
btVector3(btScalar(0.688190), btScalar(-0.499997), btScalar(0.525736)),
|
||||
btVector3(btScalar(-0.262869), btScalar(-0.809012), btScalar(0.525738)),
|
||||
btVector3(btScalar(-0.850648), btScalar(0.000000), btScalar(0.525736)),
|
||||
btVector3(btScalar(-0.262869), btScalar(0.809012), btScalar(0.525738)),
|
||||
btVector3(btScalar(0.688190), btScalar(0.499997), btScalar(0.525736)),
|
||||
btVector3(btScalar(0.525730), btScalar(0.000000), btScalar(0.850652)),
|
||||
btVector3(btScalar(0.162456), btScalar(-0.499995), btScalar(0.850654)),
|
||||
btVector3(btScalar(-0.425323), btScalar(-0.309011), btScalar(0.850654)),
|
||||
btVector3(btScalar(-0.425323), btScalar(0.309011), btScalar(0.850654)),
|
||||
btVector3(btScalar(0.162456), btScalar(0.499995), btScalar(0.850654))};
|
||||
|
||||
return sPenetrationDirections;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -23,18 +23,14 @@ subject to the following restrictions:
|
||||
class btMinkowskiPenetrationDepthSolver : public btConvexPenetrationDepthSolver
|
||||
{
|
||||
protected:
|
||||
|
||||
static btVector3* getPenetrationDirections();
|
||||
static btVector3* getPenetrationDirections();
|
||||
|
||||
public:
|
||||
|
||||
virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver,
|
||||
const btConvexShape* convexA,const btConvexShape* convexB,
|
||||
const btTransform& transA,const btTransform& transB,
|
||||
btVector3& v, btVector3& pa, btVector3& pb,
|
||||
class btIDebugDraw* debugDraw
|
||||
);
|
||||
virtual bool calcPenDepth(btSimplexSolverInterface& simplexSolver,
|
||||
const btConvexShape* convexA, const btConvexShape* convexB,
|
||||
const btTransform& transA, const btTransform& transB,
|
||||
btVector3& v, btVector3& pa, btVector3& pb,
|
||||
class btIDebugDraw* debugDraw);
|
||||
};
|
||||
|
||||
#endif //BT_MINKOWSKI_PENETRATION_DEPTH_SOLVER_H
|
||||
|
||||
#endif //BT_MINKOWSKI_PENETRATION_DEPTH_SOLVER_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -13,7 +13,6 @@ subject to the following restrictions:
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "btPersistentManifold.h"
|
||||
#include "LinearMath/btTransform.h"
|
||||
#include "LinearMath/btSerializer.h"
|
||||
@@ -24,83 +23,76 @@ subject to the following restrictions:
|
||||
#define btCollisionObjectData btCollisionObjectFloatData
|
||||
#endif
|
||||
|
||||
btScalar gContactBreakingThreshold = btScalar(0.02);
|
||||
ContactDestroyedCallback gContactDestroyedCallback = 0;
|
||||
ContactProcessedCallback gContactProcessedCallback = 0;
|
||||
ContactStartedCallback gContactStartedCallback = 0;
|
||||
ContactEndedCallback gContactEndedCallback = 0;
|
||||
btScalar gContactBreakingThreshold = btScalar(0.02);
|
||||
ContactDestroyedCallback gContactDestroyedCallback = 0;
|
||||
ContactProcessedCallback gContactProcessedCallback = 0;
|
||||
ContactStartedCallback gContactStartedCallback = 0;
|
||||
ContactEndedCallback gContactEndedCallback = 0;
|
||||
///gContactCalcArea3Points will approximate the convex hull area using 3 points
|
||||
///when setting it to false, it will use 4 points to compute the area: it is more accurate but slower
|
||||
bool gContactCalcArea3Points = true;
|
||||
|
||||
bool gContactCalcArea3Points = true;
|
||||
|
||||
btPersistentManifold::btPersistentManifold()
|
||||
:btTypedObject(BT_PERSISTENT_MANIFOLD_TYPE),
|
||||
m_body0(0),
|
||||
m_body1(0),
|
||||
m_cachedPoints (0),
|
||||
m_companionIdA(0),
|
||||
m_companionIdB(0),
|
||||
m_index1a(0)
|
||||
: btTypedObject(BT_PERSISTENT_MANIFOLD_TYPE),
|
||||
m_body0(0),
|
||||
m_body1(0),
|
||||
m_cachedPoints(0),
|
||||
m_companionIdA(0),
|
||||
m_companionIdB(0),
|
||||
m_index1a(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef DEBUG_PERSISTENCY
|
||||
#include <stdio.h>
|
||||
void btPersistentManifold::DebugPersistency()
|
||||
void btPersistentManifold::DebugPersistency()
|
||||
{
|
||||
int i;
|
||||
printf("DebugPersistency : numPoints %d\n",m_cachedPoints);
|
||||
for (i=0;i<m_cachedPoints;i++)
|
||||
printf("DebugPersistency : numPoints %d\n", m_cachedPoints);
|
||||
for (i = 0; i < m_cachedPoints; i++)
|
||||
{
|
||||
printf("m_pointCache[%d].m_userPersistentData = %x\n",i,m_pointCache[i].m_userPersistentData);
|
||||
printf("m_pointCache[%d].m_userPersistentData = %x\n", i, m_pointCache[i].m_userPersistentData);
|
||||
}
|
||||
}
|
||||
#endif //DEBUG_PERSISTENCY
|
||||
#endif //DEBUG_PERSISTENCY
|
||||
|
||||
void btPersistentManifold::clearUserCache(btManifoldPoint& pt)
|
||||
{
|
||||
|
||||
void* oldPtr = pt.m_userPersistentData;
|
||||
if (oldPtr)
|
||||
{
|
||||
#ifdef DEBUG_PERSISTENCY
|
||||
int i;
|
||||
int occurance = 0;
|
||||
for (i=0;i<m_cachedPoints;i++)
|
||||
for (i = 0; i < m_cachedPoints; i++)
|
||||
{
|
||||
if (m_pointCache[i].m_userPersistentData == oldPtr)
|
||||
{
|
||||
occurance++;
|
||||
if (occurance>1)
|
||||
if (occurance > 1)
|
||||
printf("error in clearUserCache\n");
|
||||
}
|
||||
}
|
||||
btAssert(occurance<=0);
|
||||
#endif //DEBUG_PERSISTENCY
|
||||
btAssert(occurance <= 0);
|
||||
#endif //DEBUG_PERSISTENCY
|
||||
|
||||
if (pt.m_userPersistentData && gContactDestroyedCallback)
|
||||
{
|
||||
(*gContactDestroyedCallback)(pt.m_userPersistentData);
|
||||
pt.m_userPersistentData = 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG_PERSISTENCY
|
||||
DebugPersistency();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static inline btScalar calcArea4Points(const btVector3 &p0,const btVector3 &p1,const btVector3 &p2,const btVector3 &p3)
|
||||
static inline btScalar calcArea4Points(const btVector3& p0, const btVector3& p1, const btVector3& p2, const btVector3& p3)
|
||||
{
|
||||
// It calculates possible 3 area constructed from random 4 points and returns the biggest one.
|
||||
|
||||
btVector3 a[3],b[3];
|
||||
btVector3 a[3], b[3];
|
||||
a[0] = p0 - p1;
|
||||
a[1] = p0 - p2;
|
||||
a[2] = p0 - p3;
|
||||
@@ -113,100 +105,102 @@ static inline btScalar calcArea4Points(const btVector3 &p0,const btVector3 &p1,c
|
||||
btVector3 tmp1 = a[1].cross(b[1]);
|
||||
btVector3 tmp2 = a[2].cross(b[2]);
|
||||
|
||||
return btMax(btMax(tmp0.length2(),tmp1.length2()),tmp2.length2());
|
||||
return btMax(btMax(tmp0.length2(), tmp1.length2()), tmp2.length2());
|
||||
}
|
||||
|
||||
int btPersistentManifold::sortCachedPoints(const btManifoldPoint& pt)
|
||||
int btPersistentManifold::sortCachedPoints(const btManifoldPoint& pt)
|
||||
{
|
||||
//calculate 4 possible cases areas, and take biggest area
|
||||
//also need to keep 'deepest'
|
||||
|
||||
int maxPenetrationIndex = -1;
|
||||
//calculate 4 possible cases areas, and take biggest area
|
||||
//also need to keep 'deepest'
|
||||
|
||||
int maxPenetrationIndex = -1;
|
||||
#define KEEP_DEEPEST_POINT 1
|
||||
#ifdef KEEP_DEEPEST_POINT
|
||||
btScalar maxPenetration = pt.getDistance();
|
||||
for (int i=0;i<4;i++)
|
||||
btScalar maxPenetration = pt.getDistance();
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (m_pointCache[i].getDistance() < maxPenetration)
|
||||
{
|
||||
if (m_pointCache[i].getDistance() < maxPenetration)
|
||||
{
|
||||
maxPenetrationIndex = i;
|
||||
maxPenetration = m_pointCache[i].getDistance();
|
||||
}
|
||||
maxPenetrationIndex = i;
|
||||
maxPenetration = m_pointCache[i].getDistance();
|
||||
}
|
||||
#endif //KEEP_DEEPEST_POINT
|
||||
|
||||
btScalar res0(btScalar(0.)),res1(btScalar(0.)),res2(btScalar(0.)),res3(btScalar(0.));
|
||||
}
|
||||
#endif //KEEP_DEEPEST_POINT
|
||||
|
||||
btScalar res0(btScalar(0.)), res1(btScalar(0.)), res2(btScalar(0.)), res3(btScalar(0.));
|
||||
|
||||
if (gContactCalcArea3Points)
|
||||
{
|
||||
if (maxPenetrationIndex != 0)
|
||||
{
|
||||
btVector3 a0 = pt.m_localPointA-m_pointCache[1].m_localPointA;
|
||||
btVector3 b0 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA;
|
||||
btVector3 a0 = pt.m_localPointA - m_pointCache[1].m_localPointA;
|
||||
btVector3 b0 = m_pointCache[3].m_localPointA - m_pointCache[2].m_localPointA;
|
||||
btVector3 cross = a0.cross(b0);
|
||||
res0 = cross.length2();
|
||||
}
|
||||
if (maxPenetrationIndex != 1)
|
||||
{
|
||||
btVector3 a1 = pt.m_localPointA-m_pointCache[0].m_localPointA;
|
||||
btVector3 b1 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA;
|
||||
btVector3 a1 = pt.m_localPointA - m_pointCache[0].m_localPointA;
|
||||
btVector3 b1 = m_pointCache[3].m_localPointA - m_pointCache[2].m_localPointA;
|
||||
btVector3 cross = a1.cross(b1);
|
||||
res1 = cross.length2();
|
||||
}
|
||||
|
||||
if (maxPenetrationIndex != 2)
|
||||
{
|
||||
btVector3 a2 = pt.m_localPointA-m_pointCache[0].m_localPointA;
|
||||
btVector3 b2 = m_pointCache[3].m_localPointA-m_pointCache[1].m_localPointA;
|
||||
btVector3 a2 = pt.m_localPointA - m_pointCache[0].m_localPointA;
|
||||
btVector3 b2 = m_pointCache[3].m_localPointA - m_pointCache[1].m_localPointA;
|
||||
btVector3 cross = a2.cross(b2);
|
||||
res2 = cross.length2();
|
||||
}
|
||||
|
||||
if (maxPenetrationIndex != 3)
|
||||
{
|
||||
btVector3 a3 = pt.m_localPointA-m_pointCache[0].m_localPointA;
|
||||
btVector3 b3 = m_pointCache[2].m_localPointA-m_pointCache[1].m_localPointA;
|
||||
btVector3 a3 = pt.m_localPointA - m_pointCache[0].m_localPointA;
|
||||
btVector3 b3 = m_pointCache[2].m_localPointA - m_pointCache[1].m_localPointA;
|
||||
btVector3 cross = a3.cross(b3);
|
||||
res3 = cross.length2();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(maxPenetrationIndex != 0) {
|
||||
res0 = calcArea4Points(pt.m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[2].m_localPointA,m_pointCache[3].m_localPointA);
|
||||
if (maxPenetrationIndex != 0)
|
||||
{
|
||||
res0 = calcArea4Points(pt.m_localPointA, m_pointCache[1].m_localPointA, m_pointCache[2].m_localPointA, m_pointCache[3].m_localPointA);
|
||||
}
|
||||
|
||||
if(maxPenetrationIndex != 1) {
|
||||
res1 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[2].m_localPointA,m_pointCache[3].m_localPointA);
|
||||
if (maxPenetrationIndex != 1)
|
||||
{
|
||||
res1 = calcArea4Points(pt.m_localPointA, m_pointCache[0].m_localPointA, m_pointCache[2].m_localPointA, m_pointCache[3].m_localPointA);
|
||||
}
|
||||
|
||||
if(maxPenetrationIndex != 2) {
|
||||
res2 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[3].m_localPointA);
|
||||
if (maxPenetrationIndex != 2)
|
||||
{
|
||||
res2 = calcArea4Points(pt.m_localPointA, m_pointCache[0].m_localPointA, m_pointCache[1].m_localPointA, m_pointCache[3].m_localPointA);
|
||||
}
|
||||
|
||||
if(maxPenetrationIndex != 3) {
|
||||
res3 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[2].m_localPointA);
|
||||
if (maxPenetrationIndex != 3)
|
||||
{
|
||||
res3 = calcArea4Points(pt.m_localPointA, m_pointCache[0].m_localPointA, m_pointCache[1].m_localPointA, m_pointCache[2].m_localPointA);
|
||||
}
|
||||
}
|
||||
btVector4 maxvec(res0,res1,res2,res3);
|
||||
btVector4 maxvec(res0, res1, res2, res3);
|
||||
int biggestarea = maxvec.closestAxis4();
|
||||
return biggestarea;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int btPersistentManifold::getCacheEntry(const btManifoldPoint& newPoint) const
|
||||
{
|
||||
btScalar shortestDist = getContactBreakingThreshold() * getContactBreakingThreshold();
|
||||
btScalar shortestDist = getContactBreakingThreshold() * getContactBreakingThreshold();
|
||||
int size = getNumContacts();
|
||||
int nearestPoint = -1;
|
||||
for( int i = 0; i < size; i++ )
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
const btManifoldPoint &mp = m_pointCache[i];
|
||||
const btManifoldPoint& mp = m_pointCache[i];
|
||||
|
||||
btVector3 diffA = mp.m_localPointA- newPoint.m_localPointA;
|
||||
btVector3 diffA = mp.m_localPointA - newPoint.m_localPointA;
|
||||
const btScalar distToManiPoint = diffA.dot(diffA);
|
||||
if( distToManiPoint < shortestDist )
|
||||
if (distToManiPoint < shortestDist)
|
||||
{
|
||||
shortestDist = distToManiPoint;
|
||||
nearestPoint = i;
|
||||
@@ -221,7 +215,7 @@ int btPersistentManifold::addManifoldPoint(const btManifoldPoint& newPoint, bool
|
||||
{
|
||||
btAssert(validContactDistance(newPoint));
|
||||
}
|
||||
|
||||
|
||||
int insertIndex = getNumContacts();
|
||||
if (insertIndex == MANIFOLD_CACHE_SIZE)
|
||||
{
|
||||
@@ -232,91 +226,87 @@ int btPersistentManifold::addManifoldPoint(const btManifoldPoint& newPoint, bool
|
||||
insertIndex = 0;
|
||||
#endif
|
||||
clearUserCache(m_pointCache[insertIndex]);
|
||||
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cachedPoints++;
|
||||
|
||||
|
||||
}
|
||||
if (insertIndex<0)
|
||||
insertIndex=0;
|
||||
if (insertIndex < 0)
|
||||
insertIndex = 0;
|
||||
|
||||
btAssert(m_pointCache[insertIndex].m_userPersistentData==0);
|
||||
btAssert(m_pointCache[insertIndex].m_userPersistentData == 0);
|
||||
m_pointCache[insertIndex] = newPoint;
|
||||
return insertIndex;
|
||||
}
|
||||
|
||||
btScalar btPersistentManifold::getContactBreakingThreshold() const
|
||||
btScalar btPersistentManifold::getContactBreakingThreshold() const
|
||||
{
|
||||
return m_contactBreakingThreshold;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void btPersistentManifold::refreshContactPoints(const btTransform& trA,const btTransform& trB)
|
||||
void btPersistentManifold::refreshContactPoints(const btTransform& trA, const btTransform& trB)
|
||||
{
|
||||
int i;
|
||||
#ifdef DEBUG_PERSISTENCY
|
||||
printf("refreshContactPoints posA = (%f,%f,%f) posB = (%f,%f,%f)\n",
|
||||
trA.getOrigin().getX(),
|
||||
trA.getOrigin().getY(),
|
||||
trA.getOrigin().getZ(),
|
||||
trB.getOrigin().getX(),
|
||||
trB.getOrigin().getY(),
|
||||
trB.getOrigin().getZ());
|
||||
#endif //DEBUG_PERSISTENCY
|
||||
trA.getOrigin().getX(),
|
||||
trA.getOrigin().getY(),
|
||||
trA.getOrigin().getZ(),
|
||||
trB.getOrigin().getX(),
|
||||
trB.getOrigin().getY(),
|
||||
trB.getOrigin().getZ());
|
||||
#endif //DEBUG_PERSISTENCY
|
||||
/// first refresh worldspace positions and distance
|
||||
for (i=getNumContacts()-1;i>=0;i--)
|
||||
for (i = getNumContacts() - 1; i >= 0; i--)
|
||||
{
|
||||
btManifoldPoint &manifoldPoint = m_pointCache[i];
|
||||
manifoldPoint.m_positionWorldOnA = trA( manifoldPoint.m_localPointA );
|
||||
manifoldPoint.m_positionWorldOnB = trB( manifoldPoint.m_localPointB );
|
||||
manifoldPoint.m_distance1 = (manifoldPoint.m_positionWorldOnA - manifoldPoint.m_positionWorldOnB).dot(manifoldPoint.m_normalWorldOnB);
|
||||
btManifoldPoint& manifoldPoint = m_pointCache[i];
|
||||
manifoldPoint.m_positionWorldOnA = trA(manifoldPoint.m_localPointA);
|
||||
manifoldPoint.m_positionWorldOnB = trB(manifoldPoint.m_localPointB);
|
||||
manifoldPoint.m_distance1 = (manifoldPoint.m_positionWorldOnA - manifoldPoint.m_positionWorldOnB).dot(manifoldPoint.m_normalWorldOnB);
|
||||
manifoldPoint.m_lifeTime++;
|
||||
}
|
||||
|
||||
/// then
|
||||
/// then
|
||||
btScalar distance2d;
|
||||
btVector3 projectedDifference,projectedPoint;
|
||||
for (i=getNumContacts()-1;i>=0;i--)
|
||||
btVector3 projectedDifference, projectedPoint;
|
||||
for (i = getNumContacts() - 1; i >= 0; i--)
|
||||
{
|
||||
|
||||
btManifoldPoint &manifoldPoint = m_pointCache[i];
|
||||
btManifoldPoint& manifoldPoint = m_pointCache[i];
|
||||
//contact becomes invalid when signed distance exceeds margin (projected on contactnormal direction)
|
||||
if (!validContactDistance(manifoldPoint))
|
||||
{
|
||||
removeContactPoint(i);
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
//todo: friction anchor may require the contact to be around a bit longer
|
||||
//todo: friction anchor may require the contact to be around a bit longer
|
||||
//contact also becomes invalid when relative movement orthogonal to normal exceeds margin
|
||||
projectedPoint = manifoldPoint.m_positionWorldOnA - manifoldPoint.m_normalWorldOnB * manifoldPoint.m_distance1;
|
||||
projectedDifference = manifoldPoint.m_positionWorldOnB - projectedPoint;
|
||||
distance2d = projectedDifference.dot(projectedDifference);
|
||||
if (distance2d > getContactBreakingThreshold()*getContactBreakingThreshold() )
|
||||
if (distance2d > getContactBreakingThreshold() * getContactBreakingThreshold())
|
||||
{
|
||||
removeContactPoint(i);
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
//contact point processed callback
|
||||
if (gContactProcessedCallback)
|
||||
(*gContactProcessedCallback)(manifoldPoint,(void*)m_body0,(void*)m_body1);
|
||||
(*gContactProcessedCallback)(manifoldPoint, (void*)m_body0, (void*)m_body1);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_PERSISTENCY
|
||||
DebugPersistency();
|
||||
#endif //
|
||||
#endif //
|
||||
}
|
||||
|
||||
|
||||
int btPersistentManifold::calculateSerializeBufferSize() const
|
||||
int btPersistentManifold::calculateSerializeBufferSize() const
|
||||
{
|
||||
return sizeof(btPersistentManifoldData);
|
||||
}
|
||||
|
||||
const char* btPersistentManifold::serialize(const class btPersistentManifold* manifold, void* dataBuffer, class btSerializer* serializer) const
|
||||
const char* btPersistentManifold::serialize(const class btPersistentManifold* manifold, void* dataBuffer, class btSerializer* serializer) const
|
||||
{
|
||||
btPersistentManifoldData* dataOut = (btPersistentManifoldData*)dataBuffer;
|
||||
memset(dataOut, 0, sizeof(btPersistentManifoldData));
|
||||
@@ -379,7 +369,7 @@ void btPersistentManifold::deSerialize(const struct btPersistentManifoldDoubleDa
|
||||
for (int i = 0; i < this->getNumContacts(); i++)
|
||||
{
|
||||
btManifoldPoint& pt = m_pointCache[i];
|
||||
|
||||
|
||||
pt.m_appliedImpulse = manifoldDataPtr->m_pointCacheAppliedImpulse[i];
|
||||
pt.m_appliedImpulseLateral1 = manifoldDataPtr->m_pointCacheAppliedImpulseLateral1[i];
|
||||
pt.m_appliedImpulseLateral2 = manifoldDataPtr->m_pointCacheAppliedImpulseLateral2[i];
|
||||
@@ -409,7 +399,6 @@ void btPersistentManifold::deSerialize(const struct btPersistentManifoldDoubleDa
|
||||
pt.m_contactMotion1 = manifoldDataPtr->m_pointCacheContactMotion1[i];
|
||||
pt.m_contactMotion2 = manifoldDataPtr->m_pointCacheContactMotion2[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void btPersistentManifold::deSerialize(const struct btPersistentManifoldFloatData* manifoldDataPtr)
|
||||
@@ -455,5 +444,4 @@ void btPersistentManifold::deSerialize(const struct btPersistentManifoldFloatDat
|
||||
pt.m_contactMotion1 = manifoldDataPtr->m_pointCacheContactMotion1[i];
|
||||
pt.m_contactMotion2 = manifoldDataPtr->m_pointCacheContactMotion2[i];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,7 +16,6 @@ subject to the following restrictions:
|
||||
#ifndef BT_PERSISTENT_MANIFOLD_H
|
||||
#define BT_PERSISTENT_MANIFOLD_H
|
||||
|
||||
|
||||
#include "LinearMath/btVector3.h"
|
||||
#include "LinearMath/btTransform.h"
|
||||
#include "btManifoldPoint.h"
|
||||
@@ -34,14 +33,14 @@ extern btScalar gContactBreakingThreshold;
|
||||
class btPersistentManifold;
|
||||
|
||||
typedef bool (*ContactDestroyedCallback)(void* userPersistentData);
|
||||
typedef bool (*ContactProcessedCallback)(btManifoldPoint& cp,void* body0,void* body1);
|
||||
typedef void (*ContactStartedCallback)(btPersistentManifold* const &manifold);
|
||||
typedef void (*ContactEndedCallback)(btPersistentManifold* const &manifold);
|
||||
extern ContactDestroyedCallback gContactDestroyedCallback;
|
||||
typedef bool (*ContactProcessedCallback)(btManifoldPoint& cp, void* body0, void* body1);
|
||||
typedef void (*ContactStartedCallback)(btPersistentManifold* const& manifold);
|
||||
typedef void (*ContactEndedCallback)(btPersistentManifold* const& manifold);
|
||||
extern ContactDestroyedCallback gContactDestroyedCallback;
|
||||
extern ContactProcessedCallback gContactProcessedCallback;
|
||||
extern ContactStartedCallback gContactStartedCallback;
|
||||
extern ContactEndedCallback gContactEndedCallback;
|
||||
#endif //SWIG
|
||||
#endif //SWIG
|
||||
|
||||
//the enum starts at 1024 to avoid type conflicts with btTypedConstraint
|
||||
enum btContactManifoldTypes
|
||||
@@ -60,73 +59,74 @@ enum btContactManifoldTypes
|
||||
///the contact point with deepest penetration is always kept, and it tries to maximuze the area covered by the points
|
||||
///note that some pairs of objects might have more then one contact manifold.
|
||||
|
||||
|
||||
//ATTRIBUTE_ALIGNED128( class) btPersistentManifold : public btTypedObject
|
||||
ATTRIBUTE_ALIGNED16( class) btPersistentManifold : public btTypedObject
|
||||
ATTRIBUTE_ALIGNED16(class)
|
||||
btPersistentManifold : public btTypedObject
|
||||
{
|
||||
|
||||
btManifoldPoint m_pointCache[MANIFOLD_CACHE_SIZE];
|
||||
|
||||
/// this two body pointers can point to the physics rigidbody class.
|
||||
const btCollisionObject* m_body0;
|
||||
const btCollisionObject* m_body1;
|
||||
|
||||
int m_cachedPoints;
|
||||
int m_cachedPoints;
|
||||
|
||||
btScalar m_contactBreakingThreshold;
|
||||
btScalar m_contactProcessingThreshold;
|
||||
btScalar m_contactBreakingThreshold;
|
||||
btScalar m_contactProcessingThreshold;
|
||||
|
||||
|
||||
/// sort cached points so most isolated points come first
|
||||
int sortCachedPoints(const btManifoldPoint& pt);
|
||||
int sortCachedPoints(const btManifoldPoint& pt);
|
||||
|
||||
int findContactPoint(const btManifoldPoint* unUsed, int numUnused,const btManifoldPoint& pt);
|
||||
int findContactPoint(const btManifoldPoint* unUsed, int numUnused, const btManifoldPoint& pt);
|
||||
|
||||
public:
|
||||
|
||||
BT_DECLARE_ALIGNED_ALLOCATOR();
|
||||
|
||||
int m_companionIdA;
|
||||
int m_companionIdB;
|
||||
int m_companionIdA;
|
||||
int m_companionIdB;
|
||||
|
||||
int m_index1a;
|
||||
|
||||
btPersistentManifold();
|
||||
|
||||
btPersistentManifold(const btCollisionObject* body0,const btCollisionObject* body1,int , btScalar contactBreakingThreshold,btScalar contactProcessingThreshold)
|
||||
btPersistentManifold(const btCollisionObject* body0, const btCollisionObject* body1, int, btScalar contactBreakingThreshold, btScalar contactProcessingThreshold)
|
||||
: btTypedObject(BT_PERSISTENT_MANIFOLD_TYPE),
|
||||
m_body0(body0),m_body1(body1),m_cachedPoints(0),
|
||||
m_contactBreakingThreshold(contactBreakingThreshold),
|
||||
m_contactProcessingThreshold(contactProcessingThreshold),
|
||||
m_companionIdA(0),
|
||||
m_companionIdB(0),
|
||||
m_index1a(0)
|
||||
m_body0(body0),
|
||||
m_body1(body1),
|
||||
m_cachedPoints(0),
|
||||
m_contactBreakingThreshold(contactBreakingThreshold),
|
||||
m_contactProcessingThreshold(contactProcessingThreshold),
|
||||
m_companionIdA(0),
|
||||
m_companionIdB(0),
|
||||
m_index1a(0)
|
||||
{
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE const btCollisionObject* getBody0() const { return m_body0;}
|
||||
SIMD_FORCE_INLINE const btCollisionObject* getBody1() const { return m_body1;}
|
||||
SIMD_FORCE_INLINE const btCollisionObject* getBody0() const { return m_body0; }
|
||||
SIMD_FORCE_INLINE const btCollisionObject* getBody1() const { return m_body1; }
|
||||
|
||||
void setBodies(const btCollisionObject* body0,const btCollisionObject* body1)
|
||||
void setBodies(const btCollisionObject* body0, const btCollisionObject* body1)
|
||||
{
|
||||
m_body0 = body0;
|
||||
m_body1 = body1;
|
||||
}
|
||||
|
||||
void clearUserCache(btManifoldPoint& pt);
|
||||
void clearUserCache(btManifoldPoint & pt);
|
||||
|
||||
#ifdef DEBUG_PERSISTENCY
|
||||
void DebugPersistency();
|
||||
#endif //
|
||||
|
||||
SIMD_FORCE_INLINE int getNumContacts() const { return m_cachedPoints;}
|
||||
void DebugPersistency();
|
||||
#endif //
|
||||
|
||||
SIMD_FORCE_INLINE int getNumContacts() const
|
||||
{
|
||||
return m_cachedPoints;
|
||||
}
|
||||
/// the setNumContacts API is usually not used, except when you gather/fill all contacts manually
|
||||
void setNumContacts(int cachedPoints)
|
||||
{
|
||||
m_cachedPoints = cachedPoints;
|
||||
}
|
||||
|
||||
|
||||
SIMD_FORCE_INLINE const btManifoldPoint& getContactPoint(int index) const
|
||||
{
|
||||
btAssert(index < m_cachedPoints);
|
||||
@@ -140,39 +140,36 @@ public:
|
||||
}
|
||||
|
||||
///@todo: get this margin from the current physics / collision environment
|
||||
btScalar getContactBreakingThreshold() const;
|
||||
btScalar getContactBreakingThreshold() const;
|
||||
|
||||
btScalar getContactProcessingThreshold() const
|
||||
btScalar getContactProcessingThreshold() const
|
||||
{
|
||||
return m_contactProcessingThreshold;
|
||||
}
|
||||
|
||||
|
||||
void setContactBreakingThreshold(btScalar contactBreakingThreshold)
|
||||
{
|
||||
m_contactBreakingThreshold = contactBreakingThreshold;
|
||||
}
|
||||
|
||||
void setContactProcessingThreshold(btScalar contactProcessingThreshold)
|
||||
void setContactProcessingThreshold(btScalar contactProcessingThreshold)
|
||||
{
|
||||
m_contactProcessingThreshold = contactProcessingThreshold;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int getCacheEntry(const btManifoldPoint& newPoint) const;
|
||||
|
||||
int addManifoldPoint( const btManifoldPoint& newPoint, bool isPredictive=false);
|
||||
int addManifoldPoint(const btManifoldPoint& newPoint, bool isPredictive = false);
|
||||
|
||||
void removeContactPoint (int index)
|
||||
void removeContactPoint(int index)
|
||||
{
|
||||
clearUserCache(m_pointCache[index]);
|
||||
|
||||
int lastUsedIndex = getNumContacts() - 1;
|
||||
// m_pointCache[index] = m_pointCache[lastUsedIndex];
|
||||
if(index != lastUsedIndex)
|
||||
// m_pointCache[index] = m_pointCache[lastUsedIndex];
|
||||
if (index != lastUsedIndex)
|
||||
{
|
||||
m_pointCache[index] = m_pointCache[lastUsedIndex];
|
||||
m_pointCache[index] = m_pointCache[lastUsedIndex];
|
||||
//get rid of duplicated userPersistentData pointer
|
||||
m_pointCache[lastUsedIndex].m_userPersistentData = 0;
|
||||
m_pointCache[lastUsedIndex].m_appliedImpulse = 0.f;
|
||||
@@ -182,7 +179,7 @@ public:
|
||||
m_pointCache[lastUsedIndex].m_lifeTime = 0;
|
||||
}
|
||||
|
||||
btAssert(m_pointCache[lastUsedIndex].m_userPersistentData==0);
|
||||
btAssert(m_pointCache[lastUsedIndex].m_userPersistentData == 0);
|
||||
m_cachedPoints--;
|
||||
|
||||
if (gContactEndedCallback && m_cachedPoints == 0)
|
||||
@@ -243,13 +240,12 @@ public:
|
||||
return pt.m_distance1 <= getContactBreakingThreshold();
|
||||
}
|
||||
/// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin
|
||||
void refreshContactPoints( const btTransform& trA,const btTransform& trB);
|
||||
void refreshContactPoints(const btTransform& trA, const btTransform& trB);
|
||||
|
||||
|
||||
SIMD_FORCE_INLINE void clearManifold()
|
||||
SIMD_FORCE_INLINE void clearManifold()
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<m_cachedPoints;i++)
|
||||
for (i = 0; i < m_cachedPoints; i++)
|
||||
{
|
||||
clearUserCache(m_pointCache[i]);
|
||||
}
|
||||
@@ -261,15 +257,13 @@ public:
|
||||
m_cachedPoints = 0;
|
||||
}
|
||||
|
||||
int calculateSerializeBufferSize() const;
|
||||
const char* serialize(const class btPersistentManifold* manifold, void* dataBuffer, class btSerializer* serializer) const;
|
||||
int calculateSerializeBufferSize() const;
|
||||
const char* serialize(const class btPersistentManifold* manifold, void* dataBuffer, class btSerializer* serializer) const;
|
||||
void deSerialize(const struct btPersistentManifoldDoubleData* manifoldDataPtr);
|
||||
void deSerialize(const struct btPersistentManifoldFloatData* manifoldDataPtr);
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
// clang-format off
|
||||
|
||||
struct btPersistentManifoldDoubleData
|
||||
{
|
||||
@@ -362,17 +356,14 @@ struct btPersistentManifoldFloatData
|
||||
btCollisionObjectFloatData *m_body1;
|
||||
};
|
||||
|
||||
// clang-format on
|
||||
|
||||
#ifdef BT_USE_DOUBLE_PRECISION
|
||||
#define btPersistentManifoldData btPersistentManifoldDoubleData
|
||||
#define btPersistentManifoldDataName "btPersistentManifoldDoubleData"
|
||||
#define btPersistentManifoldData btPersistentManifoldDoubleData
|
||||
#define btPersistentManifoldDataName "btPersistentManifoldDoubleData"
|
||||
#else
|
||||
#define btPersistentManifoldData btPersistentManifoldFloatData
|
||||
#define btPersistentManifoldDataName "btPersistentManifoldFloatData"
|
||||
#endif //BT_USE_DOUBLE_PRECISION
|
||||
#define btPersistentManifoldData btPersistentManifoldFloatData
|
||||
#define btPersistentManifoldDataName "btPersistentManifoldFloatData"
|
||||
#endif //BT_USE_DOUBLE_PRECISION
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif //BT_PERSISTENT_MANIFOLD_H
|
||||
#endif //BT_PERSISTENT_MANIFOLD_H
|
||||
|
||||
@@ -18,38 +18,33 @@ subject to the following restrictions:
|
||||
|
||||
#include "btDiscreteCollisionDetectorInterface.h"
|
||||
|
||||
|
||||
|
||||
struct btPointCollector : public btDiscreteCollisionDetectorInterface::Result
|
||||
{
|
||||
|
||||
|
||||
btVector3 m_normalOnBInWorld;
|
||||
btVector3 m_pointInWorld;
|
||||
btScalar m_distance;//negative means penetration
|
||||
btScalar m_distance; //negative means penetration
|
||||
|
||||
bool m_hasResult;
|
||||
bool m_hasResult;
|
||||
|
||||
btPointCollector ()
|
||||
: m_distance(btScalar(BT_LARGE_FLOAT)),m_hasResult(false)
|
||||
btPointCollector()
|
||||
: m_distance(btScalar(BT_LARGE_FLOAT)), m_hasResult(false)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void setShapeIdentifiersA(int partId0,int index0)
|
||||
virtual void setShapeIdentifiersA(int partId0, int index0)
|
||||
{
|
||||
(void)partId0;
|
||||
(void)index0;
|
||||
|
||||
}
|
||||
virtual void setShapeIdentifiersB(int partId1,int index1)
|
||||
virtual void setShapeIdentifiersB(int partId1, int index1)
|
||||
{
|
||||
(void)partId1;
|
||||
(void)index1;
|
||||
}
|
||||
|
||||
virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
|
||||
virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
|
||||
{
|
||||
if (depth< m_distance)
|
||||
if (depth < m_distance)
|
||||
{
|
||||
m_hasResult = true;
|
||||
m_normalOnBInWorld = normalOnBInWorld;
|
||||
@@ -60,5 +55,4 @@ struct btPointCollector : public btDiscreteCollisionDetectorInterface::Result
|
||||
}
|
||||
};
|
||||
|
||||
#endif //BT_POINT_COLLECTOR_H
|
||||
|
||||
#endif //BT_POINT_COLLECTOR_H
|
||||
|
||||
@@ -13,45 +13,42 @@ subject to the following restrictions:
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
///This file was written by Erwin Coumans
|
||||
///Separating axis rest based on work from Pierre Terdiman, see
|
||||
///And contact clipping based on work from Simon Hobbs
|
||||
|
||||
|
||||
#include "btPolyhedralContactClipping.h"
|
||||
#include "BulletCollision/CollisionShapes/btConvexPolyhedron.h"
|
||||
|
||||
#include <float.h> //for FLT_MAX
|
||||
#include <float.h> //for FLT_MAX
|
||||
|
||||
int gExpectedNbTests=0;
|
||||
int gExpectedNbTests = 0;
|
||||
int gActualNbTests = 0;
|
||||
bool gUseInternalObject = true;
|
||||
|
||||
// Clips a face to the back of a plane
|
||||
void btPolyhedralContactClipping::clipFace(const btVertexArray& pVtxIn, btVertexArray& ppVtxOut, const btVector3& planeNormalWS,btScalar planeEqWS)
|
||||
void btPolyhedralContactClipping::clipFace(const btVertexArray& pVtxIn, btVertexArray& ppVtxOut, const btVector3& planeNormalWS, btScalar planeEqWS)
|
||||
{
|
||||
|
||||
int ve;
|
||||
btScalar ds, de;
|
||||
int numVerts = pVtxIn.size();
|
||||
if (numVerts < 2)
|
||||
return;
|
||||
|
||||
btVector3 firstVertex=pVtxIn[pVtxIn.size()-1];
|
||||
btVector3 firstVertex = pVtxIn[pVtxIn.size() - 1];
|
||||
btVector3 endVertex = pVtxIn[0];
|
||||
|
||||
ds = planeNormalWS.dot(firstVertex)+planeEqWS;
|
||||
|
||||
ds = planeNormalWS.dot(firstVertex) + planeEqWS;
|
||||
|
||||
for (ve = 0; ve < numVerts; ve++)
|
||||
{
|
||||
endVertex=pVtxIn[ve];
|
||||
endVertex = pVtxIn[ve];
|
||||
|
||||
de = planeNormalWS.dot(endVertex)+planeEqWS;
|
||||
de = planeNormalWS.dot(endVertex) + planeEqWS;
|
||||
|
||||
if (ds<0)
|
||||
if (ds < 0)
|
||||
{
|
||||
if (de<0)
|
||||
if (de < 0)
|
||||
{
|
||||
// Start < 0, end < 0, so output endVertex
|
||||
ppVtxOut.push_back(endVertex);
|
||||
@@ -59,15 +56,15 @@ void btPolyhedralContactClipping::clipFace(const btVertexArray& pVtxIn, btVertex
|
||||
else
|
||||
{
|
||||
// Start < 0, end >= 0, so output intersection
|
||||
ppVtxOut.push_back( firstVertex.lerp(endVertex,btScalar(ds * 1.f/(ds - de))));
|
||||
ppVtxOut.push_back(firstVertex.lerp(endVertex, btScalar(ds * 1.f / (ds - de))));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (de<0)
|
||||
if (de < 0)
|
||||
{
|
||||
// Start >= 0, end < 0 so output intersection and end
|
||||
ppVtxOut.push_back(firstVertex.lerp(endVertex,btScalar(ds * 1.f/(ds - de))));
|
||||
ppVtxOut.push_back(firstVertex.lerp(endVertex, btScalar(ds * 1.f / (ds - de))));
|
||||
ppVtxOut.push_back(endVertex);
|
||||
}
|
||||
}
|
||||
@@ -76,47 +73,44 @@ void btPolyhedralContactClipping::clipFace(const btVertexArray& pVtxIn, btVertex
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool TestSepAxis(const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btVector3& sep_axis, btScalar& depth, btVector3& witnessPointA, btVector3& witnessPointB)
|
||||
static bool TestSepAxis(const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA, const btTransform& transB, const btVector3& sep_axis, btScalar& depth, btVector3& witnessPointA, btVector3& witnessPointB)
|
||||
{
|
||||
btScalar Min0,Max0;
|
||||
btScalar Min1,Max1;
|
||||
btVector3 witnesPtMinA,witnesPtMaxA;
|
||||
btVector3 witnesPtMinB,witnesPtMaxB;
|
||||
btScalar Min0, Max0;
|
||||
btScalar Min1, Max1;
|
||||
btVector3 witnesPtMinA, witnesPtMaxA;
|
||||
btVector3 witnesPtMinB, witnesPtMaxB;
|
||||
|
||||
hullA.project(transA,sep_axis, Min0, Max0,witnesPtMinA,witnesPtMaxA);
|
||||
hullB.project(transB, sep_axis, Min1, Max1,witnesPtMinB,witnesPtMaxB);
|
||||
hullA.project(transA, sep_axis, Min0, Max0, witnesPtMinA, witnesPtMaxA);
|
||||
hullB.project(transB, sep_axis, Min1, Max1, witnesPtMinB, witnesPtMaxB);
|
||||
|
||||
if(Max0<Min1 || Max1<Min0)
|
||||
if (Max0 < Min1 || Max1 < Min0)
|
||||
return false;
|
||||
|
||||
btScalar d0 = Max0 - Min1;
|
||||
btAssert(d0>=0.0f);
|
||||
btAssert(d0 >= 0.0f);
|
||||
btScalar d1 = Max1 - Min0;
|
||||
btAssert(d1>=0.0f);
|
||||
if (d0<d1)
|
||||
btAssert(d1 >= 0.0f);
|
||||
if (d0 < d1)
|
||||
{
|
||||
depth = d0;
|
||||
witnessPointA = witnesPtMaxA;
|
||||
witnessPointB = witnesPtMinB;
|
||||
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
depth = d1;
|
||||
witnessPointA = witnesPtMinA;
|
||||
witnessPointB = witnesPtMaxB;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int gActualSATPairTests=0;
|
||||
static int gActualSATPairTests = 0;
|
||||
|
||||
inline bool IsAlmostZero(const btVector3& v)
|
||||
{
|
||||
if(btFabs(v.x())>1e-6 || btFabs(v.y())>1e-6 || btFabs(v.z())>1e-6) return false;
|
||||
if (btFabs(v.x()) > 1e-6 || btFabs(v.y()) > 1e-6 || btFabs(v.z()) > 1e-6) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -125,9 +119,9 @@ inline bool IsAlmostZero(const btVector3& v)
|
||||
inline void BoxSupport(const btScalar extents[3], const btScalar sv[3], btScalar p[3])
|
||||
{
|
||||
// This version is ~11.000 cycles (4%) faster overall in one of the tests.
|
||||
// IR(p[0]) = IR(extents[0])|(IR(sv[0])&SIGN_BITMASK);
|
||||
// IR(p[1]) = IR(extents[1])|(IR(sv[1])&SIGN_BITMASK);
|
||||
// IR(p[2]) = IR(extents[2])|(IR(sv[2])&SIGN_BITMASK);
|
||||
// IR(p[0]) = IR(extents[0])|(IR(sv[0])&SIGN_BITMASK);
|
||||
// IR(p[1]) = IR(extents[1])|(IR(sv[1])&SIGN_BITMASK);
|
||||
// IR(p[2]) = IR(extents[2])|(IR(sv[2])&SIGN_BITMASK);
|
||||
p[0] = sv[0] < 0.0f ? -extents[0] : extents[0];
|
||||
p[1] = sv[1] < 0.0f ? -extents[1] : extents[1];
|
||||
p[2] = sv[2] < 0.0f ? -extents[2] : extents[2];
|
||||
@@ -140,90 +134,94 @@ void InverseTransformPoint3x3(btVector3& out, const btVector3& in, const btTrans
|
||||
const btVector3& r1 = rot[1];
|
||||
const btVector3& r2 = rot[2];
|
||||
|
||||
const btScalar x = r0.x()*in.x() + r1.x()*in.y() + r2.x()*in.z();
|
||||
const btScalar y = r0.y()*in.x() + r1.y()*in.y() + r2.y()*in.z();
|
||||
const btScalar z = r0.z()*in.x() + r1.z()*in.y() + r2.z()*in.z();
|
||||
const btScalar x = r0.x() * in.x() + r1.x() * in.y() + r2.x() * in.z();
|
||||
const btScalar y = r0.y() * in.x() + r1.y() * in.y() + r2.y() * in.z();
|
||||
const btScalar z = r0.z() * in.x() + r1.z() * in.y() + r2.z() * in.z();
|
||||
|
||||
out.setValue(x, y, z);
|
||||
}
|
||||
|
||||
bool TestInternalObjects( const btTransform& trans0, const btTransform& trans1, const btVector3& delta_c, const btVector3& axis, const btConvexPolyhedron& convex0, const btConvexPolyhedron& convex1, btScalar dmin)
|
||||
bool TestInternalObjects(const btTransform& trans0, const btTransform& trans1, const btVector3& delta_c, const btVector3& axis, const btConvexPolyhedron& convex0, const btConvexPolyhedron& convex1, btScalar dmin)
|
||||
{
|
||||
const btScalar dp = delta_c.dot(axis);
|
||||
|
||||
btVector3 localAxis0;
|
||||
InverseTransformPoint3x3(localAxis0, axis,trans0);
|
||||
InverseTransformPoint3x3(localAxis0, axis, trans0);
|
||||
btVector3 localAxis1;
|
||||
InverseTransformPoint3x3(localAxis1, axis,trans1);
|
||||
InverseTransformPoint3x3(localAxis1, axis, trans1);
|
||||
|
||||
btScalar p0[3];
|
||||
BoxSupport(convex0.m_extents, localAxis0, p0);
|
||||
btScalar p1[3];
|
||||
BoxSupport(convex1.m_extents, localAxis1, p1);
|
||||
|
||||
const btScalar Radius0 = p0[0]*localAxis0.x() + p0[1]*localAxis0.y() + p0[2]*localAxis0.z();
|
||||
const btScalar Radius1 = p1[0]*localAxis1.x() + p1[1]*localAxis1.y() + p1[2]*localAxis1.z();
|
||||
const btScalar Radius0 = p0[0] * localAxis0.x() + p0[1] * localAxis0.y() + p0[2] * localAxis0.z();
|
||||
const btScalar Radius1 = p1[0] * localAxis1.x() + p1[1] * localAxis1.y() + p1[2] * localAxis1.z();
|
||||
|
||||
const btScalar MinRadius = Radius0>convex0.m_radius ? Radius0 : convex0.m_radius;
|
||||
const btScalar MaxRadius = Radius1>convex1.m_radius ? Radius1 : convex1.m_radius;
|
||||
const btScalar MinRadius = Radius0 > convex0.m_radius ? Radius0 : convex0.m_radius;
|
||||
const btScalar MaxRadius = Radius1 > convex1.m_radius ? Radius1 : convex1.m_radius;
|
||||
|
||||
const btScalar MinMaxRadius = MaxRadius + MinRadius;
|
||||
const btScalar d0 = MinMaxRadius + dp;
|
||||
const btScalar d1 = MinMaxRadius - dp;
|
||||
|
||||
const btScalar depth = d0<d1 ? d0:d1;
|
||||
if(depth>dmin)
|
||||
const btScalar depth = d0 < d1 ? d0 : d1;
|
||||
if (depth > dmin)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
#endif //TEST_INTERNAL_OBJECTS
|
||||
#endif //TEST_INTERNAL_OBJECTS
|
||||
|
||||
|
||||
|
||||
SIMD_FORCE_INLINE void btSegmentsClosestPoints(
|
||||
SIMD_FORCE_INLINE void btSegmentsClosestPoints(
|
||||
btVector3& ptsVector,
|
||||
btVector3& offsetA,
|
||||
btVector3& offsetB,
|
||||
btScalar& tA, btScalar& tB,
|
||||
const btVector3& translation,
|
||||
const btVector3& dirA, btScalar hlenA,
|
||||
const btVector3& dirB, btScalar hlenB )
|
||||
const btVector3& dirB, btScalar hlenB)
|
||||
{
|
||||
// compute the parameters of the closest points on each line segment
|
||||
|
||||
btScalar dirA_dot_dirB = btDot(dirA,dirB);
|
||||
btScalar dirA_dot_trans = btDot(dirA,translation);
|
||||
btScalar dirB_dot_trans = btDot(dirB,translation);
|
||||
btScalar dirA_dot_dirB = btDot(dirA, dirB);
|
||||
btScalar dirA_dot_trans = btDot(dirA, translation);
|
||||
btScalar dirB_dot_trans = btDot(dirB, translation);
|
||||
|
||||
btScalar denom = 1.0f - dirA_dot_dirB * dirA_dot_dirB;
|
||||
|
||||
if ( denom == 0.0f ) {
|
||||
if (denom == 0.0f)
|
||||
{
|
||||
tA = 0.0f;
|
||||
} else {
|
||||
tA = ( dirA_dot_trans - dirB_dot_trans * dirA_dot_dirB ) / denom;
|
||||
if ( tA < -hlenA )
|
||||
}
|
||||
else
|
||||
{
|
||||
tA = (dirA_dot_trans - dirB_dot_trans * dirA_dot_dirB) / denom;
|
||||
if (tA < -hlenA)
|
||||
tA = -hlenA;
|
||||
else if ( tA > hlenA )
|
||||
else if (tA > hlenA)
|
||||
tA = hlenA;
|
||||
}
|
||||
|
||||
tB = tA * dirA_dot_dirB - dirB_dot_trans;
|
||||
|
||||
if ( tB < -hlenB ) {
|
||||
if (tB < -hlenB)
|
||||
{
|
||||
tB = -hlenB;
|
||||
tA = tB * dirA_dot_dirB + dirA_dot_trans;
|
||||
|
||||
if ( tA < -hlenA )
|
||||
if (tA < -hlenA)
|
||||
tA = -hlenA;
|
||||
else if ( tA > hlenA )
|
||||
else if (tA > hlenA)
|
||||
tA = hlenA;
|
||||
} else if ( tB > hlenB ) {
|
||||
}
|
||||
else if (tB > hlenB)
|
||||
{
|
||||
tB = hlenB;
|
||||
tA = tB * dirA_dot_dirB + dirA_dot_trans;
|
||||
|
||||
if ( tA < -hlenA )
|
||||
if (tA < -hlenA)
|
||||
tA = -hlenA;
|
||||
else if ( tA > hlenA )
|
||||
else if (tA > hlenA)
|
||||
tA = hlenA;
|
||||
}
|
||||
|
||||
@@ -235,44 +233,42 @@ void InverseTransformPoint3x3(btVector3& out, const btVector3& in, const btTrans
|
||||
ptsVector = translation - offsetA + offsetB;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool btPolyhedralContactClipping::findSeparatingAxis( const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, btVector3& sep, btDiscreteCollisionDetectorInterface::Result& resultOut)
|
||||
bool btPolyhedralContactClipping::findSeparatingAxis(const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA, const btTransform& transB, btVector3& sep, btDiscreteCollisionDetectorInterface::Result& resultOut)
|
||||
{
|
||||
gActualSATPairTests++;
|
||||
|
||||
//#ifdef TEST_INTERNAL_OBJECTS
|
||||
//#ifdef TEST_INTERNAL_OBJECTS
|
||||
const btVector3 c0 = transA * hullA.m_localCenter;
|
||||
const btVector3 c1 = transB * hullB.m_localCenter;
|
||||
const btVector3 DeltaC2 = c0 - c1;
|
||||
//#endif
|
||||
//#endif
|
||||
|
||||
btScalar dmin = FLT_MAX;
|
||||
int curPlaneTests=0;
|
||||
int curPlaneTests = 0;
|
||||
|
||||
int numFacesA = hullA.m_faces.size();
|
||||
// Test normals from hullA
|
||||
for(int i=0;i<numFacesA;i++)
|
||||
for (int i = 0; i < numFacesA; i++)
|
||||
{
|
||||
const btVector3 Normal(hullA.m_faces[i].m_plane[0], hullA.m_faces[i].m_plane[1], hullA.m_faces[i].m_plane[2]);
|
||||
btVector3 faceANormalWS = transA.getBasis() * Normal;
|
||||
if (DeltaC2.dot(faceANormalWS)<0)
|
||||
faceANormalWS*=-1.f;
|
||||
if (DeltaC2.dot(faceANormalWS) < 0)
|
||||
faceANormalWS *= -1.f;
|
||||
|
||||
curPlaneTests++;
|
||||
#ifdef TEST_INTERNAL_OBJECTS
|
||||
gExpectedNbTests++;
|
||||
if(gUseInternalObject && !TestInternalObjects(transA,transB, DeltaC2, faceANormalWS, hullA, hullB, dmin))
|
||||
if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, faceANormalWS, hullA, hullB, dmin))
|
||||
continue;
|
||||
gActualNbTests++;
|
||||
#endif
|
||||
|
||||
btScalar d;
|
||||
btVector3 wA,wB;
|
||||
if(!TestSepAxis( hullA, hullB, transA,transB, faceANormalWS, d,wA,wB))
|
||||
btVector3 wA, wB;
|
||||
if (!TestSepAxis(hullA, hullB, transA, transB, faceANormalWS, d, wA, wB))
|
||||
return false;
|
||||
|
||||
if(d<dmin)
|
||||
if (d < dmin)
|
||||
{
|
||||
dmin = d;
|
||||
sep = faceANormalWS;
|
||||
@@ -281,92 +277,89 @@ bool btPolyhedralContactClipping::findSeparatingAxis( const btConvexPolyhedron&
|
||||
|
||||
int numFacesB = hullB.m_faces.size();
|
||||
// Test normals from hullB
|
||||
for(int i=0;i<numFacesB;i++)
|
||||
for (int i = 0; i < numFacesB; i++)
|
||||
{
|
||||
const btVector3 Normal(hullB.m_faces[i].m_plane[0], hullB.m_faces[i].m_plane[1], hullB.m_faces[i].m_plane[2]);
|
||||
btVector3 WorldNormal = transB.getBasis() * Normal;
|
||||
if (DeltaC2.dot(WorldNormal)<0)
|
||||
WorldNormal *=-1.f;
|
||||
if (DeltaC2.dot(WorldNormal) < 0)
|
||||
WorldNormal *= -1.f;
|
||||
|
||||
curPlaneTests++;
|
||||
#ifdef TEST_INTERNAL_OBJECTS
|
||||
gExpectedNbTests++;
|
||||
if(gUseInternalObject && !TestInternalObjects(transA,transB,DeltaC2, WorldNormal, hullA, hullB, dmin))
|
||||
if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, WorldNormal, hullA, hullB, dmin))
|
||||
continue;
|
||||
gActualNbTests++;
|
||||
#endif
|
||||
|
||||
btScalar d;
|
||||
btVector3 wA,wB;
|
||||
if(!TestSepAxis(hullA, hullB,transA,transB, WorldNormal,d,wA,wB))
|
||||
btVector3 wA, wB;
|
||||
if (!TestSepAxis(hullA, hullB, transA, transB, WorldNormal, d, wA, wB))
|
||||
return false;
|
||||
|
||||
if(d<dmin)
|
||||
if (d < dmin)
|
||||
{
|
||||
dmin = d;
|
||||
sep = WorldNormal;
|
||||
}
|
||||
}
|
||||
|
||||
btVector3 edgeAstart,edgeAend,edgeBstart,edgeBend;
|
||||
int edgeA=-1;
|
||||
int edgeB=-1;
|
||||
btVector3 edgeAstart, edgeAend, edgeBstart, edgeBend;
|
||||
int edgeA = -1;
|
||||
int edgeB = -1;
|
||||
btVector3 worldEdgeA;
|
||||
btVector3 worldEdgeB;
|
||||
btVector3 witnessPointA(0,0,0),witnessPointB(0,0,0);
|
||||
|
||||
btVector3 witnessPointA(0, 0, 0), witnessPointB(0, 0, 0);
|
||||
|
||||
int curEdgeEdge = 0;
|
||||
// Test edges
|
||||
for(int e0=0;e0<hullA.m_uniqueEdges.size();e0++)
|
||||
for (int e0 = 0; e0 < hullA.m_uniqueEdges.size(); e0++)
|
||||
{
|
||||
const btVector3 edge0 = hullA.m_uniqueEdges[e0];
|
||||
const btVector3 WorldEdge0 = transA.getBasis() * edge0;
|
||||
for(int e1=0;e1<hullB.m_uniqueEdges.size();e1++)
|
||||
for (int e1 = 0; e1 < hullB.m_uniqueEdges.size(); e1++)
|
||||
{
|
||||
const btVector3 edge1 = hullB.m_uniqueEdges[e1];
|
||||
const btVector3 WorldEdge1 = transB.getBasis() * edge1;
|
||||
|
||||
btVector3 Cross = WorldEdge0.cross(WorldEdge1);
|
||||
curEdgeEdge++;
|
||||
if(!IsAlmostZero(Cross))
|
||||
if (!IsAlmostZero(Cross))
|
||||
{
|
||||
Cross = Cross.normalize();
|
||||
if (DeltaC2.dot(Cross)<0)
|
||||
if (DeltaC2.dot(Cross) < 0)
|
||||
Cross *= -1.f;
|
||||
|
||||
|
||||
#ifdef TEST_INTERNAL_OBJECTS
|
||||
gExpectedNbTests++;
|
||||
if(gUseInternalObject && !TestInternalObjects(transA,transB,DeltaC2, Cross, hullA, hullB, dmin))
|
||||
if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, Cross, hullA, hullB, dmin))
|
||||
continue;
|
||||
gActualNbTests++;
|
||||
#endif
|
||||
|
||||
btScalar dist;
|
||||
btVector3 wA,wB;
|
||||
if(!TestSepAxis( hullA, hullB, transA,transB, Cross, dist,wA,wB))
|
||||
btVector3 wA, wB;
|
||||
if (!TestSepAxis(hullA, hullB, transA, transB, Cross, dist, wA, wB))
|
||||
return false;
|
||||
|
||||
if(dist<dmin)
|
||||
if (dist < dmin)
|
||||
{
|
||||
dmin = dist;
|
||||
sep = Cross;
|
||||
edgeA=e0;
|
||||
edgeB=e1;
|
||||
edgeA = e0;
|
||||
edgeB = e1;
|
||||
worldEdgeA = WorldEdge0;
|
||||
worldEdgeB = WorldEdge1;
|
||||
witnessPointA=wA;
|
||||
witnessPointB=wB;
|
||||
witnessPointA = wA;
|
||||
witnessPointB = wB;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (edgeA>=0&&edgeB>=0)
|
||||
if (edgeA >= 0 && edgeB >= 0)
|
||||
{
|
||||
// printf("edge-edge\n");
|
||||
// printf("edge-edge\n");
|
||||
//add an edge-edge contact
|
||||
|
||||
btVector3 ptsVector;
|
||||
@@ -375,57 +368,55 @@ bool btPolyhedralContactClipping::findSeparatingAxis( const btConvexPolyhedron&
|
||||
btScalar tA;
|
||||
btScalar tB;
|
||||
|
||||
btVector3 translation = witnessPointB-witnessPointA;
|
||||
btVector3 translation = witnessPointB - witnessPointA;
|
||||
|
||||
btVector3 dirA = worldEdgeA;
|
||||
btVector3 dirB = worldEdgeB;
|
||||
|
||||
|
||||
btScalar hlenB = 1e30f;
|
||||
btScalar hlenA = 1e30f;
|
||||
|
||||
btSegmentsClosestPoints(ptsVector,offsetA,offsetB,tA,tB,
|
||||
translation,
|
||||
dirA, hlenA,
|
||||
dirB,hlenB);
|
||||
btSegmentsClosestPoints(ptsVector, offsetA, offsetB, tA, tB,
|
||||
translation,
|
||||
dirA, hlenA,
|
||||
dirB, hlenB);
|
||||
|
||||
btScalar nlSqrt = ptsVector.length2();
|
||||
if (nlSqrt>SIMD_EPSILON)
|
||||
if (nlSqrt > SIMD_EPSILON)
|
||||
{
|
||||
btScalar nl = btSqrt(nlSqrt);
|
||||
ptsVector *= 1.f/nl;
|
||||
if (ptsVector.dot(DeltaC2)<0.f)
|
||||
ptsVector *= 1.f / nl;
|
||||
if (ptsVector.dot(DeltaC2) < 0.f)
|
||||
{
|
||||
ptsVector*=-1.f;
|
||||
ptsVector *= -1.f;
|
||||
}
|
||||
btVector3 ptOnB = witnessPointB + offsetB;
|
||||
btScalar distance = nl;
|
||||
resultOut.addContactPoint(ptsVector, ptOnB,-distance);
|
||||
resultOut.addContactPoint(ptsVector, ptOnB, -distance);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if((DeltaC2.dot(sep))<0.0f)
|
||||
if ((DeltaC2.dot(sep)) < 0.0f)
|
||||
sep = -sep;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void btPolyhedralContactClipping::clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1,btVertexArray& worldVertsB2, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut)
|
||||
void btPolyhedralContactClipping::clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1, btVertexArray& worldVertsB2, const btScalar minDist, btScalar maxDist, btDiscreteCollisionDetectorInterface::Result& resultOut)
|
||||
{
|
||||
worldVertsB2.resize(0);
|
||||
btVertexArray* pVtxIn = &worldVertsB1;
|
||||
btVertexArray* pVtxOut = &worldVertsB2;
|
||||
pVtxOut->reserve(pVtxIn->size());
|
||||
|
||||
int closestFaceA=-1;
|
||||
int closestFaceA = -1;
|
||||
{
|
||||
btScalar dmin = FLT_MAX;
|
||||
for(int face=0;face<hullA.m_faces.size();face++)
|
||||
for (int face = 0; face < hullA.m_faces.size(); face++)
|
||||
{
|
||||
const btVector3 Normal(hullA.m_faces[face].m_plane[0], hullA.m_faces[face].m_plane[1], hullA.m_faces[face].m_plane[2]);
|
||||
const btVector3 faceANormalWS = transA.getBasis() * Normal;
|
||||
|
||||
|
||||
btScalar d = faceANormalWS.dot(separatingNormal);
|
||||
if (d < dmin)
|
||||
{
|
||||
@@ -434,69 +425,66 @@ void btPolyhedralContactClipping::clipFaceAgainstHull(const btVector3& separatin
|
||||
}
|
||||
}
|
||||
}
|
||||
if (closestFaceA<0)
|
||||
if (closestFaceA < 0)
|
||||
return;
|
||||
|
||||
const btFace& polyA = hullA.m_faces[closestFaceA];
|
||||
|
||||
// clip polygon to back of planes of all faces of hull A that are adjacent to witness face
|
||||
// clip polygon to back of planes of all faces of hull A that are adjacent to witness face
|
||||
int numVerticesA = polyA.m_indices.size();
|
||||
for(int e0=0;e0<numVerticesA;e0++)
|
||||
for (int e0 = 0; e0 < numVerticesA; e0++)
|
||||
{
|
||||
const btVector3& a = hullA.m_vertices[polyA.m_indices[e0]];
|
||||
const btVector3& b = hullA.m_vertices[polyA.m_indices[(e0+1)%numVerticesA]];
|
||||
const btVector3& b = hullA.m_vertices[polyA.m_indices[(e0 + 1) % numVerticesA]];
|
||||
const btVector3 edge0 = a - b;
|
||||
const btVector3 WorldEdge0 = transA.getBasis() * edge0;
|
||||
btVector3 worldPlaneAnormal1 = transA.getBasis()* btVector3(polyA.m_plane[0],polyA.m_plane[1],polyA.m_plane[2]);
|
||||
btVector3 worldPlaneAnormal1 = transA.getBasis() * btVector3(polyA.m_plane[0], polyA.m_plane[1], polyA.m_plane[2]);
|
||||
|
||||
btVector3 planeNormalWS1 = -WorldEdge0.cross(worldPlaneAnormal1);//.cross(WorldEdge0);
|
||||
btVector3 worldA1 = transA*a;
|
||||
btVector3 planeNormalWS1 = -WorldEdge0.cross(worldPlaneAnormal1); //.cross(WorldEdge0);
|
||||
btVector3 worldA1 = transA * a;
|
||||
btScalar planeEqWS1 = -worldA1.dot(planeNormalWS1);
|
||||
|
||||
|
||||
//int otherFace=0;
|
||||
#ifdef BLA1
|
||||
int otherFace = polyA.m_connectedFaces[e0];
|
||||
btVector3 localPlaneNormal (hullA.m_faces[otherFace].m_plane[0],hullA.m_faces[otherFace].m_plane[1],hullA.m_faces[otherFace].m_plane[2]);
|
||||
btVector3 localPlaneNormal(hullA.m_faces[otherFace].m_plane[0], hullA.m_faces[otherFace].m_plane[1], hullA.m_faces[otherFace].m_plane[2]);
|
||||
btScalar localPlaneEq = hullA.m_faces[otherFace].m_plane[3];
|
||||
|
||||
btVector3 planeNormalWS = transA.getBasis()*localPlaneNormal;
|
||||
btScalar planeEqWS=localPlaneEq-planeNormalWS.dot(transA.getOrigin());
|
||||
#else
|
||||
btVector3 planeNormalWS = transA.getBasis() * localPlaneNormal;
|
||||
btScalar planeEqWS = localPlaneEq - planeNormalWS.dot(transA.getOrigin());
|
||||
#else
|
||||
btVector3 planeNormalWS = planeNormalWS1;
|
||||
btScalar planeEqWS=planeEqWS1;
|
||||
|
||||
btScalar planeEqWS = planeEqWS1;
|
||||
|
||||
#endif
|
||||
//clip face
|
||||
|
||||
clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);
|
||||
btSwap(pVtxIn,pVtxOut);
|
||||
clipFace(*pVtxIn, *pVtxOut, planeNormalWS, planeEqWS);
|
||||
btSwap(pVtxIn, pVtxOut);
|
||||
pVtxOut->resize(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//#define ONLY_REPORT_DEEPEST_POINT
|
||||
//#define ONLY_REPORT_DEEPEST_POINT
|
||||
|
||||
btVector3 point;
|
||||
|
||||
|
||||
// only keep points that are behind the witness face
|
||||
{
|
||||
btVector3 localPlaneNormal (polyA.m_plane[0],polyA.m_plane[1],polyA.m_plane[2]);
|
||||
btVector3 localPlaneNormal(polyA.m_plane[0], polyA.m_plane[1], polyA.m_plane[2]);
|
||||
btScalar localPlaneEq = polyA.m_plane[3];
|
||||
btVector3 planeNormalWS = transA.getBasis()*localPlaneNormal;
|
||||
btScalar planeEqWS=localPlaneEq-planeNormalWS.dot(transA.getOrigin());
|
||||
for (int i=0;i<pVtxIn->size();i++)
|
||||
btVector3 planeNormalWS = transA.getBasis() * localPlaneNormal;
|
||||
btScalar planeEqWS = localPlaneEq - planeNormalWS.dot(transA.getOrigin());
|
||||
for (int i = 0; i < pVtxIn->size(); i++)
|
||||
{
|
||||
btVector3 vtx = pVtxIn->at(i);
|
||||
btScalar depth = planeNormalWS.dot(vtx)+planeEqWS;
|
||||
if (depth <=minDist)
|
||||
btScalar depth = planeNormalWS.dot(vtx) + planeEqWS;
|
||||
if (depth <= minDist)
|
||||
{
|
||||
// printf("clamped: depth=%f to minDist=%f\n",depth,minDist);
|
||||
// printf("clamped: depth=%f to minDist=%f\n",depth,minDist);
|
||||
depth = minDist;
|
||||
}
|
||||
|
||||
if (depth <=maxDist)
|
||||
if (depth <= maxDist)
|
||||
{
|
||||
btVector3 point = pVtxIn->at(i);
|
||||
#ifdef ONLY_REPORT_DEEPEST_POINT
|
||||
@@ -507,40 +495,32 @@ void btPolyhedralContactClipping::clipFaceAgainstHull(const btVector3& separatin
|
||||
{
|
||||
printf("error in btPolyhedralContactClipping depth = %f\n", depth);
|
||||
printf("likely wrong separatingNormal passed in\n");
|
||||
}
|
||||
#endif
|
||||
resultOut.addContactPoint(separatingNormal,point,depth);
|
||||
}
|
||||
#endif
|
||||
resultOut.addContactPoint(separatingNormal, point, depth);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef ONLY_REPORT_DEEPEST_POINT
|
||||
if (curMaxDist<maxDist)
|
||||
if (curMaxDist < maxDist)
|
||||
{
|
||||
resultOut.addContactPoint(separatingNormal,point,curMaxDist);
|
||||
resultOut.addContactPoint(separatingNormal, point, curMaxDist);
|
||||
}
|
||||
#endif //ONLY_REPORT_DEEPEST_POINT
|
||||
|
||||
#endif //ONLY_REPORT_DEEPEST_POINT
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void btPolyhedralContactClipping::clipHullAgainstHull(const btVector3& separatingNormal1, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btScalar minDist, btScalar maxDist,btVertexArray& worldVertsB1,btVertexArray& worldVertsB2,btDiscreteCollisionDetectorInterface::Result& resultOut)
|
||||
void btPolyhedralContactClipping::clipHullAgainstHull(const btVector3& separatingNormal1, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA, const btTransform& transB, const btScalar minDist, btScalar maxDist, btVertexArray& worldVertsB1, btVertexArray& worldVertsB2, btDiscreteCollisionDetectorInterface::Result& resultOut)
|
||||
{
|
||||
|
||||
btVector3 separatingNormal = separatingNormal1.normalized();
|
||||
// const btVector3 c0 = transA * hullA.m_localCenter;
|
||||
// const btVector3 c1 = transB * hullB.m_localCenter;
|
||||
// const btVector3 c0 = transA * hullA.m_localCenter;
|
||||
// const btVector3 c1 = transB * hullB.m_localCenter;
|
||||
//const btVector3 DeltaC2 = c0 - c1;
|
||||
|
||||
|
||||
|
||||
int closestFaceB=-1;
|
||||
int closestFaceB = -1;
|
||||
btScalar dmax = -FLT_MAX;
|
||||
{
|
||||
for(int face=0;face<hullB.m_faces.size();face++)
|
||||
for (int face = 0; face < hullB.m_faces.size(); face++)
|
||||
{
|
||||
const btVector3 Normal(hullB.m_faces[face].m_plane[0], hullB.m_faces[face].m_plane[1], hullB.m_faces[face].m_plane[2]);
|
||||
const btVector3 WorldNormal = transB.getBasis() * Normal;
|
||||
@@ -553,18 +533,16 @@ void btPolyhedralContactClipping::clipHullAgainstHull(const btVector3& separatin
|
||||
}
|
||||
}
|
||||
worldVertsB1.resize(0);
|
||||
{
|
||||
const btFace& polyB = hullB.m_faces[closestFaceB];
|
||||
const int numVertices = polyB.m_indices.size();
|
||||
for(int e0=0;e0<numVertices;e0++)
|
||||
{
|
||||
const btVector3& b = hullB.m_vertices[polyB.m_indices[e0]];
|
||||
worldVertsB1.push_back(transB*b);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (closestFaceB>=0)
|
||||
clipFaceAgainstHull(separatingNormal, hullA, transA,worldVertsB1, worldVertsB2,minDist, maxDist,resultOut);
|
||||
{
|
||||
const btFace& polyB = hullB.m_faces[closestFaceB];
|
||||
const int numVertices = polyB.m_indices.size();
|
||||
for (int e0 = 0; e0 < numVertices; e0++)
|
||||
{
|
||||
const btVector3& b = hullB.m_vertices[polyB.m_indices[e0]];
|
||||
worldVertsB1.push_back(transB * b);
|
||||
}
|
||||
}
|
||||
|
||||
if (closestFaceB >= 0)
|
||||
clipFaceAgainstHull(separatingNormal, hullA, transA, worldVertsB1, worldVertsB2, minDist, maxDist, resultOut);
|
||||
}
|
||||
|
||||
@@ -13,14 +13,11 @@ subject to the following restrictions:
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
///This file was written by Erwin Coumans
|
||||
|
||||
|
||||
#ifndef BT_POLYHEDRAL_CONTACT_CLIPPING_H
|
||||
#define BT_POLYHEDRAL_CONTACT_CLIPPING_H
|
||||
|
||||
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
#include "LinearMath/btTransform.h"
|
||||
#include "btDiscreteCollisionDetectorInterface.h"
|
||||
@@ -32,18 +29,14 @@ typedef btAlignedObjectArray<btVector3> btVertexArray;
|
||||
// Clips a face to the back of a plane
|
||||
struct btPolyhedralContactClipping
|
||||
{
|
||||
static void clipHullAgainstHull(const btVector3& separatingNormal1, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA, const btTransform& transB, const btScalar minDist, btScalar maxDist, btVertexArray& worldVertsB1, btVertexArray& worldVertsB2, btDiscreteCollisionDetectorInterface::Result& resultOut);
|
||||
|
||||
static void clipHullAgainstHull(const btVector3& separatingNormal1, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btScalar minDist, btScalar maxDist,btVertexArray& worldVertsB1,btVertexArray& worldVertsB2,btDiscreteCollisionDetectorInterface::Result& resultOut);
|
||||
static void clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1, btVertexArray& worldVertsB2, const btScalar minDist, btScalar maxDist, btDiscreteCollisionDetectorInterface::Result& resultOut);
|
||||
|
||||
static void clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1,btVertexArray& worldVertsB2, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut);
|
||||
|
||||
|
||||
static bool findSeparatingAxis( const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, btVector3& sep, btDiscreteCollisionDetectorInterface::Result& resultOut);
|
||||
static bool findSeparatingAxis(const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA, const btTransform& transB, btVector3& sep, btDiscreteCollisionDetectorInterface::Result& resultOut);
|
||||
|
||||
///the clipFace method is used internally
|
||||
static void clipFace(const btVertexArray& pVtxIn, btVertexArray& ppVtxOut, const btVector3& planeNormalWS,btScalar planeEqWS);
|
||||
|
||||
static void clipFace(const btVertexArray& pVtxIn, btVertexArray& ppVtxOut, const btVector3& planeNormalWS, btScalar planeEqWS);
|
||||
};
|
||||
|
||||
#endif // BT_POLYHEDRAL_CONTACT_CLIPPING_H
|
||||
|
||||
#endif // BT_POLYHEDRAL_CONTACT_CLIPPING_H
|
||||
|
||||
@@ -23,39 +23,38 @@ subject to the following restrictions:
|
||||
#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
|
||||
#include "btRaycastCallback.h"
|
||||
|
||||
btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const btVector3& to, unsigned int flags)
|
||||
:
|
||||
m_from(from),
|
||||
m_to(to),
|
||||
//@BP Mod
|
||||
m_flags(flags),
|
||||
m_hitFraction(btScalar(1.))
|
||||
btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from, const btVector3& to, unsigned int flags)
|
||||
: m_from(from),
|
||||
m_to(to),
|
||||
//@BP Mod
|
||||
m_flags(flags),
|
||||
m_hitFraction(btScalar(1.))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex)
|
||||
void btTriangleRaycastCallback::processTriangle(btVector3* triangle, int partId, int triangleIndex)
|
||||
{
|
||||
const btVector3 &vert0=triangle[0];
|
||||
const btVector3 &vert1=triangle[1];
|
||||
const btVector3 &vert2=triangle[2];
|
||||
const btVector3& vert0 = triangle[0];
|
||||
const btVector3& vert1 = triangle[1];
|
||||
const btVector3& vert2 = triangle[2];
|
||||
|
||||
btVector3 v10; v10 = vert1 - vert0 ;
|
||||
btVector3 v20; v20 = vert2 - vert0 ;
|
||||
btVector3 v10;
|
||||
v10 = vert1 - vert0;
|
||||
btVector3 v20;
|
||||
v20 = vert2 - vert0;
|
||||
|
||||
btVector3 triangleNormal;
|
||||
triangleNormal = v10.cross(v20);
|
||||
|
||||
btVector3 triangleNormal; triangleNormal = v10.cross( v20 );
|
||||
|
||||
const btScalar dist = vert0.dot(triangleNormal);
|
||||
btScalar dist_a = triangleNormal.dot(m_from) ;
|
||||
dist_a-= dist;
|
||||
btScalar dist_a = triangleNormal.dot(m_from);
|
||||
dist_a -= dist;
|
||||
btScalar dist_b = triangleNormal.dot(m_to);
|
||||
dist_b -= dist;
|
||||
|
||||
if ( dist_a * dist_b >= btScalar(0.0) )
|
||||
if (dist_a * dist_b >= btScalar(0.0))
|
||||
{
|
||||
return ; // same sign
|
||||
return; // same sign
|
||||
}
|
||||
|
||||
if (((m_flags & kF_FilterBackfaces) != 0) && (dist_a <= btScalar(0.0)))
|
||||
@@ -64,52 +63,52 @@ void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId,
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const btScalar proj_length=dist_a-dist_b;
|
||||
const btScalar distance = (dist_a)/(proj_length);
|
||||
const btScalar proj_length = dist_a - dist_b;
|
||||
const btScalar distance = (dist_a) / (proj_length);
|
||||
// Now we have the intersection point on the plane, we'll see if it's inside the triangle
|
||||
// Add an epsilon as a tolerance for the raycast,
|
||||
// in case the ray hits exacly on the edge of the triangle.
|
||||
// It must be scaled for the triangle size.
|
||||
|
||||
if(distance < m_hitFraction)
|
||||
|
||||
if (distance < m_hitFraction)
|
||||
{
|
||||
|
||||
|
||||
btScalar edge_tolerance =triangleNormal.length2();
|
||||
btScalar edge_tolerance = triangleNormal.length2();
|
||||
edge_tolerance *= btScalar(-0.0001);
|
||||
btVector3 point; point.setInterpolate3( m_from, m_to, distance);
|
||||
btVector3 point;
|
||||
point.setInterpolate3(m_from, m_to, distance);
|
||||
{
|
||||
btVector3 v0p; v0p = vert0 - point;
|
||||
btVector3 v1p; v1p = vert1 - point;
|
||||
btVector3 cp0; cp0 = v0p.cross( v1p );
|
||||
btVector3 v0p;
|
||||
v0p = vert0 - point;
|
||||
btVector3 v1p;
|
||||
v1p = vert1 - point;
|
||||
btVector3 cp0;
|
||||
cp0 = v0p.cross(v1p);
|
||||
|
||||
if ( (btScalar)(cp0.dot(triangleNormal)) >=edge_tolerance)
|
||||
if ((btScalar)(cp0.dot(triangleNormal)) >= edge_tolerance)
|
||||
{
|
||||
|
||||
|
||||
btVector3 v2p; v2p = vert2 - point;
|
||||
btVector3 v2p;
|
||||
v2p = vert2 - point;
|
||||
btVector3 cp1;
|
||||
cp1 = v1p.cross( v2p);
|
||||
if ( (btScalar)(cp1.dot(triangleNormal)) >=edge_tolerance)
|
||||
cp1 = v1p.cross(v2p);
|
||||
if ((btScalar)(cp1.dot(triangleNormal)) >= edge_tolerance)
|
||||
{
|
||||
btVector3 cp2;
|
||||
cp2 = v2p.cross(v0p);
|
||||
|
||||
if ( (btScalar)(cp2.dot(triangleNormal)) >=edge_tolerance)
|
||||
{
|
||||
//@BP Mod
|
||||
// Triangle normal isn't normalized
|
||||
triangleNormal.normalize();
|
||||
|
||||
//@BP Mod - Allow for unflipped normal when raycasting against backfaces
|
||||
if ((btScalar)(cp2.dot(triangleNormal)) >= edge_tolerance)
|
||||
{
|
||||
//@BP Mod
|
||||
// Triangle normal isn't normalized
|
||||
triangleNormal.normalize();
|
||||
|
||||
//@BP Mod - Allow for unflipped normal when raycasting against backfaces
|
||||
if (((m_flags & kF_KeepUnflippedNormal) == 0) && (dist_a <= btScalar(0.0)))
|
||||
{
|
||||
m_hitFraction = reportHit(-triangleNormal,distance,partId,triangleIndex);
|
||||
m_hitFraction = reportHit(-triangleNormal, distance, partId, triangleIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_hitFraction = reportHit(triangleNormal,distance,partId,triangleIndex);
|
||||
m_hitFraction = reportHit(triangleNormal, distance, partId, triangleIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,8 +117,7 @@ void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
btTriangleConvexcastCallback::btTriangleConvexcastCallback (const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin)
|
||||
btTriangleConvexcastCallback::btTriangleConvexcastCallback(const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin)
|
||||
{
|
||||
m_convexShape = convexShape;
|
||||
m_convexShapeFrom = convexShapeFrom;
|
||||
@@ -130,14 +128,13 @@ btTriangleConvexcastCallback::btTriangleConvexcastCallback (const btConvexShape*
|
||||
m_allowedPenetration = 0.f;
|
||||
}
|
||||
|
||||
void
|
||||
btTriangleConvexcastCallback::processTriangle (btVector3* triangle, int partId, int triangleIndex)
|
||||
void btTriangleConvexcastCallback::processTriangle(btVector3* triangle, int partId, int triangleIndex)
|
||||
{
|
||||
btTriangleShape triangleShape (triangle[0], triangle[1], triangle[2]);
|
||||
triangleShape.setMargin(m_triangleCollisionMargin);
|
||||
btTriangleShape triangleShape(triangle[0], triangle[1], triangle[2]);
|
||||
triangleShape.setMargin(m_triangleCollisionMargin);
|
||||
|
||||
btVoronoiSimplexSolver simplexSolver;
|
||||
btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver;
|
||||
btVoronoiSimplexSolver simplexSolver;
|
||||
btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver;
|
||||
|
||||
//#define USE_SUBSIMPLEX_CONVEX_CAST 1
|
||||
//if you reenable USE_SUBSIMPLEX_CONVEX_CAST see commented out code below
|
||||
@@ -145,21 +142,21 @@ btTriangleConvexcastCallback::processTriangle (btVector3* triangle, int partId,
|
||||
btSubsimplexConvexCast convexCaster(m_convexShape, &triangleShape, &simplexSolver);
|
||||
#else
|
||||
//btGjkConvexCast convexCaster(m_convexShape,&triangleShape,&simplexSolver);
|
||||
btContinuousConvexCollision convexCaster(m_convexShape,&triangleShape,&simplexSolver,&gjkEpaPenetrationSolver);
|
||||
#endif //#USE_SUBSIMPLEX_CONVEX_CAST
|
||||
|
||||
btContinuousConvexCollision convexCaster(m_convexShape, &triangleShape, &simplexSolver, &gjkEpaPenetrationSolver);
|
||||
#endif //#USE_SUBSIMPLEX_CONVEX_CAST
|
||||
|
||||
btConvexCast::CastResult castResult;
|
||||
castResult.m_fraction = btScalar(1.);
|
||||
castResult.m_allowedPenetration = m_allowedPenetration;
|
||||
if (convexCaster.calcTimeOfImpact(m_convexShapeFrom,m_convexShapeTo,m_triangleToWorld, m_triangleToWorld, castResult))
|
||||
if (convexCaster.calcTimeOfImpact(m_convexShapeFrom, m_convexShapeTo, m_triangleToWorld, m_triangleToWorld, castResult))
|
||||
{
|
||||
//add hit
|
||||
if (castResult.m_normal.length2() > btScalar(0.0001))
|
||||
{
|
||||
{
|
||||
if (castResult.m_fraction < m_hitFraction)
|
||||
{
|
||||
/* btContinuousConvexCast's normal is already in world space */
|
||||
/*
|
||||
/* btContinuousConvexCast's normal is already in world space */
|
||||
/*
|
||||
#ifdef USE_SUBSIMPLEX_CONVEX_CAST
|
||||
//rotate normal into worldspace
|
||||
castResult.m_normal = m_convexShapeFrom.getBasis() * castResult.m_normal;
|
||||
@@ -167,11 +164,11 @@ btTriangleConvexcastCallback::processTriangle (btVector3* triangle, int partId,
|
||||
*/
|
||||
castResult.m_normal.normalize();
|
||||
|
||||
reportHit (castResult.m_normal,
|
||||
castResult.m_hitPoint,
|
||||
castResult.m_fraction,
|
||||
partId,
|
||||
triangleIndex);
|
||||
reportHit(castResult.m_normal,
|
||||
castResult.m_hitPoint,
|
||||
castResult.m_fraction,
|
||||
partId,
|
||||
triangleIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,35 +21,33 @@ subject to the following restrictions:
|
||||
struct btBroadphaseProxy;
|
||||
class btConvexShape;
|
||||
|
||||
class btTriangleRaycastCallback: public btTriangleCallback
|
||||
class btTriangleRaycastCallback : public btTriangleCallback
|
||||
{
|
||||
public:
|
||||
|
||||
//input
|
||||
btVector3 m_from;
|
||||
btVector3 m_to;
|
||||
|
||||
//@BP Mod - allow backface filtering and unflipped normals
|
||||
enum EFlags
|
||||
{
|
||||
kF_None = 0,
|
||||
kF_FilterBackfaces = 1 << 0,
|
||||
kF_KeepUnflippedNormal = 1 << 1, // Prevents returned face normal getting flipped when a ray hits a back-facing triangle
|
||||
///SubSimplexConvexCastRaytest is the default, even if kF_None is set.
|
||||
kF_UseSubSimplexConvexCastRaytest = 1 << 2, // Uses an approximate but faster ray versus convex intersection algorithm
|
||||
kF_UseGjkConvexCastRaytest = 1 << 3,
|
||||
kF_Terminator = 0xFFFFFFFF
|
||||
};
|
||||
unsigned int m_flags;
|
||||
//@BP Mod - allow backface filtering and unflipped normals
|
||||
enum EFlags
|
||||
{
|
||||
kF_None = 0,
|
||||
kF_FilterBackfaces = 1 << 0,
|
||||
kF_KeepUnflippedNormal = 1 << 1, // Prevents returned face normal getting flipped when a ray hits a back-facing triangle
|
||||
///SubSimplexConvexCastRaytest is the default, even if kF_None is set.
|
||||
kF_UseSubSimplexConvexCastRaytest = 1 << 2, // Uses an approximate but faster ray versus convex intersection algorithm
|
||||
kF_UseGjkConvexCastRaytest = 1 << 3,
|
||||
kF_Terminator = 0xFFFFFFFF
|
||||
};
|
||||
unsigned int m_flags;
|
||||
|
||||
btScalar m_hitFraction;
|
||||
btScalar m_hitFraction;
|
||||
|
||||
btTriangleRaycastCallback(const btVector3& from, const btVector3& to, unsigned int flags = 0);
|
||||
|
||||
btTriangleRaycastCallback(const btVector3& from,const btVector3& to, unsigned int flags=0);
|
||||
|
||||
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
|
||||
|
||||
virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) = 0;
|
||||
|
||||
virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex) = 0;
|
||||
};
|
||||
|
||||
class btTriangleConvexcastCallback : public btTriangleCallback
|
||||
@@ -63,12 +61,11 @@ public:
|
||||
btScalar m_triangleCollisionMargin;
|
||||
btScalar m_allowedPenetration;
|
||||
|
||||
btTriangleConvexcastCallback (const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin);
|
||||
btTriangleConvexcastCallback(const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin);
|
||||
|
||||
virtual void processTriangle (btVector3* triangle, int partId, int triangleIndex);
|
||||
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
|
||||
|
||||
virtual btScalar reportHit (const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex) = 0;
|
||||
virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex) = 0;
|
||||
};
|
||||
|
||||
#endif //BT_RAYCAST_TRI_CALLBACK_H
|
||||
|
||||
#endif //BT_RAYCAST_TRI_CALLBACK_H
|
||||
|
||||
@@ -13,8 +13,6 @@ subject to the following restrictions:
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef BT_SIMPLEX_SOLVER_INTERFACE_H
|
||||
#define BT_SIMPLEX_SOLVER_INTERFACE_H
|
||||
|
||||
@@ -31,33 +29,30 @@ subject to the following restrictions:
|
||||
/// voronoi regions or barycentric coordinates
|
||||
class btSimplexSolverInterface
|
||||
{
|
||||
public:
|
||||
virtual ~btSimplexSolverInterface() {};
|
||||
public:
|
||||
virtual ~btSimplexSolverInterface(){};
|
||||
|
||||
virtual void reset() = 0;
|
||||
|
||||
virtual void addVertex(const btVector3& w, const btVector3& p, const btVector3& q) = 0;
|
||||
|
||||
|
||||
virtual bool closest(btVector3& v) = 0;
|
||||
|
||||
virtual btScalar maxVertex() = 0;
|
||||
|
||||
virtual bool fullSimplex() const = 0;
|
||||
|
||||
virtual int getSimplex(btVector3 *pBuf, btVector3 *qBuf, btVector3 *yBuf) const = 0;
|
||||
virtual int getSimplex(btVector3* pBuf, btVector3* qBuf, btVector3* yBuf) const = 0;
|
||||
|
||||
virtual bool inSimplex(const btVector3& w) = 0;
|
||||
|
||||
|
||||
virtual void backup_closest(btVector3& v) = 0;
|
||||
|
||||
virtual bool emptySimplex() const = 0;
|
||||
|
||||
virtual void compute_points(btVector3& p1, btVector3& p2) = 0;
|
||||
|
||||
virtual int numVertices() const =0;
|
||||
|
||||
|
||||
virtual int numVertices() const = 0;
|
||||
};
|
||||
#endif
|
||||
#endif //BT_SIMPLEX_SOLVER_INTERFACE_H
|
||||
|
||||
#endif //BT_SIMPLEX_SOLVER_INTERFACE_H
|
||||
|
||||
@@ -13,7 +13,6 @@ subject to the following restrictions:
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "btSubSimplexConvexCast.h"
|
||||
#include "BulletCollision/CollisionShapes/btConvexShape.h"
|
||||
|
||||
@@ -22,9 +21,10 @@ subject to the following restrictions:
|
||||
#include "btPointCollector.h"
|
||||
#include "LinearMath/btTransformUtil.h"
|
||||
|
||||
btSubsimplexConvexCast::btSubsimplexConvexCast (const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver)
|
||||
:m_simplexSolver(simplexSolver),
|
||||
m_convexA(convexA),m_convexB(convexB)
|
||||
btSubsimplexConvexCast::btSubsimplexConvexCast(const btConvexShape* convexA, const btConvexShape* convexB, btSimplexSolverInterface* simplexSolver)
|
||||
: m_simplexSolver(simplexSolver),
|
||||
m_convexA(convexA),
|
||||
m_convexB(convexB)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -35,19 +35,18 @@ m_convexA(convexA),m_convexB(convexB)
|
||||
#else
|
||||
#define MAX_ITERATIONS 32
|
||||
#endif
|
||||
bool btSubsimplexConvexCast::calcTimeOfImpact(
|
||||
const btTransform& fromA,
|
||||
const btTransform& toA,
|
||||
const btTransform& fromB,
|
||||
const btTransform& toB,
|
||||
CastResult& result)
|
||||
bool btSubsimplexConvexCast::calcTimeOfImpact(
|
||||
const btTransform& fromA,
|
||||
const btTransform& toA,
|
||||
const btTransform& fromB,
|
||||
const btTransform& toB,
|
||||
CastResult& result)
|
||||
{
|
||||
|
||||
m_simplexSolver->reset();
|
||||
|
||||
btVector3 linVelA,linVelB;
|
||||
linVelA = toA.getOrigin()-fromA.getOrigin();
|
||||
linVelB = toB.getOrigin()-fromB.getOrigin();
|
||||
btVector3 linVelA, linVelB;
|
||||
linVelA = toA.getOrigin() - fromA.getOrigin();
|
||||
linVelB = toB.getOrigin() - fromB.getOrigin();
|
||||
|
||||
btScalar lambda = btScalar(0.);
|
||||
|
||||
@@ -55,43 +54,39 @@ bool btSubsimplexConvexCast::calcTimeOfImpact(
|
||||
btTransform interpolatedTransB = fromB;
|
||||
|
||||
///take relative motion
|
||||
btVector3 r = (linVelA-linVelB);
|
||||
btVector3 r = (linVelA - linVelB);
|
||||
btVector3 v;
|
||||
|
||||
btVector3 supVertexA = fromA(m_convexA->localGetSupportingVertex(-r*fromA.getBasis()));
|
||||
btVector3 supVertexB = fromB(m_convexB->localGetSupportingVertex(r*fromB.getBasis()));
|
||||
v = supVertexA-supVertexB;
|
||||
|
||||
btVector3 supVertexA = fromA(m_convexA->localGetSupportingVertex(-r * fromA.getBasis()));
|
||||
btVector3 supVertexB = fromB(m_convexB->localGetSupportingVertex(r * fromB.getBasis()));
|
||||
v = supVertexA - supVertexB;
|
||||
int maxIter = MAX_ITERATIONS;
|
||||
|
||||
btVector3 n;
|
||||
n.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
|
||||
|
||||
n.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
|
||||
|
||||
btVector3 c;
|
||||
|
||||
|
||||
|
||||
|
||||
btScalar dist2 = v.length2();
|
||||
|
||||
#ifdef BT_USE_DOUBLE_PRECISION
|
||||
btScalar epsilon = SIMD_EPSILON * 10;
|
||||
#else
|
||||
//todo: epsilon kept for backward compatibility of unit tests.
|
||||
//will need to digg deeper to make the algorithm more robust
|
||||
//since, a large epsilon can cause an early termination with false
|
||||
//positive results (ray intersections that shouldn't be there)
|
||||
//todo: epsilon kept for backward compatibility of unit tests.
|
||||
//will need to digg deeper to make the algorithm more robust
|
||||
//since, a large epsilon can cause an early termination with false
|
||||
//positive results (ray intersections that shouldn't be there)
|
||||
btScalar epsilon = btScalar(0.0001);
|
||||
#endif //BT_USE_DOUBLE_PRECISION
|
||||
#endif //BT_USE_DOUBLE_PRECISION
|
||||
|
||||
|
||||
btVector3 w,p;
|
||||
btVector3 w, p;
|
||||
btScalar VdotR;
|
||||
|
||||
while ( (dist2 > epsilon) && maxIter--)
|
||||
|
||||
while ((dist2 > epsilon) && maxIter--)
|
||||
{
|
||||
supVertexA = interpolatedTransA(m_convexA->localGetSupportingVertex(-v*interpolatedTransA.getBasis()));
|
||||
supVertexB = interpolatedTransB(m_convexB->localGetSupportingVertex(v*interpolatedTransB.getBasis()));
|
||||
w = supVertexA-supVertexB;
|
||||
supVertexA = interpolatedTransA(m_convexA->localGetSupportingVertex(-v * interpolatedTransA.getBasis()));
|
||||
supVertexB = interpolatedTransB(m_convexB->localGetSupportingVertex(v * interpolatedTransB.getBasis()));
|
||||
w = supVertexA - supVertexB;
|
||||
|
||||
btScalar VdotW = v.dot(w);
|
||||
|
||||
@@ -100,68 +95,63 @@ bool btSubsimplexConvexCast::calcTimeOfImpact(
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( VdotW > btScalar(0.))
|
||||
if (VdotW > btScalar(0.))
|
||||
{
|
||||
VdotR = v.dot(r);
|
||||
|
||||
if (VdotR >= -(SIMD_EPSILON*SIMD_EPSILON))
|
||||
if (VdotR >= -(SIMD_EPSILON * SIMD_EPSILON))
|
||||
return false;
|
||||
else
|
||||
{
|
||||
lambda = lambda - VdotW / VdotR;
|
||||
//interpolate to next lambda
|
||||
// x = s + lambda * r;
|
||||
interpolatedTransA.getOrigin().setInterpolate3(fromA.getOrigin(),toA.getOrigin(),lambda);
|
||||
interpolatedTransB.getOrigin().setInterpolate3(fromB.getOrigin(),toB.getOrigin(),lambda);
|
||||
interpolatedTransA.getOrigin().setInterpolate3(fromA.getOrigin(), toA.getOrigin(), lambda);
|
||||
interpolatedTransB.getOrigin().setInterpolate3(fromB.getOrigin(), toB.getOrigin(), lambda);
|
||||
//m_simplexSolver->reset();
|
||||
//check next line
|
||||
w = supVertexA-supVertexB;
|
||||
|
||||
w = supVertexA - supVertexB;
|
||||
|
||||
n = v;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
///Just like regular GJK only add the vertex if it isn't already (close) to current vertex, it would lead to divisions by zero and NaN etc.
|
||||
if (!m_simplexSolver->inSimplex(w))
|
||||
m_simplexSolver->addVertex( w, supVertexA , supVertexB);
|
||||
m_simplexSolver->addVertex(w, supVertexA, supVertexB);
|
||||
|
||||
if (m_simplexSolver->closest(v))
|
||||
{
|
||||
dist2 = v.length2();
|
||||
|
||||
|
||||
//todo: check this normal for validity
|
||||
//n=v;
|
||||
//printf("V=%f , %f, %f\n",v[0],v[1],v[2]);
|
||||
//printf("DIST2=%f\n",dist2);
|
||||
//printf("numverts = %i\n",m_simplexSolver->numVertices());
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
dist2 = btScalar(0.);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//int numiter = MAX_ITERATIONS - maxIter;
|
||||
// printf("number of iterations: %d", numiter);
|
||||
|
||||
// printf("number of iterations: %d", numiter);
|
||||
|
||||
//don't report a time of impact when moving 'away' from the hitnormal
|
||||
|
||||
|
||||
result.m_fraction = lambda;
|
||||
if (n.length2() >= (SIMD_EPSILON*SIMD_EPSILON))
|
||||
if (n.length2() >= (SIMD_EPSILON * SIMD_EPSILON))
|
||||
result.m_normal = n.normalized();
|
||||
else
|
||||
result.m_normal = btVector3(btScalar(0.0), btScalar(0.0), btScalar(0.0));
|
||||
|
||||
//don't report time of impact for motion away from the contact normal (or causes minor penetration)
|
||||
if (result.m_normal.dot(r)>=-result.m_allowedPenetration)
|
||||
if (result.m_normal.dot(r) >= -result.m_allowedPenetration)
|
||||
return false;
|
||||
|
||||
btVector3 hitA,hitB;
|
||||
m_simplexSolver->compute_points(hitA,hitB);
|
||||
result.m_hitPoint=hitB;
|
||||
btVector3 hitA, hitB;
|
||||
m_simplexSolver->compute_points(hitA, hitB);
|
||||
result.m_hitPoint = hitB;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ subject to the following restrictions:
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BT_SUBSIMPLEX_CONVEX_CAST_H
|
||||
#define BT_SUBSIMPLEX_CONVEX_CAST_H
|
||||
|
||||
@@ -28,23 +27,21 @@ class btConvexShape;
|
||||
class btSubsimplexConvexCast : public btConvexCast
|
||||
{
|
||||
btSimplexSolverInterface* m_simplexSolver;
|
||||
const btConvexShape* m_convexA;
|
||||
const btConvexShape* m_convexB;
|
||||
const btConvexShape* m_convexA;
|
||||
const btConvexShape* m_convexB;
|
||||
|
||||
public:
|
||||
|
||||
btSubsimplexConvexCast (const btConvexShape* shapeA,const btConvexShape* shapeB,btSimplexSolverInterface* simplexSolver);
|
||||
btSubsimplexConvexCast(const btConvexShape* shapeA, const btConvexShape* shapeB, btSimplexSolverInterface* simplexSolver);
|
||||
|
||||
//virtual ~btSubsimplexConvexCast();
|
||||
///SimsimplexConvexCast calculateTimeOfImpact calculates the time of impact+normal for the linear cast (sweep) between two moving objects.
|
||||
///Precondition is that objects should not penetration/overlap at the start from the interval. Overlap can be tested using btGjkPairDetector.
|
||||
virtual bool calcTimeOfImpact(
|
||||
const btTransform& fromA,
|
||||
const btTransform& toA,
|
||||
const btTransform& fromB,
|
||||
const btTransform& toB,
|
||||
CastResult& result);
|
||||
|
||||
virtual bool calcTimeOfImpact(
|
||||
const btTransform& fromA,
|
||||
const btTransform& toA,
|
||||
const btTransform& fromB,
|
||||
const btTransform& toB,
|
||||
CastResult& result);
|
||||
};
|
||||
|
||||
#endif //BT_SUBSIMPLEX_CONVEX_CAST_H
|
||||
#endif //BT_SUBSIMPLEX_CONVEX_CAST_H
|
||||
|
||||
@@ -23,26 +23,24 @@ subject to the following restrictions:
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "btVoronoiSimplexSolver.h"
|
||||
|
||||
#define VERTA 0
|
||||
#define VERTB 1
|
||||
#define VERTC 2
|
||||
#define VERTD 3
|
||||
#define VERTA 0
|
||||
#define VERTB 1
|
||||
#define VERTC 2
|
||||
#define VERTD 3
|
||||
|
||||
#define CATCH_DEGENERATE_TETRAHEDRON 1
|
||||
void btVoronoiSimplexSolver::removeVertex(int index)
|
||||
void btVoronoiSimplexSolver::removeVertex(int index)
|
||||
{
|
||||
|
||||
btAssert(m_numVertices>0);
|
||||
btAssert(m_numVertices > 0);
|
||||
m_numVertices--;
|
||||
m_simplexVectorW[index] = m_simplexVectorW[m_numVertices];
|
||||
m_simplexPointsP[index] = m_simplexPointsP[m_numVertices];
|
||||
m_simplexPointsQ[index] = m_simplexPointsQ[m_numVertices];
|
||||
}
|
||||
|
||||
void btVoronoiSimplexSolver::reduceVertices (const btUsageBitfield& usedVerts)
|
||||
void btVoronoiSimplexSolver::reduceVertices(const btUsageBitfield& usedVerts)
|
||||
{
|
||||
if ((numVertices() >= 4) && (!usedVerts.usedVertexD))
|
||||
removeVertex(3);
|
||||
@@ -52,29 +50,22 @@ void btVoronoiSimplexSolver::reduceVertices (const btUsageBitfield& usedVerts)
|
||||
|
||||
if ((numVertices() >= 2) && (!usedVerts.usedVertexB))
|
||||
removeVertex(1);
|
||||
|
||||
|
||||
if ((numVertices() >= 1) && (!usedVerts.usedVertexA))
|
||||
removeVertex(0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//clear the simplex, remove all the vertices
|
||||
void btVoronoiSimplexSolver::reset()
|
||||
{
|
||||
m_cachedValidClosest = false;
|
||||
m_numVertices = 0;
|
||||
m_needsUpdate = true;
|
||||
m_lastW = btVector3(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
|
||||
m_lastW = btVector3(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
|
||||
m_cachedBC.reset();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//add a vertex
|
||||
//add a vertex
|
||||
void btVoronoiSimplexSolver::addVertex(const btVector3& w, const btVector3& p, const btVector3& q)
|
||||
{
|
||||
m_lastW = w;
|
||||
@@ -87,9 +78,8 @@ void btVoronoiSimplexSolver::addVertex(const btVector3& w, const btVector3& p, c
|
||||
m_numVertices++;
|
||||
}
|
||||
|
||||
bool btVoronoiSimplexSolver::updateClosestVectorAndPoints()
|
||||
bool btVoronoiSimplexSolver::updateClosestVectorAndPoints()
|
||||
{
|
||||
|
||||
if (m_needsUpdate)
|
||||
{
|
||||
m_cachedBC.reset();
|
||||
@@ -98,127 +88,131 @@ bool btVoronoiSimplexSolver::updateClosestVectorAndPoints()
|
||||
|
||||
switch (numVertices())
|
||||
{
|
||||
case 0:
|
||||
case 0:
|
||||
m_cachedValidClosest = false;
|
||||
break;
|
||||
case 1:
|
||||
case 1:
|
||||
{
|
||||
m_cachedP1 = m_simplexPointsP[0];
|
||||
m_cachedP2 = m_simplexPointsQ[0];
|
||||
m_cachedV = m_cachedP1-m_cachedP2; //== m_simplexVectorW[0]
|
||||
m_cachedV = m_cachedP1 - m_cachedP2; //== m_simplexVectorW[0]
|
||||
m_cachedBC.reset();
|
||||
m_cachedBC.setBarycentricCoordinates(btScalar(1.),btScalar(0.),btScalar(0.),btScalar(0.));
|
||||
m_cachedBC.setBarycentricCoordinates(btScalar(1.), btScalar(0.), btScalar(0.), btScalar(0.));
|
||||
m_cachedValidClosest = m_cachedBC.isValid();
|
||||
break;
|
||||
};
|
||||
case 2:
|
||||
case 2:
|
||||
{
|
||||
//closest point origin from line segment
|
||||
const btVector3& from = m_simplexVectorW[0];
|
||||
const btVector3& to = m_simplexVectorW[1];
|
||||
btVector3 nearest;
|
||||
//closest point origin from line segment
|
||||
const btVector3& from = m_simplexVectorW[0];
|
||||
const btVector3& to = m_simplexVectorW[1];
|
||||
btVector3 nearest;
|
||||
|
||||
btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.));
|
||||
btVector3 diff = p - from;
|
||||
btVector3 v = to - from;
|
||||
btScalar t = v.dot(diff);
|
||||
|
||||
if (t > 0) {
|
||||
btScalar dotVV = v.dot(v);
|
||||
if (t < dotVV) {
|
||||
t /= dotVV;
|
||||
diff -= t*v;
|
||||
m_cachedBC.m_usedVertices.usedVertexA = true;
|
||||
m_cachedBC.m_usedVertices.usedVertexB = true;
|
||||
} else {
|
||||
t = 1;
|
||||
diff -= v;
|
||||
//reduce to 1 point
|
||||
m_cachedBC.m_usedVertices.usedVertexB = true;
|
||||
}
|
||||
} else
|
||||
btVector3 p(btScalar(0.), btScalar(0.), btScalar(0.));
|
||||
btVector3 diff = p - from;
|
||||
btVector3 v = to - from;
|
||||
btScalar t = v.dot(diff);
|
||||
|
||||
if (t > 0)
|
||||
{
|
||||
btScalar dotVV = v.dot(v);
|
||||
if (t < dotVV)
|
||||
{
|
||||
t = 0;
|
||||
//reduce to 1 point
|
||||
t /= dotVV;
|
||||
diff -= t * v;
|
||||
m_cachedBC.m_usedVertices.usedVertexA = true;
|
||||
m_cachedBC.m_usedVertices.usedVertexB = true;
|
||||
}
|
||||
m_cachedBC.setBarycentricCoordinates(1-t,t);
|
||||
nearest = from + t*v;
|
||||
else
|
||||
{
|
||||
t = 1;
|
||||
diff -= v;
|
||||
//reduce to 1 point
|
||||
m_cachedBC.m_usedVertices.usedVertexB = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
t = 0;
|
||||
//reduce to 1 point
|
||||
m_cachedBC.m_usedVertices.usedVertexA = true;
|
||||
}
|
||||
m_cachedBC.setBarycentricCoordinates(1 - t, t);
|
||||
nearest = from + t * v;
|
||||
|
||||
m_cachedP1 = m_simplexPointsP[0] + t * (m_simplexPointsP[1] - m_simplexPointsP[0]);
|
||||
m_cachedP2 = m_simplexPointsQ[0] + t * (m_simplexPointsQ[1] - m_simplexPointsQ[0]);
|
||||
m_cachedV = m_cachedP1 - m_cachedP2;
|
||||
|
||||
reduceVertices(m_cachedBC.m_usedVertices);
|
||||
m_cachedP1 = m_simplexPointsP[0] + t * (m_simplexPointsP[1] - m_simplexPointsP[0]);
|
||||
m_cachedP2 = m_simplexPointsQ[0] + t * (m_simplexPointsQ[1] - m_simplexPointsQ[0]);
|
||||
m_cachedV = m_cachedP1 - m_cachedP2;
|
||||
|
||||
m_cachedValidClosest = m_cachedBC.isValid();
|
||||
break;
|
||||
reduceVertices(m_cachedBC.m_usedVertices);
|
||||
|
||||
m_cachedValidClosest = m_cachedBC.isValid();
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
//closest point origin from triangle
|
||||
btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.));
|
||||
|
||||
const btVector3& a = m_simplexVectorW[0];
|
||||
const btVector3& b = m_simplexVectorW[1];
|
||||
const btVector3& c = m_simplexVectorW[2];
|
||||
|
||||
closestPtPointTriangle(p,a,b,c,m_cachedBC);
|
||||
m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
|
||||
m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
|
||||
m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2];
|
||||
|
||||
m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
|
||||
m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
|
||||
m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2];
|
||||
|
||||
m_cachedV = m_cachedP1-m_cachedP2;
|
||||
|
||||
reduceVertices (m_cachedBC.m_usedVertices);
|
||||
m_cachedValidClosest = m_cachedBC.isValid();
|
||||
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
case 3:
|
||||
{
|
||||
//closest point origin from triangle
|
||||
btVector3 p(btScalar(0.), btScalar(0.), btScalar(0.));
|
||||
|
||||
const btVector3& a = m_simplexVectorW[0];
|
||||
const btVector3& b = m_simplexVectorW[1];
|
||||
const btVector3& c = m_simplexVectorW[2];
|
||||
|
||||
closestPtPointTriangle(p, a, b, c, m_cachedBC);
|
||||
m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
|
||||
m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
|
||||
m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2];
|
||||
|
||||
m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
|
||||
m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
|
||||
m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2];
|
||||
|
||||
m_cachedV = m_cachedP1 - m_cachedP2;
|
||||
|
||||
reduceVertices(m_cachedBC.m_usedVertices);
|
||||
m_cachedValidClosest = m_cachedBC.isValid();
|
||||
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
btVector3 p(btScalar(0.), btScalar(0.), btScalar(0.));
|
||||
|
||||
|
||||
btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.));
|
||||
|
||||
const btVector3& a = m_simplexVectorW[0];
|
||||
const btVector3& b = m_simplexVectorW[1];
|
||||
const btVector3& c = m_simplexVectorW[2];
|
||||
const btVector3& d = m_simplexVectorW[3];
|
||||
|
||||
bool hasSeparation = closestPtPointTetrahedron(p,a,b,c,d,m_cachedBC);
|
||||
bool hasSeparation = closestPtPointTetrahedron(p, a, b, c, d, m_cachedBC);
|
||||
|
||||
if (hasSeparation)
|
||||
{
|
||||
|
||||
m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
|
||||
m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
|
||||
m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2] +
|
||||
m_simplexPointsP[3] * m_cachedBC.m_barycentricCoords[3];
|
||||
m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
|
||||
m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2] +
|
||||
m_simplexPointsP[3] * m_cachedBC.m_barycentricCoords[3];
|
||||
|
||||
m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
|
||||
m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
|
||||
m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2] +
|
||||
m_simplexPointsQ[3] * m_cachedBC.m_barycentricCoords[3];
|
||||
m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
|
||||
m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2] +
|
||||
m_simplexPointsQ[3] * m_cachedBC.m_barycentricCoords[3];
|
||||
|
||||
m_cachedV = m_cachedP1-m_cachedP2;
|
||||
reduceVertices (m_cachedBC.m_usedVertices);
|
||||
} else
|
||||
m_cachedV = m_cachedP1 - m_cachedP2;
|
||||
reduceVertices(m_cachedBC.m_usedVertices);
|
||||
}
|
||||
else
|
||||
{
|
||||
// printf("sub distance got penetration\n");
|
||||
// printf("sub distance got penetration\n");
|
||||
|
||||
if (m_cachedBC.m_degenerate)
|
||||
{
|
||||
m_cachedValidClosest = false;
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cachedValidClosest = true;
|
||||
//degenerate case == false, penetration = true + zero
|
||||
m_cachedV.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
|
||||
m_cachedV.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -228,7 +222,7 @@ bool btVoronoiSimplexSolver::updateClosestVectorAndPoints()
|
||||
//closest point origin from tetrahedron
|
||||
break;
|
||||
}
|
||||
default:
|
||||
default:
|
||||
{
|
||||
m_cachedValidClosest = false;
|
||||
}
|
||||
@@ -236,7 +230,6 @@ bool btVoronoiSimplexSolver::updateClosestVectorAndPoints()
|
||||
}
|
||||
|
||||
return m_cachedValidClosest;
|
||||
|
||||
}
|
||||
|
||||
//return/calculate the closest vertex
|
||||
@@ -247,13 +240,11 @@ bool btVoronoiSimplexSolver::closest(btVector3& v)
|
||||
return succes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
btScalar btVoronoiSimplexSolver::maxVertex()
|
||||
{
|
||||
int i, numverts = numVertices();
|
||||
btScalar maxV = btScalar(0.);
|
||||
for (i=0;i<numverts;i++)
|
||||
for (i = 0; i < numverts; i++)
|
||||
{
|
||||
btScalar curLen2 = m_simplexVectorW[i].length2();
|
||||
if (maxV < curLen2)
|
||||
@@ -262,13 +253,11 @@ btScalar btVoronoiSimplexSolver::maxVertex()
|
||||
return maxV;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//return the current simplex
|
||||
int btVoronoiSimplexSolver::getSimplex(btVector3 *pBuf, btVector3 *qBuf, btVector3 *yBuf) const
|
||||
//return the current simplex
|
||||
int btVoronoiSimplexSolver::getSimplex(btVector3* pBuf, btVector3* qBuf, btVector3* yBuf) const
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<numVertices();i++)
|
||||
for (i = 0; i < numVertices(); i++)
|
||||
{
|
||||
yBuf[i] = m_simplexVectorW[i];
|
||||
pBuf[i] = m_simplexPointsP[i];
|
||||
@@ -277,20 +266,17 @@ int btVoronoiSimplexSolver::getSimplex(btVector3 *pBuf, btVector3 *qBuf, btVecto
|
||||
return numVertices();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool btVoronoiSimplexSolver::inSimplex(const btVector3& w)
|
||||
{
|
||||
bool found = false;
|
||||
int i, numverts = numVertices();
|
||||
//btScalar maxV = btScalar(0.);
|
||||
|
||||
|
||||
//w is in the current (reduced) simplex
|
||||
for (i=0;i<numverts;i++)
|
||||
for (i = 0; i < numverts; i++)
|
||||
{
|
||||
#ifdef BT_USE_EQUAL_VERTEX_THRESHOLD
|
||||
if ( m_simplexVectorW[i].distance2(w) <= m_equalVertexThreshold)
|
||||
if (m_simplexVectorW[i].distance2(w) <= m_equalVertexThreshold)
|
||||
#else
|
||||
if (m_simplexVectorW[i] == w)
|
||||
#endif
|
||||
@@ -303,199 +289,190 @@ bool btVoronoiSimplexSolver::inSimplex(const btVector3& w)
|
||||
//check in case lastW is already removed
|
||||
if (w == m_lastW)
|
||||
return true;
|
||||
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
void btVoronoiSimplexSolver::backup_closest(btVector3& v)
|
||||
void btVoronoiSimplexSolver::backup_closest(btVector3& v)
|
||||
{
|
||||
v = m_cachedV;
|
||||
}
|
||||
|
||||
|
||||
bool btVoronoiSimplexSolver::emptySimplex() const
|
||||
bool btVoronoiSimplexSolver::emptySimplex() const
|
||||
{
|
||||
return (numVertices() == 0);
|
||||
|
||||
}
|
||||
|
||||
void btVoronoiSimplexSolver::compute_points(btVector3& p1, btVector3& p2)
|
||||
void btVoronoiSimplexSolver::compute_points(btVector3& p1, btVector3& p2)
|
||||
{
|
||||
updateClosestVectorAndPoints();
|
||||
p1 = m_cachedP1;
|
||||
p2 = m_cachedP2;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool btVoronoiSimplexSolver::closestPtPointTriangle(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c,btSubSimplexClosestResult& result)
|
||||
bool btVoronoiSimplexSolver::closestPtPointTriangle(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, btSubSimplexClosestResult& result)
|
||||
{
|
||||
result.m_usedVertices.reset();
|
||||
|
||||
// Check if P in vertex region outside A
|
||||
btVector3 ab = b - a;
|
||||
btVector3 ac = c - a;
|
||||
btVector3 ap = p - a;
|
||||
btScalar d1 = ab.dot(ap);
|
||||
btScalar d2 = ac.dot(ap);
|
||||
if (d1 <= btScalar(0.0) && d2 <= btScalar(0.0))
|
||||
// Check if P in vertex region outside A
|
||||
btVector3 ab = b - a;
|
||||
btVector3 ac = c - a;
|
||||
btVector3 ap = p - a;
|
||||
btScalar d1 = ab.dot(ap);
|
||||
btScalar d2 = ac.dot(ap);
|
||||
if (d1 <= btScalar(0.0) && d2 <= btScalar(0.0))
|
||||
{
|
||||
result.m_closestPointOnSimplex = a;
|
||||
result.m_usedVertices.usedVertexA = true;
|
||||
result.setBarycentricCoordinates(1,0,0);
|
||||
return true;// a; // barycentric coordinates (1,0,0)
|
||||
result.setBarycentricCoordinates(1, 0, 0);
|
||||
return true; // a; // barycentric coordinates (1,0,0)
|
||||
}
|
||||
|
||||
// Check if P in vertex region outside B
|
||||
btVector3 bp = p - b;
|
||||
btScalar d3 = ab.dot(bp);
|
||||
btScalar d4 = ac.dot(bp);
|
||||
if (d3 >= btScalar(0.0) && d4 <= d3)
|
||||
// Check if P in vertex region outside B
|
||||
btVector3 bp = p - b;
|
||||
btScalar d3 = ab.dot(bp);
|
||||
btScalar d4 = ac.dot(bp);
|
||||
if (d3 >= btScalar(0.0) && d4 <= d3)
|
||||
{
|
||||
result.m_closestPointOnSimplex = b;
|
||||
result.m_usedVertices.usedVertexB = true;
|
||||
result.setBarycentricCoordinates(0,1,0);
|
||||
result.setBarycentricCoordinates(0, 1, 0);
|
||||
|
||||
return true; // b; // barycentric coordinates (0,1,0)
|
||||
return true; // b; // barycentric coordinates (0,1,0)
|
||||
}
|
||||
// Check if P in edge region of AB, if so return projection of P onto AB
|
||||
btScalar vc = d1*d4 - d3*d2;
|
||||
if (vc <= btScalar(0.0) && d1 >= btScalar(0.0) && d3 <= btScalar(0.0)) {
|
||||
btScalar v = d1 / (d1 - d3);
|
||||
// Check if P in edge region of AB, if so return projection of P onto AB
|
||||
btScalar vc = d1 * d4 - d3 * d2;
|
||||
if (vc <= btScalar(0.0) && d1 >= btScalar(0.0) && d3 <= btScalar(0.0))
|
||||
{
|
||||
btScalar v = d1 / (d1 - d3);
|
||||
result.m_closestPointOnSimplex = a + v * ab;
|
||||
result.m_usedVertices.usedVertexA = true;
|
||||
result.m_usedVertices.usedVertexB = true;
|
||||
result.setBarycentricCoordinates(1-v,v,0);
|
||||
result.setBarycentricCoordinates(1 - v, v, 0);
|
||||
return true;
|
||||
//return a + v * ab; // barycentric coordinates (1-v,v,0)
|
||||
}
|
||||
//return a + v * ab; // barycentric coordinates (1-v,v,0)
|
||||
}
|
||||
|
||||
// Check if P in vertex region outside C
|
||||
btVector3 cp = p - c;
|
||||
btScalar d5 = ab.dot(cp);
|
||||
btScalar d6 = ac.dot(cp);
|
||||
if (d6 >= btScalar(0.0) && d5 <= d6)
|
||||
// Check if P in vertex region outside C
|
||||
btVector3 cp = p - c;
|
||||
btScalar d5 = ab.dot(cp);
|
||||
btScalar d6 = ac.dot(cp);
|
||||
if (d6 >= btScalar(0.0) && d5 <= d6)
|
||||
{
|
||||
result.m_closestPointOnSimplex = c;
|
||||
result.m_usedVertices.usedVertexC = true;
|
||||
result.setBarycentricCoordinates(0,0,1);
|
||||
return true;//c; // barycentric coordinates (0,0,1)
|
||||
result.setBarycentricCoordinates(0, 0, 1);
|
||||
return true; //c; // barycentric coordinates (0,0,1)
|
||||
}
|
||||
|
||||
// Check if P in edge region of AC, if so return projection of P onto AC
|
||||
btScalar vb = d5*d2 - d1*d6;
|
||||
if (vb <= btScalar(0.0) && d2 >= btScalar(0.0) && d6 <= btScalar(0.0)) {
|
||||
btScalar w = d2 / (d2 - d6);
|
||||
// Check if P in edge region of AC, if so return projection of P onto AC
|
||||
btScalar vb = d5 * d2 - d1 * d6;
|
||||
if (vb <= btScalar(0.0) && d2 >= btScalar(0.0) && d6 <= btScalar(0.0))
|
||||
{
|
||||
btScalar w = d2 / (d2 - d6);
|
||||
result.m_closestPointOnSimplex = a + w * ac;
|
||||
result.m_usedVertices.usedVertexA = true;
|
||||
result.m_usedVertices.usedVertexC = true;
|
||||
result.setBarycentricCoordinates(1-w,0,w);
|
||||
result.setBarycentricCoordinates(1 - w, 0, w);
|
||||
return true;
|
||||
//return a + w * ac; // barycentric coordinates (1-w,0,w)
|
||||
}
|
||||
//return a + w * ac; // barycentric coordinates (1-w,0,w)
|
||||
}
|
||||
|
||||
// Check if P in edge region of BC, if so return projection of P onto BC
|
||||
btScalar va = d3 * d6 - d5 * d4;
|
||||
if (va <= btScalar(0.0) && (d4 - d3) >= btScalar(0.0) && (d5 - d6) >= btScalar(0.0))
|
||||
{
|
||||
btScalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
|
||||
|
||||
// Check if P in edge region of BC, if so return projection of P onto BC
|
||||
btScalar va = d3*d6 - d5*d4;
|
||||
if (va <= btScalar(0.0) && (d4 - d3) >= btScalar(0.0) && (d5 - d6) >= btScalar(0.0)) {
|
||||
btScalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
|
||||
|
||||
result.m_closestPointOnSimplex = b + w * (c - b);
|
||||
result.m_usedVertices.usedVertexB = true;
|
||||
result.m_usedVertices.usedVertexC = true;
|
||||
result.setBarycentricCoordinates(0,1-w,w);
|
||||
return true;
|
||||
// return b + w * (c - b); // barycentric coordinates (0,1-w,w)
|
||||
}
|
||||
result.setBarycentricCoordinates(0, 1 - w, w);
|
||||
return true;
|
||||
// return b + w * (c - b); // barycentric coordinates (0,1-w,w)
|
||||
}
|
||||
|
||||
// P inside face region. Compute Q through its barycentric coordinates (u,v,w)
|
||||
btScalar denom = btScalar(1.0) / (va + vb + vc);
|
||||
btScalar v = vb * denom;
|
||||
btScalar w = vc * denom;
|
||||
|
||||
// P inside face region. Compute Q through its barycentric coordinates (u,v,w)
|
||||
btScalar denom = btScalar(1.0) / (va + vb + vc);
|
||||
btScalar v = vb * denom;
|
||||
btScalar w = vc * denom;
|
||||
|
||||
result.m_closestPointOnSimplex = a + ab * v + ac * w;
|
||||
result.m_usedVertices.usedVertexA = true;
|
||||
result.m_usedVertices.usedVertexB = true;
|
||||
result.m_usedVertices.usedVertexC = true;
|
||||
result.setBarycentricCoordinates(1-v-w,v,w);
|
||||
|
||||
result.setBarycentricCoordinates(1 - v - w, v, w);
|
||||
|
||||
return true;
|
||||
// return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = btScalar(1.0) - v - w
|
||||
|
||||
// return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = btScalar(1.0) - v - w
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// Test if point p and d lie on opposite sides of plane through abc
|
||||
int btVoronoiSimplexSolver::pointOutsideOfPlane(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d)
|
||||
{
|
||||
btVector3 normal = (b-a).cross(c-a);
|
||||
btVector3 normal = (b - a).cross(c - a);
|
||||
|
||||
btScalar signp = (p - a).dot(normal); // [AP AB AC]
|
||||
btScalar signd = (d - a).dot( normal); // [AD AB AC]
|
||||
btScalar signp = (p - a).dot(normal); // [AP AB AC]
|
||||
btScalar signd = (d - a).dot(normal); // [AD AB AC]
|
||||
|
||||
#ifdef CATCH_DEGENERATE_TETRAHEDRON
|
||||
#ifdef BT_USE_DOUBLE_PRECISION
|
||||
if (signd * signd < (btScalar(1e-8) * btScalar(1e-8)))
|
||||
if (signd * signd < (btScalar(1e-8) * btScalar(1e-8)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
if (signd * signd < (btScalar(1e-4) * btScalar(1e-4)))
|
||||
{
|
||||
// printf("affine dependent/degenerate\n");//
|
||||
// printf("affine dependent/degenerate\n");//
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
// Points on opposite sides if expression signs are opposite
|
||||
return signp * signd < btScalar(0.);
|
||||
return signp * signd < btScalar(0.);
|
||||
}
|
||||
|
||||
|
||||
bool btVoronoiSimplexSolver::closestPtPointTetrahedron(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, btSubSimplexClosestResult& finalResult)
|
||||
bool btVoronoiSimplexSolver::closestPtPointTetrahedron(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, btSubSimplexClosestResult& finalResult)
|
||||
{
|
||||
btSubSimplexClosestResult tempResult;
|
||||
|
||||
// Start out assuming point inside all halfspaces, so closest to itself
|
||||
// Start out assuming point inside all halfspaces, so closest to itself
|
||||
finalResult.m_closestPointOnSimplex = p;
|
||||
finalResult.m_usedVertices.reset();
|
||||
finalResult.m_usedVertices.usedVertexA = true;
|
||||
finalResult.m_usedVertices.usedVertexA = true;
|
||||
finalResult.m_usedVertices.usedVertexB = true;
|
||||
finalResult.m_usedVertices.usedVertexC = true;
|
||||
finalResult.m_usedVertices.usedVertexD = true;
|
||||
|
||||
int pointOutsideABC = pointOutsideOfPlane(p, a, b, c, d);
|
||||
int pointOutsideABC = pointOutsideOfPlane(p, a, b, c, d);
|
||||
int pointOutsideACD = pointOutsideOfPlane(p, a, c, d, b);
|
||||
int pointOutsideADB = pointOutsideOfPlane(p, a, d, b, c);
|
||||
int pointOutsideBDC = pointOutsideOfPlane(p, b, d, c, a);
|
||||
int pointOutsideADB = pointOutsideOfPlane(p, a, d, b, c);
|
||||
int pointOutsideBDC = pointOutsideOfPlane(p, b, d, c, a);
|
||||
|
||||
if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0)
|
||||
{
|
||||
finalResult.m_degenerate = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!pointOutsideABC && !pointOutsideACD && !pointOutsideADB && !pointOutsideBDC)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
btScalar bestSqDist = FLT_MAX;
|
||||
// If point outside face abc then compute closest point on abc
|
||||
if (pointOutsideABC)
|
||||
if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0)
|
||||
{
|
||||
closestPtPointTriangle(p, a, b, c,tempResult);
|
||||
finalResult.m_degenerate = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!pointOutsideABC && !pointOutsideACD && !pointOutsideADB && !pointOutsideBDC)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
btScalar bestSqDist = FLT_MAX;
|
||||
// If point outside face abc then compute closest point on abc
|
||||
if (pointOutsideABC)
|
||||
{
|
||||
closestPtPointTriangle(p, a, b, c, tempResult);
|
||||
btVector3 q = tempResult.m_closestPointOnSimplex;
|
||||
|
||||
btScalar sqDist = (q - p).dot( q - p);
|
||||
// Update best closest point if (squared) distance is less than current best
|
||||
if (sqDist < bestSqDist) {
|
||||
|
||||
btScalar sqDist = (q - p).dot(q - p);
|
||||
// Update best closest point if (squared) distance is less than current best
|
||||
if (sqDist < bestSqDist)
|
||||
{
|
||||
bestSqDist = sqDist;
|
||||
finalResult.m_closestPointOnSimplex = q;
|
||||
//convert result bitmask!
|
||||
@@ -504,25 +481,22 @@ bool btVoronoiSimplexSolver::closestPtPointTetrahedron(const btVector3& p, const
|
||||
finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexB;
|
||||
finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC;
|
||||
finalResult.setBarycentricCoordinates(
|
||||
tempResult.m_barycentricCoords[VERTA],
|
||||
tempResult.m_barycentricCoords[VERTB],
|
||||
tempResult.m_barycentricCoords[VERTC],
|
||||
0
|
||||
);
|
||||
|
||||
tempResult.m_barycentricCoords[VERTA],
|
||||
tempResult.m_barycentricCoords[VERTB],
|
||||
tempResult.m_barycentricCoords[VERTC],
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Repeat test for face acd
|
||||
if (pointOutsideACD)
|
||||
if (pointOutsideACD)
|
||||
{
|
||||
closestPtPointTriangle(p, a, c, d,tempResult);
|
||||
closestPtPointTriangle(p, a, c, d, tempResult);
|
||||
btVector3 q = tempResult.m_closestPointOnSimplex;
|
||||
//convert result bitmask!
|
||||
|
||||
btScalar sqDist = (q - p).dot( q - p);
|
||||
if (sqDist < bestSqDist)
|
||||
btScalar sqDist = (q - p).dot(q - p);
|
||||
if (sqDist < bestSqDist)
|
||||
{
|
||||
bestSqDist = sqDist;
|
||||
finalResult.m_closestPointOnSimplex = q;
|
||||
@@ -532,52 +506,46 @@ bool btVoronoiSimplexSolver::closestPtPointTetrahedron(const btVector3& p, const
|
||||
finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexB;
|
||||
finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexC;
|
||||
finalResult.setBarycentricCoordinates(
|
||||
tempResult.m_barycentricCoords[VERTA],
|
||||
0,
|
||||
tempResult.m_barycentricCoords[VERTB],
|
||||
tempResult.m_barycentricCoords[VERTC]
|
||||
);
|
||||
|
||||
tempResult.m_barycentricCoords[VERTA],
|
||||
0,
|
||||
tempResult.m_barycentricCoords[VERTB],
|
||||
tempResult.m_barycentricCoords[VERTC]);
|
||||
}
|
||||
}
|
||||
// Repeat test for face adb
|
||||
}
|
||||
// Repeat test for face adb
|
||||
|
||||
|
||||
if (pointOutsideADB)
|
||||
{
|
||||
closestPtPointTriangle(p, a, d, b,tempResult);
|
||||
closestPtPointTriangle(p, a, d, b, tempResult);
|
||||
btVector3 q = tempResult.m_closestPointOnSimplex;
|
||||
//convert result bitmask!
|
||||
|
||||
btScalar sqDist = (q - p).dot( q - p);
|
||||
if (sqDist < bestSqDist)
|
||||
btScalar sqDist = (q - p).dot(q - p);
|
||||
if (sqDist < bestSqDist)
|
||||
{
|
||||
bestSqDist = sqDist;
|
||||
finalResult.m_closestPointOnSimplex = q;
|
||||
finalResult.m_usedVertices.reset();
|
||||
finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
|
||||
finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexC;
|
||||
|
||||
|
||||
finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
|
||||
finalResult.setBarycentricCoordinates(
|
||||
tempResult.m_barycentricCoords[VERTA],
|
||||
tempResult.m_barycentricCoords[VERTC],
|
||||
0,
|
||||
tempResult.m_barycentricCoords[VERTB]
|
||||
);
|
||||
|
||||
tempResult.m_barycentricCoords[VERTA],
|
||||
tempResult.m_barycentricCoords[VERTC],
|
||||
0,
|
||||
tempResult.m_barycentricCoords[VERTB]);
|
||||
}
|
||||
}
|
||||
// Repeat test for face bdc
|
||||
|
||||
}
|
||||
// Repeat test for face bdc
|
||||
|
||||
if (pointOutsideBDC)
|
||||
{
|
||||
closestPtPointTriangle(p, b, d, c,tempResult);
|
||||
closestPtPointTriangle(p, b, d, c, tempResult);
|
||||
btVector3 q = tempResult.m_closestPointOnSimplex;
|
||||
//convert result bitmask!
|
||||
btScalar sqDist = (q - p).dot( q - p);
|
||||
if (sqDist < bestSqDist)
|
||||
btScalar sqDist = (q - p).dot(q - p);
|
||||
if (sqDist < bestSqDist)
|
||||
{
|
||||
bestSqDist = sqDist;
|
||||
finalResult.m_closestPointOnSimplex = q;
|
||||
@@ -588,25 +556,22 @@ bool btVoronoiSimplexSolver::closestPtPointTetrahedron(const btVector3& p, const
|
||||
finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
|
||||
|
||||
finalResult.setBarycentricCoordinates(
|
||||
0,
|
||||
tempResult.m_barycentricCoords[VERTA],
|
||||
tempResult.m_barycentricCoords[VERTC],
|
||||
tempResult.m_barycentricCoords[VERTB]
|
||||
);
|
||||
|
||||
0,
|
||||
tempResult.m_barycentricCoords[VERTA],
|
||||
tempResult.m_barycentricCoords[VERTC],
|
||||
tempResult.m_barycentricCoords[VERTB]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//help! we ended up full !
|
||||
|
||||
|
||||
if (finalResult.m_usedVertices.usedVertexA &&
|
||||
finalResult.m_usedVertices.usedVertexB &&
|
||||
finalResult.m_usedVertices.usedVertexC &&
|
||||
finalResult.m_usedVertices.usedVertexD)
|
||||
finalResult.m_usedVertices.usedVertexD)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,15 +13,11 @@ subject to the following restrictions:
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef BT_VORONOI_SIMPLEX_SOLVER_H
|
||||
#define BT_VORONOI_SIMPLEX_SOLVER_H
|
||||
|
||||
#include "btSimplexSolverInterface.h"
|
||||
|
||||
|
||||
|
||||
#define VORONOI_SIMPLEX_MAX_VERTS 5
|
||||
|
||||
///disable next define, or use defaultCollisionConfiguration->getSimplexSolver()->setEqualVertexThreshold(0.f) to disable/configure
|
||||
@@ -31,9 +27,10 @@ subject to the following restrictions:
|
||||
#define VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD 1e-12f
|
||||
#else
|
||||
#define VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD 0.0001f
|
||||
#endif//BT_USE_DOUBLE_PRECISION
|
||||
#endif //BT_USE_DOUBLE_PRECISION
|
||||
|
||||
struct btUsageBitfield{
|
||||
struct btUsageBitfield
|
||||
{
|
||||
btUsageBitfield()
|
||||
{
|
||||
reset();
|
||||
@@ -46,140 +43,131 @@ struct btUsageBitfield{
|
||||
usedVertexC = false;
|
||||
usedVertexD = false;
|
||||
}
|
||||
unsigned short usedVertexA : 1;
|
||||
unsigned short usedVertexB : 1;
|
||||
unsigned short usedVertexC : 1;
|
||||
unsigned short usedVertexD : 1;
|
||||
unsigned short unused1 : 1;
|
||||
unsigned short unused2 : 1;
|
||||
unsigned short unused3 : 1;
|
||||
unsigned short unused4 : 1;
|
||||
unsigned short usedVertexA : 1;
|
||||
unsigned short usedVertexB : 1;
|
||||
unsigned short usedVertexC : 1;
|
||||
unsigned short usedVertexD : 1;
|
||||
unsigned short unused1 : 1;
|
||||
unsigned short unused2 : 1;
|
||||
unsigned short unused3 : 1;
|
||||
unsigned short unused4 : 1;
|
||||
};
|
||||
|
||||
|
||||
struct btSubSimplexClosestResult
|
||||
struct btSubSimplexClosestResult
|
||||
{
|
||||
btVector3 m_closestPointOnSimplex;
|
||||
btVector3 m_closestPointOnSimplex;
|
||||
//MASK for m_usedVertices
|
||||
//stores the simplex vertex-usage, using the MASK,
|
||||
//stores the simplex vertex-usage, using the MASK,
|
||||
// if m_usedVertices & MASK then the related vertex is used
|
||||
btUsageBitfield m_usedVertices;
|
||||
btScalar m_barycentricCoords[4];
|
||||
btUsageBitfield m_usedVertices;
|
||||
btScalar m_barycentricCoords[4];
|
||||
bool m_degenerate;
|
||||
|
||||
void reset()
|
||||
void reset()
|
||||
{
|
||||
m_degenerate = false;
|
||||
setBarycentricCoordinates();
|
||||
m_usedVertices.reset();
|
||||
}
|
||||
bool isValid()
|
||||
bool isValid()
|
||||
{
|
||||
bool valid = (m_barycentricCoords[0] >= btScalar(0.)) &&
|
||||
(m_barycentricCoords[1] >= btScalar(0.)) &&
|
||||
(m_barycentricCoords[2] >= btScalar(0.)) &&
|
||||
(m_barycentricCoords[3] >= btScalar(0.));
|
||||
|
||||
(m_barycentricCoords[1] >= btScalar(0.)) &&
|
||||
(m_barycentricCoords[2] >= btScalar(0.)) &&
|
||||
(m_barycentricCoords[3] >= btScalar(0.));
|
||||
|
||||
return valid;
|
||||
}
|
||||
void setBarycentricCoordinates(btScalar a=btScalar(0.),btScalar b=btScalar(0.),btScalar c=btScalar(0.),btScalar d=btScalar(0.))
|
||||
void setBarycentricCoordinates(btScalar a = btScalar(0.), btScalar b = btScalar(0.), btScalar c = btScalar(0.), btScalar d = btScalar(0.))
|
||||
{
|
||||
m_barycentricCoords[0] = a;
|
||||
m_barycentricCoords[1] = b;
|
||||
m_barycentricCoords[2] = c;
|
||||
m_barycentricCoords[3] = d;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/// btVoronoiSimplexSolver is an implementation of the closest point distance algorithm from a 1-4 points simplex to the origin.
|
||||
/// Can be used with GJK, as an alternative to Johnson distance algorithm.
|
||||
#ifdef NO_VIRTUAL_INTERFACE
|
||||
ATTRIBUTE_ALIGNED16(class) btVoronoiSimplexSolver
|
||||
ATTRIBUTE_ALIGNED16(class)
|
||||
btVoronoiSimplexSolver
|
||||
#else
|
||||
ATTRIBUTE_ALIGNED16(class) btVoronoiSimplexSolver : public btSimplexSolverInterface
|
||||
ATTRIBUTE_ALIGNED16(class)
|
||||
btVoronoiSimplexSolver : public btSimplexSolverInterface
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
|
||||
BT_DECLARE_ALIGNED_ALLOCATOR();
|
||||
|
||||
int m_numVertices;
|
||||
int m_numVertices;
|
||||
|
||||
btVector3 m_simplexVectorW[VORONOI_SIMPLEX_MAX_VERTS];
|
||||
btVector3 m_simplexPointsP[VORONOI_SIMPLEX_MAX_VERTS];
|
||||
btVector3 m_simplexPointsQ[VORONOI_SIMPLEX_MAX_VERTS];
|
||||
btVector3 m_simplexVectorW[VORONOI_SIMPLEX_MAX_VERTS];
|
||||
btVector3 m_simplexPointsP[VORONOI_SIMPLEX_MAX_VERTS];
|
||||
btVector3 m_simplexPointsQ[VORONOI_SIMPLEX_MAX_VERTS];
|
||||
|
||||
|
||||
|
||||
btVector3 m_cachedP1;
|
||||
btVector3 m_cachedP2;
|
||||
btVector3 m_cachedV;
|
||||
btVector3 m_lastW;
|
||||
|
||||
btScalar m_equalVertexThreshold;
|
||||
bool m_cachedValidClosest;
|
||||
btVector3 m_cachedP1;
|
||||
btVector3 m_cachedP2;
|
||||
btVector3 m_cachedV;
|
||||
btVector3 m_lastW;
|
||||
|
||||
btScalar m_equalVertexThreshold;
|
||||
bool m_cachedValidClosest;
|
||||
|
||||
btSubSimplexClosestResult m_cachedBC;
|
||||
|
||||
bool m_needsUpdate;
|
||||
|
||||
void removeVertex(int index);
|
||||
void reduceVertices (const btUsageBitfield& usedVerts);
|
||||
bool updateClosestVectorAndPoints();
|
||||
bool m_needsUpdate;
|
||||
|
||||
bool closestPtPointTetrahedron(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, btSubSimplexClosestResult& finalResult);
|
||||
int pointOutsideOfPlane(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d);
|
||||
bool closestPtPointTriangle(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c,btSubSimplexClosestResult& result);
|
||||
void removeVertex(int index);
|
||||
void reduceVertices(const btUsageBitfield& usedVerts);
|
||||
bool updateClosestVectorAndPoints();
|
||||
|
||||
bool closestPtPointTetrahedron(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, btSubSimplexClosestResult& finalResult);
|
||||
int pointOutsideOfPlane(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d);
|
||||
bool closestPtPointTriangle(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, btSubSimplexClosestResult& result);
|
||||
|
||||
public:
|
||||
|
||||
btVoronoiSimplexSolver()
|
||||
: m_equalVertexThreshold(VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD)
|
||||
: m_equalVertexThreshold(VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD)
|
||||
{
|
||||
}
|
||||
void reset();
|
||||
void reset();
|
||||
|
||||
void addVertex(const btVector3& w, const btVector3& p, const btVector3& q);
|
||||
void addVertex(const btVector3& w, const btVector3& p, const btVector3& q);
|
||||
|
||||
void setEqualVertexThreshold(btScalar threshold)
|
||||
{
|
||||
m_equalVertexThreshold = threshold;
|
||||
}
|
||||
void setEqualVertexThreshold(btScalar threshold)
|
||||
{
|
||||
m_equalVertexThreshold = threshold;
|
||||
}
|
||||
|
||||
btScalar getEqualVertexThreshold() const
|
||||
{
|
||||
return m_equalVertexThreshold;
|
||||
}
|
||||
btScalar getEqualVertexThreshold() const
|
||||
{
|
||||
return m_equalVertexThreshold;
|
||||
}
|
||||
|
||||
bool closest(btVector3& v);
|
||||
bool closest(btVector3 & v);
|
||||
|
||||
btScalar maxVertex();
|
||||
btScalar maxVertex();
|
||||
|
||||
bool fullSimplex() const
|
||||
{
|
||||
return (m_numVertices == 4);
|
||||
}
|
||||
bool fullSimplex() const
|
||||
{
|
||||
return (m_numVertices == 4);
|
||||
}
|
||||
|
||||
int getSimplex(btVector3 *pBuf, btVector3 *qBuf, btVector3 *yBuf) const;
|
||||
int getSimplex(btVector3 * pBuf, btVector3 * qBuf, btVector3 * yBuf) const;
|
||||
|
||||
bool inSimplex(const btVector3& w);
|
||||
|
||||
void backup_closest(btVector3& v) ;
|
||||
bool inSimplex(const btVector3& w);
|
||||
|
||||
bool emptySimplex() const ;
|
||||
void backup_closest(btVector3 & v);
|
||||
|
||||
void compute_points(btVector3& p1, btVector3& p2) ;
|
||||
|
||||
int numVertices() const
|
||||
{
|
||||
return m_numVertices;
|
||||
}
|
||||
bool emptySimplex() const;
|
||||
|
||||
void compute_points(btVector3 & p1, btVector3 & p2);
|
||||
|
||||
int numVertices() const
|
||||
{
|
||||
return m_numVertices;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //BT_VORONOI_SIMPLEX_SOLVER_H
|
||||
|
||||
#endif //BT_VORONOI_SIMPLEX_SOLVER_H
|
||||
|
||||
Reference in New Issue
Block a user