EntityList PhysicsWorld::ObbCollisionQuery(const OBB &obb, int collisionGroup, int collisionMask) { PROFILE(PhysicsWorld_ObbCollisionQuery); std::set<btCollisionObjectWrapper*> objects; EntityList entities; btBoxShape box(obb.HalfSize()); // Note: Bullet uses box halfsize float3x3 m(obb.axis[0], obb.axis[1], obb.axis[2]); btTransform t1(m.ToQuat(), obb.CenterPoint()); #include "DisableMemoryLeakCheck.h" btRigidBody* tempRigidBody = new btRigidBody(1.0f, 0, &box); #include "EnableMemoryLeakCheck.h" tempRigidBody->setWorldTransform(t1); world_->addRigidBody(tempRigidBody, collisionGroup, collisionMask); tempRigidBody->activate(); // To make sure we get collision results from static sleeping rigidbodies, activate the temp rigid body ObbCallback resultCallback(objects); world_->contactTest(tempRigidBody, resultCallback); for (std::set<btCollisionObjectWrapper*>::iterator i = objects.begin(); i != objects.end(); ++i) { EC_RigidBody* body = static_cast<EC_RigidBody*>((*i)->getCollisionObject()->getUserPointer()); if (body && body->ParentEntity()) entities.push_back(body->ParentEntity()->shared_from_this()); } world_->removeRigidBody(tempRigidBody); delete tempRigidBody; return entities; }
void Flow::phaseEnd() { _transition = false; spScene current = _current; spScene next = _next; _current = 0; _next = 0; if ((next->_dialog && _back) || !next->_dialog) { current->_holder->detach(); current->postHiding(); } getStage()->insertChildBefore(_touchBlocker, next->getHolder()); if (!_back || !current->_dialog) next->postShowing(); if (_back) next->sceneHidden(current); getStage()->removeEventListener(TouchEvent::CLICK, CLOSURE(this, &Flow::blockedTouch)); if (current->_done) { current->leaving(); if (current->_resultCB) { current->_resultCB(¤t->_finishEvent); current->_resultCB = resultCallback(); } } if (current->_remove) { OX_ASSERT(next->_dialog == false); std::vector<spScene>::iterator i = std::find(scenes.begin(), scenes.end(), current); OX_ASSERT(i != scenes.end()); scenes.erase(i); } if (_wasTouchBlocked) { log::messageln("send blocked touch"); TouchEvent click(TouchEvent::CLICK, true, _blockedTouchPosition); getStage()->handleEvent(&click); _wasTouchBlocked = false; } }
bool Raytracer::singleObjectRaytest(const btVector3& rayFrom,const btVector3& rayTo,btVector3& worldNormal,btVector3& worldHitPoint) { btScalar closestHitResults = 1.f; ClosestRayResultCallback resultCallback(rayFrom,rayTo); bool hasHit = false; btConvexCast::CastResult rayResult; btSphereShape pointShape(0.0f); btTransform rayFromTrans; btTransform rayToTrans; rayFromTrans.setIdentity(); rayFromTrans.setOrigin(rayFrom); rayToTrans.setIdentity(); rayToTrans.setOrigin(rayTo); for (int s=0;s<numObjects;s++) { //comment-out next line to get all hits, instead of just the closest hit //resultCallback.m_closestHitFraction = 1.f; //do some culling, ray versus aabb btVector3 aabbMin,aabbMax; shapePtr[s]->getAabb(transforms[s],aabbMin,aabbMax); btScalar hitLambda = 1.f; btVector3 hitNormal; btCollisionObject tmpObj; tmpObj.setWorldTransform(transforms[s]); if (btRayAabb(rayFrom,rayTo,aabbMin,aabbMax,hitLambda,hitNormal)) { //reset previous result btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans, &tmpObj, shapePtr[s], transforms[s], resultCallback); if (resultCallback.hasHit()) { //float fog = 1.f - 0.1f * rayResult.m_fraction; resultCallback.m_hitNormalWorld.normalize();//.m_normal.normalize(); worldNormal = resultCallback.m_hitNormalWorld; //worldNormal = transforms[s].getBasis() *rayResult.m_normal; worldNormal.normalize(); hasHit = true; } } } return hasHit; }
bool Raytracer::worldRaytest(const btVector3& rayFrom,const btVector3& rayTo,btVector3& worldNormal,btVector3& worldHitPoint) { struct AllRayResultCallback : public RayResultCallback { AllRayResultCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld) :m_rayFromWorld(rayFromWorld), m_rayToWorld(rayToWorld) { } btVector3 m_rayFromWorld;//used to calculate hitPointWorld from hitFraction btVector3 m_rayToWorld; btVector3 m_hitNormalWorld; btVector3 m_hitPointWorld; virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) { //caller already does the filter on the m_closestHitFraction btAssert(rayResult.m_hitFraction <= m_closestHitFraction); m_closestHitFraction = rayResult.m_hitFraction; m_collisionObject = rayResult.m_collisionObject; if (normalInWorldSpace) { m_hitNormalWorld = rayResult.m_hitNormalLocal; } else { ///need to transform normal into worldspace m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal; } m_hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction); return 1.f; } }; AllRayResultCallback resultCallback(rayFrom,rayTo); // ClosestRayResultCallback resultCallback(rayFrom,rayTo); m_collisionWorld->rayTest(rayFrom,rayTo,resultCallback); if (resultCallback.hasHit()) { worldNormal = resultCallback.m_hitNormalWorld; return true; } return false; }
JNIEXPORT void JNICALL Java_com_jme3_bullet_PhysicsSpace_rayTest_1native (JNIEnv * env, jobject object, jobject to, jobject from, jlong spaceId, jobject resultlist) { jmePhysicsSpace* space = reinterpret_cast<jmePhysicsSpace*> (spaceId); if (space == NULL) { jclass newExc = env->FindClass("java/lang/NullPointerException"); env->ThrowNew(newExc, "The physics space does not exist."); return; } struct AllRayResultCallback : public btCollisionWorld::RayResultCallback { AllRayResultCallback(const btVector3& rayFromWorld, const btVector3 & rayToWorld) : m_rayFromWorld(rayFromWorld), m_rayToWorld(rayToWorld) { } jobject resultlist; JNIEnv* env; btVector3 m_rayFromWorld; //used to calculate hitPointWorld from hitFraction btVector3 m_rayToWorld; btVector3 m_hitNormalWorld; btVector3 m_hitPointWorld; virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace) { if (normalInWorldSpace) { m_hitNormalWorld = rayResult.m_hitNormalLocal; } else { m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis() * rayResult.m_hitNormalLocal; } m_hitPointWorld.setInterpolate3(m_rayFromWorld, m_rayToWorld, rayResult.m_hitFraction); jmeBulletUtil::addResult(env, resultlist, m_hitNormalWorld, m_hitPointWorld, rayResult.m_hitFraction, rayResult.m_collisionObject); return 1.f; } }; btVector3 native_to = btVector3(); jmeBulletUtil::convert(env, to, &native_to); btVector3 native_from = btVector3(); jmeBulletUtil::convert(env, from, &native_from); AllRayResultCallback resultCallback(native_from, native_to); resultCallback.env = env; resultCallback.resultlist = resultlist; space->getDynamicsWorld()->rayTest(native_from, native_to, resultCallback); return; }
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ //see http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=4152&hilit=raytest //for reference void PhysicsZone::rayCast(Math::Ray _ray, Math::Real _maxDistance, I_CollisionVisitor& _visitor) { Math::Vector3 offset = _ray.getDirection(); offset.normalize(); offset *= _maxDistance; Math::Point3 endpoint = _ray.getOrigin() + offset; //(m_pZone, _ray.getOrigin().m_array, endpoint.m_array, rayCastFilter, &rayCastQuery, rayCastPrefilter); btVector3 tquatFrom = btVector3(_ray.getOrigin().m_x,_ray.getOrigin().m_y,_ray.getOrigin().m_z); btVector3 tquatTo = btVector3(_ray.getOrigin().m_x,_ray.getOrigin().m_y,_ray.getOrigin().m_z); RayResultCallback resultCallback(tquatFrom,tquatTo); m_pZone->rayTest(tquatFrom,tquatTo,resultCallback); }
castResult Raycast::cast(const btVector3& rayFrom, const btVector3& rayTo) { result.hit = false; btCollisionWorld::ClosestRayResultCallback resultCallback(rayFrom,rayTo); btDynWorld->rayTest(rayFrom,rayTo,resultCallback); if (resultCallback.hasHit()) { // cerr << "1 true" << endl; result.hitBody = resultCallback.m_collisionObject; result.hit = true; result.hitPosition = resultCallback.m_hitPointWorld; /* if ( result.hitBody ) { cerr << "2 true" << endl; result.hit = true; result.hitPosition = resultCallback.m_hitPointWorld; }*/ } return result; }