Add threshold parameter to collision pick with minimum of 0

This commit is contained in:
sabrina-shanman 2018-08-27 14:12:24 -07:00
parent 51683b0b53
commit 397b03d5d5
4 changed files with 28 additions and 11 deletions

View file

@ -391,7 +391,7 @@ PickResultPointer CollisionPick::getEntityIntersection(const CollisionRegion& pi
return std::make_shared<CollisionPickResult>(pick.toVariantMap(), CollisionPickResult::LOAD_STATE_NOT_LOADED, std::vector<ContactTestResult>(), std::vector<ContactTestResult>());
}
auto entityIntersections = _physicsEngine->contactTest(USER_COLLISION_MASK_ENTITIES, *pick.shapeInfo, pick.transform);
auto entityIntersections = _physicsEngine->contactTest(USER_COLLISION_MASK_ENTITIES, *pick.shapeInfo, pick.transform, USER_COLLISION_GROUP_DYNAMIC, pick.threshold);
filterIntersections(entityIntersections);
return std::make_shared<CollisionPickResult>(pick, CollisionPickResult::LOAD_STATE_LOADED, entityIntersections, std::vector<ContactTestResult>());
}
@ -406,7 +406,7 @@ PickResultPointer CollisionPick::getAvatarIntersection(const CollisionRegion& pi
return std::make_shared<CollisionPickResult>(pick, CollisionPickResult::LOAD_STATE_NOT_LOADED, std::vector<ContactTestResult>(), std::vector<ContactTestResult>());
}
auto avatarIntersections = _physicsEngine->contactTest(USER_COLLISION_MASK_AVATARS, *pick.shapeInfo, pick.transform);
auto avatarIntersections = _physicsEngine->contactTest(USER_COLLISION_MASK_AVATARS, *pick.shapeInfo, pick.transform, USER_COLLISION_GROUP_DYNAMIC, pick.threshold);
filterIntersections(avatarIntersections);
return std::make_shared<CollisionPickResult>(pick, CollisionPickResult::LOAD_STATE_LOADED, std::vector<ContactTestResult>(), avatarIntersections);
}

View file

