From 996b71fa9a09c69cd4f9da652ff8cc25ef8f41d5 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 23 Oct 2017 10:44:14 -0700 Subject: [PATCH 1/3] avoid incorrect ShapeManager dupes for compound shapes --- libraries/shared/src/ShapeInfo.cpp | 32 ++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/libraries/shared/src/ShapeInfo.cpp b/libraries/shared/src/ShapeInfo.cpp index a556548b25..f3dd9d11a6 100644 --- a/libraries/shared/src/ShapeInfo.cpp +++ b/libraries/shared/src/ShapeInfo.cpp @@ -46,6 +46,8 @@ void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString } break; case SHAPE_TYPE_COMPOUND: + case SHAPE_TYPE_SIMPLE_HULL: + case SHAPE_TYPE_SIMPLE_COMPOUND: case SHAPE_TYPE_STATIC_MESH: _url = QUrl(url); break; @@ -250,16 +252,26 @@ const DoubleHashKey& ShapeInfo::getHash() const { } _doubleHashKey.setHash2(hash); - if (_type == SHAPE_TYPE_COMPOUND || _type == SHAPE_TYPE_STATIC_MESH) { - QString url = _url.toString(); - if (!url.isEmpty()) { - // fold the urlHash into both parts - QByteArray baUrl = url.toLocal8Bit(); - const char *cUrl = baUrl.data(); - uint32_t urlHash = qChecksum(cUrl, baUrl.count()); - _doubleHashKey.setHash(_doubleHashKey.getHash() ^ urlHash); - _doubleHashKey.setHash2(_doubleHashKey.getHash2() ^ urlHash); - } + QString url = _url.toString(); + if (!url.isEmpty()) { + // fold the urlHash into both parts + QByteArray baUrl = url.toLocal8Bit(); + uint32_t urlHash = qChecksum(baUrl.data(), baUrl.size()); + _doubleHashKey.setHash(_doubleHashKey.getHash() ^ urlHash); + _doubleHashKey.setHash2(_doubleHashKey.getHash2() ^ urlHash); + } + + uint32_t numHulls = 0; + if (_type == SHAPE_TYPE_COMPOUND || _type == SHAPE_TYPE_SIMPLE_COMPOUND) { + numHulls = (uint32_t)_pointCollection.size(); + } else if (_type == SHAPE_TYPE_SIMPLE_HULL) { + numHulls = 1; + } + if (numHulls > 0) { + hash = DoubleHashKey::hashFunction(numHulls, primeIndex++); + _doubleHashKey.setHash(_doubleHashKey.getHash() ^ hash); + hash = DoubleHashKey::hashFunction2(numHulls); + _doubleHashKey.setHash2(_doubleHashKey.getHash2() ^ hash); } } return _doubleHashKey; From 29efe53f74574488cda7e5543c3c8e0a7ab0bb77 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 23 Oct 2017 17:55:19 -0700 Subject: [PATCH 2/3] repair debug rendering of collision shapes --- .../src/RenderableModelEntityItem.cpp | 70 ++++++++++++------- .../src/RenderableModelEntityItem.h | 10 ++- 2 files changed, 53 insertions(+), 27 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index ff5bce4607..7db19704b4 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -695,12 +695,8 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) { void RenderableModelEntityItem::setCollisionShape(const btCollisionShape* shape) { const void* key = static_cast(shape); if (_collisionMeshKey != key) { - if (_collisionMeshKey) { - collisionMeshCache.releaseMesh(_collisionMeshKey); - } _collisionMeshKey = key; - // toggle _showCollisionGeometry forces re-evaluation later - _showCollisionGeometry = !_showCollisionGeometry; + emit requestCollisionGeometryUpdate(); } } @@ -1103,6 +1099,10 @@ bool ModelEntityRenderer::needsRenderUpdate() const { if (model->getRenderItemsNeedUpdate()) { return true; } + + if (_needsCollisionGeometryUpdate) { + return true; + } } return Parent::needsRenderUpdate(); } @@ -1169,6 +1169,15 @@ bool ModelEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin return false; } +void ModelEntityRenderer::setCollisionMeshKey(const void*key) { + if (key != _collisionMeshKey) { + if (_collisionMeshKey) { + collisionMeshCache.releaseMesh(_collisionMeshKey); + } + _collisionMeshKey = key; + } +} + void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__); if (_hasModel != entity->hasModel()) { @@ -1201,6 +1210,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce model = std::make_shared(nullptr, entity.get()); connect(model.get(), &Model::setURLFinished, this, &ModelEntityRenderer::requestRenderUpdate); connect(model.get(), &Model::requestRenderUpdate, this, &ModelEntityRenderer::requestRenderUpdate); + connect(entity.get(), &RenderableModelEntityItem::requestCollisionGeometryUpdate, this, &ModelEntityRenderer::flagForCollisionGeometryUpdate); model->setLoadingPriority(EntityTreeRenderer::getEntityLoadingPriority(*entity)); model->init(); entity->setModel(model); @@ -1259,6 +1269,26 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce } // TODO? early exit here when not visible? + if (_needsCollisionGeometryUpdate) { + setCollisionMeshKey(entity->getCollisionMeshKey()); + _needsCollisionGeometryUpdate = false; + ShapeType type = entity->getShapeType(); + if (_showCollisionGeometry && type != SHAPE_TYPE_STATIC_MESH && type != SHAPE_TYPE_NONE) { + // NOTE: it is OK if _collisionMeshKey is nullptr + model::MeshPointer mesh = collisionMeshCache.getMesh(_collisionMeshKey); + // NOTE: the model will render the collisionGeometry if it has one + _model->setCollisionMesh(mesh); + } else { + if (_collisionMeshKey) { + // release mesh + collisionMeshCache.releaseMesh(_collisionMeshKey); + } + // clear model's collision geometry + model::MeshPointer mesh = nullptr; + _model->setCollisionMesh(mesh); + } + } + { DETAILED_PROFILE_RANGE(simulation_physics, "Fixup"); if (model->needsFixupInScene()) { @@ -1297,6 +1327,11 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce } } +void ModelEntityRenderer::flagForCollisionGeometryUpdate() { + _needsCollisionGeometryUpdate = true; + emit requestRenderUpdate(); +} + // NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items void ModelEntityRenderer::doRender(RenderArgs* args) { DETAILED_PROFILE_RANGE(render_detail, "MetaModelRender"); @@ -1327,28 +1362,11 @@ void ModelEntityRenderer::doRender(RenderArgs* args) { // Remap textures for the next frame to avoid flicker // remapTextures(); -#if 0 - // update whether the model should be showing collision mesh (this may flag for fixupInScene) - bool showingCollisionGeometry = (bool)(args->_debugFlags & (int)RenderArgs::RENDER_DEBUG_HULLS); - if (showingCollisionGeometry != _showCollisionGeometry) { - ShapeType type = _entity->getShapeType(); - _showCollisionGeometry = showingCollisionGeometry; - if (_showCollisionGeometry && type != SHAPE_TYPE_STATIC_MESH && type != SHAPE_TYPE_NONE) { - // NOTE: it is OK if _collisionMeshKey is nullptr - model::MeshPointer mesh = collisionMeshCache.getMesh(_collisionMeshKey); - // NOTE: the model will render the collisionGeometry if it has one - _model->setCollisionMesh(mesh); - } else { - // release mesh - if (_collisionMeshKey) { - collisionMeshCache.releaseMesh(_collisionMeshKey); - } - // clear model's collision geometry - model::MeshPointer mesh = nullptr; - _model->setCollisionMesh(mesh); - } + bool showCollisionGeometry = (bool)(args->_debugFlags & (int)RenderArgs::RENDER_DEBUG_HULLS); + if (showCollisionGeometry != _showCollisionGeometry) { + _showCollisionGeometry = showCollisionGeometry; + flagForCollisionGeometryUpdate(); } -#endif } void ModelEntityRenderer::mapJoints(const TypedEntityPointer& entity, const QStringList& modelJointNames) { diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index a50ca63382..0272bed575 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -50,6 +50,8 @@ private: }; class RenderableModelEntityItem : public ModelEntityWrapper { + Q_OBJECT + friend class render::entities::ModelEntityRenderer; using Parent = ModelEntityWrapper; public: @@ -105,6 +107,10 @@ public: virtual QStringList getJointNames() const override; bool getMeshes(MeshProxyList& result) override; + const void* getCollisionMeshKey() const { return _collisionMeshKey; } + +signals: + void requestCollisionGeometryUpdate(); private: bool needsUpdateModelBounds() const; @@ -117,7 +123,6 @@ private: QVariantMap _originalTextures; bool _dimensionsInitialized { true }; bool _needsJointSimulation { false }; - bool _showCollisionGeometry { false }; const void* _collisionMeshKey { nullptr }; }; @@ -141,6 +146,8 @@ protected: virtual bool needsRenderUpdate() const override; virtual void doRender(RenderArgs* args) override; virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override; + void flagForCollisionGeometryUpdate(); + void setCollisionMeshKey(const void* key); private: void animate(const TypedEntityPointer& entity); @@ -163,6 +170,7 @@ private: bool _needsJointSimulation{ false }; bool _showCollisionGeometry{ false }; + bool _needsCollisionGeometryUpdate{ false }; const void* _collisionMeshKey{ nullptr }; // used on client side From 27f4d182d97c9c7b74b757c6a8bdab78e7274083 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 23 Oct 2017 17:56:26 -0700 Subject: [PATCH 3/3] fix scale of rendered collision geometry --- libraries/render-utils/src/Model.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 964a1961d6..97f62a3ce0 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -235,7 +235,6 @@ void Model::updateRenderItems() { self->updateClusterMatrices(); Transform modelTransform = self->getTransform(); - Transform physicsTransform = modelTransform; modelTransform.setScale(glm::vec3(1.0f)); uint32_t deleteGeometryCounter = self->_deleteGeometryCounter; @@ -259,13 +258,12 @@ void Model::updateRenderItems() { }); } - // collision mesh does not share the same unit scale as the FBX file's mesh: only apply offset Transform collisionMeshOffset; collisionMeshOffset.setIdentity(); foreach(auto itemID, self->_collisionRenderItemsMap.keys()) { - transaction.updateItem(itemID, [physicsTransform, collisionMeshOffset](MeshPartPayload& data) { + transaction.updateItem(itemID, [modelTransform, collisionMeshOffset](MeshPartPayload& data) { // update the model transform for this render item. - data.updateTransform(physicsTransform, collisionMeshOffset); + data.updateTransform(modelTransform, collisionMeshOffset); }); }