bool Px3World::castRay( const Point3F &startPnt, const Point3F &endPnt, RayInfo *ri, const Point3F &impulse ) { physx::PxVec3 orig = px3Cast<physx::PxVec3>( startPnt ); physx::PxVec3 dir = px3Cast<physx::PxVec3>( endPnt - startPnt ); physx::PxF32 maxDist = dir.magnitude(); dir.normalize(); U32 groups = 0xffffffff; groups &= ~( PX3_TRIGGER ); // No trigger shapes! physx::PxHitFlags outFlags(physx::PxHitFlag::eDISTANCE | physx::PxHitFlag::eIMPACT | physx::PxHitFlag::eNORMAL); physx::PxQueryFilterData filterData(physx::PxQueryFlag::eSTATIC|physx::PxQueryFlag::eDYNAMIC); filterData.data.word0 = groups; physx::PxRaycastBuffer buf; if(!mScene->raycast(orig,dir,maxDist,buf,outFlags,filterData)) return false; if(!buf.hasBlock) return false; const physx::PxRaycastHit hit = buf.block; physx::PxRigidActor *actor = hit.actor; PhysicsUserData *userData = PhysicsUserData::cast( actor->userData ); if ( ri ) { ri->object = ( userData != NULL ) ? userData->getObject() : NULL; if ( ri->object == NULL ) ri->distance = hit.distance; ri->normal = px3Cast<Point3F>( hit.normal ); ri->point = px3Cast<Point3F>( hit.position ); ri->t = maxDist / hit.distance; } if ( impulse.isZero() || !actor->isRigidDynamic() || actor->is<physx::PxRigidDynamic>()->getRigidDynamicFlags() & physx::PxRigidDynamicFlag::eKINEMATIC ) return true; physx::PxRigidBody *body = actor->is<physx::PxRigidBody>(); physx::PxVec3 force = px3Cast<physx::PxVec3>( impulse ); physx::PxRigidBodyExt::addForceAtPos(*body,force,hit.position,physx::PxForceMode::eIMPULSE); return true; }
PhysicsBody* BtWorld::castRay( const Point3F &start, const Point3F &end, U32 bodyTypes ) { btVector3 startPt = btCast<btVector3>( start ); btVector3 endPt = btCast<btVector3>( end ); btCollisionWorld::ClosestRayResultCallback result( startPt, endPt ); mDynamicsWorld->rayTest( startPt, endPt, result ); if ( !result.hasHit() || !result.m_collisionObject ) return NULL; PhysicsUserData *userData = PhysicsUserData::cast( result.m_collisionObject->getUserPointer() ); if ( !userData ) return NULL; return userData->getBody(); }
PhysicsBody* Px3World::castRay( const Point3F &start, const Point3F &end, U32 bodyTypes ) { physx::PxVec3 orig = px3Cast<physx::PxVec3>( start ); physx::PxVec3 dir = px3Cast<physx::PxVec3>( end - start ); physx::PxF32 maxDist = dir.magnitude(); dir.normalize(); U32 groups = 0xFFFFFFFF; if ( !( bodyTypes & BT_Player ) ) groups &= ~( PX3_PLAYER ); // TODO: For now always skip triggers and debris, // but we should consider how game specifc this API // should be in the future. groups &= ~( PX3_TRIGGER ); // triggers groups &= ~( PX3_DEBRIS ); // debris physx::PxHitFlags outFlags(physx::PxHitFlag::eDISTANCE | physx::PxHitFlag::eIMPACT | physx::PxHitFlag::eNORMAL); physx::PxQueryFilterData filterData; if(bodyTypes & BT_Static) filterData.flags |= physx::PxQueryFlag::eSTATIC; if(bodyTypes & BT_Dynamic) filterData.flags |= physx::PxQueryFlag::eDYNAMIC; filterData.data.word0 = groups; physx::PxRaycastBuffer buf; if( !mScene->raycast(orig,dir,maxDist,buf,outFlags,filterData) ) return NULL; if(!buf.hasBlock) return NULL; physx::PxRigidActor *actor = buf.block.actor; PhysicsUserData *userData = PhysicsUserData::cast( actor->userData ); if( !userData ) return NULL; return userData->getBody(); }