From 4254d38cddbb3cc18d0807d7180a4f8903a9985d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 13 Nov 2014 17:40:21 -0800 Subject: [PATCH 01/22] Update buttons to grid tool --- examples/html/gridControls.html | 145 +++++++++++++------------------- examples/html/style.css | 95 +++++++++++++++++++++ examples/libraries/gridTool.js | 9 ++ 3 files changed, 163 insertions(+), 86 deletions(-) create mode 100644 examples/html/style.css diff --git a/examples/html/gridControls.html b/examples/html/gridControls.html index e7bf1cdf8c..4cb935e600 100644 --- a/examples/html/gridControls.html +++ b/examples/html/gridControls.html @@ -1,5 +1,6 @@ + -
-
+
- -
-
-
- +
+ + + +
- -
-
-
- +
+ + + +
- -
-
-
- +
+ + + +
- -
-
-
- +
+ + + +
- -
-
-
+
+ + + + +
+ +
+ + +
+ +
+ + + +
+
+ + +
diff --git a/examples/html/style.css b/examples/html/style.css new file mode 100644 index 0000000000..1625fd094f --- /dev/null +++ b/examples/html/style.css @@ -0,0 +1,95 @@ +* { +} + +body { + margin: 0; + padding: 0; + + background-color: #efefef; + font-family: Sans-Serif; + font-size: 12px; + + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +input { + line-height: 2; +} + +.input-left { + display: inline-block; + width: 20px; +} + +.color-box { + display: inline-block; + width: 20px; + height: 20px; + border: 1px solid black; + margin: 2px; + cursor: pointer; +} + +.color-box.highlight { + width: 18px; + height: 18px; + border: 2px solid black; +} + +.section-header { + background: #AAA; + border-bottom: 1px solid #CCC; + background-color: #333333; + color: #999; + padding: 4px; +} + +.section-header label { + font-weight: bold; +} + +.multi-property-section { +} +.property-section { + display: block; + margin: 10 10; + height: 30px; +} + +.property-section label { + font-weight: bold; + vertical-align: middle; +} + +.property-section span { + float: right; +} + +.grid-section { + border-top: 1px solid #DDD; + background-color: #efefef; +} + +input[type=button] { + cursor: pointer; + background-color: #608e96; + border-color: #608e96; + border-radius: 5px; + padding: 5px 10px; + border: 0; + color: #fff; + font-weight: bold; + margin: 0 2px; + margin-top: 5px; + font-size: .9em; +} + +input.coord { + width: 6em; + height: 2em; +} diff --git a/examples/libraries/gridTool.js b/examples/libraries/gridTool.js index 34e25d6733..04547a6918 100644 --- a/examples/libraries/gridTool.js +++ b/examples/libraries/gridTool.js @@ -174,6 +174,15 @@ GridTool = function(opts) { for (var i = 0; i < listeners.length; i++) { listeners[i](data); } + } else if (data.type == "action") { + var action = data.action; + if (action == "moveToAvatar") { + grid.setPosition(MyAvatar.position); + } else if (action == "moveToSelection") { + var newPosition = selectionManager.worldPosition; + newPosition = Vec3.subtract(newPosition, { x: 0, y: selectionManager.worldDimensions.y * 0.5, z: 0 }); + grid.setPosition(newPosition); + } } }); From 49563dbff7a9c90844e8c837de015f38649a880d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 13 Nov 2014 17:41:51 -0800 Subject: [PATCH 02/22] Add entityProperties tool window --- examples/html/entityProperties.html | 561 ++++++++++++++++++++++ examples/libraries/entitySelectionTool.js | 15 +- examples/newEditEntities.js | 35 +- 3 files changed, 605 insertions(+), 6 deletions(-) create mode 100644 examples/html/entityProperties.html diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html new file mode 100644 index 0000000000..408e83198f --- /dev/null +++ b/examples/html/entityProperties.html @@ -0,0 +1,561 @@ + + + + + + +
+ +
+
+
+ + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + X + Y + Z + +
+ +
+ + + X + Y + Z + +
+ +
+ + + + +
+
+ + + + +
+
+ + + + +
+ +
+ + + X + Y + Z + +
+
+ + + + +
+
+ + + Pitch + Roll + Yaw + +
+
+ + + + +
+ +
+ + + X + Y + Z + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ + +
+
+ + + Red + Green + Blue + +
+
+ + +
+
+ + + + +
+
+ + + + +
+
+ + + + +
+
+ + + + +
+
+ + +
+
+ + + + +
+
+ + + Red + Green + Blue + +
+
+ + + Red + Green + Blue + +
+
+ + + Red + Green + Blue + +
+
+ + + + +
+
+ + + + +
+
+ + + + +
+
+ + + + +
+
+ + + + +
+
+
+ + + diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 22f75cb187..6733ccaf39 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -23,12 +23,13 @@ SelectionManager = (function() { that.savedProperties = {}; - that.eventListener = null; that.selections = []; // These are selections that don't have a known ID yet that.pendingSelections = []; var pendingSelectionTimer = null; + var listeners = []; + that.localRotation = Quat.fromPitchYawRollDegrees(0, 0, 0); that.localPosition = { x: 0, y: 0, z: 0 }; that.localDimensions = { x: 0, y: 0, z: 0 }; @@ -46,8 +47,8 @@ SelectionManager = (function() { } }; - that.setEventListener = function(func) { - that.eventListener = func; + that.addEventListener = function(func) { + listeners.push(func); }; that.hasSelection = function() { @@ -187,8 +188,12 @@ SelectionManager = (function() { SelectionDisplay.setSpaceMode(SPACE_WORLD); } - if (that.eventListener) { - that.eventListener(); + for (var i = 0; i < listeners.length; i++) { + try { + listeners[i](); + } catch (e) { + print("got exception"); + } } }; diff --git a/examples/newEditEntities.js b/examples/newEditEntities.js index 68e0d0c146..f5af558fa1 100644 --- a/examples/newEditEntities.js +++ b/examples/newEditEntities.js @@ -39,7 +39,7 @@ Script.include("libraries/gridTool.js"); var grid = Grid(); gridTool = GridTool({ horizontalGrid: grid }); -selectionManager.setEventListener(selectionDisplay.updateHandles); +selectionManager.addEventListener(selectionDisplay.updateHandles); var windowDimensions = Controller.getViewportDimensions(); var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/"; @@ -908,3 +908,36 @@ function pushCommandForSelections(createdEntityData, deletedEntityData) { } UndoStack.pushCommand(applyEntityProperties, undoData, applyEntityProperties, redoData); } + +PropertiesTool = function(opts) { + var that = {}; + + var url = Script.resolvePath('html/entityProperties.html'); + var webView = new WebWindow('Entity Properties', url, 200, 280); + + webView.setVisible(true); + + selectionManager.addEventListener(function() { + data = { + type: 'update', + }; + if (selectionManager.hasSelection()) { + data.properties = Entities.getEntityProperties(selectionManager.selections[0]); + } + webView.eventBridge.emitScriptEvent(JSON.stringify(data)); + }); + + webView.eventBridge.webEventReceived.connect(function(data) { + print(data); + data = JSON.parse(data); + if (data.type == "update") { + Entities.editEntity(selectionManager.selections[0], data.properties); + selectionManager._update(); + } + }); + + return that; +}; + +propertiesTool = PropertiesTool(); + From 55612cc5962f6c2b30445b1a6fdbe6938d4d6f47 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 13 Nov 2014 17:46:20 -0800 Subject: [PATCH 03/22] Add title to WebWindowClass --- examples/libraries/gridTool.js | 2 +- interface/src/scripting/WebWindowClass.cpp | 8 +++++--- interface/src/scripting/WebWindowClass.h | 2 +- interface/src/scripting/WindowScriptingInterface.cpp | 4 ++-- interface/src/scripting/WindowScriptingInterface.h | 2 +- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/examples/libraries/gridTool.js b/examples/libraries/gridTool.js index 04547a6918..9945fe3e98 100644 --- a/examples/libraries/gridTool.js +++ b/examples/libraries/gridTool.js @@ -159,7 +159,7 @@ GridTool = function(opts) { var listeners = []; var url = Script.resolvePath('html/gridControls.html'); - var webView = new WebWindow(url, 200, 280); + var webView = new WebWindow('Grid', url, 200, 280); horizontalGrid.addListener(function(data) { webView.eventBridge.emitScriptEvent(JSON.stringify(data)); diff --git a/interface/src/scripting/WebWindowClass.cpp b/interface/src/scripting/WebWindowClass.cpp index d280d8eecf..01a7983098 100644 --- a/interface/src/scripting/WebWindowClass.cpp +++ b/interface/src/scripting/WebWindowClass.cpp @@ -28,7 +28,8 @@ void ScriptEventBridge::emitScriptEvent(const QString& data) { emit scriptEventReceived(data); } -WebWindowClass::WebWindowClass(const QString& url, int width, int height) + +WebWindowClass::WebWindowClass(const QString& title, const QString& url, int width, int height) : QObject(NULL), _window(new QWidget(NULL, Qt::Tool)), _eventBridge(new ScriptEventBridge(this)) { @@ -59,8 +60,9 @@ QScriptValue WebWindowClass::constructor(QScriptContext* context, QScriptEngine* QMetaObject::invokeMethod(WindowScriptingInterface::getInstance(), "doCreateWebWindow", Qt::BlockingQueuedConnection, Q_RETURN_ARG(WebWindowClass*, retVal), Q_ARG(const QString&, file), - Q_ARG(int, context->argument(1).toInteger()), - Q_ARG(int, context->argument(2).toInteger())); + Q_ARG(QString, context->argument(1).toString()), + Q_ARG(int, context->argument(2).toInteger()), + Q_ARG(int, context->argument(3).toInteger())); connect(engine, &QScriptEngine::destroyed, retVal, &WebWindowClass::deleteLater); diff --git a/interface/src/scripting/WebWindowClass.h b/interface/src/scripting/WebWindowClass.h index 7b77299774..928b8fb23b 100644 --- a/interface/src/scripting/WebWindowClass.h +++ b/interface/src/scripting/WebWindowClass.h @@ -34,7 +34,7 @@ class WebWindowClass : public QObject { Q_OBJECT Q_PROPERTY(QObject* eventBridge READ getEventBridge) public: - WebWindowClass(const QString& url, int width, int height); + WebWindowClass(const QString& title, const QString& url, int width, int height); ~WebWindowClass(); static QScriptValue constructor(QScriptContext* context, QScriptEngine* engine); diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 8c2066f253..8a79cad6e1 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -34,8 +34,8 @@ WindowScriptingInterface::WindowScriptingInterface() : { } -WebWindowClass* WindowScriptingInterface::doCreateWebWindow(const QString& url, int width, int height) { - return new WebWindowClass(url, width, height); +WebWindowClass* WindowScriptingInterface::doCreateWebWindow(const QString& title, const QString& url, int width, int height) { + return new WebWindowClass(title, url, width, height); } QScriptValue WindowScriptingInterface::hasFocus() { diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 5529d31efd..0b320f23a1 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -78,7 +78,7 @@ private slots: void nonBlockingFormAccepted() { _nonBlockingFormActive = false; _formResult = QDialog::Accepted; emit nonBlockingFormClosed(); } void nonBlockingFormRejected() { _nonBlockingFormActive = false; _formResult = QDialog::Rejected; emit nonBlockingFormClosed(); } - WebWindowClass* doCreateWebWindow(const QString& url, int width, int height); + WebWindowClass* doCreateWebWindow(const QString& title, const QString& url, int width, int height); private: WindowScriptingInterface(); From 03f155bcd8d5f9405563cae5fd43bafa3f2b0779 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 13 Nov 2014 17:47:02 -0800 Subject: [PATCH 04/22] Add tool window --- interface/src/Application.cpp | 4 ++++ interface/src/Application.h | 4 ++++ interface/src/Menu.cpp | 11 +++++++++++ interface/src/Menu.h | 2 ++ interface/src/scripting/WebWindowClass.cpp | 17 ++++++++++------- interface/src/scripting/WebWindowClass.h | 2 +- 6 files changed, 32 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b1c969b66f..3958011ba2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -370,6 +370,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : // enable mouse tracking; otherwise, we only get drag events _glWidget->setMouseTracking(true); + _toolWindow = new QMainWindow(); + _toolWindow->setWindowFlags(_toolWindow->windowFlags() | Qt::WindowStaysOnTopHint); + _toolWindow->setWindowTitle("Tools"); + // initialization continues in initializeGL when OpenGL context is ready // Tell our voxel edit sender about our known jurisdictions diff --git a/interface/src/Application.h b/interface/src/Application.h index eee2581e2e..a6f94f0ab5 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -244,6 +244,8 @@ public: void lockOctreeSceneStats() { _octreeSceneStatsLock.lockForRead(); } void unlockOctreeSceneStats() { _octreeSceneStatsLock.unlock(); } + QMainWindow* getToolWindow() { return _toolWindow ; } + GeometryCache* getGeometryCache() { return &_geometryCache; } AnimationCache* getAnimationCache() { return &_animationCache; } TextureCache* getTextureCache() { return &_textureCache; } @@ -457,6 +459,8 @@ private: MainWindow* _window; GLCanvas* _glWidget; // our GLCanvas has a couple extra features + QMainWindow* _toolWindow; + BandwidthMeter _bandwidthMeter; QThread* _nodeThread; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index cd074805b6..fd0db559ff 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -247,6 +247,12 @@ Menu::Menu() : _chatWindow = new ChatWindow(Application::getInstance()->getWindow()); #endif + addActionToQMenuAndActionHash(toolsMenu, + MenuOption::ToolWindow, + Qt::CTRL | Qt::ALT | Qt::Key_T, + this, + SLOT(toggleToolWindow())); + addActionToQMenuAndActionHash(toolsMenu, MenuOption::Console, Qt::CTRL | Qt::ALT | Qt::Key_J, @@ -1461,6 +1467,11 @@ void Menu::toggleConsole() { _jsConsole->setVisible(!_jsConsole->isVisible()); } +void Menu::toggleToolWindow() { + QMainWindow* toolWindow = Application::getInstance()->getToolWindow(); + toolWindow->setVisible(!toolWindow->isVisible()); +} + void Menu::audioMuteToggled() { QAction *muteAction = _actionHash.value(MenuOption::MuteAudio); if (muteAction) { diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 8af91ccae4..badd79759f 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -224,6 +224,7 @@ private slots: void showScriptEditor(); void showChat(); void toggleConsole(); + void toggleToolWindow(); void toggleChat(); void audioMuteToggled(); void displayNameLocationResponse(const QString& errorString); @@ -491,6 +492,7 @@ namespace MenuOption { const QString StringHair = "String Hair"; const QString SuppressShortTimings = "Suppress Timings Less than 10ms"; const QString TestPing = "Test Ping"; + const QString ToolWindow = "Tool Window"; const QString TransmitterDrive = "Transmitter Drive"; const QString TurnWithHead = "Turn using Head"; const QString UploadAttachment = "Upload Attachment Model"; diff --git a/interface/src/scripting/WebWindowClass.cpp b/interface/src/scripting/WebWindowClass.cpp index 01a7983098..1645fe2f56 100644 --- a/interface/src/scripting/WebWindowClass.cpp +++ b/interface/src/scripting/WebWindowClass.cpp @@ -11,9 +11,13 @@ #include #include +#include +#include #include #include +#include +#include "Application.h" #include "WindowScriptingInterface.h" #include "WebWindowClass.h" @@ -31,18 +35,17 @@ void ScriptEventBridge::emitScriptEvent(const QString& data) { WebWindowClass::WebWindowClass(const QString& title, const QString& url, int width, int height) : QObject(NULL), - _window(new QWidget(NULL, Qt::Tool)), _eventBridge(new ScriptEventBridge(this)) { + QMainWindow* toolWindow = Application::getInstance()->getToolWindow(); + + _window = new QDockWidget(title, toolWindow); QWebView* webView = new QWebView(_window); webView->page()->mainFrame()->addToJavaScriptWindowObject("EventBridge", _eventBridge); webView->setUrl(url); - QVBoxLayout* layout = new QVBoxLayout(_window); - _window->setLayout(layout); - layout->addWidget(webView); - layout->setSpacing(0); - layout->setContentsMargins(0, 0, 0, 0); - _window->setGeometry(0, 0, width, height); + _window->setWidget(webView); + + toolWindow->addDockWidget(Qt::RightDockWidgetArea, _window); connect(this, &WebWindowClass::destroyed, _window, &QWidget::deleteLater); } diff --git a/interface/src/scripting/WebWindowClass.h b/interface/src/scripting/WebWindowClass.h index 928b8fb23b..c37b7aea48 100644 --- a/interface/src/scripting/WebWindowClass.h +++ b/interface/src/scripting/WebWindowClass.h @@ -44,7 +44,7 @@ public slots: ScriptEventBridge* getEventBridge() const { return _eventBridge; } private: - QWidget* _window; + QDockWidget* _window; ScriptEventBridge* _eventBridge; }; From a6f027e33aadc9bc22cd1ac74b2f6003ebd7b354 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 13 Nov 2014 18:31:32 -0800 Subject: [PATCH 05/22] Fix entity edit grid not hiding when disabling tools --- examples/libraries/gridTool.js | 8 +++++++- examples/newEditEntities.js | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/examples/libraries/gridTool.js b/examples/libraries/gridTool.js index 9945fe3e98..d8b84babf9 100644 --- a/examples/libraries/gridTool.js +++ b/examples/libraries/gridTool.js @@ -31,6 +31,7 @@ Grid = function(opts) { that.getMajorIncrement = function() { return minorGridSpacing * majorGridEvery; }; that.visible = false; + that.enabled = false; that.getOrigin = function() { return origin; @@ -38,6 +39,11 @@ Grid = function(opts) { that.getSnapToGrid = function() { return snapToGrid; }; + that.setEnabled = function(enabled) { + that.enabled = enabled; + updateGrid(); + } + that.setVisible = function(visible, noUpdate) { that.visible = visible; updateGrid(); @@ -127,7 +133,7 @@ Grid = function(opts) { function updateGrid() { Overlays.editOverlay(gridOverlay, { position: { x: origin.y, y: origin.y, z: -origin.y }, - visible: that.visible, + visible: that.visible && that.enabled, minorGridWidth: minorGridSpacing, majorGridEvery: majorGridEvery, color: gridColor, diff --git a/examples/newEditEntities.js b/examples/newEditEntities.js index 8a2c8a636d..0b8eebfee5 100644 --- a/examples/newEditEntities.js +++ b/examples/newEditEntities.js @@ -272,11 +272,13 @@ var toolBar = (function () { isActive = !isActive; if (!isActive) { gridTool.setVisible(false); + grid.setEnabled(false); selectionManager.clearSelections(); cameraManager.disable(); } else { cameraManager.enable(); gridTool.setVisible(Menu.isOptionChecked(MENU_GRID_TOOL_ENABLED)); + grid.setEnabled(true); } return true; } From 6a4f1c857f3bcae8c8412b496b1a83c96a637fc6 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 13 Nov 2014 18:35:04 -0800 Subject: [PATCH 06/22] fix a couple bugs --- interface/src/renderer/Model.cpp | 8 ++++---- libraries/octree/src/OctreeElement.cpp | 5 +++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index c007f44f2e..09aaa63929 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -537,7 +537,7 @@ void Model::renderSetup(RenderArgs* args) { } } - if (!_meshGroupsKnown) { + if (!_meshGroupsKnown && isLoadedWithTextures()) { segregateMeshGroups(); } } @@ -628,7 +628,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args); opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, args); // render translucent meshes afterwards //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); @@ -649,7 +649,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, true, args); GLBATCH(glDisable)(GL_ALPHA_TEST); GLBATCH(glEnable)(GL_BLEND); @@ -673,7 +673,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, true, args); } GLBATCH(glDepthMask)(true); diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index a0a331beb3..32dafc0b68 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -16,6 +16,7 @@ #include +#include #include #include #include @@ -1159,6 +1160,10 @@ OctreeElement* OctreeElement::addChildAtIndex(int childIndex) { bool OctreeElement::safeDeepDeleteChildAtIndex(int childIndex, int recursionCount) { bool deleteApproved = false; if (recursionCount > DANGEROUSLY_DEEP_RECURSION) { + static QString repeatedMessage + = LogHandler::getInstance().addRepeatedMessageRegex( + "OctreeElement::safeDeepDeleteChildAtIndex() reached DANGEROUSLY_DEEP_RECURSION, bailing!"); + qDebug() << "OctreeElement::safeDeepDeleteChildAtIndex() reached DANGEROUSLY_DEEP_RECURSION, bailing!"; return deleteApproved; } From 3658d65028c57945cef9d6376f3814d90fe24a02 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 13 Nov 2014 20:02:19 -0800 Subject: [PATCH 07/22] Remove grid tool from menu --- examples/newEditEntities.js | 25 ++++++++++------------ interface/src/scripting/WebWindowClass.cpp | 13 +++++------ interface/src/scripting/WebWindowClass.h | 2 +- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/examples/newEditEntities.js b/examples/newEditEntities.js index 0b8eebfee5..cc3c0fceda 100644 --- a/examples/newEditEntities.js +++ b/examples/newEditEntities.js @@ -55,13 +55,11 @@ var wantEntityGlow = false; var SPAWN_DISTANCE = 1; var DEFAULT_DIMENSION = 0.20; -var MENU_GRID_TOOL_ENABLED = 'Grid Tool'; var MENU_INSPECT_TOOL_ENABLED = "Inspect Tool"; var MENU_EASE_ON_FOCUS = "Ease Orientation on Focus"; var SETTING_INSPECT_TOOL_ENABLED = "inspectToolEnabled"; var SETTING_EASE_ON_FOCUS = "cameraEaseOnFocus"; -var SETTING_GRID_TOOL_ENABLED = 'GridToolEnabled'; var modelURLs = [ HIFI_PUBLIC_BUCKET + "models/entities/2-Terrain:%20Alder.fbx", @@ -273,12 +271,14 @@ var toolBar = (function () { if (!isActive) { gridTool.setVisible(false); grid.setEnabled(false); + propertiesTool.setVisible(false); selectionManager.clearSelections(); cameraManager.disable(); } else { cameraManager.enable(); - gridTool.setVisible(Menu.isOptionChecked(MENU_GRID_TOOL_ENABLED)); + gridTool.setVisible(true); grid.setEnabled(true); + propertiesTool.setVisible(true); } return true; } @@ -610,10 +610,6 @@ function setupModelMenus() { Menu.addMenuItem({ menuName: "File", menuItemName: "Import Models", shortcutKey: "CTRL+META+I", afterItem: "Export Models" }); Menu.addMenuItem({ menuName: "Developer", menuItemName: "Debug Ryans Rotation Problems", isCheckable: true }); - Menu.addMenuItem({ menuName: "View", menuItemName: MENU_GRID_TOOL_ENABLED, afterItem: "Edit Entities Help...", isCheckable: true, - isChecked: Settings.getValue(SETTING_GRID_TOOL_ENABLED) == 'true'}); - Menu.addMenuItem({ menuName: "View", menuItemName: MENU_INSPECT_TOOL_ENABLED, afterItem: MENU_GRID_TOOL_ENABLED, - isCheckable: true, isChecked: Settings.getValue(SETTING_INSPECT_TOOL_ENABLED) == "true" }); Menu.addMenuItem({ menuName: "View", menuItemName: MENU_EASE_ON_FOCUS, afterItem: MENU_INSPECT_TOOL_ENABLED, isCheckable: true, isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) == "true" }); } @@ -638,8 +634,6 @@ function cleanupModelMenus() { Menu.removeMenuItem("File", "Import Models"); Menu.removeMenuItem("Developer", "Debug Ryans Rotation Problems"); - Settings.setValue(SETTING_GRID_TOOL_ENABLED, Menu.isOptionChecked(MENU_GRID_TOOL_ENABLED)); - Menu.removeMenuItem("View", MENU_GRID_TOOL_ENABLED); Menu.removeMenuItem("View", MENU_INSPECT_TOOL_ENABLED); Menu.removeMenuItem("View", MENU_EASE_ON_FOCUS); } @@ -751,10 +745,6 @@ function handeMenuEvent(menuItem) { } } else if (menuItem == "Import Models") { modelImporter.doImport(); - } else if (menuItem == MENU_GRID_TOOL_ENABLED) { - if (isActive) { - gridTool.setVisible(Menu.isOptionChecked(MENU_GRID_TOOL_ENABLED)); - } } tooltip.show(false); } @@ -920,7 +910,14 @@ PropertiesTool = function(opts) { var url = Script.resolvePath('html/entityProperties.html'); var webView = new WebWindow('Entity Properties', url, 200, 280); - webView.setVisible(true); + var visible = false; + + webView.setVisible(visible); + + that.setVisible = function(newVisible) { + visible = newVisible; + webView.setVisible(visible); + }; selectionManager.addEventListener(function() { data = { diff --git a/interface/src/scripting/WebWindowClass.cpp b/interface/src/scripting/WebWindowClass.cpp index 1645fe2f56..7f11dbe580 100644 --- a/interface/src/scripting/WebWindowClass.cpp +++ b/interface/src/scripting/WebWindowClass.cpp @@ -39,22 +39,23 @@ WebWindowClass::WebWindowClass(const QString& title, const QString& url, int wid QMainWindow* toolWindow = Application::getInstance()->getToolWindow(); - _window = new QDockWidget(title, toolWindow); - QWebView* webView = new QWebView(_window); + _dockWidget = new QDockWidget(title, toolWindow); + _dockWidget->setFeatures(QDockWidget::DockWidgetMovable); + QWebView* webView = new QWebView(_dockWidget); webView->page()->mainFrame()->addToJavaScriptWindowObject("EventBridge", _eventBridge); webView->setUrl(url); - _window->setWidget(webView); + _dockWidget->setWidget(webView); - toolWindow->addDockWidget(Qt::RightDockWidgetArea, _window); + toolWindow->addDockWidget(Qt::RightDockWidgetArea, _dockWidget); - connect(this, &WebWindowClass::destroyed, _window, &QWidget::deleteLater); + connect(this, &WebWindowClass::destroyed, _dockWidget, &QWidget::deleteLater); } WebWindowClass::~WebWindowClass() { } void WebWindowClass::setVisible(bool visible) { - QMetaObject::invokeMethod(_window, "setVisible", Qt::BlockingQueuedConnection, Q_ARG(bool, visible)); + QMetaObject::invokeMethod(_dockWidget, "setVisible", Qt::BlockingQueuedConnection, Q_ARG(bool, visible)); } QScriptValue WebWindowClass::constructor(QScriptContext* context, QScriptEngine* engine) { diff --git a/interface/src/scripting/WebWindowClass.h b/interface/src/scripting/WebWindowClass.h index c37b7aea48..ae0d14ae06 100644 --- a/interface/src/scripting/WebWindowClass.h +++ b/interface/src/scripting/WebWindowClass.h @@ -44,7 +44,7 @@ public slots: ScriptEventBridge* getEventBridge() const { return _eventBridge; } private: - QDockWidget* _window; + QDockWidget* _dockWidget; ScriptEventBridge* _eventBridge; }; From 5da0d1e55a287a965a8c7959d9f00fc7b62c3f2a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 13 Nov 2014 20:53:31 -0800 Subject: [PATCH 08/22] fix regexs for dangerously deep recurssion suppression --- libraries/octree/src/Octree.cpp | 8 ++++---- libraries/octree/src/OctreeElement.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 4450689949..93ee8c95d0 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -74,7 +74,7 @@ void Octree::recurseElementWithOperation(OctreeElement* element, RecurseOctreeOp if (recursionCount > DANGEROUSLY_DEEP_RECURSION) { static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex( - "Octree::recurseElementWithOperation() reached DANGEROUSLY_DEEP_RECURSION, bailing!"); + "Octree::recurseElementWithOperation\\(\\) reached DANGEROUSLY_DEEP_RECURSION, bailing!"); qDebug() << "Octree::recurseElementWithOperation() reached DANGEROUSLY_DEEP_RECURSION, bailing!"; return; @@ -96,7 +96,7 @@ void Octree::recurseElementWithPostOperation(OctreeElement* element, RecurseOctr if (recursionCount > DANGEROUSLY_DEEP_RECURSION) { static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex( - "Octree::recurseElementWithPostOperation() reached DANGEROUSLY_DEEP_RECURSION, bailing!"); + "Octree::recurseElementWithPostOperation\\(\\) reached DANGEROUSLY_DEEP_RECURSION, bailing!"); qDebug() << "Octree::recurseElementWithPostOperation() reached DANGEROUSLY_DEEP_RECURSION, bailing!"; return; @@ -126,7 +126,7 @@ void Octree::recurseElementWithOperationDistanceSorted(OctreeElement* element, R if (recursionCount > DANGEROUSLY_DEEP_RECURSION) { static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex( - "Octree::recurseElementWithOperationDistanceSorted() reached DANGEROUSLY_DEEP_RECURSION, bailing!"); + "Octree::recurseElementWithOperationDistanceSorted\\(\\) reached DANGEROUSLY_DEEP_RECURSION, bailing!"); qDebug() << "Octree::recurseElementWithOperationDistanceSorted() reached DANGEROUSLY_DEEP_RECURSION, bailing!"; return; @@ -167,7 +167,7 @@ bool Octree::recurseElementWithOperator(OctreeElement* element, RecurseOctreeOpe if (recursionCount > DANGEROUSLY_DEEP_RECURSION) { static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex( - "Octree::recurseElementWithOperator() reached DANGEROUSLY_DEEP_RECURSION, bailing!"); + "Octree::recurseElementWithOperator\\(\\) reached DANGEROUSLY_DEEP_RECURSION, bailing!"); qDebug() << "Octree::recurseElementWithOperator() reached DANGEROUSLY_DEEP_RECURSION, bailing!"; return false; diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index 32dafc0b68..e5db8b24f8 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -1162,7 +1162,7 @@ bool OctreeElement::safeDeepDeleteChildAtIndex(int childIndex, int recursionCoun if (recursionCount > DANGEROUSLY_DEEP_RECURSION) { static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex( - "OctreeElement::safeDeepDeleteChildAtIndex() reached DANGEROUSLY_DEEP_RECURSION, bailing!"); + "OctreeElement::safeDeepDeleteChildAtIndex\\(\\) reached DANGEROUSLY_DEEP_RECURSION, bailing!"); qDebug() << "OctreeElement::safeDeepDeleteChildAtIndex() reached DANGEROUSLY_DEEP_RECURSION, bailing!"; return deleteApproved; From 744f9bc508960d45cd7f02b4f02c4b4c690754af Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 13 Nov 2014 22:26:18 -0800 Subject: [PATCH 09/22] better handle corrupt packets that would cause unreasonably deep recursion --- libraries/octree/src/Octree.cpp | 52 ++++++++++++++++---------- libraries/octree/src/Octree.h | 2 +- libraries/octree/src/OctreeConstants.h | 3 +- libraries/octree/src/OctreeElement.h | 2 - 4 files changed, 36 insertions(+), 23 deletions(-) diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 93ee8c95d0..e9cf1158fa 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -231,8 +231,18 @@ OctreeElement* Octree::nodeForOctalCode(OctreeElement* ancestorElement, } // returns the element created! -OctreeElement* Octree::createMissingElement(OctreeElement* lastParentElement, const unsigned char* codeToReach) { +OctreeElement* Octree::createMissingElement(OctreeElement* lastParentElement, const unsigned char* codeToReach, int recursionCount) { + + if (recursionCount > DANGEROUSLY_DEEP_RECURSION) { + static QString repeatedMessage + = LogHandler::getInstance().addRepeatedMessageRegex( + "Octree::createMissingElement\\(\\) reached DANGEROUSLY_DEEP_RECURSION, bailing!"); + + qDebug() << "Octree::createMissingElement() reached DANGEROUSLY_DEEP_RECURSION, bailing!"; + return lastParentElement; + } int indexOfNewChild = branchIndexWithDescendant(lastParentElement->getOctalCode(), codeToReach); + // If this parent element is a leaf, then you know the child path doesn't exist, so deal with // breaking up the leaf first, which will also create a child path if (lastParentElement->requiresSplit()) { @@ -246,7 +256,7 @@ OctreeElement* Octree::createMissingElement(OctreeElement* lastParentElement, co if (*lastParentElement->getChildAtIndex(indexOfNewChild)->getOctalCode() == *codeToReach) { return lastParentElement->getChildAtIndex(indexOfNewChild); } else { - return createMissingElement(lastParentElement->getChildAtIndex(indexOfNewChild), codeToReach); + return createMissingElement(lastParentElement->getChildAtIndex(indexOfNewChild), codeToReach, recursionCount + 1); } } @@ -255,25 +265,20 @@ int Octree::readElementData(OctreeElement* destinationElement, const unsigned ch int bytesLeftToRead = bytesAvailable; int bytesRead = 0; - bool wantDebug = false; // give this destination element the child mask from the packet const unsigned char ALL_CHILDREN_ASSUMED_TO_EXIST = 0xFF; if ((size_t)bytesLeftToRead < sizeof(unsigned char)) { - if (wantDebug) { - qDebug() << "UNEXPECTED: readElementData() only had " << bytesLeftToRead << " bytes. " - "Not enough for meaningful data."; - } + qDebug() << "UNEXPECTED: readElementData() only had " << bytesLeftToRead << " bytes. " + "Not enough for meaningful data."; return bytesAvailable; // assume we read the entire buffer... } if (destinationElement->getScale() < SCALE_AT_DANGEROUSLY_DEEP_RECURSION) { - if (wantDebug) { - qDebug() << "UNEXPECTED: readElementData() destination element is unreasonably small [" - << destinationElement->getScale() * (float)TREE_SCALE << " meters] " - << " Discarding " << bytesAvailable << " remaining bytes."; - } + qDebug() << "UNEXPECTED: readElementData() destination element is unreasonably small [" + << destinationElement->getScale() * (float)TREE_SCALE << " meters] " + << " Discarding " << bytesAvailable << " remaining bytes."; return bytesAvailable; // assume we read the entire buffer... } @@ -322,7 +327,7 @@ int Octree::readElementData(OctreeElement* destinationElement, const unsigned ch : sizeof(childInBufferMask); if (bytesLeftToRead < bytesForMasks) { - if (wantDebug) { + if (bytesLeftToRead > 0) { qDebug() << "UNEXPECTED: readElementDataFromBuffer() only had " << bytesLeftToRead << " bytes before masks. " "Not enough for meaningful data."; } @@ -385,7 +390,6 @@ void Octree::readBitstreamToTree(const unsigned char * bitstream, unsigned long ReadBitstreamToTreeParams& args) { int bytesRead = 0; const unsigned char* bitstreamAt = bitstream; - bool wantDebug = false; // If destination element is not included, set it to root if (!args.destinationElement) { @@ -398,14 +402,24 @@ void Octree::readBitstreamToTree(const unsigned char * bitstream, unsigned long while (bitstreamAt < bitstream + bufferSizeBytes) { OctreeElement* bitstreamRootElement = nodeForOctalCode(args.destinationElement, (unsigned char *)bitstreamAt, NULL); - int numberOfThreeBitSectionsInStream = numberOfThreeBitSectionsInCode(bitstreamAt, bufferSizeBytes); + if (numberOfThreeBitSectionsInStream > UNREASONABLY_DEEP_RECURSION) { + static QString repeatedMessage + = LogHandler::getInstance().addRepeatedMessageRegex( + "UNEXPECTED: parsing of the octal code would make UNREASONABLY_DEEP_RECURSION... " + "numberOfThreeBitSectionsInStream: \\d+ This buffer is corrupt. Returning." + ); + + + qDebug() << "UNEXPECTED: parsing of the octal code would make UNREASONABLY_DEEP_RECURSION... " + "numberOfThreeBitSectionsInStream:" << numberOfThreeBitSectionsInStream << + "This buffer is corrupt. Returning."; + return; + } if (numberOfThreeBitSectionsInStream == OVERFLOWED_OCTCODE_BUFFER) { - if (wantDebug) { - qDebug() << "UNEXPECTED: parsing of the octal code would overflow the buffer. " - "This buffer is corrupt. Returning."; - } + qDebug() << "UNEXPECTED: parsing of the octal code would overflow the buffer. " + "This buffer is corrupt. Returning."; return; } diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 42cbb3c38d..4ac7e22d90 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -373,7 +373,7 @@ protected: static bool countOctreeElementsOperation(OctreeElement* element, void* extraData); OctreeElement* nodeForOctalCode(OctreeElement* ancestorElement, const unsigned char* needleCode, OctreeElement** parentOfFoundElement) const; - OctreeElement* createMissingElement(OctreeElement* lastParentElement, const unsigned char* codeToReach); + OctreeElement* createMissingElement(OctreeElement* lastParentElement, const unsigned char* codeToReach, int recursionCount = 0); int readElementData(OctreeElement *destinationElement, const unsigned char* nodeData, int bufferSizeBytes, ReadBitstreamToTreeParams& args); diff --git a/libraries/octree/src/OctreeConstants.h b/libraries/octree/src/OctreeConstants.h index 4186b90888..e924676771 100644 --- a/libraries/octree/src/OctreeConstants.h +++ b/libraries/octree/src/OctreeConstants.h @@ -35,10 +35,11 @@ const int MAX_TREE_SLICE_BYTES = 26; const float VIEW_FRUSTUM_FOV_OVERSEND = 60.0f; // These are guards to prevent our voxel tree recursive routines from spinning out of control -const int UNREASONABLY_DEEP_RECURSION = 20; // use this for something that you want to be shallow, but not spin out +const int UNREASONABLY_DEEP_RECURSION = 29; // use this for something that you want to be shallow, but not spin out const int DANGEROUSLY_DEEP_RECURSION = 200; // use this for something that needs to go deeper const float SCALE_AT_UNREASONABLY_DEEP_RECURSION = (1.0f / powf(2.0f, UNREASONABLY_DEEP_RECURSION)); const float SCALE_AT_DANGEROUSLY_DEEP_RECURSION = (1.0f / powf(2.0f, DANGEROUSLY_DEEP_RECURSION)); +const float SMALLEST_REASONABLE_OCTREE_ELEMENT_SCALE = SCALE_AT_UNREASONABLY_DEEP_RECURSION * 2.0f; // 0.00006103515 meter ~1/10,0000th const int DEFAULT_MAX_OCTREE_PPS = 600; // the default maximum PPS we think any octree based server should send to a client diff --git a/libraries/octree/src/OctreeElement.h b/libraries/octree/src/OctreeElement.h index 31a9dfddc1..2bd5e3ae1e 100644 --- a/libraries/octree/src/OctreeElement.h +++ b/libraries/octree/src/OctreeElement.h @@ -36,8 +36,6 @@ class ReadBitstreamToTreeParams; class Shape; class VoxelSystem; -const float SMALLEST_REASONABLE_OCTREE_ELEMENT_SCALE = (1.0f / TREE_SCALE) / 10000.0f; // 1/10,000th of a meter - // Callers who want delete hook callbacks should implement this class class OctreeElementDeleteHook { public: From 7b69642c67a301e5d75f94b8700dd0e66057f17e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 13 Nov 2014 23:03:12 -0800 Subject: [PATCH 10/22] fix bug in animation jitter on turn --- libraries/entities/src/ModelEntityItem.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 52b8f7e643..f50fe7866b 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -115,7 +115,9 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, READ_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool, animationIsPlaying); if (propertyFlags.getHasProperty(PROP_ANIMATION_PLAYING)) { - setAnimationIsPlaying(animationIsPlaying); + if (animationIsPlaying != getAnimationIsPlaying()) { + setAnimationIsPlaying(animationIsPlaying); + } } if (propertyFlags.getHasProperty(PROP_ANIMATION_FPS)) { setAnimationFPS(animationFPS); @@ -345,7 +347,6 @@ QVector ModelEntityItem::getAnimationFrame() { if (frameCount > 0) { int animationFrameIndex = (int)(glm::floor(getAnimationFrameIndex())) % frameCount; - if (animationFrameIndex < 0 || animationFrameIndex > frameCount) { animationFrameIndex = 0; } @@ -427,7 +428,9 @@ void ModelEntityItem::setAnimationSettings(const QString& value) { if (settingsMap.contains("running")) { bool running = settingsMap["running"].toBool(); - setAnimationIsPlaying(running); + if (running != getAnimationIsPlaying()) { + setAnimationIsPlaying(running); + } } if (settingsMap.contains("firstFrame")) { From 5ba213f8d191cc07fc2febe88a0eb783d9635fd6 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 14 Nov 2014 09:33:11 -0800 Subject: [PATCH 11/22] fix for function override with no return --- interface/src/ui/overlays/Planar3DOverlay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/overlays/Planar3DOverlay.cpp b/interface/src/ui/overlays/Planar3DOverlay.cpp index b2de7bdaad..ffd7d73531 100644 --- a/interface/src/ui/overlays/Planar3DOverlay.cpp +++ b/interface/src/ui/overlays/Planar3DOverlay.cpp @@ -82,7 +82,7 @@ QScriptValue Planar3DOverlay::getProperty(const QString& property) { return vec2toScriptValue(_scriptEngine, _dimensions); } - Base3DOverlay::getProperty(property); + return Base3DOverlay::getProperty(property); } bool Planar3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, From 642f436fbaf65358fe5e444fa2033bf52ea4f3ad Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 14 Nov 2014 09:56:36 -0800 Subject: [PATCH 12/22] first draft of factorizing the rendering traversal for both sides in stereo --- interface/src/Application.cpp | 14 +- interface/src/Application.h | 14 +- interface/src/devices/TV3DManager.cpp | 4 +- interface/src/entities/EntityTreeRenderer.cpp | 8 +- interface/src/entities/EntityTreeRenderer.h | 2 +- interface/src/renderer/Model.cpp | 248 +++++++++--------- interface/src/renderer/Model.h | 4 +- interface/src/ui/overlays/Overlays.cpp | 6 +- interface/src/ui/overlays/Overlays.h | 2 +- libraries/octree/src/OctreeRenderer.cpp | 4 +- libraries/octree/src/OctreeRenderer.h | 2 +- libraries/shared/src/RenderArgs.h | 2 + 12 files changed, 168 insertions(+), 142 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f11ac14d40..83a4a46403 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -723,7 +723,7 @@ void Application::paintGL() { glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); - displaySide(*whichCamera); + displaySide(RenderContext(*whichCamera)); glPopMatrix(); if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { @@ -2873,12 +2873,16 @@ QImage Application::renderAvatarBillboard() { return image; } -void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { +//void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { +void Application::displaySide(RenderContext& renderContext) { PROFILE_RANGE(__FUNCTION__); PerformanceTimer perfTimer("display"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide()"); // transform by eye offset + Camera& whichCamera = renderContext._whichCamera; + bool selfAvatarOnly = renderContext._selfAvatarOnly; + // load the view frustum loadViewFrustum(whichCamera, _displayViewFrustum); @@ -3020,7 +3024,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { PerformanceTimer perfTimer("entities"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide() ... entities..."); - _entities.render(); + _entities.render(RenderArgs::DEFAULT_RENDER_MODE, renderContext._renderSide); } // render JS/scriptable overlays @@ -3265,7 +3269,7 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { _shadowMatrices[i] = glm::transpose(glm::transpose(_shadowMatrices[i]) * glm::translate(-delta)); } - displaySide(_mirrorCamera, true); + displaySide(RenderContext(_mirrorCamera, true)); // restore absolute translations _myAvatar->getSkeletonModel().setTranslation(absoluteSkeletonTranslation); @@ -3279,7 +3283,7 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { _shadowMatrices[i] = savedShadowMatrices[i]; } } else { - displaySide(_mirrorCamera, true); + displaySide(RenderContext(_mirrorCamera, true)); } glPopMatrix(); diff --git a/interface/src/Application.h b/interface/src/Application.h index cba39317a5..2cea413dd4 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -262,7 +262,19 @@ public: QImage renderAvatarBillboard(); - void displaySide(Camera& whichCamera, bool selfAvatarOnly = false); + struct RenderContext { + Camera& _whichCamera; + bool _selfAvatarOnly; + RenderArgs::RenderSide _renderSide; + + RenderContext(Camera& whichCamera, bool selfAvatarOnly = false, RenderArgs::RenderSide renderSide = RenderArgs::MONO) : + _whichCamera(whichCamera), + _selfAvatarOnly(selfAvatarOnly), + _renderSide(renderSide) { + } + }; + // void displaySide(Camera& whichCamera, bool selfAvatarOnly = false); + void displaySide(RenderContext& renderContext); /// Stores the current modelview matrix as the untranslated view matrix to use for transforms and the supplied vector as /// the view matrix translation. diff --git a/interface/src/devices/TV3DManager.cpp b/interface/src/devices/TV3DManager.cpp index 872f4ce7e6..bd0129f88e 100644 --- a/interface/src/devices/TV3DManager.cpp +++ b/interface/src/devices/TV3DManager.cpp @@ -126,7 +126,7 @@ void TV3DManager::display(Camera& whichCamera) { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - Application::getInstance()->displaySide(whichCamera); + Application::getInstance()->displaySide(Application::RenderContext(whichCamera, false, RenderArgs::STEREO_LEFT)); if (displayOverlays) { applicationOverlay.displayOverlayTexture3DTV(whichCamera, _aspect, fov); @@ -156,7 +156,7 @@ void TV3DManager::display(Camera& whichCamera) { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - Application::getInstance()->displaySide(whichCamera); + Application::getInstance()->displaySide(Application::RenderContext(whichCamera, false, RenderArgs::STEREO_RIGHT)); if (displayOverlays) { applicationOverlay.displayOverlayTexture3DTV(whichCamera, _aspect, fov); diff --git a/interface/src/entities/EntityTreeRenderer.cpp b/interface/src/entities/EntityTreeRenderer.cpp index 99e4916c62..2209a992c1 100644 --- a/interface/src/entities/EntityTreeRenderer.cpp +++ b/interface/src/entities/EntityTreeRenderer.cpp @@ -252,15 +252,15 @@ void EntityTreeRenderer::checkEnterLeaveEntities() { } } -void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode) { +void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide) { bool dontRenderAsScene = !Menu::getInstance()->isOptionChecked(MenuOption::RenderEntitiesAsScene); if (dontRenderAsScene) { - OctreeRenderer::render(renderMode); + OctreeRenderer::render(renderMode, renderSide); } else { if (_tree) { - Model::startScene(); - RenderArgs args = { this, _viewFrustum, getSizeScale(), getBoundaryLevelAdjust(), renderMode, + Model::startScene(renderSide); + RenderArgs args = { this, _viewFrustum, getSizeScale(), getBoundaryLevelAdjust(), renderMode, renderSide, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; _tree->lockForRead(); _tree->recurseTreeWithOperation(renderOperation, &args); diff --git a/interface/src/entities/EntityTreeRenderer.h b/interface/src/entities/EntityTreeRenderer.h index 7c1c81b6c9..66107b368a 100644 --- a/interface/src/entities/EntityTreeRenderer.h +++ b/interface/src/entities/EntityTreeRenderer.h @@ -56,7 +56,7 @@ public: void processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode); virtual void init(); - virtual void render(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE); + virtual void render(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::RenderSide renderSide = RenderArgs::MONO); virtual const FBXGeometry* getGeometryForEntity(const EntityItem* entityItem); virtual const Model* getModelForEntityItem(const EntityItem* entityItem); diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index c007f44f2e..71e42d32e0 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1484,8 +1484,10 @@ void Model::deleteGeometry() { // Scene rendering support QVector Model::_modelsInScene; gpu::Batch Model::_sceneRenderBatch; -void Model::startScene() { - _modelsInScene.clear(); +void Model::startScene(RenderArgs::RenderSide renderSide) { + if (renderSide != RenderArgs::STEREO_RIGHT) { + _modelsInScene.clear(); + } } void Model::setupBatchTransform(gpu::Batch& batch) { @@ -1503,146 +1505,152 @@ void Model::setupBatchTransform(gpu::Batch& batch) { void Model::endScene(RenderMode mode, RenderArgs* args) { PROFILE_RANGE(__FUNCTION__); - // Let's introduce a gpu::Batch to capture all the calls to the graphics api - _sceneRenderBatch.clear(); - gpu::Batch& batch = _sceneRenderBatch; + auto side = RenderArgs::MONO; + if (args) side = args->_renderSide; - GLBATCH(glDisable)(GL_COLOR_MATERIAL); + if (side != RenderArgs::STEREO_RIGHT) { + // Let's introduce a gpu::Batch to capture all the calls to the graphics api + _sceneRenderBatch.clear(); + gpu::Batch& batch = _sceneRenderBatch; + + GLBATCH(glDisable)(GL_COLOR_MATERIAL); + + if (mode == DIFFUSE_RENDER_MODE || mode == NORMAL_RENDER_MODE) { + GLBATCH(glDisable)(GL_CULL_FACE); + } else { + GLBATCH(glEnable)(GL_CULL_FACE); + if (mode == SHADOW_RENDER_MODE) { + GLBATCH(glCullFace)(GL_FRONT); + } + } + + // render opaque meshes with alpha testing + + GLBATCH(glDisable)(GL_BLEND); + GLBATCH(glEnable)(GL_ALPHA_TEST); - if (mode == DIFFUSE_RENDER_MODE || mode == NORMAL_RENDER_MODE) { - GLBATCH(glDisable)(GL_CULL_FACE); - } else { - GLBATCH(glEnable)(GL_CULL_FACE); if (mode == SHADOW_RENDER_MODE) { - GLBATCH(glCullFace)(GL_FRONT); + GLBATCH(glAlphaFunc)(GL_EQUAL, 0.0f); } - } - - // render opaque meshes with alpha testing - - GLBATCH(glDisable)(GL_BLEND); - GLBATCH(glEnable)(GL_ALPHA_TEST); - - if (mode == SHADOW_RENDER_MODE) { - GLBATCH(glAlphaFunc)(GL_EQUAL, 0.0f); - } - /*Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers( - mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE, - mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE, - mode == DEFAULT_RENDER_MODE); - */ - { - GLenum buffers[3]; - int bufferCount = 0; - if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { - buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; + /*Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers( + mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE, + mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE, + mode == DEFAULT_RENDER_MODE); + */ + { + GLenum buffers[3]; + int bufferCount = 0; + if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { + buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; + } + if (mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE) { + buffers[bufferCount++] = GL_COLOR_ATTACHMENT1; + } + if (mode == DEFAULT_RENDER_MODE) { + buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; + } + GLBATCH(glDrawBuffers)(bufferCount, buffers); } - if (mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE) { + + const float DEFAULT_ALPHA_THRESHOLD = 0.5f; + + int opaqueMeshPartsRendered = 0; + + // now, for each model in the scene, render the mesh portions + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args); + opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, args); + + // render translucent meshes afterwards + //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); + { + GLenum buffers[2]; + int bufferCount = 0; buffers[bufferCount++] = GL_COLOR_ATTACHMENT1; - } - if (mode == DEFAULT_RENDER_MODE) { buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; + GLBATCH(glDrawBuffers)(bufferCount, buffers); } - GLBATCH(glDrawBuffers)(bufferCount, buffers); + + int translucentParts = 0; + const float MOSTLY_OPAQUE_THRESHOLD = 0.75f; + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, true, args); + + GLBATCH(glDisable)(GL_ALPHA_TEST); + GLBATCH(glEnable)(GL_BLEND); + GLBATCH(glDepthMask)(false); + GLBATCH(glDepthFunc)(GL_LEQUAL); + + //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true); + { + GLenum buffers[1]; + int bufferCount = 0; + buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; + GLBATCH(glDrawBuffers)(bufferCount, buffers); + } + + if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { + const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f; + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args); + translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, true, args); + } + + GLBATCH(glDepthMask)(true); + GLBATCH(glDepthFunc)(GL_LESS); + GLBATCH(glDisable)(GL_CULL_FACE); + + if (mode == SHADOW_RENDER_MODE) { + GLBATCH(glCullFace)(GL_BACK); + } + + // deactivate vertex arrays after drawing + GLBATCH(glDisableClientState)(GL_NORMAL_ARRAY); + GLBATCH(glDisableClientState)(GL_VERTEX_ARRAY); + GLBATCH(glDisableClientState)(GL_TEXTURE_COORD_ARRAY); + GLBATCH(glDisableClientState)(GL_COLOR_ARRAY); + GLBATCH(glDisableVertexAttribArray)(gpu::Stream::TANGENT); + GLBATCH(glDisableVertexAttribArray)(gpu::Stream::SKIN_CLUSTER_INDEX); + GLBATCH(glDisableVertexAttribArray)(gpu::Stream::SKIN_CLUSTER_WEIGHT); + + // bind with 0 to switch back to normal operation + GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, 0); + GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, 0); + GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); + if (args) { + args->_translucentMeshPartsRendered = translucentParts; + args->_opaqueMeshPartsRendered = opaqueMeshPartsRendered; } - const float DEFAULT_ALPHA_THRESHOLD = 0.5f; - - int opaqueMeshPartsRendered = 0; - - // now, for each model in the scene, render the mesh portions - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args); - opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, args); - - // render translucent meshes afterwards - //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); - { - GLenum buffers[2]; - int bufferCount = 0; - buffers[bufferCount++] = GL_COLOR_ATTACHMENT1; - buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; - GLBATCH(glDrawBuffers)(bufferCount, buffers); } - int translucentParts = 0; - const float MOSTLY_OPAQUE_THRESHOLD = 0.75f; - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, true, args); - - GLBATCH(glDisable)(GL_ALPHA_TEST); - GLBATCH(glEnable)(GL_BLEND); - GLBATCH(glDepthMask)(false); - GLBATCH(glDepthFunc)(GL_LEQUAL); - - //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true); - { - GLenum buffers[1]; - int bufferCount = 0; - buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; - GLBATCH(glDrawBuffers)(bufferCount, buffers); - } - - if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { - const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f; - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args); - translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, true, args); - } - - GLBATCH(glDepthMask)(true); - GLBATCH(glDepthFunc)(GL_LESS); - GLBATCH(glDisable)(GL_CULL_FACE); - - if (mode == SHADOW_RENDER_MODE) { - GLBATCH(glCullFace)(GL_BACK); - } - - // deactivate vertex arrays after drawing - GLBATCH(glDisableClientState)(GL_NORMAL_ARRAY); - GLBATCH(glDisableClientState)(GL_VERTEX_ARRAY); - GLBATCH(glDisableClientState)(GL_TEXTURE_COORD_ARRAY); - GLBATCH(glDisableClientState)(GL_COLOR_ARRAY); - GLBATCH(glDisableVertexAttribArray)(gpu::Stream::TANGENT); - GLBATCH(glDisableVertexAttribArray)(gpu::Stream::SKIN_CLUSTER_INDEX); - GLBATCH(glDisableVertexAttribArray)(gpu::Stream::SKIN_CLUSTER_WEIGHT); - - // bind with 0 to switch back to normal operation - GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, 0); - GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, 0); - GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); - // Render! { PROFILE_RANGE("render Batch"); - ::gpu::GLBackend::renderBatch(batch); + ::gpu::GLBackend::renderBatch(_sceneRenderBatch); } // restore all the default material settings Application::getInstance()->setupWorldLight(); - if (args) { - args->_translucentMeshPartsRendered = translucentParts; - args->_opaqueMeshPartsRendered = opaqueMeshPartsRendered; - } } bool Model::renderInScene(float alpha, RenderArgs* args) { diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 32c072dc99..4dceb07655 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -31,7 +31,7 @@ class QScriptEngine; class Shape; -class RenderArgs; +#include "RenderArgs.h" class ViewFrustum; @@ -91,7 +91,7 @@ public: bool render(float alpha = 1.0f, RenderMode mode = DEFAULT_RENDER_MODE, RenderArgs* args = NULL); // Scene rendering support - static void startScene(); + static void startScene(RenderArgs::RenderSide renderSide); bool renderInScene(float alpha = 1.0f, RenderArgs* args = NULL); static void endScene(RenderMode mode = DEFAULT_RENDER_MODE, RenderArgs* args = NULL); diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 4bdabcc566..6584fce396 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -84,14 +84,14 @@ void Overlays::render2D() { RenderArgs args = { NULL, Application::getInstance()->getViewFrustum(), Menu::getInstance()->getVoxelSizeScale(), Menu::getInstance()->getBoundaryLevelAdjust(), - RenderArgs::DEFAULT_RENDER_MODE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::MONO, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; foreach(Overlay* thisOverlay, _overlays2D) { thisOverlay->render(&args); } } -void Overlays::render3D(RenderArgs::RenderMode renderMode) { +void Overlays::render3D(RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide) { QReadLocker lock(&_lock); if (_overlays3D.size() == 0) { return; @@ -106,7 +106,7 @@ void Overlays::render3D(RenderArgs::RenderMode renderMode) { RenderArgs args = { NULL, Application::getInstance()->getViewFrustum(), Menu::getInstance()->getVoxelSizeScale(), Menu::getInstance()->getBoundaryLevelAdjust(), - renderMode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + renderMode, renderSide, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; foreach(Overlay* thisOverlay, _overlays3D) { diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 66232196f2..31e4ad1ebc 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -39,7 +39,7 @@ public: ~Overlays(); void init(QGLWidget* parent); void update(float deltatime); - void render3D(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE); + void render3D(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::RenderSide renderSide = RenderArgs::MONO); void render2D(); public slots: diff --git a/libraries/octree/src/OctreeRenderer.cpp b/libraries/octree/src/OctreeRenderer.cpp index a8aafbe34d..5bcf49a1a4 100644 --- a/libraries/octree/src/OctreeRenderer.cpp +++ b/libraries/octree/src/OctreeRenderer.cpp @@ -162,8 +162,8 @@ bool OctreeRenderer::renderOperation(OctreeElement* element, void* extraData) { return false; } -void OctreeRenderer::render(RenderArgs::RenderMode renderMode) { - RenderArgs args = { this, _viewFrustum, getSizeScale(), getBoundaryLevelAdjust(), renderMode, +void OctreeRenderer::render(RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide) { + RenderArgs args = { this, _viewFrustum, getSizeScale(), getBoundaryLevelAdjust(), renderMode, renderSide, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; if (_tree) { _tree->lockForRead(); diff --git a/libraries/octree/src/OctreeRenderer.h b/libraries/octree/src/OctreeRenderer.h index d418467012..e8612b4cb6 100644 --- a/libraries/octree/src/OctreeRenderer.h +++ b/libraries/octree/src/OctreeRenderer.h @@ -52,7 +52,7 @@ public: virtual void init(); /// render the content of the octree - virtual void render(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE); + virtual void render(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::RenderSide renderSide = RenderArgs::MONO); ViewFrustum* getViewFrustum() const { return _viewFrustum; } void setViewFrustum(ViewFrustum* viewFrustum) { _viewFrustum = viewFrustum; } diff --git a/libraries/shared/src/RenderArgs.h b/libraries/shared/src/RenderArgs.h index 1ed43f94ad..e447472fee 100644 --- a/libraries/shared/src/RenderArgs.h +++ b/libraries/shared/src/RenderArgs.h @@ -18,12 +18,14 @@ class OctreeRenderer; class RenderArgs { public: enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE }; + enum RenderSide { MONO, STEREO_LEFT, STEREO_RIGHT }; OctreeRenderer* _renderer; ViewFrustum* _viewFrustum; float _sizeScale; int _boundaryLevelAdjust; RenderMode _renderMode; + RenderSide _renderSide; int _elementsTouched; int _itemsRendered; From 20fdd6d8117405296b02e7a383630dc95aab0ae4 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 14 Nov 2014 10:31:30 -0800 Subject: [PATCH 13/22] Disable model overlay properties example It causes intermittent crashes in NetworkGeometry::setTextureWithNameToURL() --- examples/overlaysExample.js | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/examples/overlaysExample.js b/examples/overlaysExample.js index 3ab70a0562..0d47f7ca64 100644 --- a/examples/overlaysExample.js +++ b/examples/overlaysExample.js @@ -194,20 +194,23 @@ print("Cube overlay color =\n" + "green: " + cubeColor.green + "\n" + "blue: " + cubeColor.blue ); -var modelOverlayProperties = { - textures: { - filename1: "http://url1", - filename2: "http://url2" - } -} -var modelOverlay = Overlays.addOverlay("model", modelOverlayProperties); -var textures = Overlays.getProperty(modelOverlay, "textures"); -var textureValues = ""; -for (key in textures) { - textureValues += "\n" + key + ": " + textures[key]; -} -print("Model overlay textures =" + textureValues); -Overlays.deleteOverlay(modelOverlay); + +// This model overlay example causes intermittent crashes in NetworkGeometry::setTextureWithNameToURL() +//var modelOverlayProperties = { +// textures: { +// filename1: HIFI_PUBLIC_BUCKET + "images/testing-swatches.svg", +// filename2: HIFI_PUBLIC_BUCKET + "images/hifi-interface-tools.svg" +// } +//} +//var modelOverlay = Overlays.addOverlay("model", modelOverlayProperties); +//var textures = Overlays.getProperty(modelOverlay, "textures"); +//var textureValues = ""; +//for (key in textures) { +// textureValues += "\n" + key + ": " + textures[key]; +//} +//print("Model overlay textures =" + textureValues); +//Overlays.deleteOverlay(modelOverlay); + print("Unknown overlay property =\n" + Overlays.getProperty(1000, "text")); // value = undefined // When our script shuts down, we should clean up all of our overlays From 86284036f1c6d8054c97bef7b43c9ca39b3b2d6a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 14 Nov 2014 10:35:13 -0800 Subject: [PATCH 14/22] put back timestamp in log --- libraries/shared/src/LogHandler.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/shared/src/LogHandler.cpp b/libraries/shared/src/LogHandler.cpp index dfac02b912..a13f3a9dad 100644 --- a/libraries/shared/src/LogHandler.cpp +++ b/libraries/shared/src/LogHandler.cpp @@ -119,6 +119,8 @@ QString LogHandler::printMessage(LogMsgType type, const QMessageLogContext& cont char dateString[100]; strftime(dateString, sizeof(dateString), DATE_STRING_FORMAT, localTime); + prefixString.append(QString(" [%1]").arg(dateString)); + if (_shouldOutputPID) { prefixString.append(QString(" [%1").arg(getpid())); From 903cd05ff83eb1f79c80829ef556ce28788d1b88 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 14 Nov 2014 10:39:45 -0800 Subject: [PATCH 15/22] put newlines back in interface log --- interface/src/Application.cpp | 2 +- interface/src/FileLogger.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 605bd62118..5e158352bb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -124,7 +124,7 @@ void messageHandler(QtMsgType type, const QMessageLogContext& context, const QSt QString logMessage = LogHandler::getInstance().printMessage((LogMsgType) type, context, message); if (!logMessage.isEmpty()) { - Application::getInstance()->getLogger()->addMessage(qPrintable(logMessage)); + Application::getInstance()->getLogger()->addMessage(qPrintable(logMessage + "\n")); } } diff --git a/interface/src/FileLogger.cpp b/interface/src/FileLogger.cpp index 505cb6a029..4808842036 100644 --- a/interface/src/FileLogger.cpp +++ b/interface/src/FileLogger.cpp @@ -41,7 +41,7 @@ void FileLogger::addMessage(QString message) { QFile file(_fileName); if (file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) { QTextStream out(&file); - out << message << "\n"; + out << message; } } From 604b1b620b628fcb2c9b24699cbe999b79bca0bf Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 14 Nov 2014 10:52:08 -0800 Subject: [PATCH 16/22] Move dock window to ToolWindow --- interface/src/Application.cpp | 2 +- interface/src/Application.h | 5 +- interface/src/scripting/WebWindowClass.cpp | 6 +- interface/src/ui/ToolWindow.cpp | 82 ++++++++++++++++++++++ interface/src/ui/ToolWindow.h | 40 +++++++++++ 5 files changed, 131 insertions(+), 4 deletions(-) create mode 100644 interface/src/ui/ToolWindow.cpp create mode 100644 interface/src/ui/ToolWindow.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index eefc41cf24..1664cc700e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -373,7 +373,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : // enable mouse tracking; otherwise, we only get drag events _glWidget->setMouseTracking(true); - _toolWindow = new QMainWindow(); + _toolWindow = new ToolWindow(); _toolWindow->setWindowFlags(_toolWindow->windowFlags() | Qt::WindowStaysOnTopHint); _toolWindow->setWindowTitle("Tools"); diff --git a/interface/src/Application.h b/interface/src/Application.h index f2a6615cbf..d31833897f 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -82,6 +82,7 @@ #include "ui/overlays/Overlays.h" #include "ui/ApplicationOverlay.h" #include "ui/RunningScriptsWidget.h" +#include "ui/ToolWindow.h" #include "ui/VoxelImportDialog.h" #include "voxels/VoxelFade.h" #include "voxels/VoxelHideShowThread.h" @@ -246,7 +247,7 @@ public: void lockOctreeSceneStats() { _octreeSceneStatsLock.lockForRead(); } void unlockOctreeSceneStats() { _octreeSceneStatsLock.unlock(); } - QMainWindow* getToolWindow() { return _toolWindow ; } + ToolWindow* getToolWindow() { return _toolWindow ; } GeometryCache* getGeometryCache() { return &_geometryCache; } AnimationCache* getAnimationCache() { return &_animationCache; } @@ -461,7 +462,7 @@ private: MainWindow* _window; GLCanvas* _glWidget; // our GLCanvas has a couple extra features - QMainWindow* _toolWindow; + ToolWindow* _toolWindow; BandwidthMeter _bandwidthMeter; diff --git a/interface/src/scripting/WebWindowClass.cpp b/interface/src/scripting/WebWindowClass.cpp index 7f11dbe580..cc6f4fbfff 100644 --- a/interface/src/scripting/WebWindowClass.cpp +++ b/interface/src/scripting/WebWindowClass.cpp @@ -37,7 +37,7 @@ WebWindowClass::WebWindowClass(const QString& title, const QString& url, int wid : QObject(NULL), _eventBridge(new ScriptEventBridge(this)) { - QMainWindow* toolWindow = Application::getInstance()->getToolWindow(); + ToolWindow* toolWindow = Application::getInstance()->getToolWindow(); _dockWidget = new QDockWidget(title, toolWindow); _dockWidget->setFeatures(QDockWidget::DockWidgetMovable); @@ -55,6 +55,10 @@ WebWindowClass::~WebWindowClass() { } void WebWindowClass::setVisible(bool visible) { + if (visible) { + QMetaObject::invokeMethod( + Application::getInstance()->getToolWindow(), "setVisible", Qt::BlockingQueuedConnection, Q_ARG(bool, visible)); + } QMetaObject::invokeMethod(_dockWidget, "setVisible", Qt::BlockingQueuedConnection, Q_ARG(bool, visible)); } diff --git a/interface/src/ui/ToolWindow.cpp b/interface/src/ui/ToolWindow.cpp new file mode 100644 index 0000000000..1375ff1ea5 --- /dev/null +++ b/interface/src/ui/ToolWindow.cpp @@ -0,0 +1,82 @@ +// +// ToolWindow.cpp +// interface/src/ui +// +// Created by Ryan Huffman on 11/13/14. +// 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 "Application.h" +#include "ToolWindow.h" +#include "UIUtil.h" + +const int DEFAULT_WIDTH = 300; + +ToolWindow::ToolWindow(QWidget* parent) : + QMainWindow(parent), + _hasShown(false), + _lastGeometry() { +} + +bool ToolWindow::event(QEvent* event) { + QEvent::Type type = event->type(); + if (type == QEvent::Show) { + if (!_hasShown) { + _hasShown = true; + + QMainWindow* mainWindow = Application::getInstance()->getWindow(); + QRect mainGeometry = mainWindow->geometry(); + + int titleBarHeight = UIUtil::getWindowTitleBarHeight(this); + int menuBarHeight = Menu::getInstance()->geometry().height(); + int topMargin = titleBarHeight + menuBarHeight; + + _lastGeometry = QRect(mainGeometry.topLeft().x(), mainGeometry.topLeft().y() + topMargin, + DEFAULT_WIDTH, mainGeometry.height() - topMargin); + } + setGeometry(_lastGeometry); + return true; + } else if (type == QEvent::Hide) { + _lastGeometry = geometry(); + return true; + } + + return QMainWindow::event(event); +} + +void ToolWindow::onChildVisibilityUpdated(bool visible) { + if (visible) { + setVisible(true); + } else { + bool hasVisible = false; + QList dockWidgets = findChildren(); + for (int i = 0; i < dockWidgets.count(); i++) { + if (dockWidgets[i]->isVisible()) { + hasVisible = true; + break; + } + } + setVisible(hasVisible); + } +} + +void ToolWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget* dockWidget) { + QMainWindow::addDockWidget(area, dockWidget); + + connect(dockWidget, &QDockWidget::visibilityChanged, this, &ToolWindow::onChildVisibilityUpdated); +} + +void ToolWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget* dockWidget, Qt::Orientation orientation) { + QMainWindow::addDockWidget(area, dockWidget, orientation); + + connect(dockWidget, &QDockWidget::visibilityChanged, this, &ToolWindow::onChildVisibilityUpdated); +} + +void ToolWindow::removeDockWidget(QDockWidget* dockWidget) { + QMainWindow::removeDockWidget(dockWidget); + + disconnect(dockWidget, &QDockWidget::visibilityChanged, this, &ToolWindow::onChildVisibilityUpdated); +} diff --git a/interface/src/ui/ToolWindow.h b/interface/src/ui/ToolWindow.h new file mode 100644 index 0000000000..87b94d46df --- /dev/null +++ b/interface/src/ui/ToolWindow.h @@ -0,0 +1,40 @@ +// +// ToolWindow.h +// interface/src/ui +// +// Created by Ryan Huffman on 11/13/14. +// 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_ToolWindow_h +#define hifi_ToolWindow_h + +#include +#include +#include +#include +#include + +class ToolWindow : public QMainWindow { + Q_OBJECT +public: + ToolWindow(QWidget* parent = NULL); + + virtual bool event(QEvent* event); + virtual void addDockWidget(Qt::DockWidgetArea area, QDockWidget* dockWidget); + virtual void addDockWidget(Qt::DockWidgetArea area, QDockWidget* dockWidget, Qt::Orientation orientation); + virtual void removeDockWidget(QDockWidget* dockWidget); + +public slots: + void onChildVisibilityUpdated(bool visible); + + +private: + bool _hasShown; + QRect _lastGeometry; +}; + +#endif // hifi_ToolWindow_h From cc78000641968b24aa3824f78fb1b88dd49c5389 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 14 Nov 2014 11:22:11 -0800 Subject: [PATCH 17/22] introduce the concept of side thorugh out the rendering traversal --- interface/src/Application.cpp | 14 +++++--------- interface/src/Application.h | 13 +------------ interface/src/devices/TV3DManager.cpp | 4 ++-- 3 files changed, 8 insertions(+), 23 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 48fa2413ea..792ad2d62e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -724,7 +724,7 @@ void Application::paintGL() { glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); - displaySide(RenderContext(*whichCamera)); + displaySide(*whichCamera); glPopMatrix(); if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { @@ -2874,16 +2874,12 @@ QImage Application::renderAvatarBillboard() { return image; } -//void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { -void Application::displaySide(RenderContext& renderContext) { +void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly, RenderArgs::RenderSide renderSide) { PROFILE_RANGE(__FUNCTION__); PerformanceTimer perfTimer("display"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide()"); // transform by eye offset - Camera& whichCamera = renderContext._whichCamera; - bool selfAvatarOnly = renderContext._selfAvatarOnly; - // load the view frustum loadViewFrustum(whichCamera, _displayViewFrustum); @@ -3025,7 +3021,7 @@ void Application::displaySide(RenderContext& renderContext) { PerformanceTimer perfTimer("entities"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide() ... entities..."); - _entities.render(RenderArgs::DEFAULT_RENDER_MODE, renderContext._renderSide); + _entities.render(RenderArgs::DEFAULT_RENDER_MODE, renderSide); } // render JS/scriptable overlays @@ -3270,7 +3266,7 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { _shadowMatrices[i] = glm::transpose(glm::transpose(_shadowMatrices[i]) * glm::translate(-delta)); } - displaySide(RenderContext(_mirrorCamera, true)); + displaySide(_mirrorCamera, true); // restore absolute translations _myAvatar->getSkeletonModel().setTranslation(absoluteSkeletonTranslation); @@ -3284,7 +3280,7 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { _shadowMatrices[i] = savedShadowMatrices[i]; } } else { - displaySide(RenderContext(_mirrorCamera, true)); + displaySide(_mirrorCamera, true); } glPopMatrix(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 2cea413dd4..178849eec4 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -262,19 +262,8 @@ public: QImage renderAvatarBillboard(); - struct RenderContext { - Camera& _whichCamera; - bool _selfAvatarOnly; - RenderArgs::RenderSide _renderSide; - - RenderContext(Camera& whichCamera, bool selfAvatarOnly = false, RenderArgs::RenderSide renderSide = RenderArgs::MONO) : - _whichCamera(whichCamera), - _selfAvatarOnly(selfAvatarOnly), - _renderSide(renderSide) { - } - }; // void displaySide(Camera& whichCamera, bool selfAvatarOnly = false); - void displaySide(RenderContext& renderContext); + void displaySide(Camera& whichCamera, bool selfAvatarOnly = false, RenderArgs::RenderSide renderSide = RenderArgs::MONO); /// Stores the current modelview matrix as the untranslated view matrix to use for transforms and the supplied vector as /// the view matrix translation. diff --git a/interface/src/devices/TV3DManager.cpp b/interface/src/devices/TV3DManager.cpp index bd0129f88e..d7d7353b24 100644 --- a/interface/src/devices/TV3DManager.cpp +++ b/interface/src/devices/TV3DManager.cpp @@ -126,7 +126,7 @@ void TV3DManager::display(Camera& whichCamera) { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - Application::getInstance()->displaySide(Application::RenderContext(whichCamera, false, RenderArgs::STEREO_LEFT)); + Application::getInstance()->displaySide(whichCamera, false, RenderArgs::STEREO_LEFT); if (displayOverlays) { applicationOverlay.displayOverlayTexture3DTV(whichCamera, _aspect, fov); @@ -156,7 +156,7 @@ void TV3DManager::display(Camera& whichCamera) { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - Application::getInstance()->displaySide(Application::RenderContext(whichCamera, false, RenderArgs::STEREO_RIGHT)); + Application::getInstance()->displaySide(whichCamera, false, RenderArgs::STEREO_RIGHT); if (displayOverlays) { applicationOverlay.displayOverlayTexture3DTV(whichCamera, _aspect, fov); From d9ae3eb5b61dc0216b900bcef094a8a7f8153545 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 14 Nov 2014 12:07:59 -0800 Subject: [PATCH 18/22] clean version of the simple stereo ack, not available for Occulus yet --- interface/src/renderer/Model.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 28bf1ddd3e..aeff8e9a67 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1505,10 +1505,11 @@ void Model::setupBatchTransform(gpu::Batch& batch) { void Model::endScene(RenderMode mode, RenderArgs* args) { PROFILE_RANGE(__FUNCTION__); - auto side = RenderArgs::MONO; - if (args) side = args->_renderSide; + RenderArgs::RenderSide renderSide = RenderArgs::MONO; + if (args) renderSide = args->_renderSide; - if (side != RenderArgs::STEREO_RIGHT) { + // Do the rendering batch creation for mono or left eye, not for right eye + if (renderSide != RenderArgs::STEREO_RIGHT) { // Let's introduce a gpu::Batch to capture all the calls to the graphics api _sceneRenderBatch.clear(); gpu::Batch& batch = _sceneRenderBatch; From 14eb87aefd094c95fcde6c1fdf0d2e83f8df4b08 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 14 Nov 2014 12:23:47 -0800 Subject: [PATCH 19/22] Eliminate wacky scales in favor of newfangled "meters." --- interface/src/MetavoxelSystem.cpp | 3 +-- interface/src/ModelUploader.cpp | 2 +- interface/src/avatar/FaceModel.cpp | 3 +-- interface/src/avatar/SkeletonModel.cpp | 6 ++---- libraries/fbx/src/FBXReader.cpp | 2 +- 5 files changed, 6 insertions(+), 10 deletions(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 4c0acc553a..5d8f77eedc 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -3164,8 +3164,7 @@ void StaticModelRenderer::applyRotation(const glm::quat& rotation) { } void StaticModelRenderer::applyScale(float scale) { - const float SCALE_MULTIPLIER = 0.0006f; - _model->setScale(glm::vec3(scale, scale, scale) * SCALE_MULTIPLIER); + _model->setScale(glm::vec3(scale, scale, scale)); } void StaticModelRenderer::applyURL(const QUrl& url) { diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp index b117197f48..2599f39e83 100644 --- a/interface/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -157,7 +157,7 @@ bool ModelUploader::zip() { // mixamo/autodesk defaults if (!mapping.contains(SCALE_FIELD)) { - mapping.insert(SCALE_FIELD, 15.0); + mapping.insert(SCALE_FIELD, 1.0); } QVariantHash joints = mapping.value(JOINT_FIELD).toHash(); if (!joints.contains("jointEyeLeft")) { diff --git a/interface/src/avatar/FaceModel.cpp b/interface/src/avatar/FaceModel.cpp index 70f59f0661..5a30e8634d 100644 --- a/interface/src/avatar/FaceModel.cpp +++ b/interface/src/avatar/FaceModel.cpp @@ -34,8 +34,7 @@ void FaceModel::simulate(float deltaTime, bool fullUpdate) { neckParentRotation = owningAvatar->getOrientation(); } setRotation(neckParentRotation); - const float MODEL_SCALE = 0.0006f; - setScale(glm::vec3(1.0f, 1.0f, 1.0f) * _owningHead->getScale() * MODEL_SCALE); + setScale(glm::vec3(1.0f, 1.0f, 1.0f) * _owningHead->getScale()); setPupilDilation(_owningHead->getPupilDilation()); setBlendshapeCoefficients(_owningHead->getBlendshapeCoefficients()); diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index e760813fe5..7ca105f483 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -36,8 +36,6 @@ SkeletonModel::~SkeletonModel() { _ragdoll = NULL; } -const float MODEL_SCALE = 0.0006f; - void SkeletonModel::setJointStates(QVector states) { Model::setJointStates(states); @@ -57,7 +55,7 @@ void SkeletonModel::setJointStates(QVector states) { _defaultEyeModelPosition.z = -_defaultEyeModelPosition.z; // Skeleton may have already been scaled so unscale it - _defaultEyeModelPosition = MODEL_SCALE * _defaultEyeModelPosition / _scale; + _defaultEyeModelPosition = _defaultEyeModelPosition / _scale; } // the SkeletonModel override of updateJointState() will clear the translation part @@ -80,7 +78,7 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { setTranslation(_owningAvatar->getSkeletonPosition()); static const glm::quat refOrientation = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)); setRotation(_owningAvatar->getOrientation() * refOrientation); - setScale(glm::vec3(1.0f, 1.0f, 1.0f) * _owningAvatar->getScale() * MODEL_SCALE); + setScale(glm::vec3(1.0f, 1.0f, 1.0f) * _owningAvatar->getScale()); setBlendshapeCoefficients(_owningAvatar->getHead()->getBlendshapeCoefficients()); Model::simulate(deltaTime, fullUpdate); diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 7ba5e7bc24..4ffd3f6286 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1456,7 +1456,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } // get offset transform from mapping - float offsetScale = mapping.value("scale", 1.0f).toFloat() * unitScaleFactor; + float offsetScale = mapping.value("scale", 1.0f).toFloat() * unitScaleFactor * METERS_PER_CENTIMETER; glm::quat offsetRotation = glm::quat(glm::radians(glm::vec3(mapping.value("rx").toFloat(), mapping.value("ry").toFloat(), mapping.value("rz").toFloat()))); geometry.offset = glm::translate(glm::vec3(mapping.value("tx").toFloat(), mapping.value("ty").toFloat(), From 43a6a0420bdc650f9e10ca01cd34e013648d9a86 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 14 Nov 2014 12:24:38 -0800 Subject: [PATCH 20/22] remove useless comments --- interface/src/Application.h | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/Application.h b/interface/src/Application.h index 178849eec4..8ffad07122 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -262,7 +262,6 @@ public: QImage renderAvatarBillboard(); - // void displaySide(Camera& whichCamera, bool selfAvatarOnly = false); void displaySide(Camera& whichCamera, bool selfAvatarOnly = false, RenderArgs::RenderSide renderSide = RenderArgs::MONO); /// Stores the current modelview matrix as the untranslated view matrix to use for transforms and the supplied vector as From 4f878682a9df73fea04596f68e14021bc05b1a39 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 14 Nov 2014 12:38:50 -0800 Subject: [PATCH 21/22] fix syntax --- interface/src/renderer/Model.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index aeff8e9a67..fc3845d94f 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1506,7 +1506,9 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { PROFILE_RANGE(__FUNCTION__); RenderArgs::RenderSide renderSide = RenderArgs::MONO; - if (args) renderSide = args->_renderSide; + if (args) { + renderSide = args->_renderSide; + } // Do the rendering batch creation for mono or left eye, not for right eye if (renderSide != RenderArgs::STEREO_RIGHT) { From 779f5f76145dd6ff573368e5955de2cadbd59cc8 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 14 Nov 2014 13:02:02 -0800 Subject: [PATCH 22/22] Default avatar fixes. --- interface/resources/meshes/defaultAvatar_body.fst | 2 +- interface/resources/meshes/defaultAvatar_head.fst | 2 +- libraries/avatars/src/AvatarData.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/resources/meshes/defaultAvatar_body.fst b/interface/resources/meshes/defaultAvatar_body.fst index 5874c206db..f061a87726 100644 --- a/interface/resources/meshes/defaultAvatar_body.fst +++ b/interface/resources/meshes/defaultAvatar_body.fst @@ -1,6 +1,6 @@ filename=defaultAvatar/body.fbx texdir=defaultAvatar -scale=130 +scale=8.666 joint = jointRoot = jointRoot joint = jointLean = jointSpine joint = jointNeck = jointNeck diff --git a/interface/resources/meshes/defaultAvatar_head.fst b/interface/resources/meshes/defaultAvatar_head.fst index 34cf44f0e4..c2478ce7d9 100644 --- a/interface/resources/meshes/defaultAvatar_head.fst +++ b/interface/resources/meshes/defaultAvatar_head.fst @@ -2,7 +2,7 @@ name= defaultAvatar_head filename=defaultAvatar/head.fbx texdir=defaultAvatar -scale=80 +scale=5.333 rx=0 ry=0 rz=0 diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 6b882a1389..c8e5e61d49 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -91,8 +91,8 @@ const float MAX_AUDIO_LOUDNESS = 1000.0; // close enough for mouth animation const int AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS = 1000; const int AVATAR_BILLBOARD_PACKET_SEND_INTERVAL_MSECS = 5000; -const QUrl DEFAULT_HEAD_MODEL_URL = QUrl("http://public.highfidelity.io/meshes/defaultAvatar_head.fst"); -const QUrl DEFAULT_BODY_MODEL_URL = QUrl("http://public.highfidelity.io/meshes/defaultAvatar_body.fst"); +const QUrl DEFAULT_HEAD_MODEL_URL = QUrl("http://public.highfidelity.io/models/heads/defaultAvatar_head.fst"); +const QUrl DEFAULT_BODY_MODEL_URL = QUrl("http://public.highfidelity.io/models/skeletons/defaultAvatar_body.fst"); enum KeyState { NO_KEY_DOWN = 0,