From 5ec277e45893514d585397d7869bcb1919ab7304 Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Tue, 24 Jul 2018 15:47:49 -0700 Subject: [PATCH] Move bullet references in collision pick API to PhysicsEngine --- interface/src/Application.cpp | 2 +- interface/src/raypick/CollisionPick.cpp | 73 ++-------------- interface/src/raypick/CollisionPick.h | 83 ++++--------------- .../src/raypick/PickScriptingInterface.cpp | 2 +- .../src/raypick/PickScriptingInterface.h | 8 +- libraries/physics/src/PhysicsEngine.cpp | 72 ++++++++++++++++ libraries/physics/src/PhysicsEngine.h | 23 +++++ 7 files changed, 121 insertions(+), 142 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ad61e6a4a1..bc2055bd06 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6656,7 +6656,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe auto pickScriptingInterface = DependencyManager::get(); pickScriptingInterface->registerMetaTypes(scriptEngine.data()); - pickScriptingInterface->setCollisionWorld(_physicsEngine->getDynamicsWorld()); + pickScriptingInterface->setPhysicsEngine(_physicsEngine); // connect this script engines printedMessage signal to the global ScriptEngines these various messages connect(scriptEngine.data(), &ScriptEngine::printedMessage, diff --git a/interface/src/raypick/CollisionPick.cpp b/interface/src/raypick/CollisionPick.cpp index 7330a64267..8ef2890299 100644 --- a/interface/src/raypick/CollisionPick.cpp +++ b/interface/src/raypick/CollisionPick.cpp @@ -271,12 +271,9 @@ PickResultPointer CollisionPick::getEntityIntersection(const CollisionRegion& pi // Cannot compute result return std::make_shared(); } - - auto entityCollisionCallback = AllObjectMotionStatesCallback(pick.shapeInfo, pick.transform); - btCollisionWorld* collisionWorld = const_cast(_collisionWorld); - collisionWorld->contactTest(&entityCollisionCallback.collisionObject, entityCollisionCallback); - - return std::make_shared(pick, entityCollisionCallback.intersectingObjects, std::vector()); + + const auto& intersectingEntities = _physicsEngine->getCollidingInRegion(MOTIONSTATE_TYPE_ENTITY, pick.shapeInfo, pick.transform); + return std::make_shared(pick, intersectingEntities, std::vector()); } PickResultPointer CollisionPick::getOverlayIntersection(const CollisionRegion& pick) { @@ -289,70 +286,10 @@ PickResultPointer CollisionPick::getAvatarIntersection(const CollisionRegion& pi return std::make_shared(); } - auto avatarCollisionCallback = AllObjectMotionStatesCallback(pick.shapeInfo, pick.transform); - btCollisionWorld* collisionWorld = const_cast(_collisionWorld); - collisionWorld->contactTest(&avatarCollisionCallback.collisionObject, avatarCollisionCallback); - - return std::make_shared(pick, std::vector(), avatarCollisionCallback.intersectingObjects); + const auto& intersectingAvatars = _physicsEngine->getCollidingInRegion(MOTIONSTATE_TYPE_AVATAR, pick.shapeInfo, pick.transform); + return std::make_shared(pick, std::vector(), intersectingAvatars); } PickResultPointer CollisionPick::getHUDIntersection(const CollisionRegion& pick) { return getDefaultResult(QVariantMap()); -} - -RigidBodyFilterResultCallback::RigidBodyFilterResultCallback(const ShapeInfo& shapeInfo, const Transform& transform) : - btCollisionWorld::ContactResultCallback(), collisionObject() { - const btCollisionShape* collisionShape = ObjectMotionState::getShapeManager()->getShape(shapeInfo); - - collisionObject.setCollisionShape(const_cast(collisionShape)); - - btTransform bulletTransform; - bulletTransform.setOrigin(glmToBullet(transform.getTranslation())); - bulletTransform.setRotation(glmToBullet(transform.getRotation())); - - collisionObject.setWorldTransform(bulletTransform); -} - -RigidBodyFilterResultCallback::~RigidBodyFilterResultCallback() { - ObjectMotionState::getShapeManager()->releaseShape(collisionObject.getCollisionShape()); -} - -bool RigidBodyFilterResultCallback::needsCollision(btBroadphaseProxy* proxy) const { - return true; -} - -btScalar RigidBodyFilterResultCallback::addSingleResult(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0, int partId0, int index0, const btCollisionObjectWrapper* colObj1, int partId1, int index1) { - const btCollisionObject* otherBody; - btVector3 point; - btVector3 otherPoint; - if (colObj0->m_collisionObject == &collisionObject) { - otherBody = colObj1->m_collisionObject; - point = cp.m_localPointA; - otherPoint = cp.m_localPointB; - } - else { - otherBody = colObj0->m_collisionObject; - point = cp.m_localPointB; - otherPoint = cp.m_localPointA; - } - if (!(otherBody->getInternalType() & btCollisionObject::CO_RIGID_BODY)) { - return 0; - } - const btRigidBody* collisionCandidate = static_cast(otherBody); - const btMotionState* motionStateCandidate = collisionCandidate->getMotionState(); - - checkOrAddCollidingState(motionStateCandidate, point, otherPoint); - - return 0; -} - -template -void AllObjectMotionStatesCallback::checkOrAddCollidingState(const btMotionState* otherMotionState, btVector3& point, btVector3& otherPoint) { - const T* candidate = dynamic_cast(otherMotionState); - if (!candidate) { - return; - } - - // This is the correct object type. Add it to the list. - intersectingObjects.emplace_back(candidate->getObjectID(), bulletToGLM(point), bulletToGLM(otherPoint)); } \ No newline at end of file diff --git a/interface/src/raypick/CollisionPick.h b/interface/src/raypick/CollisionPick.h index 3d2bc2c4c9..ef1fdc7b0c 100644 --- a/interface/src/raypick/CollisionPick.h +++ b/interface/src/raypick/CollisionPick.h @@ -8,44 +8,13 @@ #ifndef hifi_CollisionPick_h #define hifi_CollisionPick_h -#include - -#include -#include -#include +#include +#include #include #include class CollisionPickResult : public PickResult { public: - struct EntityIntersection { - EntityIntersection() { } - - EntityIntersection(const EntityIntersection& entityIntersection) : - id(entityIntersection.id), - pickCollisionPoint(entityIntersection.pickCollisionPoint), - entityCollisionPoint(entityIntersection.entityCollisionPoint) { - } - - EntityIntersection(QUuid id, glm::vec3 pickCollisionPoint, glm::vec3 entityCollisionPoint) : - id(id), - pickCollisionPoint(pickCollisionPoint), - entityCollisionPoint(entityCollisionPoint) { - } - - QVariantMap toVariantMap() { - QVariantMap variantMap; - variantMap["objectID"] = id; - variantMap["pickCollisionPoint"] = vec3toVariant(pickCollisionPoint); - variantMap["entityCollisionPoint"] = vec3toVariant(entityCollisionPoint); - return variantMap; - } - - QUuid id; - glm::vec3 pickCollisionPoint; - glm::vec3 entityCollisionPoint; - }; - CollisionPickResult() {} CollisionPickResult(const QVariantMap& pickVariant) : PickResult(pickVariant) {} @@ -73,13 +42,21 @@ public: QVariantList qIntersectingEntities; for (auto intersectingEntity : intersectingEntities) { - qIntersectingEntities.append(intersectingEntity.toVariantMap()); + QVariantMap qIntersectingEntity; + qIntersectingEntity["objectID"] = intersectingEntity.id; + qIntersectingEntity["pickCollisionPoint"] = vec3toVariant(intersectingEntity.pickCollisionPoint); + qIntersectingEntity["entityCollisionPoint"] = vec3toVariant(intersectingEntity.entityCollisionPoint); + qIntersectingEntities.append(qIntersectingEntity); } variantMap["intersectingEntities"] = qIntersectingEntities; QVariantList qIntersectingAvatars; for (auto intersectingAvatar : intersectingAvatars) { - qIntersectingAvatars.append(intersectingAvatar.toVariantMap()); + QVariantMap qIntersectingAvatar; + qIntersectingAvatar["objectID"] = intersectingAvatar.id; + qIntersectingAvatar["pickCollisionPoint"] = vec3toVariant(intersectingAvatar.pickCollisionPoint); + qIntersectingAvatar["entityCollisionPoint"] = vec3toVariant(intersectingAvatar.entityCollisionPoint); + qIntersectingAvatars.append(qIntersectingAvatar); } variantMap["intersectingAvatars"] = qIntersectingAvatars; @@ -111,10 +88,10 @@ public: class CollisionPick : public Pick { public: - CollisionPick(const PickFilter& filter, float maxDistance, bool enabled, CollisionRegion collisionRegion, const btCollisionWorld* collisionWorld) : + CollisionPick(const PickFilter& filter, float maxDistance, bool enabled, CollisionRegion collisionRegion, PhysicsEnginePointer physicsEngine) : Pick(filter, maxDistance, enabled), _mathPick(collisionRegion), - _collisionWorld(collisionWorld) { + _physicsEngine(physicsEngine) { } CollisionRegion getMathematicalPick() const override; @@ -130,38 +107,8 @@ protected: void computeShapeInfo(CollisionRegion& pick, ShapeInfo& shapeInfo, QSharedPointer resource); CollisionRegion _mathPick; - const btCollisionWorld* _collisionWorld; + PhysicsEnginePointer _physicsEngine; QSharedPointer _cachedResource; }; -// Callback for checking the motion states of all colliding rigid bodies for candidacy to be added to a list -struct RigidBodyFilterResultCallback : public btCollisionWorld::ContactResultCallback { - RigidBodyFilterResultCallback(const ShapeInfo& shapeInfo, const Transform& transform); - - ~RigidBodyFilterResultCallback(); - - RigidBodyFilterResultCallback(btCollisionObject& testCollisionObject) : - btCollisionWorld::ContactResultCallback(), collisionObject(testCollisionObject) { - } - - btCollisionObject collisionObject; - - virtual bool needsCollision(btBroadphaseProxy* proxy) const; - - // Check candidacy for adding to a list - virtual void checkOrAddCollidingState(const btMotionState* otherMotionState, btVector3& point, btVector3& otherPoint) = 0; - - btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0, int partId0, int index0, const btCollisionObjectWrapper* colObj1, int partId1, int index1) override; -}; - -// Callback for getting colliding ObjectMotionStates in the world, or optionally a more specific type. -template -struct AllObjectMotionStatesCallback : public RigidBodyFilterResultCallback { - AllObjectMotionStatesCallback(const ShapeInfo& shapeInfo, const Transform& transform) : RigidBodyFilterResultCallback(shapeInfo, transform) { } - - std::vector intersectingObjects; - - void checkOrAddCollidingState(const btMotionState* otherMotionState, btVector3& point, btVector3& otherPoint) override; -}; - #endif // hifi_CollisionPick_h \ No newline at end of file diff --git a/interface/src/raypick/PickScriptingInterface.cpp b/interface/src/raypick/PickScriptingInterface.cpp index 526d099cb4..3417eaf431 100644 --- a/interface/src/raypick/PickScriptingInterface.cpp +++ b/interface/src/raypick/PickScriptingInterface.cpp @@ -157,7 +157,7 @@ unsigned int PickScriptingInterface::createCollisionPick(const QVariant& propert CollisionRegion collisionRegion(propMap); - return DependencyManager::get()->addPick(PickQuery::Collision, std::make_shared(filter, maxDistance, enabled, collisionRegion, _collisionWorld)); + return DependencyManager::get()->addPick(PickQuery::Collision, std::make_shared(filter, maxDistance, enabled, collisionRegion, _physicsEngine)); } void PickScriptingInterface::enablePick(unsigned int uid) { diff --git a/interface/src/raypick/PickScriptingInterface.h b/interface/src/raypick/PickScriptingInterface.h index 48bc6e598e..5eb370adf7 100644 --- a/interface/src/raypick/PickScriptingInterface.h +++ b/interface/src/raypick/PickScriptingInterface.h @@ -9,10 +9,10 @@ #define hifi_PickScriptingInterface_h #include -#include #include #include +#include #include /**jsdoc @@ -277,12 +277,12 @@ public slots: static constexpr unsigned int INTERSECTED_HUD() { return IntersectionType::HUD; } // Set to allow CollisionPicks to have access to the physics engine - void setCollisionWorld(const btCollisionWorld* collisionWorld) { - _collisionWorld = collisionWorld; + void setPhysicsEngine(PhysicsEnginePointer physicsEngine) { + _physicsEngine = physicsEngine; } protected: - const btCollisionWorld* _collisionWorld; + PhysicsEnginePointer _physicsEngine; }; #endif // hifi_PickScriptingInterface_h diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 66a4edb486..e82e201bb5 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -840,3 +840,75 @@ void PhysicsEngine::setShowBulletConstraintLimits(bool value) { } } +struct AllContactsCallback : public btCollisionWorld::ContactResultCallback { + AllContactsCallback(MotionStateType desiredObjectType, const ShapeInfo& shapeInfo, const Transform& transform) : + desiredObjectType(desiredObjectType), + btCollisionWorld::ContactResultCallback(), + collisionObject() { + const btCollisionShape* collisionShape = ObjectMotionState::getShapeManager()->getShape(shapeInfo); + + collisionObject.setCollisionShape(const_cast(collisionShape)); + + btTransform bulletTransform; + bulletTransform.setOrigin(glmToBullet(transform.getTranslation())); + bulletTransform.setRotation(glmToBullet(transform.getRotation())); + + collisionObject.setWorldTransform(bulletTransform); + } + + ~AllContactsCallback() { + ObjectMotionState::getShapeManager()->releaseShape(collisionObject.getCollisionShape()); + } + + AllContactsCallback(btCollisionObject& testCollisionObject) : + btCollisionWorld::ContactResultCallback(), collisionObject(testCollisionObject) { + } + + MotionStateType desiredObjectType; + btCollisionObject collisionObject; + std::vector intersectingObjects; + + virtual bool needsCollision(btBroadphaseProxy* proxy) const { + return true; + } + + btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0, int partId0, int index0, const btCollisionObjectWrapper* colObj1, int partId1, int index1) override { + const btCollisionObject* otherBody; + btVector3 point; + btVector3 otherPoint; + if (colObj0->m_collisionObject == &collisionObject) { + otherBody = colObj1->m_collisionObject; + point = cp.m_localPointA; + otherPoint = cp.m_localPointB; + } + else { + otherBody = colObj0->m_collisionObject; + point = cp.m_localPointB; + otherPoint = cp.m_localPointA; + } + + if (!(otherBody->getInternalType() & btCollisionObject::CO_RIGID_BODY)) { + return 0; + } + const btRigidBody* collisionCandidate = static_cast(otherBody); + const btMotionState* motionStateCandidate = collisionCandidate->getMotionState(); + + const ObjectMotionState* candidate = dynamic_cast(motionStateCandidate); + if (!candidate || candidate->getType() != desiredObjectType) { + return 0; + } + + // This is the correct object type. Add it to the list. + intersectingObjects.emplace_back(candidate->getObjectID(), bulletToGLM(point), bulletToGLM(otherPoint)); + + return 0; + } +}; + +std::vector PhysicsEngine::getCollidingInRegion(MotionStateType desiredObjectType, const ShapeInfo& regionShapeInfo, const Transform& regionTransform) const { + auto contactCallback = AllContactsCallback(desiredObjectType, regionShapeInfo, regionTransform); + _dynamicsWorld->contactTest(&contactCallback.collisionObject, contactCallback); + + return contactCallback.intersectingObjects; +} + diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index 6a491c3791..42005b5a5d 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -43,6 +43,26 @@ public: void* _b; // ObjectMotionState pointer }; +struct EntityIntersection { + EntityIntersection() { } + + EntityIntersection(const EntityIntersection& entityIntersection) : + id(entityIntersection.id), + pickCollisionPoint(entityIntersection.pickCollisionPoint), + entityCollisionPoint(entityIntersection.entityCollisionPoint) { + } + + EntityIntersection(QUuid id, glm::vec3 selfCollisionPoint, glm::vec3 otherCollisionPoint) : + id(id), + pickCollisionPoint(selfCollisionPoint), + entityCollisionPoint(otherCollisionPoint) { + } + + QUuid id; + glm::vec3 pickCollisionPoint; + glm::vec3 entityCollisionPoint; +}; + using ContactMap = std::map; using CollisionEvents = std::vector; @@ -105,6 +125,9 @@ public: void setShowBulletConstraints(bool value); void setShowBulletConstraintLimits(bool value); + // Function for getting colliding ObjectMotionStates in the world of specified type + std::vector getCollidingInRegion(MotionStateType desiredObjectType, const ShapeInfo& regionShapeInfo, const Transform& regionTransform) const; + private: QList removeDynamicsForBody(btRigidBody* body); void addObjectToDynamicsWorld(ObjectMotionState* motionState);