From 726928c14c061d958b96362d73e88efda367ccdf Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 19 Jul 2016 09:38:54 -0700 Subject: [PATCH] creae collision Geometry from mesh --- libraries/entities-renderer/CMakeLists.txt | 2 +- .../src/RenderableModelEntityItem.cpp | 17 ++++++++++++- .../src/RenderableModelEntityItem.h | 1 + .../src/model-networking/ModelCache.h | 7 +++--- .../physics/src/CollisionRenderMeshCache.cpp | 24 ++++++++++++------- .../physics/src/CollisionRenderMeshCache.h | 4 +++- libraries/render-utils/src/Model.cpp | 22 +++++++++++++++++ libraries/render-utils/src/Model.h | 3 ++- 8 files changed, 64 insertions(+), 16 deletions(-) diff --git a/libraries/entities-renderer/CMakeLists.txt b/libraries/entities-renderer/CMakeLists.txt index 0063f4a701..9218b94fe1 100644 --- a/libraries/entities-renderer/CMakeLists.txt +++ b/libraries/entities-renderer/CMakeLists.txt @@ -1,7 +1,7 @@ set(TARGET_NAME entities-renderer) AUTOSCRIBE_SHADER_LIB(gpu model procedural render render-utils) setup_hifi_library(Widgets Network Script) -link_hifi_libraries(shared gpu procedural model model-networking script-engine render render-utils) +link_hifi_libraries(shared gpu procedural model model-networking script-engine render render-utils physics) target_bullet() diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 2ff5e236fc..cdf94017ff 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -917,8 +918,22 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) { } } +static CollisionRenderMeshCache collisionMeshCache; + void RenderableModelEntityItem::setCollisionShape(const btCollisionShape* shape) { - // TODO: generate collision mesh and update _model + const void* key = static_cast(shape); + if (_collisionMeshKey != key) { + if (_collisionMeshKey) { + // releasing the shape is not strictly necessary, but + // we do it as hint to the cache's garbage collection system + collisionMeshCache.releaseMesh(_collisionMeshKey); + } + _collisionMeshKey = key; + model::MeshPointer mesh = collisionMeshCache.getMesh(_collisionMeshKey); + if (_model) { + _model->setCollisionMesh(mesh); + } + } } bool RenderableModelEntityItem::contains(const glm::vec3& point) const { diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 412cb6f296..1f44260f65 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -119,6 +119,7 @@ private: bool getAnimationFrame(); bool _needsJointSimulation { false }; + const void* _collisionMeshKey { nullptr }; }; #endif // hifi_RenderableModelEntityItem_h diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index 5c1aafdd45..fa93d3c899 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -111,13 +111,12 @@ public: QUrl getURL() const { return (bool)_resource ? _resource->getURL() : QUrl(); } -signals: - void finished(bool success); - -private: void startWatching(); void stopWatching(); +signals: + void finished(bool success); + private slots: void resourceFinished(bool success); void resourceRefreshed(); diff --git a/libraries/physics/src/CollisionRenderMeshCache.cpp b/libraries/physics/src/CollisionRenderMeshCache.cpp index 14386c6f48..22f0b986ab 100644 --- a/libraries/physics/src/CollisionRenderMeshCache.cpp +++ b/libraries/physics/src/CollisionRenderMeshCache.cpp @@ -67,12 +67,16 @@ void copyShapeToMesh(const btTransform& transform, const btConvexShape* shape, m } } -model::MeshPointer createMeshFromShape(const btCollisionShape* shape) { +model::MeshPointer createMeshFromShape(const void* pointer) { model::MeshPointer mesh; - if (!shape) { + if (!pointer) { return mesh; } + // pointer must actually be a const btCollisionShape*, but it only + // needs to be valid here when its render mesh is created. + const btCollisionShape* shape = static_cast(pointer); + int32_t shapeType = shape->getShapeType(); if (shapeType == (int32_t)COMPOUND_SHAPE_PROXYTYPE || shape->isConvex()) { // create the mesh and allocate buffers for it @@ -84,7 +88,7 @@ model::MeshPointer createMeshFromShape(const btCollisionShape* shape) { if (shapeType == (int32_t)COMPOUND_SHAPE_PROXYTYPE) { const btCompoundShape* compoundShape = static_cast(shape); int32_t numSubShapes = compoundShape->getNumChildShapes(); - for (int i = 0; i < numSubShapes; ++i) { + for (int32_t i = 0; i < numSubShapes; ++i) { const btCollisionShape* childShape = compoundShape->getChildShape(i); if (childShape->isConvex()) { const btConvexShape* convexShape = static_cast(childShape); @@ -122,6 +126,10 @@ model::MeshPointer CollisionRenderMeshCache::getMesh(CollisionRenderMeshCache::K mesh = itr->second; } } + const uint32_t MAX_NUM_PENDING_GARBAGE = 20; + if (_pendingGarbage.size() > MAX_NUM_PENDING_GARBAGE) { + collectGarbage(); + } return mesh; } @@ -131,19 +139,19 @@ bool CollisionRenderMeshCache::releaseMesh(CollisionRenderMeshCache::Key key) { } CollisionMeshMap::const_iterator itr = _meshMap.find(key); if (itr != _meshMap.end()) { + // we hold at least one reference, and the outer scope also holds at least one + // so we assert that the reference count is not 1 assert((*itr).second.use_count() != 1); + _pendingGarbage.push_back(key); - if ((*itr).second.use_count() == 1) { - // we hold all of the references inside the cache so we'll try to delete later - } return true; } return false; } void CollisionRenderMeshCache::collectGarbage() { - int numShapes = _pendingGarbage.size(); - for (int i = 0; i < numShapes; ++i) { + uint32_t numShapes = _pendingGarbage.size(); + for (int32_t i = 0; i < numShapes; ++i) { CollisionRenderMeshCache::Key key = _pendingGarbage[i]; CollisionMeshMap::const_iterator itr = _meshMap.find(key); if (itr != _meshMap.end()) { diff --git a/libraries/physics/src/CollisionRenderMeshCache.h b/libraries/physics/src/CollisionRenderMeshCache.h index ad3c86562b..0c789f3da9 100644 --- a/libraries/physics/src/CollisionRenderMeshCache.h +++ b/libraries/physics/src/CollisionRenderMeshCache.h @@ -18,6 +18,7 @@ #include +/* class btCollisionShape; namespace std { @@ -28,10 +29,11 @@ namespace std { } }; } +*/ class CollisionRenderMeshCache { public: - using Key = const btCollisionShape*; + using Key = const void*; // must actually be a const btCollisionShape* CollisionRenderMeshCache(); ~CollisionRenderMeshCache(); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index a6e1bb53f4..35e40403cf 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1336,6 +1336,28 @@ bool Model::initWhenReady(render::ScenePointer scene) { return false; } +class CollisionRenderGeometry : public Geometry { +public: + CollisionRenderGeometry(model::MeshPointer mesh) { + _fbxGeometry = std::make_shared(); + std::shared_ptr meshes = std::make_shared(); + meshes->push_back(mesh); + _meshes = meshes; + _meshParts = std::shared_ptr(); + } +}; + +void Model::setCollisionMesh(model::MeshPointer mesh) { + _collisionWatcher.stopWatching(); + _collisionGeometry = std::make_shared(mesh); + + if (_showCollisionHull) { + // TODO: need to trigger: + // (a) reconstruction of RenderItems + // (b) and reinsertion into scene if we are showing collision geometry + } +} + ModelBlender::ModelBlender() : _pendingBlenders(0) { } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 15c8e0326a..d6580b8413 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -249,6 +249,7 @@ public slots: signals: void setURLFinished(bool success); void setCollisionModelURLFinished(bool success); + void setCollisionMesh(model::MeshPointer mesh); protected: @@ -282,7 +283,7 @@ protected: bool getJointPosition(int jointIndex, glm::vec3& position) const; Geometry::Pointer _renderGeometry; // only ever set by its watcher - Geometry::Pointer _collisionGeometry; // only ever set by its watcher + Geometry::Pointer _collisionGeometry; GeometryResourceWatcher _renderWatcher; GeometryResourceWatcher _collisionWatcher;