201 lines · 7.3 KB · C
RawDownload
////  PhysicsEngine.h//  libraries/physics/src////  Created by Andrew Meadows 2014.10.29//  Copyright 2014 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// #ifndef hifi_PhysicsEngine_h#define hifi_PhysicsEngine_h #include <stdint.h>#include <set>#include <vector> #include <QUuid>#include <btBulletDynamicsCommon.h>#include <BulletCollision/CollisionDispatch/btGhostObject.h> #include "BulletUtil.h"#include "ContactInfo.h"#include "ObjectMotionState.h"#include "ThreadSafeDynamicsWorld.h"#include "ObjectAction.h"#include "ObjectConstraint.h" const float HALF_SIMULATION_EXTENT = 512.0f; // meters class CharacterController;class PhysicsDebugDraw; // simple class for keeping track of contactsclass ContactKey {public:    ContactKey() = delete;    ContactKey(void* a, void* b) : _a(a), _b(b) {}    bool operator<(const ContactKey& other) const { return _a < other._a || (_a == other._a && _b < other._b); }    bool operator==(const ContactKey& other) const { return _a == other._a && _b == other._b; }    void* _a; // ObjectMotionState pointer    void* _b; // ObjectMotionState pointer}; struct ContactTestResult {    ContactTestResult() = delete;     ContactTestResult(const ContactTestResult& contactTestResult) :        foundID(contactTestResult.foundID),        testCollisionPoint(contactTestResult.testCollisionPoint),        foundCollisionPoint(contactTestResult.foundCollisionPoint),        collisionNormal(contactTestResult.collisionNormal) {    }     ContactTestResult(const QUuid& foundID, const glm::vec3& testCollisionPoint, const glm::vec3& otherCollisionPoint, const glm::vec3& collisionNormal) :        foundID(foundID),        testCollisionPoint(testCollisionPoint),        foundCollisionPoint(otherCollisionPoint),        collisionNormal(collisionNormal) {    }     QUuid foundID;    // The deepest point of an intersection within the volume of the test shape, in world space.    glm::vec3 testCollisionPoint;    // The deepest point of an intersection within the volume of the found object, in world space.    glm::vec3 foundCollisionPoint;    // The normal vector of this intersection    glm::vec3 collisionNormal;}; using ContactMap = std::map<ContactKey, ContactInfo>;using CollisionEvents = std::vector<Collision>; class PhysicsEngine {public:    using ContactAddedCallback = bool (*)(btManifoldPoint& cp,            const btCollisionObjectWrapper* colObj0Wrap, int partId0, int index0,            const btCollisionObjectWrapper* colObj1Wrap, int partId1, int index1);     class Transaction {    public:        void clear() {            objectsToRemove.clear();            objectsToAdd.clear();            objectsToReinsert.clear();            activeStaticObjects.clear();        }        std::vector<ObjectMotionState*> objectsToRemove;        std::vector<ObjectMotionState*> objectsToAdd;        std::vector<ObjectMotionState*> objectsToReinsert;        std::vector<ObjectMotionState*> activeStaticObjects;    };     PhysicsEngine(const glm::vec3& offset);    ~PhysicsEngine();    void init();     uint32_t getNumSubsteps() const;    int32_t getNumCollisionObjects() const;     void removeObjects(const VectorOfMotionStates& objects);    void removeSetOfObjects(const SetOfMotionStates& objects); // only called during teardown     void addObjects(const VectorOfMotionStates& objects);    void changeObjects(const VectorOfMotionStates& objects);    void reinsertObject(ObjectMotionState* object);     void processTransaction(Transaction& transaction);     void stepSimulation();    void harvestPerformanceStats();    void printPerformanceStatsToFile(const QString& filename);    void updateContactMap();    void doOwnershipInfectionForConstraints();     bool hasOutgoingChanges() const { return _hasOutgoingChanges; }     /// \return reference to list of changed MotionStates.  The list is only valid until beginning of next simulation loop.    const VectorOfMotionStates& getChangedMotionStates();    const VectorOfMotionStates& getDeactivatedMotionStates() const { return _dynamicsWorld->getDeactivatedMotionStates(); }     /// \return reference to list of Collision events.  The list is only valid until beginning of next simulation loop.    const CollisionEvents& getCollisionEvents();     /// \brief prints timings for last frame if stats have been requested.    void dumpStatsIfNecessary();     /// \brief saves timings for last frame in filename    void saveNextPhysicsStats(QString filename);     /// \param offset position of simulation origin in domain-frame    void setOriginOffset(const glm::vec3& offset) { _originOffset = offset; }     /// \return position of simulation origin in domain-frame    const glm::vec3& getOriginOffset() const { return _originOffset; }     void setCharacterController(CharacterController* character);     void dumpNextStats() { _dumpNextStats = true; }     EntityDynamicPointer getDynamicByID(const QUuid& dynamicID) const;    bool addDynamic(EntityDynamicPointer dynamic);    void removeDynamic(const QUuid dynamicID);    void forEachDynamic(std::function<void(EntityDynamicPointer)> actor);     void setShowBulletWireframe(bool value);    void setShowBulletAABBs(bool value);    void setShowBulletContactPoints(bool value);    void setShowBulletConstraints(bool value);    void setShowBulletConstraintLimits(bool value);     // 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, float threshold = 0.0f) const;     void setContactAddedCallback(ContactAddedCallback cb);     btDiscreteDynamicsWorld* getDynamicsWorld() const { return _dynamicsWorld; }    void removeContacts(ObjectMotionState* motionState); private:    QList<EntityDynamicPointer> removeDynamicsForBody(btRigidBody* body);    void addObjectToDynamicsWorld(ObjectMotionState* motionState);     /// \brief bump any objects that touch this one, then remove contact info    void bumpAndPruneContacts(ObjectMotionState* motionState);     void doOwnershipInfection(const btCollisionObject* objectA, const btCollisionObject* objectB);     btClock _clock;    btDefaultCollisionConfiguration* _collisionConfig = NULL;    btCollisionDispatcher* _collisionDispatcher = NULL;    btBroadphaseInterface* _broadphaseFilter = NULL;    btSequentialImpulseConstraintSolver* _constraintSolver = NULL;    ThreadSafeDynamicsWorld* _dynamicsWorld = NULL;    btGhostPairCallback* _ghostPairCallback = NULL;    std::unique_ptr<PhysicsDebugDraw> _physicsDebugDraw;     ContactMap _contactMap;    CollisionEvents _collisionEvents;    QHash<QUuid, EntityDynamicPointer> _objectDynamics;    QHash<btRigidBody*, QSet<QUuid>> _objectDynamicsByBody;    std::set<btRigidBody*> _activeStaticBodies;    QString _statsFilename;     glm::vec3 _originOffset;     CharacterController* _myAvatarController;     uint32_t _numContactFrames { 0 };     bool _dumpNextStats { false };    bool _saveNextStats { false };    bool _hasOutgoingChanges { false }; }; typedef std::shared_ptr<PhysicsEngine> PhysicsEnginePointer; #endif // hifi_PhysicsEngine_h