void CollisionWorld::RayTestSingle(const SimdTransform& rayFromTrans,const SimdTransform& rayToTrans, CollisionObject* collisionObject, const CollisionShape* collisionShape, const SimdTransform& colObjWorldTransform, RayResultCallback& resultCallback) { SphereShape pointShape(0.0f); if (collisionShape->IsConvex()) { ConvexCast::CastResult castResult; castResult.m_fraction = 1.f;//?? ConvexShape* convexShape = (ConvexShape*) collisionShape; VoronoiSimplexSolver simplexSolver; SubsimplexConvexCast convexCaster(&pointShape,convexShape,&simplexSolver); //GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver); //ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0); if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) { //add hit if (castResult.m_normal.length2() > 0.0001f) { castResult.m_normal.normalize(); if (castResult.m_fraction < resultCallback.m_closestHitFraction) { CollisionWorld::LocalRayResult localRayResult ( collisionObject, 0, castResult.m_normal, castResult.m_fraction ); resultCallback.AddSingleResult(localRayResult); } } } } else { if (collisionShape->IsConcave()) { TriangleMeshShape* triangleMesh = (TriangleMeshShape*)collisionShape; SimdTransform worldTocollisionObject = colObjWorldTransform.inverse(); SimdVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin(); SimdVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin(); //ConvexCast::CastResult struct BridgeTriangleRaycastCallback : public TriangleRaycastCallback { CollisionWorld::RayResultCallback* m_resultCallback; CollisionObject* m_collisionObject; TriangleMeshShape* m_triangleMesh; BridgeTriangleRaycastCallback( const SimdVector3& from,const SimdVector3& to, CollisionWorld::RayResultCallback* resultCallback, CollisionObject* collisionObject,TriangleMeshShape* triangleMesh): TriangleRaycastCallback(from,to), m_resultCallback(resultCallback), m_collisionObject(collisionObject), m_triangleMesh(triangleMesh) { } virtual float ReportHit(const SimdVector3& hitNormalLocal, float hitFraction, int partId, int triangleIndex ) { CollisionWorld::LocalShapeInfo shapeInfo; shapeInfo.m_shapePart = partId; shapeInfo.m_triangleIndex = triangleIndex; CollisionWorld::LocalRayResult rayResult (m_collisionObject, &shapeInfo, hitNormalLocal, hitFraction); return m_resultCallback->AddSingleResult(rayResult); } }; BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh); rcb.m_hitFraction = resultCallback.m_closestHitFraction; SimdVector3 rayAabbMinLocal = rayFromLocal; rayAabbMinLocal.setMin(rayToLocal); SimdVector3 rayAabbMaxLocal = rayFromLocal; rayAabbMaxLocal.setMax(rayToLocal); triangleMesh->ProcessAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal); } else { //todo: use AABB tree or other BVH acceleration structure! if (collisionShape->IsCompound()) { const CompoundShape* compoundShape = static_cast<const CompoundShape*>(collisionShape); int i=0; for (i=0;i<compoundShape->GetNumChildShapes();i++) { SimdTransform childTrans = compoundShape->GetChildTransform(i); const CollisionShape* childCollisionShape = compoundShape->GetChildShape(i); SimdTransform childWorldTrans = colObjWorldTransform * childTrans; RayTestSingle(rayFromTrans,rayToTrans, collisionObject, childCollisionShape, childWorldTrans, resultCallback); } } } } }
void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& rayFromTrans,const btTransform& rayToTrans, btCollisionObject* collisionObject, const btCollisionShape* collisionShape, const btTransform& colObjWorldTransform, RayResultCallback& resultCallback,short int collisionFilterMask) { if (collisionShape->isConvex()) { btConvexCast::CastResult castResult; castResult.m_fraction = btScalar(1.);//?? btConvexShape* convexShape = (btConvexShape*) collisionShape; btVoronoiSimplexSolver simplexSolver; #define USE_SUBSIMPLEX_CONVEX_CAST 1 #ifdef USE_SUBSIMPLEX_CONVEX_CAST btSubsimplexConvexCast convexCaster(castShape,convexShape,&simplexSolver); #else //btGjkConvexCast convexCaster(castShape,convexShape,&simplexSolver); //btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0); #endif //#USE_SUBSIMPLEX_CONVEX_CAST if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) { //add hit if (castResult.m_normal.length2() > btScalar(0.0001)) { if (castResult.m_fraction < resultCallback.m_closestHitFraction) { #ifdef USE_SUBSIMPLEX_CONVEX_CAST //rotate normal into worldspace castResult.m_normal = rayFromTrans.getBasis() * castResult.m_normal; #endif //USE_SUBSIMPLEX_CONVEX_CAST castResult.m_normal.normalize(); btCollisionWorld::LocalRayResult localRayResult ( collisionObject, 0, castResult.m_normal, castResult.m_fraction ); bool normalInWorldSpace = true; resultCallback.AddSingleResult(localRayResult, normalInWorldSpace); } } } } else { if (collisionShape->isConcave()) { btTriangleMeshShape* triangleMesh = (btTriangleMeshShape*)collisionShape; btTransform worldTocollisionObject = colObjWorldTransform.inverse(); btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin(); btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin(); //ConvexCast::CastResult struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback { btCollisionWorld::RayResultCallback* m_resultCallback; btCollisionObject* m_collisionObject; btTriangleMeshShape* m_triangleMesh; BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to, btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh): btTriangleRaycastCallback(from,to), m_resultCallback(resultCallback), m_collisionObject(collisionObject), m_triangleMesh(triangleMesh) { } virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) { btCollisionWorld::LocalShapeInfo shapeInfo; shapeInfo.m_shapePart = partId; shapeInfo.m_triangleIndex = triangleIndex; btCollisionWorld::LocalRayResult rayResult (m_collisionObject, &shapeInfo, hitNormalLocal, hitFraction); bool normalInWorldSpace = false; return m_resultCallback->AddSingleResult(rayResult,normalInWorldSpace); } }; BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh); rcb.m_hitFraction = resultCallback.m_closestHitFraction; btVector3 rayAabbMinLocal = rayFromLocal; rayAabbMinLocal.setMin(rayToLocal); btVector3 rayAabbMaxLocal = rayFromLocal; rayAabbMaxLocal.setMax(rayToLocal); triangleMesh->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal); } else { //todo: use AABB tree or other BVH acceleration structure! if (collisionShape->isCompound()) { const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape); int i=0; for (i=0;i<compoundShape->getNumChildShapes();i++) { btTransform childTrans = compoundShape->getChildTransform(i); const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); btTransform childWorldTrans = colObjWorldTransform * childTrans; objectQuerySingle(castShape, rayFromTrans,rayToTrans, collisionObject, childCollisionShape, childWorldTrans, resultCallback, collisionFilterMask); } } } } }