diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index 200b620d1e..461b64a9e6 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -30,7 +30,7 @@ namespace render { } template <> void payloadRender(const RenderableEntityItemProxy::Pointer& payload, RenderArgs* args) { if (args) { - if (payload && payload->entity) { + if (payload && payload->entity && payload->entity->getVisible()) { payload->entity->render(args); } } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 9d762e53f6..7f2713da26 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -220,6 +220,8 @@ void RenderableModelEntityItem::render(RenderArgs* args) { _model->addToScene(scene, pendingChanges); } scene->enqueuePendingChanges(pendingChanges); + + _model->setVisibleInScene(getVisible(), scene); } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 975fb12624..ff13f0edf1 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -78,6 +78,7 @@ Model::Model(QObject* parent) : _showTrueJointTransforms(true), _lodDistance(0.0f), _pupilDilation(0.0f), + _isVisible(true), _url("http://invalid.com"), _blendNumber(0), _appliedBlendNumber(0), @@ -407,6 +408,7 @@ void Model::reset() { _meshGroupsKnown = false; _readyWhenAdded = false; // in case any of our users are using scenes + _needsReload = true; } bool Model::updateGeometry() { @@ -458,6 +460,7 @@ bool Model::updateGeometry() { _geometry = geometry; _meshGroupsKnown = false; _readyWhenAdded = false; // in case any of our users are using scenes + _needsReload = true; initJointStates(newJointStates); needToRebuild = true; } else if (_jointStates.isEmpty()) { @@ -680,6 +683,7 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) { _calculatedMeshTriangles.clear(); _calculatedMeshTriangles.resize(numberOfMeshes); _calculatedMeshPartBoxes.clear(); + _calculatedMeshPartOffet.clear(); for (int i = 0; i < numberOfMeshes; i++) { const FBXMesh& mesh = geometry.meshes.at(i); Extents scaledMeshExtents = calculateScaledOffsetExtents(mesh.meshExtents); @@ -688,9 +692,10 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) { if (pickAgainstTriangles) { QVector thisMeshTriangles; + qint64 partOffset = 0; for (int j = 0; j < mesh.parts.size(); j++) { const FBXMeshPart& part = mesh.parts.at(j); - + bool atLeastOnePointInBounds = false; AABox thisPartBounds; @@ -773,6 +778,11 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) { } } _calculatedMeshPartBoxes[QPair(i, j)] = thisPartBounds; + _calculatedMeshPartOffet[QPair(i, j)] = partOffset; + + partOffset += part.quadIndices.size() * sizeof(int); + partOffset += part.triangleIndices.size() * sizeof(int); + } _calculatedMeshTriangles[i] = thisMeshTriangles; _calculatedMeshPartBoxesValid = true; @@ -823,6 +833,9 @@ public: namespace render { template <> const ItemKey payloadGetKey(const TransparentMeshPart::Pointer& payload) { + if (!payload->model->isVisible()) { + return ItemKey::Builder().withInvisible().build(); + } return ItemKey::Builder::transparentShape(); } @@ -852,6 +865,9 @@ public: namespace render { template <> const ItemKey payloadGetKey(const OpaqueMeshPart::Pointer& payload) { + if (!payload->model->isVisible()) { + return ItemKey::Builder().withInvisible().build(); + } return ItemKey::Builder::opaqueShape(); } @@ -870,6 +886,18 @@ namespace render { } } +void Model::setVisibleInScene(bool newValue, std::shared_ptr scene) { + if (_isVisible != newValue) { + _isVisible = newValue; + + render::PendingChanges pendingChanges; + foreach (auto item, _renderItems.keys()) { + pendingChanges.resetItem(item, _renderItems[item]); + } + scene->enqueuePendingChanges(pendingChanges); + } +} + bool Model::addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges) { if (!_meshGroupsKnown && isLoadedWithTextures()) { @@ -891,7 +919,7 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan auto renderData = TransparentMeshPart::Pointer(renderItem); auto renderPayload = render::PayloadPointer(new TransparentMeshPart::Payload(renderData)); pendingChanges.resetItem(item, renderPayload); - _renderItems << item; + _renderItems.insert(item, renderPayload); somethingAdded = true; } foreach (auto renderItem, _opaqueRenderItems) { @@ -899,7 +927,7 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan auto renderData = OpaqueMeshPart::Pointer(renderItem); auto renderPayload = render::PayloadPointer(new OpaqueMeshPart::Payload(renderData)); pendingChanges.resetItem(item, renderPayload); - _renderItems << item; + _renderItems.insert(item, renderPayload); somethingAdded = true; } @@ -914,7 +942,7 @@ void Model::removeFromScene(std::shared_ptr scene, render::Pendin attachment->removeFromScene(scene, pendingChanges); } - foreach (auto item, _renderItems) { + foreach (auto item, _renderItems.keys()) { pendingChanges.removeItem(item); } _renderItems.clear(); @@ -1305,6 +1333,10 @@ void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bo if (_url == url && _geometry && _geometry->getURL() == url) { return; } + + _readyWhenAdded = false; // reset out render items. + _needsReload = true; + _url = url; // if so instructed, keep the current geometry until the new one is loaded @@ -1957,6 +1989,7 @@ void Model::applyNextGeometry() { _geometry = _nextGeometry; _meshGroupsKnown = false; _readyWhenAdded = false; // in case any of our users are using scenes + _needsReload = false; // we are loaded now! _nextBaseGeometry.reset(); _nextGeometry.reset(); } @@ -2018,6 +2051,12 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran if (!_readyWhenAdded) { return; // bail asap } + + // we always need these properly calculated before we can render, this will likely already have been done + // since the engine will call our getPartBounds() before rendering us. + if (!_calculatedMeshPartBoxesValid) { + recalculateMeshBoxes(true); + } auto textureCache = DependencyManager::get(); gpu::Batch& batch = *(args->_batch); @@ -2028,18 +2067,6 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran _transforms.push_back(Transform()); } - // _transforms[0] = _viewState->getViewTransform(); - // args->_viewFrustum->evalViewTransform(_transforms[0]); - - // apply entity translation offset to the viewTransform in one go (it's a preTranslate because viewTransform goes from world to eye space) - // _transforms[0].setTranslation(_translation); - - // batch.setViewTransform(_transforms[0]); - - - // const float OPAQUE_ALPHA_THRESHOLD = 0.5f; - // const float TRANSPARENT_ALPHA_THRESHOLD = 0.0f; - // auto alphaThreshold = translucent ? TRANSPARENT_ALPHA_THRESHOLD : OPAQUE_ALPHA_THRESHOLD; // FIX ME auto alphaThreshold = args->_alphaThreshold; //translucent ? TRANSPARENT_ALPHA_THRESHOLD : OPAQUE_ALPHA_THRESHOLD; // FIX ME const FBXGeometry& geometry = _geometry->getFBXGeometry(); const QVector& networkMeshes = _geometry->getMeshes(); @@ -2076,6 +2103,7 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran if (meshIndex < 0 || meshIndex >= networkMeshes.size() || meshIndex > geometry.meshes.size()) { _meshGroupsKnown = false; // regenerate these lists next time around. _readyWhenAdded = false; // in case any of our users are using scenes + _needsReload = true; return; // FIXME! } @@ -2199,19 +2227,7 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran } } - // FIX ME This is very unefficient - qint64 offset = 0; - for (int j = 0; j < partIndex; j++) { - const NetworkMeshPart& networkPart = networkMesh.parts.at(j); - const FBXMeshPart& part = mesh.parts.at(j); - if ((networkPart.isTranslucent() || part.opacity != 1.0f) != translucent) { - offset += (part.quadIndices.size() + part.triangleIndices.size()) * sizeof(int); - continue; - } - - offset += part.quadIndices.size() * sizeof(int); - offset += part.triangleIndices.size() * sizeof(int); - } + qint64 offset = _calculatedMeshPartOffet[QPair(meshIndex, partIndex)]; if (part.quadIndices.size() > 0) { batch.drawIndexed(gpu::QUADS, part.quadIndices.size(), offset); @@ -2401,6 +2417,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod if (i < 0 || i >= networkMeshes.size() || i > geometry.meshes.size()) { _meshGroupsKnown = false; // regenerate these lists next time around. _readyWhenAdded = false; // in case any of our users are using scenes + _needsReload = true; continue; } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 3795dc8731..8ad683e9e4 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -30,6 +30,7 @@ #include #include #include "PhysicsEntity.h" +#include #include #include "AnimationHandle.h" @@ -107,6 +108,9 @@ public: bool isActive() const { return _geometry && _geometry->isLoaded(); } bool isRenderable() const { return !_meshStates.isEmpty() || (isActive() && _geometry->getMeshes().isEmpty()); } + + void setVisibleInScene(bool newValue, std::shared_ptr scene); + bool isVisible() const { return _isVisible; } bool isLoadedWithTextures() const { return _geometry && _geometry->isLoadedWithTextures(); } @@ -118,7 +122,7 @@ public: // new Scene/Engine rendering support bool needsFixupInScene() { return !_readyWhenAdded && readyToAddToScene(); } - bool readyToAddToScene(RenderArgs* renderArgs = nullptr) { return isRenderable() && isActive() && isLoadedWithTextures(); } + bool readyToAddToScene(RenderArgs* renderArgs = nullptr) { return !_needsReload && isRenderable() && isActive() && isLoadedWithTextures(); } bool addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges); void removeFromScene(std::shared_ptr scene, render::PendingChanges& pendingChanges); @@ -334,6 +338,7 @@ private: QUrl _url; QUrl _collisionUrl; + bool _isVisible; gpu::Buffers _blendedVertexBuffers; std::vector _transforms; @@ -367,6 +372,9 @@ private: }; QHash, AABox> _calculatedMeshPartBoxes; // world coordinate AABoxes for all sub mesh part boxes + QHash, qint64> _calculatedMeshPartOffet; + + bool _calculatedMeshPartBoxesValid; QVector _calculatedMeshBoxes; // world coordinate AABoxes for all sub mesh boxes bool _calculatedMeshBoxesValid; @@ -528,8 +536,9 @@ private: QSet> _transparentRenderItems; QSet> _opaqueRenderItems; - QSet _renderItems; + QMap _renderItems; bool _readyWhenAdded = false; + bool _needsReload = true; private: