Move bullet references in collision pick API to PhysicsEngine

This commit is contained in:
sabrina-shanman 2018-07-24 15:47:49 -07:00
parent 4ca9899000
commit 5ec277e458
7 changed files with 121 additions and 142 deletions

View file

@ -6656,7 +6656,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
auto pickScriptingInterface = DependencyManager::get<PickScriptingInterface>(); auto pickScriptingInterface = DependencyManager::get<PickScriptingInterface>();
pickScriptingInterface->registerMetaTypes(scriptEngine.data()); 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 this script engines printedMessage signal to the global ScriptEngines these various messages
connect(scriptEngine.data(), &ScriptEngine::printedMessage, connect(scriptEngine.data(), &ScriptEngine::printedMessage,

View file

@ -271,12 +271,9 @@ PickResultPointer CollisionPick::getEntityIntersection(const CollisionRegion& pi
// Cannot compute result // Cannot compute result
return std::make_shared<CollisionPickResult>(); return std::make_shared<CollisionPickResult>();
} }
auto entityCollisionCallback = AllObjectMotionStatesCallback<EntityMotionState>(pick.shapeInfo, pick.transform); const auto& intersectingEntities = _physicsEngine->getCollidingInRegion(MOTIONSTATE_TYPE_ENTITY, pick.shapeInfo, pick.transform);
btCollisionWorld* collisionWorld = const_cast<btCollisionWorld*>(_collisionWorld); return std::make_shared<CollisionPickResult>(pick, intersectingEntities, std::vector<EntityIntersection>());
collisionWorld->contactTest(&entityCollisionCallback.collisionObject, entityCollisionCallback);
return std::make_shared<CollisionPickResult>(pick, entityCollisionCallback.intersectingObjects, std::vector<CollisionPickResult::EntityIntersection>());
} }
PickResultPointer CollisionPick::getOverlayIntersection(const CollisionRegion& pick) { PickResultPointer CollisionPick::getOverlayIntersection(const CollisionRegion& pick) {
@ -289,70 +286,10 @@ PickResultPointer CollisionPick::getAvatarIntersection(const CollisionRegion& pi
return std::make_shared<CollisionPickResult>(); return std::make_shared<CollisionPickResult>();
} }
auto avatarCollisionCallback = AllObjectMotionStatesCallback<AvatarMotionState>(pick.shapeInfo, pick.transform); const auto& intersectingAvatars = _physicsEngine->getCollidingInRegion(MOTIONSTATE_TYPE_AVATAR, pick.shapeInfo, pick.transform);
btCollisionWorld* collisionWorld = const_cast<btCollisionWorld*>(_collisionWorld); return std::make_shared<CollisionPickResult>(pick, std::vector<EntityIntersection>(), intersectingAvatars);
collisionWorld->contactTest(&avatarCollisionCallback.collisionObject, avatarCollisionCallback);
return std::make_shared<CollisionPickResult>(pick, std::vector<CollisionPickResult::EntityIntersection>(), avatarCollisionCallback.intersectingObjects);
} }
PickResultPointer CollisionPick::getHUDIntersection(const CollisionRegion& pick) { PickResultPointer CollisionPick::getHUDIntersection(const CollisionRegion& pick) {
return getDefaultResult(QVariantMap()); 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<btCollisionShape*>(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<const btRigidBody*>(otherBody);
const btMotionState* motionStateCandidate = collisionCandidate->getMotionState();
checkOrAddCollidingState(motionStateCandidate, point, otherPoint);
return 0;
}
template <typename T = ObjectMotionState>
void AllObjectMotionStatesCallback<T>::checkOrAddCollidingState(const btMotionState* otherMotionState, btVector3& point, btVector3& otherPoint) {
const T* candidate = dynamic_cast<const T*>(otherMotionState);
if (!candidate) {
return;
}
// This is the correct object type. Add it to the list.
intersectingObjects.emplace_back(candidate->getObjectID(), bulletToGLM(point), bulletToGLM(otherPoint));
} }

View file

@ -8,44 +8,13 @@
#ifndef hifi_CollisionPick_h #ifndef hifi_CollisionPick_h
#define hifi_CollisionPick_h #define hifi_CollisionPick_h
#include <btBulletDynamicsCommon.h> #include <PhysicsEngine.h>
#include <model-networking/ModelCache.h>
#include <avatar/AvatarMotionState.h>
#include <EntityMotionState.h>
#include <BulletUtil.h>
#include <RegisteredMetaTypes.h> #include <RegisteredMetaTypes.h>
#include <Pick.h> #include <Pick.h>
class CollisionPickResult : public PickResult { class CollisionPickResult : public PickResult {
public: 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() {}
CollisionPickResult(const QVariantMap& pickVariant) : PickResult(pickVariant) {} CollisionPickResult(const QVariantMap& pickVariant) : PickResult(pickVariant) {}
@ -73,13 +42,21 @@ public:
QVariantList qIntersectingEntities; QVariantList qIntersectingEntities;
for (auto intersectingEntity : intersectingEntities) { 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; variantMap["intersectingEntities"] = qIntersectingEntities;
QVariantList qIntersectingAvatars; QVariantList qIntersectingAvatars;
for (auto intersectingAvatar : intersectingAvatars) { 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; variantMap["intersectingAvatars"] = qIntersectingAvatars;
@ -111,10 +88,10 @@ public:
class CollisionPick : public Pick<CollisionRegion> { class CollisionPick : public Pick<CollisionRegion> {
public: 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), Pick(filter, maxDistance, enabled),
_mathPick(collisionRegion), _mathPick(collisionRegion),
_collisionWorld(collisionWorld) { _physicsEngine(physicsEngine) {
} }
CollisionRegion getMathematicalPick() const override; CollisionRegion getMathematicalPick() const override;
@ -130,38 +107,8 @@ protected:
void computeShapeInfo(CollisionRegion& pick, ShapeInfo& shapeInfo, QSharedPointer<GeometryResource> resource); void computeShapeInfo(CollisionRegion& pick, ShapeInfo& shapeInfo, QSharedPointer<GeometryResource> resource);
CollisionRegion _mathPick; CollisionRegion _mathPick;
const btCollisionWorld* _collisionWorld; PhysicsEnginePointer _physicsEngine;
QSharedPointer<GeometryResource> _cachedResource; QSharedPointer<GeometryResource> _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 <typename T = ObjectMotionState>
struct AllObjectMotionStatesCallback : public RigidBodyFilterResultCallback {
AllObjectMotionStatesCallback(const ShapeInfo& shapeInfo, const Transform& transform) : RigidBodyFilterResultCallback(shapeInfo, transform) { }
std::vector<CollisionPickResult::EntityIntersection> intersectingObjects;
void checkOrAddCollidingState(const btMotionState* otherMotionState, btVector3& point, btVector3& otherPoint) override;
};
#endif // hifi_CollisionPick_h #endif // hifi_CollisionPick_h

View file

@ -157,7 +157,7 @@ unsigned int PickScriptingInterface::createCollisionPick(const QVariant& propert
CollisionRegion collisionRegion(propMap); CollisionRegion collisionRegion(propMap);
return DependencyManager::get<PickManager>()->addPick(PickQuery::Collision, std::make_shared<CollisionPick>(filter, maxDistance, enabled, collisionRegion, _collisionWorld)); return DependencyManager::get<PickManager>()->addPick(PickQuery::Collision, std::make_shared<CollisionPick>(filter, maxDistance, enabled, collisionRegion, _physicsEngine));
} }
void PickScriptingInterface::enablePick(unsigned int uid) { void PickScriptingInterface::enablePick(unsigned int uid) {

View file

@ -9,10 +9,10 @@
#define hifi_PickScriptingInterface_h #define hifi_PickScriptingInterface_h
#include <QtCore/QObject> #include <QtCore/QObject>
#include <btBulletDynamicsCommon.h>
#include <RegisteredMetaTypes.h> #include <RegisteredMetaTypes.h>
#include <DependencyManager.h> #include <DependencyManager.h>
#include <PhysicsEngine.h>
#include <Pick.h> #include <Pick.h>
/**jsdoc /**jsdoc
@ -277,12 +277,12 @@ public slots:
static constexpr unsigned int INTERSECTED_HUD() { return IntersectionType::HUD; } static constexpr unsigned int INTERSECTED_HUD() { return IntersectionType::HUD; }
// Set to allow CollisionPicks to have access to the physics engine // Set to allow CollisionPicks to have access to the physics engine
void setCollisionWorld(const btCollisionWorld* collisionWorld) { void setPhysicsEngine(PhysicsEnginePointer physicsEngine) {
_collisionWorld = collisionWorld; _physicsEngine = physicsEngine;
} }
protected: protected:
const btCollisionWorld* _collisionWorld; PhysicsEnginePointer _physicsEngine;
}; };
#endif // hifi_PickScriptingInterface_h #endif // hifi_PickScriptingInterface_h

View file

@ -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<btCollisionShape*>(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<EntityIntersection> 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<const btRigidBody*>(otherBody);
const btMotionState* motionStateCandidate = collisionCandidate->getMotionState();
const ObjectMotionState* candidate = dynamic_cast<const ObjectMotionState*>(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<EntityIntersection> 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;
}

View file

@ -43,6 +43,26 @@ public:
void* _b; // ObjectMotionState pointer 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<ContactKey, ContactInfo>; using ContactMap = std::map<ContactKey, ContactInfo>;
using CollisionEvents = std::vector<Collision>; using CollisionEvents = std::vector<Collision>;
@ -105,6 +125,9 @@ public:
void setShowBulletConstraints(bool value); void setShowBulletConstraints(bool value);
void setShowBulletConstraintLimits(bool value); void setShowBulletConstraintLimits(bool value);
// Function for getting colliding ObjectMotionStates in the world of specified type
std::vector<EntityIntersection> getCollidingInRegion(MotionStateType desiredObjectType, const ShapeInfo& regionShapeInfo, const Transform& regionTransform) const;
private: private:
QList<EntityDynamicPointer> removeDynamicsForBody(btRigidBody* body); QList<EntityDynamicPointer> removeDynamicsForBody(btRigidBody* body);
void addObjectToDynamicsWorld(ObjectMotionState* motionState); void addObjectToDynamicsWorld(ObjectMotionState* motionState);