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>();
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,

View file

@ -271,12 +271,9 @@ PickResultPointer CollisionPick::getEntityIntersection(const CollisionRegion& pi
// Cannot compute result
return std::make_shared<CollisionPickResult>();
}
auto entityCollisionCallback = AllObjectMotionStatesCallback<EntityMotionState>(pick.shapeInfo, pick.transform);
btCollisionWorld* collisionWorld = const_cast<btCollisionWorld*>(_collisionWorld);
collisionWorld->contactTest(&entityCollisionCallback.collisionObject, entityCollisionCallback);
return std::make_shared<CollisionPickResult>(pick, entityCollisionCallback.intersectingObjects, std::vector<CollisionPickResult::EntityIntersection>());
const auto& intersectingEntities = _physicsEngine->getCollidingInRegion(MOTIONSTATE_TYPE_ENTITY, pick.shapeInfo, pick.transform);
return std::make_shared<CollisionPickResult>(pick, intersectingEntities, std::vector<EntityIntersection>());
}
PickResultPointer CollisionPick::getOverlayIntersection(const CollisionRegion& pick) {
@ -289,70 +286,10 @@ PickResultPointer CollisionPick::getAvatarIntersection(const CollisionRegion& pi
return std::make_shared<CollisionPickResult>();
}
auto avatarCollisionCallback = AllObjectMotionStatesCallback<AvatarMotionState>(pick.shapeInfo, pick.transform);
btCollisionWorld* collisionWorld = const_cast<btCollisionWorld*>(_collisionWorld);
collisionWorld->contactTest(&avatarCollisionCallback.collisionObject, avatarCollisionCallback);
return std::make_shared<CollisionPickResult>(pick, std::vector<CollisionPickResult::EntityIntersection>(), avatarCollisionCallback.intersectingObjects);
const auto& intersectingAvatars = _physicsEngine->getCollidingInRegion(MOTIONSTATE_TYPE_AVATAR, pick.shapeInfo, pick.transform);
return std::make_shared<CollisionPickResult>(pick, std::vector<EntityIntersection>(), 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<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
#define hifi_CollisionPick_h
#include <btBulletDynamicsCommon.h>
#include <avatar/AvatarMotionState.h>
#include <EntityMotionState.h>
#include <BulletUtil.h>
#include <PhysicsEngine.h>
#include <model-networking/ModelCache.h>
#include <RegisteredMetaTypes.h>
#include <Pick.h>
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<CollisionRegion> {
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<GeometryResource> resource);
CollisionRegion _mathPick;
const btCollisionWorld* _collisionWorld;
PhysicsEnginePointer _physicsEngine;
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

View file

@ -157,7 +157,7 @@ unsigned int PickScriptingInterface::createCollisionPick(const QVariant& propert
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) {

View file

@ -9,10 +9,10 @@
#define hifi_PickScriptingInterface_h
#include <QtCore/QObject>
#include <btBulletDynamicsCommon.h>
#include <RegisteredMetaTypes.h>
#include <DependencyManager.h>
#include <PhysicsEngine.h>
#include <Pick.h>
/**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

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
};
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 CollisionEvents = std::vector<Collision>;
@ -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<EntityIntersection> getCollidingInRegion(MotionStateType desiredObjectType, const ShapeInfo& regionShapeInfo, const Transform& regionTransform) const;
private:
QList<EntityDynamicPointer> removeDynamicsForBody(btRigidBody* body);
void addObjectToDynamicsWorld(ObjectMotionState* motionState);