@ -898,11 +898,12 @@ void PhysicsEngine::setShowBulletConstraintLimits(bool value) {
}
struct AllContactsCallback : public btCollisionWorld::ContactResultCallback {
AllContactsCallback(int32_t mask, int32_t group, const ShapeInfo& shapeInfo, const Transform& transform, btCollisionObject* myAvatarCollisionObject) :
AllContactsCallback(int32_t mask, int32_t group, const ShapeInfo& shapeInfo, const Transform& transform, btCollisionObject* myAvatarCollisionObject, float threshold) :
btCollisionWorld::ContactResultCallback(),
collisionObject(),
contacts(),
myAvatarCollisionObject(myAvatarCollisionObject) {
myAvatarCollisionObject(myAvatarCollisionObject),
threshold(threshold) {
const btCollisionShape* collisionShape = ObjectMotionState::getShapeManager()->getShape(shapeInfo);
collisionObject.setCollisionShape(const_cast<btCollisionShape*>(collisionShape));
@ -924,8 +925,13 @@ struct AllContactsCallback : public btCollisionWorld::ContactResultCallback {
btCollisionObject collisionObject;
std::vector<ContactTestResult> contacts;
btCollisionObject* myAvatarCollisionObject;
btScalar threshold;
btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0, int partId0, int index0, const btCollisionObjectWrapper* colObj1, int partId1, int index1) override {
if (cp.m_distance1 > -threshold) {
return 0;
}
const btCollisionObject* otherBody;
btVector3 penetrationPoint;
btVector3 otherPenetrationPoint;
@ -968,14 +974,14 @@ protected:
}
};
std::vector<ContactTestResult> PhysicsEngine::contactTest(uint16_t mask, const ShapeInfo& regionShapeInfo, const Transform& regionTransform, uint16_t group) const {
std::vector<ContactTestResult> PhysicsEngine::contactTest(uint16_t mask, const ShapeInfo& regionShapeInfo, const Transform& regionTransform, uint16_t group, float threshold) const {
// TODO: Give MyAvatar a motion state so we don't have to do this
btCollisionObject* myAvatarCollisionObject = nullptr;
if ((mask & USER_COLLISION_GROUP_MY_AVATAR) && _myAvatarController) {
myAvatarCollisionObject = _myAvatarController->getCollisionObject();
}
auto contactCallback = AllContactsCallback((int32_t)mask, (int32_t)group, regionShapeInfo, regionTransform, myAvatarCollisionObject);
auto contactCallback = AllContactsCallback((int32_t)mask, (int32_t)group, regionShapeInfo, regionTransform, myAvatarCollisionObject, threshold);
_dynamicsWorld->contactTest(&contactCallback.collisionObject, contactCallback);
return contactCallback.contacts;

View file

@ -142,7 +142,7 @@ public:
// Function for getting colliding objects in the world of specified type
// See PhysicsCollisionGroups.h for mask flags.
std::vector<ContactTestResult> contactTest(uint16_t mask, const ShapeInfo& regionShapeInfo, const Transform& regionTransform, uint16_t group = USER_COLLISION_GROUP_DYNAMIC) const;
std::vector<ContactTestResult> contactTest(uint16_t mask, const ShapeInfo& regionShapeInfo, const Transform& regionTransform, uint16_t group = USER_COLLISION_GROUP_DYNAMIC, float threshold = 0.0f) const;
private:
QList<EntityDynamicPointer> removeDynamicsForBody(btRigidBody* body);

View file

@ -254,12 +254,13 @@ public:
};
/**jsdoc
* A CollisionPick defines a volume for checking collisions in the physics simulation.
* A CollisionRegion defines a volume for checking collisions in the physics simulation.
* @typedef {object} CollisionPick
* @typedef {object} CollisionRegion
* @property {Shape} shape - The information about the collision region's size and shape.
* @property {Vec3} position - The position of the collision region, relative to a parent if defined.
* @property {Quat} orientation - The orientation of the collision region, relative to a parent if defined.
* @property {float} threshold - The approximate minimum penetration depth for a test object to be considered in contact with the collision region.
* @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, or an overlay.
* @property {number} parentJointIndex - The joint of the parent to parent to, for example, the joints on the model of an avatar. (default = 0, no joint)
* @property {string} joint - If "Mouse," parents the pick to the mouse. If "Head," parents the pick to MyAvatar's head. Otherwise, parents to the joint of the given name on MyAvatar.
@ -269,6 +270,7 @@ public:
CollisionRegion() { }
CollisionRegion(const CollisionRegion& collisionRegion) :
threshold(collisionRegion.threshold),
modelURL(collisionRegion.modelURL),
shapeInfo(std::make_shared<ShapeInfo>()),
transform(collisionRegion.transform)
@ -299,6 +301,10 @@ public:
}
}
if (pickVariant["threshold"].isValid()) {
threshold = glm::max(0.0f, pickVariant["threshold"].toFloat());
}
if (pickVariant["position"].isValid()) {
transform.setTranslation(vec3FromVariant(pickVariant["position"]));
}
@ -317,6 +323,8 @@ public:
collisionRegion["shape"] = shape;
collisionRegion["threshold"] = threshold;
collisionRegion["position"] = vec3toVariant(transform.getTranslation());
collisionRegion["orientation"] = quatToVariant(transform.getRotation());
@ -324,13 +332,15 @@ public:
}
operator bool() const override {
return !(glm::any(glm::isnan(transform.getTranslation())) ||
return !std::isnan(threshold) &&
!(glm::any(glm::isnan(transform.getTranslation())) ||
glm::any(glm::isnan(transform.getRotation())) ||
shapeInfo->getType() == SHAPE_TYPE_NONE);
}
bool operator==(const CollisionRegion& other) const {
return glm::all(glm::equal(transform.getTranslation(), other.transform.getTranslation())) &&
return threshold == other.threshold &&
glm::all(glm::equal(transform.getTranslation(), other.transform.getTranslation())) &&
glm::all(glm::equal(transform.getRotation(), other.transform.getRotation())) &&
glm::all(glm::equal(transform.getScale(), other.transform.getScale())) &&
shapeInfo->getType() == other.shapeInfo->getType() &&
@ -354,6 +364,7 @@ public:
// We can't compute the shapeInfo here without loading the model first, so we delegate that responsibility to the owning CollisionPick
std::shared_ptr<ShapeInfo> shapeInfo = std::make_shared<ShapeInfo>();
Transform transform;
float threshold;
};
namespace std {