From 513138ca9809cbdef7b263a8ca5c9cb4e733ae15 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Mon, 21 Mar 2016 18:28:26 -0700 Subject: [PATCH 1/4] one more crack at fixing the blender --- libraries/render-utils/src/Model.cpp | 18 ++++++++++++------ libraries/render-utils/src/Model.h | 4 ++++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 16db6532da..df186802f6 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1277,20 +1277,26 @@ void ModelBlender::noteRequiresBlend(ModelPointer model) { } return; } - _modelsRequiringBlends.insert(model); + + { + Lock lock(_mutex); + _modelsRequiringBlends.insert(model); + } } void ModelBlender::setBlendedVertices(const QPointer& model, int blendNumber, const QWeakPointer& geometry, const QVector& vertices, const QVector& normals) { + if (!model.isNull()) { model->setBlendedVertices(blendNumber, geometry, vertices, normals); } _pendingBlenders--; - while (!_modelsRequiringBlends.empty()) { - auto firstItem = _modelsRequiringBlends.begin(); - if (firstItem != _modelsRequiringBlends.end()) { - _modelsRequiringBlends.erase(firstItem); - ModelPointer nextModel = firstItem->lock(); + { + Lock lock(_mutex); + for (auto i = _modelsRequiringBlends.begin(); i != _modelsRequiringBlends.end();) { + auto weakPtr = *i; + _modelsRequiringBlends.erase(i++); // remove front of the set + ModelPointer nextModel = weakPtr.lock(); if (nextModel && nextModel->maybeStartBlender()) { _pendingBlenders++; return; diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 1e8b3f2af6..53ed82f418 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -402,11 +402,15 @@ public slots: const QVector& vertices, const QVector& normals); private: + using Mutex = std::mutex; + using Lock = std::unique_lock; + ModelBlender(); virtual ~ModelBlender(); std::set> _modelsRequiringBlends; int _pendingBlenders; + Mutex _mutex; }; From 28f25489f888abbdfbe02f20cdb215410b73834d Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 21 Mar 2016 18:46:04 -0700 Subject: [PATCH 2/4] Fix occasional crash on creating overlay tool windows --- interface/resources/qml/ToolWindow.qml | 68 +++++++++++++++----------- libraries/ui/src/QmlWindowClass.cpp | 3 -- 2 files changed, 39 insertions(+), 32 deletions(-) diff --git a/interface/resources/qml/ToolWindow.qml b/interface/resources/qml/ToolWindow.qml index 404d1c1e78..09fbf78077 100644 --- a/interface/resources/qml/ToolWindow.qml +++ b/interface/resources/qml/ToolWindow.qml @@ -17,7 +17,6 @@ Windows.Window { visible: false width: 384; height: 640; title: "Tools" - property string newTabSource property alias tabView: tabView onParentChanged: { if (parent) { @@ -32,26 +31,21 @@ Windows.Window { property alias y: toolWindow.y } - property var webTabCreator: Component { - Controls.WebView { - id: webView - property string originalUrl; - - // Both toolWindow.newTabSource and url can change, so we need - // to store the original url here, without creating any bindings - Component.onCompleted: { - originalUrl = toolWindow.newTabSource; - url = originalUrl; - } - } - } - TabView { anchors.fill: parent id: tabView; - onCountChanged: { - if (0 == count) { - toolWindow.visible = false + Repeater { + model: 4 + Tab { + active: true + enabled: false; + // we need to store the original url here for future identification + property string originalUrl: ""; + onEnabledChanged: toolWindow.updateVisiblity(); + Controls.WebView { + id: webView; + anchors.fill: parent + } } } } @@ -68,8 +62,7 @@ Windows.Window { function findIndexForUrl(source) { for (var i = 0; i < tabView.count; ++i) { var tab = tabView.getTab(i); - if (tab && tab.item && tab.item.originalUrl && - tab.item.originalUrl === source) { + if (tab.originalUrl === source) { return i; } } @@ -101,21 +94,32 @@ Windows.Window { } } + function findFreeTab() { + for (var i = 0; i < tabView.count; ++i) { + var tab = tabView.getTab(i); + if (tab && !tab.originalUrl || tab.originalUrl === "") { + return i; + } + } + console.warn("Could not find free tab"); + return -1; + } + function removeTabForUrl(source) { var index = findIndexForUrl(source); if (index < 0) { return; } + var tab = tabView.getTab(index); - tab.enabledChanged.disconnect(updateVisiblity); - tabView.removeTab(index); - console.log("Updating visibility based on child tab removed"); - updateVisiblity(); + tab.title = ""; + tab.originalUrl = ""; + tab.enabled = false; } function addWebTab(properties) { if (!properties.source) { - console.warn("Attempted to open Web Tool Pane without URl") + console.warn("Attempted to open Web Tool Pane without URL") return; } @@ -125,11 +129,17 @@ Windows.Window { return tabView.getTab(existingTabIndex); } - var title = properties.title || "Unknown"; - newTabSource = properties.source; - var newTab = tabView.addTab(title, webTabCreator); + var freeTabIndex = findFreeTab(); + if (freeTabIndex === -1) { + console.warn("Unable to add new tab"); + return; + } + + var newTab = tabView.getTab(freeTabIndex); + newTab.title = properties.title || "Unknown"; + newTab.originalUrl = properties.source; + newTab.item.url = properties.source; newTab.active = true; - newTab.enabled = false; if (properties.width) { tabView.width = Math.min(Math.max(tabView.width, properties.width), diff --git a/libraries/ui/src/QmlWindowClass.cpp b/libraries/ui/src/QmlWindowClass.cpp index 5bd40b10a9..e986ea0441 100644 --- a/libraries/ui/src/QmlWindowClass.cpp +++ b/libraries/ui/src/QmlWindowClass.cpp @@ -172,7 +172,6 @@ QScriptValue QmlWindowClass::internalConstructor(const QString& qmlSource, setupServer(); retVal = builder(newTab); retVal->_toolWindow = true; - offscreenUi->getRootContext()->engine()->setObjectOwnership(retVal->_qmlWindow, QQmlEngine::CppOwnership); registerObject(url.toLower(), retVal); return QVariant(); }); @@ -330,10 +329,8 @@ void QmlWindowClass::close() { if (_qmlWindow) { if (_toolWindow) { auto offscreenUi = DependencyManager::get(); - auto qmlWindow = _qmlWindow; offscreenUi->executeOnUiThread([=] { auto toolWindow = offscreenUi->getToolWindow(); - offscreenUi->getRootContext()->engine()->setObjectOwnership(qmlWindow, QQmlEngine::JavaScriptOwnership); auto invokeResult = QMetaObject::invokeMethod(toolWindow, "removeTabForUrl", Qt::DirectConnection, Q_ARG(QVariant, _source)); Q_ASSERT(invokeResult); From a30df07d53443e89aaf37680eb5dc6535c3b69c0 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 22 Mar 2016 09:15:29 -0700 Subject: [PATCH 3/4] PR feeback, precendence --- interface/resources/qml/ToolWindow.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/ToolWindow.qml b/interface/resources/qml/ToolWindow.qml index 09fbf78077..75aa50aa34 100644 --- a/interface/resources/qml/ToolWindow.qml +++ b/interface/resources/qml/ToolWindow.qml @@ -97,7 +97,7 @@ Windows.Window { function findFreeTab() { for (var i = 0; i < tabView.count; ++i) { var tab = tabView.getTab(i); - if (tab && !tab.originalUrl || tab.originalUrl === "") { + if (tab && (!tab.originalUrl || tab.originalUrl === "")) { return i; } } From 47fb85eaeb4057edbe2f302a4957c080923e3910 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 22 Mar 2016 11:24:12 -0700 Subject: [PATCH 4/4] be more defensive in FBXGeometry::convexHullContains --- libraries/fbx/src/FBXReader.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index b2ede33e01..de8c001566 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -78,10 +78,14 @@ bool FBXGeometry::convexHullContains(const glm::vec3& point) const { auto checkEachPrimitive = [=](FBXMesh& mesh, QVector indices, int primitiveSize) -> bool { // Check whether the point is "behind" all the primitives. + int verticesSize = mesh.vertices.size(); for (int j = 0; j < indices.size() - 2; // -2 in case the vertices aren't the right size -- we access j + 2 below j += primitiveSize) { - if (!isPointBehindTrianglesPlane(point, + if (indices[j] < verticesSize && + indices[j + 1] < verticesSize && + indices[j + 2] < verticesSize && + !isPointBehindTrianglesPlane(point, mesh.vertices[indices[j]], mesh.vertices[indices[j + 1]], mesh.vertices[indices[j + 2]])) {