Use consistent rayFrom/rayTo API for rayTest for btDbvt and btSoftBody, instead of rayCast/collideRAY(origin,direction). This means RayFromToCaster has a fraction [0..1] instead of distance [0..INF]

Renamed collideRay -> rayTest to reflect change to (rayFrom,rayTo) interface.
Re-use btRayAabb2 function from src/LinearMath/btAabbUtil2.h in btDbvt instead of duplicated implementation.
This commit is contained in:
erwin.coumans
2008-10-15 18:30:35 +00:00
parent 81fcd03af5
commit cac172d422
8 changed files with 157 additions and 142 deletions

View File

@@ -397,7 +397,7 @@ void DemoApplication::keyboardCallback(unsigned char key, int x, int y)
case '.': case '.':
{ {
shootBox(getCameraTargetPosition()); shootBox(getRayTo(x,y));//getCameraTargetPosition());
break; break;
} }
@@ -530,7 +530,7 @@ void DemoApplication::shootBox(const btVector3& destination)
btConvexShape* childShape = new btBoxShape(btVector3(1.f,1.f,1.f)); btConvexShape* childShape = new btBoxShape(btVector3(1.f,1.f,1.f));
m_shootBoxShape = new btUniformScalingShape(childShape,0.5f); m_shootBoxShape = new btUniformScalingShape(childShape,0.5f);
#else #else
m_shootBoxShape = new btBoxShape(btVector3(1.f,1.f,1.f)); m_shootBoxShape = new btSphereShape(1.f);//BoxShape(btVector3(1.f,1.f,1.f));
#endif// #endif//
} }

View File

@@ -1322,7 +1322,7 @@ void SoftDemo::clientResetScene()
m_autocam = false; m_autocam = false;
m_raycast = false; m_raycast = false;
m_cutting = false; m_cutting = false;
m_results.time = SIMD_INFINITY; m_results.fraction = 1.f;
demofncs[current_demo](this); demofncs[current_demo](this);
} }
@@ -1364,14 +1364,16 @@ void SoftDemo::renderme()
const btScalar dist=10; const btScalar dist=10;
btTransform trs; btTransform trs;
trs.setOrigin(ps); trs.setOrigin(ps);
btScalar rayLength = 1000.f;
const btScalar angle=m_animtime*0.2; const btScalar angle=m_animtime*0.2;
trs.setRotation(btQuaternion(angle,SIMD_PI/4,0)); trs.setRotation(btQuaternion(angle,SIMD_PI/4,0));
const btVector3 dir=trs.getBasis()*btVector3(0,-1,0); btVector3 dir=trs.getBasis()*btVector3(0,-1,0);
trs.setOrigin(ps-dir*dist); trs.setOrigin(ps-dir*dist);
btAlignedObjectArray<btVector3> origins; btAlignedObjectArray<btVector3> origins;
btAlignedObjectArray<btScalar> times; btAlignedObjectArray<btScalar> fractions;
origins.resize(res*res); origins.resize(res*res);
times.resize(res*res,SIMD_INFINITY); fractions.resize(res*res,1.f);
for(int y=0;y<res;++y) for(int y=0;y<res;++y)
{ {
for(int x=0;x<res;++x) for(int x=0;x<res;++x)
@@ -1383,20 +1385,22 @@ void SoftDemo::renderme()
/* Cast rays */ /* Cast rays */
{ {
m_clock.reset(); m_clock.reset();
const btVector3* org=&origins[0]; btVector3* org=&origins[0];
btScalar* mint=&times[0]; btScalar* fraction=&fractions[0];
btSoftBody** psbs=&sbs[0]; btSoftBody** psbs=&sbs[0];
btSoftBody::sRayCast results; btSoftBody::sRayCast results;
for(int i=0,ni=origins.size(),nb=sbs.size();i<ni;++i) for(int i=0,ni=origins.size(),nb=sbs.size();i<ni;++i)
{ {
for(int ib=0;ib<nb;++ib) for(int ib=0;ib<nb;++ib)
{ {
if(psbs[ib]->rayCast(*org,dir,results,*mint)) btVector3 rayFrom = *org;
btVector3 rayTo = rayFrom+dir*rayLength;
if(psbs[ib]->rayTest(rayFrom,rayTo,results))
{ {
*mint=results.time; *fraction=results.fraction;
} }
} }
++org;++mint; ++org;++fraction;
} }
long ms=btMax<long>(m_clock.getTimeMilliseconds(),1); long ms=btMax<long>(m_clock.getTimeMilliseconds(),1);
long rayperseconds=(1000*(origins.size()*sbs.size()))/ms; long rayperseconds=(1000*(origins.size()*sbs.size()))/ms;
@@ -1413,15 +1417,15 @@ void SoftDemo::renderme()
idraw->drawLine(c[2],c[0],btVector3(0,0,0)); idraw->drawLine(c[2],c[0],btVector3(0,0,0));
for(int i=0,ni=origins.size();i<ni;++i) for(int i=0,ni=origins.size();i<ni;++i)
{ {
const btScalar tim=times[i]; const btScalar fraction=fractions[i];
const btVector3& org=origins[i]; const btVector3& org=origins[i];
if(tim<SIMD_INFINITY) if(fraction<1.f)
{ {
idraw->drawLine(org,org+dir*tim,btVector3(1,0,0)); idraw->drawLine(org,org+dir*rayLength*fraction,btVector3(1,0,0));
} }
else else
{ {
idraw->drawLine(org,org-dir*0.1,btVector3(0,0,0)); idraw->drawLine(org,org-dir*rayLength*0.1,btVector3(0,0,0));
} }
} }
#undef RES #undef RES
@@ -1490,7 +1494,7 @@ void SoftDemo::keyboardCallback(unsigned char key, int x, int y)
// //
void SoftDemo::mouseMotionFunc(int x,int y) void SoftDemo::mouseMotionFunc(int x,int y)
{ {
if(m_node&&(m_results.time<SIMD_INFINITY)) if(m_node&&(m_results.fraction<1.f))
{ {
if(!m_drag) if(!m_drag)
{ {
@@ -1522,7 +1526,7 @@ if(button==0)
{ {
case 0: case 0:
{ {
m_results.time=SIMD_INFINITY; m_results.fraction=1.f;
DemoApplication::mouseFunc(button,state,x,y); DemoApplication::mouseFunc(button,state,x,y);
if(!m_pickConstraint) if(!m_pickConstraint)
{ {
@@ -1534,14 +1538,14 @@ if(button==0)
{ {
btSoftBody* psb=sbs[ib]; btSoftBody* psb=sbs[ib];
btSoftBody::sRayCast res; btSoftBody::sRayCast res;
if(psb->rayCast(rayFrom,rayDir,res,m_results.time)) if(psb->rayTest(rayFrom,rayTo,res))
{ {
m_results=res; m_results=res;
} }
} }
if(m_results.time<SIMD_INFINITY) if(m_results.fraction<1.f)
{ {
m_impact = rayFrom+rayDir*m_results.time; m_impact = rayFrom+(rayTo-rayFrom)*m_results.fraction;
m_drag = false; m_drag = false;
m_lastmousepos[0] = x; m_lastmousepos[0] = x;
m_lastmousepos[1] = y; m_lastmousepos[1] = y;
@@ -1570,14 +1574,14 @@ if(button==0)
} }
break; break;
case 1: case 1:
if((!m_drag)&&m_cutting&&(m_results.time<SIMD_INFINITY)) if((!m_drag)&&m_cutting&&(m_results.fraction<1.f))
{ {
ImplicitSphere isphere(m_impact,1); ImplicitSphere isphere(m_impact,1);
printf("Mass before: %f\r\n",m_results.body->getTotalMass()); printf("Mass before: %f\r\n",m_results.body->getTotalMass());
m_results.body->refine(&isphere,0.0001,true); m_results.body->refine(&isphere,0.0001,true);
printf("Mass after: %f\r\n",m_results.body->getTotalMass()); printf("Mass after: %f\r\n",m_results.body->getTotalMass());
} }
m_results.time=SIMD_INFINITY; m_results.fraction=1.f;
m_drag=false; m_drag=false;
DemoApplication::mouseFunc(button,state,x,y); DemoApplication::mouseFunc(button,state,x,y);
break; break;

View File

@@ -669,7 +669,7 @@ Benchmarking dbvt...
[4] btDbvt::collideTT self: 2814 ms (-20%) [4] btDbvt::collideTT self: 2814 ms (-20%)
[5] btDbvt::collideTT xform: 7379 ms (-1%) [5] btDbvt::collideTT xform: 7379 ms (-1%)
[6] btDbvt::collideTT xform,self: 7270 ms (-2%) [6] btDbvt::collideTT xform,self: 7270 ms (-2%)
[7] btDbvt::collideRAY: 6314 ms (0%),(332143 r/s) [7] btDbvt::rayTest: 6314 ms (0%),(332143 r/s)
[8] insert/remove: 2093 ms (0%),(1001983 ir/s) [8] insert/remove: 2093 ms (0%),(1001983 ir/s)
[9] updates (teleport): 1879 ms (-3%),(1116100 u/s) [9] updates (teleport): 1879 ms (-3%),(1116100 u/s)
[10] updates (jitter): 1244 ms (-4%),(1685813 u/s) [10] updates (jitter): 1244 ms (-4%),(1685813 u/s)
@@ -809,7 +809,7 @@ bool cfgBenchmark6_Enable = cfgEnable;
static const int cfgBenchmark6_Iterations = 512; static const int cfgBenchmark6_Iterations = 512;
static const btScalar cfgBenchmark6_OffsetScale = 2; static const btScalar cfgBenchmark6_OffsetScale = 2;
static const int cfgBenchmark6_Reference = 7270; static const int cfgBenchmark6_Reference = 7270;
//[7] btDbvt::collideRAY //[7] btDbvt::rayTest
bool cfgBenchmark7_Enable = cfgEnable; bool cfgBenchmark7_Enable = cfgEnable;
static const int cfgBenchmark7_Passes = 32; static const int cfgBenchmark7_Passes = 32;
static const int cfgBenchmark7_Iterations = 65536; static const int cfgBenchmark7_Iterations = 65536;
@@ -1017,13 +1017,13 @@ if(cfgBenchmark7_Enable)
} }
btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt); btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
dbvt.optimizeTopDown(); dbvt.optimizeTopDown();
printf("[7] btDbvt::collideRAY: "); printf("[7] btDbvt::rayTest: ");
wallclock.reset(); wallclock.reset();
for(int i=0;i<cfgBenchmark7_Passes;++i) for(int i=0;i<cfgBenchmark7_Passes;++i)
{ {
for(int j=0;j<cfgBenchmark7_Iterations;++j) for(int j=0;j<cfgBenchmark7_Iterations;++j)
{ {
btDbvt::collideRAY(dbvt.m_root,rayorg[j],raydir[j],policy); btDbvt::rayTest(dbvt.m_root,rayorg[j],rayorg[j]+raydir[j],policy);
} }
} }
const int time=(int)wallclock.getTimeMilliseconds(); const int time=(int)wallclock.getTimeMilliseconds();

View File

@@ -20,6 +20,7 @@ subject to the following restrictions:
#include "LinearMath/btAlignedObjectArray.h" #include "LinearMath/btAlignedObjectArray.h"
#include "LinearMath/btVector3.h" #include "LinearMath/btVector3.h"
#include "LinearMath/btTransform.h" #include "LinearMath/btTransform.h"
#include "LinearMath/btAabbUtil2.h"
// //
// Compile time configuration // Compile time configuration
@@ -156,10 +157,7 @@ DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a,
const btTransform& xform); const btTransform& xform);
DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a, DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a,
const btVector3& b); const btVector3& b);
DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a,
const btVector3& org,
const btVector3& invdir,
const unsigned* signs);
DBVT_INLINE friend btScalar Proximity( const btDbvtAabbMm& a, DBVT_INLINE friend btScalar Proximity( const btDbvtAabbMm& a,
const btDbvtAabbMm& b); const btDbvtAabbMm& b);
DBVT_INLINE friend int Select( const btDbvtAabbMm& o, DBVT_INLINE friend int Select( const btDbvtAabbMm& o,
@@ -317,9 +315,9 @@ struct btDbvt
const btDbvtVolume& volume, const btDbvtVolume& volume,
DBVT_IPOLICY); DBVT_IPOLICY);
DBVT_PREFIX DBVT_PREFIX
static void collideRAY( const btDbvtNode* root, static void rayTest( const btDbvtNode* root,
const btVector3& origin, const btVector3& rayFrom,
const btVector3& direction, const btVector3& rayTo,
DBVT_IPOLICY); DBVT_IPOLICY);
DBVT_PREFIX DBVT_PREFIX
static void collideKDOP(const btDbvtNode* root, static void collideKDOP(const btDbvtNode* root,
@@ -539,37 +537,12 @@ return( (b.x()>=a.mi.x())&&
(b.z()<=a.mx.z())); (b.z()<=a.mx.z()));
} }
//
DBVT_INLINE bool Intersect( const btDbvtAabbMm& a,
const btVector3& org,
const btVector3& invdir,
const unsigned* signs) //////////////////////////////////////
{
#if 0
const btVector3 b0((a.mi-org)*invdir);
const btVector3 b1((a.mx-org)*invdir);
const btVector3 tmin(btMin(b0[0],b1[0]),btMin(b0[1],b1[1]),btMin(b0[2],b1[2]));
const btVector3 tmax(btMax(b0[0],b1[0]),btMax(b0[1],b1[1]),btMax(b0[2],b1[2]));
const btScalar tin=btMax(tmin[0],btMax(tmin[1],tmin[2]));
const btScalar tout=btMin(tmax[0],btMin(tmax[1],tmax[2]));
return(tin<tout);
#else
const btVector3* bounds[2]={&a.mi,&a.mx};
btScalar txmin=(bounds[ signs[0]]->x()-org[0])*invdir[0];
btScalar txmax=(bounds[1-signs[0]]->x()-org[0])*invdir[0];
const btScalar tymin=(bounds[ signs[1]]->y()-org[1])*invdir[1];
const btScalar tymax=(bounds[1-signs[1]]->y()-org[1])*invdir[1];
if((txmin>tymax)||(tymin>txmax)) return(false);
if(tymin>txmin) txmin=tymin;
if(tymax<txmax) txmax=tymax;
const btScalar tzmin=(bounds[ signs[2]]->z()-org[2])*invdir[2];
const btScalar tzmax=(bounds[1-signs[2]]->z()-org[2])*invdir[2];
if((txmin>tzmax)||(tzmin>txmax)) return(false);
if(tzmin>txmin) txmin=tzmin;
if(tzmax<txmax) txmax=tzmax;
return(txmax>0);
#endif
}
// //
DBVT_INLINE btScalar Proximity( const btDbvtAabbMm& a, DBVT_INLINE btScalar Proximity( const btDbvtAabbMm& a,
@@ -875,30 +848,50 @@ if(root)
} }
} }
// //
DBVT_PREFIX DBVT_PREFIX
inline void btDbvt::collideRAY( const btDbvtNode* root, inline void btDbvt::rayTest( const btDbvtNode* root,
const btVector3& origin, const btVector3& rayFrom,
const btVector3& direction, const btVector3& rayTo,
DBVT_IPOLICY) DBVT_IPOLICY)
{ {
DBVT_CHECKTYPE DBVT_CHECKTYPE
if(root) if(root)
{ {
const btVector3 normal=direction.normalized(); btVector3 rayDir = (rayTo-rayFrom);
const btVector3 invdir( 1/normal.x(), rayDir.normalize ();
1/normal.y(),
1/normal.z()); ///what about division by zero? --> just set rayDirection[i] to INF/1e30
const unsigned signs[]={ direction.x()<0, btVector3 rayDirectionInverse;
direction.y()<0, rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0];
direction.z()<0}; rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1];
rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2];
unsigned int signs[3] = { rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
btVector3 resultNormal;
btAlignedObjectArray<const btDbvtNode*> stack; btAlignedObjectArray<const btDbvtNode*> stack;
stack.reserve(SIMPLE_STACKSIZE); stack.reserve(SIMPLE_STACKSIZE);
stack.push_back(root); stack.push_back(root);
do { do {
const btDbvtNode* node=stack[stack.size()-1]; const btDbvtNode* node=stack[stack.size()-1];
stack.pop_back(); stack.pop_back();
if(Intersect(node->volume,origin,invdir,signs))
btVector3 bounds[2] = {node->volume.Mins(),node->volume.Maxs()};
btScalar lambda_max = rayDir.dot(rayTo-rayFrom);
btScalar tmin=1.f,lambda_min=0.f;
bool result1 = btRayAabb2(rayFrom,rayDirectionInverse,signs,bounds,tmin,lambda_min,lambda_max);
#ifdef COMPARE_BTRAY_AABB2
btScalar param=1.f;
bool result2 = btRayAabb(rayFrom,rayTo,node->volume.Mins(),node->volume.Maxs(),param,resultNormal);
btAssert(result1 == result2);
#endif //TEST_BTRAY_AABB2
if(result1)
{ {
if(node->isinternal()) if(node->isinternal())
{ {

View File

@@ -229,12 +229,12 @@ void btDbvtBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo,
BroadphaseRayTester callback(rayCallback); BroadphaseRayTester callback(rayCallback);
m_sets[0].collideRAY( m_sets[0].m_root, m_sets[0].rayTest( m_sets[0].m_root,
rayFrom, rayFrom,
rayTo, rayTo,
callback); callback);
m_sets[1].collideRAY( m_sets[1].m_root, m_sets[1].rayTest( m_sets[1].m_root,
rayFrom, rayFrom,
rayTo, rayTo,
callback); callback);

View File

@@ -468,14 +468,15 @@ void btQuantizedBvh::walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCall
#ifdef RAYAABB2 #ifdef RAYAABB2
btVector3 rayFrom = raySource; btVector3 rayFrom = raySource;
btVector3 rayDirection = (rayTarget-raySource); btVector3 rayDir = (rayTarget-raySource);
rayDirection.normalize (); rayDir.normalize ();
lambda_max = rayDirection.dot(rayTarget-raySource); lambda_max = rayDir.dot(rayTarget-raySource);
///what about division by zero? --> just set rayDirection[i] to 1.0 ///what about division by zero? --> just set rayDirection[i] to 1.0
rayDirection[0] = rayDirection[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDirection[0]; btVector3 rayDirectionInverse;
rayDirection[1] = rayDirection[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDirection[1]; rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0];
rayDirection[2] = rayDirection[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDirection[2]; rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1];
unsigned int sign[3] = { rayDirection[0] < 0.0, rayDirection[1] < 0.0, rayDirection[2] < 0.0}; rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2];
unsigned int sign[3] = { rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
#endif #endif
btVector3 bounds[2]; btVector3 bounds[2];
@@ -501,7 +502,7 @@ void btQuantizedBvh::walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCall
///careful with this check: need to check division by zero (above) and fix the unQuantize method ///careful with this check: need to check division by zero (above) and fix the unQuantize method
///thanks Joerg/hiker for the reproduction case! ///thanks Joerg/hiker for the reproduction case!
///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858 ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858
rayBoxOverlap = aabbOverlap ? btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0f, lambda_max) : false; rayBoxOverlap = aabbOverlap ? btRayAabb2 (raySource, rayDirectionInverse, sign, bounds, param, 0.0f, lambda_max) : false;
#else #else
btVector3 normal; btVector3 normal;

View File

@@ -1222,17 +1222,19 @@ return(done);
} }
// //
bool btSoftBody::rayCast(const btVector3& org, bool btSoftBody::rayTest(const btVector3& rayFrom,
const btVector3& dir, const btVector3& rayTo,
sRayCast& results, sRayCast& results)
btScalar maxtime) {
{ if(m_faces.size()&&m_fdbvt.empty())
if(m_faces.size()&&m_fdbvt.empty()) initializeFaceTree(); initializeFaceTree();
results.body = this;
results.time = maxtime; results.body = this;
results.feature = eFeature::None; results.fraction = 1.f;
results.index = -1; results.feature = eFeature::None;
return(rayCast(org,dir,results.time,results.feature,results.index,false)!=0); results.index = -1;
return(rayTest(rayFrom,rayTo,results.fraction,results.feature,results.index,false)!=0);
} }
// //
@@ -1497,31 +1499,36 @@ void btSoftBody::integrateMotion()
} }
// //
btSoftBody::RayCaster::RayCaster(const btVector3& org,const btVector3& dir,btScalar mxt) btSoftBody::RayFromToCaster::RayFromToCaster(const btVector3& rayFrom,const btVector3& rayTo,btScalar mxt)
{ {
o = org; m_rayFrom = rayFrom;
d = dir; m_rayNormalizedDirection = (rayTo-rayFrom);
mint = mxt; m_rayTo = rayTo;
face = 0; m_mint = mxt;
tests = 0; m_face = 0;
m_tests = 0;
} }
// //
void btSoftBody::RayCaster::Process(const btDbvtNode* leaf) void btSoftBody::RayFromToCaster::Process(const btDbvtNode* leaf)
{ {
btSoftBody::Face& f=*(btSoftBody::Face*)leaf->data; btSoftBody::Face& f=*(btSoftBody::Face*)leaf->data;
const btScalar t=rayTriangle( o,d, const btScalar t=rayFromToTriangle( m_rayFrom,m_rayTo,m_rayNormalizedDirection,
f.m_n[0]->m_x, f.m_n[0]->m_x,
f.m_n[1]->m_x, f.m_n[1]->m_x,
f.m_n[2]->m_x, f.m_n[2]->m_x,
mint); m_mint);
if((t>0)&&(t<mint)) { mint=t;face=&f; } if((t>0)&&(t<m_mint))
++tests; {
m_mint=t;m_face=&f;
}
++m_tests;
} }
// //
btScalar btSoftBody::RayCaster::rayTriangle( const btVector3& org, btScalar btSoftBody::RayFromToCaster::rayFromToTriangle( const btVector3& rayFrom,
const btVector3& dir, const btVector3& rayTo,
const btVector3& rayNormalizedDirection,
const btVector3& a, const btVector3& a,
const btVector3& b, const btVector3& b,
const btVector3& c, const btVector3& c,
@@ -1529,16 +1536,17 @@ btScalar btSoftBody::RayCaster::rayTriangle( const btVector3& org,
{ {
static const btScalar ceps=-SIMD_EPSILON*10; static const btScalar ceps=-SIMD_EPSILON*10;
static const btScalar teps=SIMD_EPSILON*10; static const btScalar teps=SIMD_EPSILON*10;
const btVector3 n=cross(b-a,c-a); const btVector3 n=cross(b-a,c-a);
const btScalar d=dot(a,n); const btScalar d=dot(a,n);
const btScalar den=dot(dir,n); const btScalar den=dot(rayNormalizedDirection,n);
if(!btFuzzyZero(den)) if(!btFuzzyZero(den))
{ {
const btScalar num=dot(org,n)-d; const btScalar num=dot(rayFrom,n)-d;
const btScalar t=-num/den; const btScalar t=-num/den;
if((t>teps)&&(t<maxt)) if((t>teps)&&(t<maxt))
{ {
const btVector3 hit=org+dir*t; const btVector3 hit=rayFrom+rayNormalizedDirection*t;
if( (dot(n,cross(a-hit,b-hit))>ceps) && if( (dot(n,cross(a-hit,b-hit))>ceps) &&
(dot(n,cross(b-hit,c-hit))>ceps) && (dot(n,cross(b-hit,c-hit))>ceps) &&
(dot(n,cross(c-hit,a-hit))>ceps)) (dot(n,cross(c-hit,a-hit))>ceps))
@@ -1638,16 +1646,20 @@ void btSoftBody::indicesToPointers(const int* map)
} }
// //
int btSoftBody::rayCast(const btVector3& org,const btVector3& dir, int btSoftBody::rayTest(const btVector3& rayFrom,const btVector3& rayTo,
btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const
{ {
int cnt=0; int cnt=0;
if(bcountonly||m_fdbvt.empty()) if(bcountonly||m_fdbvt.empty())
{/* Full search */ {/* Full search */
btVector3 dir = rayTo-rayFrom;
dir.normalize();
for(int i=0,ni=m_faces.size();i<ni;++i) for(int i=0,ni=m_faces.size();i<ni;++i)
{ {
const btSoftBody::Face& f=m_faces[i]; const btSoftBody::Face& f=m_faces[i];
const btScalar t=RayCaster::rayTriangle( org,dir,
const btScalar t=RayFromToCaster::rayFromToTriangle( rayFrom,rayTo,dir,
f.m_n[0]->m_x, f.m_n[0]->m_x,
f.m_n[1]->m_x, f.m_n[1]->m_x,
f.m_n[2]->m_x, f.m_n[2]->m_x,
@@ -1666,13 +1678,14 @@ int btSoftBody::rayCast(const btVector3& org,const btVector3& dir,
} }
else else
{/* Use dbvt */ {/* Use dbvt */
RayCaster collider(org,dir,mint); RayFromToCaster collider(rayFrom,rayTo,mint);
btDbvt::collideRAY(m_fdbvt.m_root,org,dir,collider);
if(collider.face) btDbvt::rayTest(m_fdbvt.m_root,rayFrom,rayTo,collider);
if(collider.m_face)
{ {
mint=collider.mint; mint=collider.m_mint;
feature=btSoftBody::eFeature::Face; feature=btSoftBody::eFeature::Face;
index=(int)(collider.face-&m_faces[0]); index=(int)(collider.m_face-&m_faces[0]);
cnt=1; cnt=1;
} }
} }

View File

@@ -134,7 +134,7 @@ public:
btSoftBody* body; /// soft body btSoftBody* body; /// soft body
eFeature::_ feature; /// feature type eFeature::_ feature; /// feature type
int index; /// feature index int index; /// feature index
btScalar time; /// time of impact (rayorg+raydir*time) btScalar fraction; /// time of impact fraction (rayorg+(rayto-rayfrom)*fraction)
}; };
/* ImplicitFn */ /* ImplicitFn */
@@ -532,18 +532,21 @@ public:
btScalar radmrg; // radial margin btScalar radmrg; // radial margin
btScalar updmrg; // Update margin btScalar updmrg; // Update margin
}; };
/* RayCaster */ /// RayFromToCaster takes a ray from, ray to (instead of direction!)
struct RayCaster : btDbvt::ICollide struct RayFromToCaster : btDbvt::ICollide
{ {
btVector3 o; btVector3 m_rayFrom;
btVector3 d; btVector3 m_rayTo;
btScalar mint; btVector3 m_rayNormalizedDirection;
Face* face; btScalar m_mint;
int tests; Face* m_face;
RayCaster(const btVector3& org,const btVector3& dir,btScalar mxt); int m_tests;
RayFromToCaster(const btVector3& rayFrom,const btVector3& rayTo,btScalar mxt);
void Process(const btDbvtNode* leaf); void Process(const btDbvtNode* leaf);
static inline btScalar rayTriangle(const btVector3& org,
const btVector3& dir, static inline btScalar rayFromToTriangle(const btVector3& rayFrom,
const btVector3& rayTo,
const btVector3& rayNormalizedDirection,
const btVector3& a, const btVector3& a,
const btVector3& b, const btVector3& b,
const btVector3& c, const btVector3& c,
@@ -744,11 +747,11 @@ public:
/* CutLink */ /* CutLink */
bool cutLink(int node0,int node1,btScalar position); bool cutLink(int node0,int node1,btScalar position);
bool cutLink(const Node* node0,const Node* node1,btScalar position); bool cutLink(const Node* node0,const Node* node1,btScalar position);
/* Ray casting */
bool rayCast(const btVector3& org, ///Ray casting using rayFrom and rayTo in worldspace, (not direction!)
const btVector3& dir, bool rayTest(const btVector3& rayFrom,
sRayCast& results, const btVector3& rayTo,
btScalar maxtime=SIMD_INFINITY); sRayCast& results);
/* Solver presets */ /* Solver presets */
void setSolver(eSolverPresets::_ preset); void setSolver(eSolverPresets::_ preset);
/* predictMotion */ /* predictMotion */
@@ -798,7 +801,8 @@ public:
// //
void pointersToIndices(); void pointersToIndices();
void indicesToPointers(const int* map=0); void indicesToPointers(const int* map=0);
int rayCast(const btVector3& org,const btVector3& dir,
int rayTest(const btVector3& rayFrom,const btVector3& rayTo,
btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const; btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const;
void initializeFaceTree(); void initializeFaceTree();
btVector3 evaluateCom() const; btVector3 evaluateCom() const;