diff --git a/libraries/physics/src/PhysicsWorld.cpp b/libraries/physics/src/PhysicsWorld.cpp new file mode 100644 index 0000000000..9364b77e65 --- /dev/null +++ b/libraries/physics/src/PhysicsWorld.cpp @@ -0,0 +1,23 @@ +// +// PhysicsWorld.cpp +// libraries/physcis/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 +// + +#include "PhysicsWorld.h" + +PhysicsWorld::~PhysicsWorld() { +} + +void PhysicsWorld::init() { + _collisionConfig = new btDefaultCollisionConfiguration(); + _collisionDispatcher = new btCollisionDispatcher(_collisionConfig); + _broadphaseFilter = new btDbvtBroadphase(); + _constraintSolver = new btSequentialImpulseConstraintSolver; + _dynamicsWorld = new btDiscreteDynamicsWorld(_collisionDispatcher, _broadphaseFilter, _constraintSolver, _collisionConfig); +} diff --git a/libraries/physics/src/PhysicsWorld.h b/libraries/physics/src/PhysicsWorld.h new file mode 100644 index 0000000000..778e5280d8 --- /dev/null +++ b/libraries/physics/src/PhysicsWorld.h @@ -0,0 +1,41 @@ +// +// PhysicsWorld.h +// libraries/physcis/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_PhysicsWorld_h +#define hifi_PhysicsWorld_h + +#ifdef USE_BULLET_PHYSICS + +#include + +class PhysicsWorld { +public: + + PhysicsWorld() : _collisionConfig(NULL), _collisionDispatcher(NULL), + _broadphaseFilter(NULL), _constraintSolver(NULL), _dynamicsWorld(NULL) { } + + ~PhysicsWorld(); + + void init(); + +protected: + btDefaultCollisionConfiguration* _collisionConfig; + btCollisionDispatcher* _collisionDispatcher; + btBroadphaseInterface* _broadphaseFilter; + btSequentialImpulseConstraintSolver* _constraintSolver; + btDiscreteDynamicsWorld* _dynamicsWorld; + +private: +}; + + +#endif // USE_BULLET_PHYSICS +#endif // hifi_PhysicsWorld_h diff --git a/libraries/physics/src/ShapeManager.cpp b/libraries/physics/src/ShapeManager.cpp new file mode 100644 index 0000000000..99c1d8b2ef --- /dev/null +++ b/libraries/physics/src/ShapeManager.cpp @@ -0,0 +1,94 @@ +// +// ShapeManager.cpp +// libraries/physcis/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 +// + +#ifdef USE_BULLET_PHYSICS +#include "ShapeManager.h" + +ShapeManager::ShapeManager() { +} + +ShapeManager::~ShapeManager() { + int numShapes = _shapeMap.size(); + for (int i = 0; i < numShapes; ++i) { + ShapeReference* shapeRef = _shapeMap.getAtIndex(i); + delete shapeRef->_shape; + } +} + + +btCollisionShape* ShapeManager::getShape(const ShapeInfo& info) { + int key = info.getHash(); + ShapeReference* shapeRef = _shapeMap.find(key); + if (shapeRef) { + shapeRef->_refCount++; + return shapeRef->_shape; + } else { + btCollisionShape* shape = info.createShape(); + if (shape) { + ShapeReference newRef; + newRef._refCount = 1; + newRef._shape = shape; + _shapeMap.insert(key, newRef); + } + return shape; + } +} + +bool ShapeManager::releaseShape(const ShapeInfo& info) { + int key = info.getHash(); + ShapeReference* shapeRef = _shapeMap.find(key); + if (shapeRef) { + if (shapeRef->_refCount > 0) { + shapeRef->_refCount--; + if (shapeRef->_refCount == 0) { + _pendingGarbage.push_back(key); + const int MAX_GARBAGE_CAPACITY = 127; + if (_pendingGarbage.size() > MAX_GARBAGE_CAPACITY) { + collectGarbage(); + } + } + return true; + } else { + // attempt to remove shape that has no refs + assert(false); + } + } else { + // attempt to remove unmanaged shape + assert(false); + } + return false; +} + +void ShapeManager::collectGarbage() { + int numShapes = _pendingGarbage.size(); + for (int i = 0; i < numShapes; ++i) { + int key = _pendingGarbage[i]; + ShapeReference* shapeRef = _shapeMap.find(key); + assert(shapeRef != NULL); + if (shapeRef->_refCount == 0) { + delete shapeRef->_shape; + _shapeMap.remove(key); + } + } + _pendingGarbage.clear(); +} + +int ShapeManager::getNumReferences(const ShapeInfo& info) const { + int key = info.getHash(); + const ShapeReference* shapeRef = _shapeMap.find(key); + if (shapeRef) { + return shapeRef->_refCount; + } + return -1; +} + + +#endif // USE_BULLET_PHYSICS diff --git a/libraries/physics/src/ShapeManager.h b/libraries/physics/src/ShapeManager.h new file mode 100644 index 0000000000..0a1f75c7c8 --- /dev/null +++ b/libraries/physics/src/ShapeManager.h @@ -0,0 +1,88 @@ +// +// ShapeManager.h +// libraries/physcis/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_ShapeManager_h +#define hifi_ShapeManager_h + +#ifdef USE_BULLET_PHYSICS + +#include +#include + +struct ShapeInfo { + int _type; + btVector3 _size; + + ShapeInfo() : _type(BOX_SHAPE_PROXYTYPE), _size(1.0f, 1.0f, 1.0f) {} + + virtual int getHash() const { + // successfully multiply components of size by primes near 256 and convert to U32 + unsigned int key = (unsigned int)(241.0f * _size.getX()) + + 241 * (unsigned int)(251.0f * _size.getY()) + + (241 * 251) * (unsigned int)(257.0f * _size.getZ()); + // then scramble the results + key += ~(key << 15); + key ^= (key >> 10); + key += (key << 3); + key ^= (key >> 6); + key += ~(key << 11); + key ^= (key >> 16); + // finally XOR with type + key ^= _type; + return key; + } + + virtual btCollisionShape* createShape() const { + const float MAX_SHAPE_DIMENSION = 100.0f; + const float MIN_SHAPE_DIMENSION = 0.01f; + for (int i = 0; i < 3; ++i) { + float side = _size[i]; + if (side > MAX_SHAPE_DIMENSION || side < MIN_SHAPE_DIMENSION) { + return NULL; + } + } + // default behavior is to create a btBoxShape + return new btBoxShape(0.5f * _size); + } +}; + +struct ShapeReference { + int _refCount; + btCollisionShape* _shape; + ShapeReference() : _refCount(0), _shape(NULL) {} +}; + +class ShapeManager { +public: + + ShapeManager(); + ~ShapeManager(); + + /// \return pointer to shape + btCollisionShape* getShape(const ShapeInfo& info); + + /// \return true if shape was found and released + bool releaseShape(const ShapeInfo& info); + + /// delete shapes that have zero references + void collectGarbage(); + + // validation methods + int getNumShapes() const { return _shapeMap.size(); } + int getNumReferences(const ShapeInfo& info) const; + +private: + btHashMap _shapeMap; + btAlignedObjectArray _pendingGarbage; +}; + +#endif // USE_BULLET_PHYSICS +#endif // hifi_ShapeManager_h