// // CharacterGhostObject.cpp // libraries/physics/src // // Created by Andrew Meadows 2016.08.26 // Copyright 2016 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "CharacterGhostObject.h" #include #include #include #include "CharacterRayResult.h" #include "CharacterGhostShape.h" CharacterGhostObject::~CharacterGhostObject() { removeFromWorld(); if (_ghostShape) { delete _ghostShape; _ghostShape = nullptr; setCollisionShape(nullptr); } } void CharacterGhostObject::setCollisionGroupAndMask(int32_t group, int32_t mask) { _collisionFilterGroup = group; _collisionFilterMask = mask; // TODO: if this probe is in the world reset ghostObject overlap cache } void CharacterGhostObject::getCollisionGroupAndMask(int32_t& group, int32_t& mask) const { group = _collisionFilterGroup; mask = _collisionFilterMask; } void CharacterGhostObject::setRadiusAndHalfHeight(btScalar radius, btScalar halfHeight) { _radius = radius; _halfHeight = halfHeight; } // override of btCollisionObject::setCollisionShape() void CharacterGhostObject::setCharacterShape(btConvexHullShape* shape) { assert(shape); // we create our own shape with an expanded Aabb for more reliable sweep tests if (_ghostShape) { delete _ghostShape; } _ghostShape = new CharacterGhostShape(static_cast(shape)); setCollisionShape(_ghostShape); } void CharacterGhostObject::setCollisionWorld(btCollisionWorld* world) { if (world != _world) { removeFromWorld(); _world = world; addToWorld(); } } bool CharacterGhostObject::rayTest(const btVector3& start, const btVector3& end, CharacterRayResult& result) const { if (_world && _inWorld) { btGhostObject::rayTest(start, end, result); } return result.hasHit(); } void CharacterGhostObject::refreshOverlappingPairCache() { assert(_world && _inWorld); btVector3 minAabb, maxAabb; getCollisionShape()->getAabb(getWorldTransform(), minAabb, maxAabb); // this updates both pairCaches: world broadphase and ghostobject _world->getBroadphase()->setAabb(getBroadphaseHandle(), minAabb, maxAabb, _world->getDispatcher()); } void CharacterGhostObject::removeFromWorld() { if (_world && _inWorld) { _world->removeCollisionObject(this); _inWorld = false; } } void CharacterGhostObject::addToWorld() { if (_world && !_inWorld) { assert(getCollisionShape()); setCollisionFlags(getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE); _world->addCollisionObject(this, _collisionFilterGroup, _collisionFilterMask); _inWorld = true; } }