From 22190c1340aac18ba59b0c653482740eea101cef Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Thu, 22 May 2014 17:55:25 -0700 Subject: [PATCH 01/45] Made overlays thread safe for write operations, which solved a script crash. --- interface/src/ui/overlays/Overlays.cpp | 6 +++--- interface/src/ui/overlays/Overlays.h | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 9e4a594bbc..6c6f150ae7 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -96,7 +96,6 @@ void Overlays::render3D() { } } -// TODO: make multi-threaded safe unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& properties) { unsigned int thisID = 0; bool created = false; @@ -140,6 +139,7 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope } if (created) { + QWriteLocker lock(&_lock); thisID = _nextOverlayID; _nextOverlayID++; if (is3D) { @@ -152,9 +152,9 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope return thisID; } -// TODO: make multi-threaded safe bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) { Overlay* thisOverlay = NULL; + QWriteLocker lock(&_lock); if (_overlays2D.contains(id)) { thisOverlay = _overlays2D[id]; } else if (_overlays3D.contains(id)) { @@ -167,9 +167,9 @@ bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) { return false; } -// TODO: make multi-threaded safe void Overlays::deleteOverlay(unsigned int id) { Overlay* overlayToDelete; + QWriteLocker lock(&_lock); if (_overlays2D.contains(id)) { overlayToDelete = _overlays2D.take(id); } else if (_overlays3D.contains(id)) { diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index b3477be0c2..20015b8af9 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -45,6 +45,7 @@ private: QList _overlaysToDelete; unsigned int _nextOverlayID; QGLWidget* _parent; + QReadWriteLock _lock; }; From 55ed3e98a5615e4b739407860b27e0a0779f1dce Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Fri, 23 May 2014 10:44:40 -0700 Subject: [PATCH 02/45] Added some missing locks to make Overlays thread safe for reading as well. --- interface/src/ui/overlays/Overlays.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 6c6f150ae7..bcac86d7f1 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -39,6 +39,7 @@ void Overlays::init(QGLWidget* parent) { } void Overlays::update(float deltatime) { + QWriteLocker lock(&_lock); foreach (Overlay* thisOverlay, _overlays2D) { thisOverlay->update(deltatime); } @@ -52,12 +53,14 @@ void Overlays::update(float deltatime) { } void Overlays::render2D() { + QReadLocker lock(&_lock); foreach(Overlay* thisOverlay, _overlays2D) { thisOverlay->render(); } } void Overlays::render3D() { + QReadLocker lock(&_lock); if (_overlays3D.size() == 0) { return; } @@ -182,6 +185,7 @@ void Overlays::deleteOverlay(unsigned int id) { } unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) { + QReadLocker lock(&_lock); QMapIterator i(_overlays2D); i.toBack(); while (i.hasPrevious()) { From 495a54291c6fd01b889373fa7e8af6e44cfcac92 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 23 May 2014 10:57:14 -0700 Subject: [PATCH 03/45] Use local viewer model for specular. --- interface/resources/shaders/model.frag | 5 ++++- interface/resources/shaders/model.vert | 6 ++++++ interface/resources/shaders/model_normal_map.frag | 7 +++++-- interface/resources/shaders/model_normal_map.vert | 6 +++++- .../resources/shaders/model_normal_specular_map.frag | 7 +++++-- interface/resources/shaders/model_specular_map.frag | 5 ++++- interface/resources/shaders/skin_model.vert | 9 ++++++--- .../resources/shaders/skin_model_normal_map.vert | 11 +++++++---- 8 files changed, 42 insertions(+), 14 deletions(-) diff --git a/interface/resources/shaders/model.frag b/interface/resources/shaders/model.frag index a9d93f2f6a..488736abf9 100644 --- a/interface/resources/shaders/model.frag +++ b/interface/resources/shaders/model.frag @@ -14,6 +14,9 @@ // the diffuse texture uniform sampler2D diffuseMap; +// the interpolated position +varying vec4 position; + // the interpolated normal varying vec4 normal; @@ -26,7 +29,7 @@ void main(void) { gl_FrontLightProduct[0].diffuse * (diffuse * facingLight)); // compute the specular component (sans exponent) - float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position + vec4(0.0, 0.0, 1.0, 0.0)), + float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(vec4(position.xyz, 0.0))), normalizedNormal)); // modulate texture by base color and add specular contribution diff --git a/interface/resources/shaders/model.vert b/interface/resources/shaders/model.vert index 904e3c2a8b..f78ed5045b 100644 --- a/interface/resources/shaders/model.vert +++ b/interface/resources/shaders/model.vert @@ -11,6 +11,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +// the interpolated position +varying vec4 position; + // the interpolated normal varying vec4 normal; @@ -19,6 +22,9 @@ void main(void) { // transform and store the normal for interpolation normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); + // likewise with the position + position = gl_ModelViewMatrix * gl_Vertex; + // pass along the vertex color gl_FrontColor = gl_Color; diff --git a/interface/resources/shaders/model_normal_map.frag b/interface/resources/shaders/model_normal_map.frag index 392be1f1cf..8444f2d6ea 100644 --- a/interface/resources/shaders/model_normal_map.frag +++ b/interface/resources/shaders/model_normal_map.frag @@ -17,6 +17,9 @@ uniform sampler2D diffuseMap; // the normal map texture uniform sampler2D normalMap; +// the interpolated position +varying vec4 interpolatedPosition; + // the interpolated normal varying vec4 interpolatedNormal; @@ -38,8 +41,8 @@ void main(void) { gl_FrontLightProduct[0].diffuse * (diffuse * facingLight)); // compute the specular component (sans exponent) - float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position + vec4(0.0, 0.0, 1.0, 0.0)), - viewNormal)); + float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - + normalize(vec4(vec3(interpolatedPosition), 0.0))), viewNormal)); // modulate texture by base color and add specular contribution gl_FragColor = base * texture2D(diffuseMap, gl_TexCoord[0].st) + diff --git a/interface/resources/shaders/model_normal_map.vert b/interface/resources/shaders/model_normal_map.vert index 3607501acf..b013a0a736 100644 --- a/interface/resources/shaders/model_normal_map.vert +++ b/interface/resources/shaders/model_normal_map.vert @@ -14,6 +14,9 @@ // the tangent vector attribute vec3 tangent; +// the interpolated position +varying vec4 interpolatedPosition; + // the interpolated normal varying vec4 interpolatedNormal; @@ -22,7 +25,8 @@ varying vec4 interpolatedTangent; void main(void) { - // transform and store the normal and tangent for interpolation + // transform and store the position, normal and tangent for interpolation + interpolatedPosition = gl_ModelViewMatrix * gl_Vertex; interpolatedNormal = gl_ModelViewMatrix * vec4(gl_Normal, 0.0); interpolatedTangent = gl_ModelViewMatrix * vec4(tangent, 0.0); diff --git a/interface/resources/shaders/model_normal_specular_map.frag b/interface/resources/shaders/model_normal_specular_map.frag index dbbb343c62..357677d82a 100644 --- a/interface/resources/shaders/model_normal_specular_map.frag +++ b/interface/resources/shaders/model_normal_specular_map.frag @@ -20,6 +20,9 @@ uniform sampler2D normalMap; // the specular map texture uniform sampler2D specularMap; +// the interpolated position +varying vec4 interpolatedPosition; + // the interpolated normal varying vec4 interpolatedNormal; @@ -41,8 +44,8 @@ void main(void) { gl_FrontLightProduct[0].diffuse * (diffuse * facingLight)); // compute the specular component (sans exponent) - float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position + vec4(0.0, 0.0, 1.0, 0.0)), - viewNormal)); + float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - + normalize(vec4(interpolatedPosition.xyz, 0.0))), viewNormal)); // modulate texture by base color and add specular contribution gl_FragColor = base * texture2D(diffuseMap, gl_TexCoord[0].st) + vec4(pow(specular, gl_FrontMaterial.shininess) * diff --git a/interface/resources/shaders/model_specular_map.frag b/interface/resources/shaders/model_specular_map.frag index b955b5cfa6..a07324cd1b 100644 --- a/interface/resources/shaders/model_specular_map.frag +++ b/interface/resources/shaders/model_specular_map.frag @@ -17,6 +17,9 @@ uniform sampler2D diffuseMap; // the specular texture uniform sampler2D specularMap; +// the interpolated position in view space +varying vec4 position; + // the interpolated normal varying vec4 normal; @@ -29,7 +32,7 @@ void main(void) { gl_FrontLightProduct[0].diffuse * (diffuse * facingLight)); // compute the specular component (sans exponent) - float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position + vec4(0.0, 0.0, 1.0, 0.0)), + float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(vec4(position.xyz, 0.0))), normalizedNormal)); // modulate texture by base color and add specular contribution diff --git a/interface/resources/shaders/skin_model.vert b/interface/resources/shaders/skin_model.vert index 12320ba9a9..f743609dc3 100644 --- a/interface/resources/shaders/skin_model.vert +++ b/interface/resources/shaders/skin_model.vert @@ -19,11 +19,14 @@ uniform mat4 clusterMatrices[MAX_CLUSTERS]; attribute vec4 clusterIndices; attribute vec4 clusterWeights; +// the interpolated position +varying vec4 position; + // the interpolated normal varying vec4 normal; void main(void) { - vec4 position = vec4(0.0, 0.0, 0.0, 0.0); + position = vec4(0.0, 0.0, 0.0, 0.0); normal = vec4(0.0, 0.0, 0.0, 0.0); for (int i = 0; i < INDICES_PER_VERTEX; i++) { mat4 clusterMatrix = clusterMatrices[int(clusterIndices[i])]; @@ -31,7 +34,7 @@ void main(void) { position += clusterMatrix * gl_Vertex * clusterWeight; normal += clusterMatrix * vec4(gl_Normal, 0.0) * clusterWeight; } - position = gl_ModelViewProjectionMatrix * position; + position = gl_ModelViewMatrix * position; normal = normalize(gl_ModelViewMatrix * normal); // pass along the vertex color @@ -40,5 +43,5 @@ void main(void) { // and the texture coordinates gl_TexCoord[0] = gl_MultiTexCoord0; - gl_Position = position; + gl_Position = gl_ProjectionMatrix * position; } diff --git a/interface/resources/shaders/skin_model_normal_map.vert b/interface/resources/shaders/skin_model_normal_map.vert index 872cbe2fc3..5dbc32626a 100644 --- a/interface/resources/shaders/skin_model_normal_map.vert +++ b/interface/resources/shaders/skin_model_normal_map.vert @@ -22,6 +22,9 @@ attribute vec3 tangent; attribute vec4 clusterIndices; attribute vec4 clusterWeights; +// the interpolated position +varying vec4 interpolatedPosition; + // the interpolated normal varying vec4 interpolatedNormal; @@ -29,17 +32,17 @@ varying vec4 interpolatedNormal; varying vec4 interpolatedTangent; void main(void) { - vec4 position = vec4(0.0, 0.0, 0.0, 0.0); + interpolatedPosition = vec4(0.0, 0.0, 0.0, 0.0); interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0); interpolatedTangent = vec4(0.0, 0.0, 0.0, 0.0); for (int i = 0; i < INDICES_PER_VERTEX; i++) { mat4 clusterMatrix = clusterMatrices[int(clusterIndices[i])]; float clusterWeight = clusterWeights[i]; - position += clusterMatrix * gl_Vertex * clusterWeight; + interpolatedPosition += clusterMatrix * gl_Vertex * clusterWeight; interpolatedNormal += clusterMatrix * vec4(gl_Normal, 0.0) * clusterWeight; interpolatedTangent += clusterMatrix * vec4(tangent, 0.0) * clusterWeight; } - position = gl_ModelViewProjectionMatrix * position; + interpolatedPosition = gl_ModelViewMatrix * interpolatedPosition; interpolatedNormal = gl_ModelViewMatrix * interpolatedNormal; interpolatedTangent = gl_ModelViewMatrix * interpolatedTangent; @@ -49,5 +52,5 @@ void main(void) { // and the texture coordinates gl_TexCoord[0] = gl_MultiTexCoord0; - gl_Position = position; + gl_Position = gl_ProjectionMatrix * interpolatedPosition; } From 38ae1f3be329c5c2a26aa4dae672f7d1d4326cad Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Fri, 23 May 2014 11:17:55 -0700 Subject: [PATCH 04/45] Added a new lock specific to deleting, and improved safety --- interface/src/ui/overlays/Overlays.cpp | 43 ++++++++++++++++---------- interface/src/ui/overlays/Overlays.h | 1 + 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index bcac86d7f1..da7b05ead7 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -39,15 +39,22 @@ void Overlays::init(QGLWidget* parent) { } void Overlays::update(float deltatime) { - QWriteLocker lock(&_lock); - foreach (Overlay* thisOverlay, _overlays2D) { - thisOverlay->update(deltatime); + + { + QWriteLocker lock(&_lock); + foreach(Overlay* thisOverlay, _overlays2D) { + thisOverlay->update(deltatime); + } + foreach(Overlay* thisOverlay, _overlays3D) { + thisOverlay->update(deltatime); + } } - foreach (Overlay* thisOverlay, _overlays3D) { - thisOverlay->update(deltatime); - } - while (!_overlaysToDelete.isEmpty()) { - delete _overlaysToDelete.takeLast(); + + if (!_overlaysToDelete.isEmpty()) { + QWriteLocker lock(&_deleteLock); + do { + delete _overlaysToDelete.takeLast(); + } while (!_overlaysToDelete.isEmpty()); } } @@ -172,15 +179,19 @@ bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) { void Overlays::deleteOverlay(unsigned int id) { Overlay* overlayToDelete; - QWriteLocker lock(&_lock); - if (_overlays2D.contains(id)) { - overlayToDelete = _overlays2D.take(id); - } else if (_overlays3D.contains(id)) { - overlayToDelete = _overlays3D.take(id); - } else { - return; + + { + QWriteLocker lock(&_lock); + if (_overlays2D.contains(id)) { + overlayToDelete = _overlays2D.take(id); + } else if (_overlays3D.contains(id)) { + overlayToDelete = _overlays3D.take(id); + } else { + return; + } } - + + QWriteLocker lock(&_deleteLock); _overlaysToDelete.push_back(overlayToDelete); } diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 20015b8af9..2fbdb993f4 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -46,6 +46,7 @@ private: unsigned int _nextOverlayID; QGLWidget* _parent; QReadWriteLock _lock; + QReadWriteLock _deleteLock; }; From c36273122647c31efb253f019237e0b5472f5053 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 26 May 2014 09:57:37 -0700 Subject: [PATCH 05/45] Add support to load script engines not based on a file --- interface/src/Application.cpp | 19 ++++++++++++------- interface/src/Application.h | 2 +- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1e3e11910e..76fc29e97a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3381,15 +3381,20 @@ ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScript return _scriptEnginesHash[scriptName]; } - // start the script on a new thread... - ScriptEngine* scriptEngine = new ScriptEngine(QUrl(scriptName), &_controllerScriptingInterface); - _scriptEnginesHash.insert(scriptName, scriptEngine); + ScriptEngine* scriptEngine; + if (scriptName.isNull()) { + scriptEngine = new ScriptEngine(NO_SCRIPT, "", &_controllerScriptingInterface); + } else { + // start the script on a new thread... + scriptEngine = new ScriptEngine(QUrl(scriptName), &_controllerScriptingInterface); + _scriptEnginesHash.insert(scriptName, scriptEngine); - if (!scriptEngine->hasScript()) { - qDebug() << "Application::loadScript(), script failed to load..."; - return NULL; + if (!scriptEngine->hasScript()) { + qDebug() << "Application::loadScript(), script failed to load..."; + return NULL; + } + _runningScriptsWidget->setRunningScripts(getRunningScripts()); } - _runningScriptsWidget->setRunningScripts(getRunningScripts()); // setup the packet senders and jurisdiction listeners of the script engine's scripting interfaces so // we can use the same ones from the application. diff --git a/interface/src/Application.h b/interface/src/Application.h index ea0de764b9..9ff2009f2d 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -290,7 +290,7 @@ public slots: void loadScriptURLDialog(); void toggleLogDialog(); void initAvatarAndViewFrustum(); - ScriptEngine* loadScript(const QString& fileNameString, bool loadScriptFromEditor = false); + ScriptEngine* loadScript(const QString& fileNameString = QString(), bool loadScriptFromEditor = false); void stopAllScripts(bool restart = false); void stopScript(const QString& scriptName); void reloadAllScripts(); From 3d28cff9dfe5f66c9ef2cac7a8ae8e35446b2cf8 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 26 May 2014 09:58:06 -0700 Subject: [PATCH 06/45] Add console to menu --- interface/src/Menu.cpp | 15 +++++++++++++++ interface/src/Menu.h | 4 ++++ 2 files changed, 19 insertions(+) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index e1d0c6a574..103cefbb2f 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -78,6 +78,7 @@ Menu::Menu() : _faceshiftEyeDeflection(DEFAULT_FACESHIFT_EYE_DEFLECTION), _frustumDrawMode(FRUSTUM_DRAW_MODE_ALL), _viewFrustumOffset(DEFAULT_FRUSTUM_OFFSET), + _jsConsole(NULL), _octreeStatsDialog(NULL), _lodToolsDialog(NULL), _maxVoxels(DEFAULT_MAX_VOXELS_PER_SYSTEM), @@ -222,6 +223,12 @@ Menu::Menu() : _chatWindow = new ChatWindow(Application::getInstance()->getWindow()); #endif + addActionToQMenuAndActionHash(toolsMenu, + MenuOption::Console, + Qt::CTRL | Qt::Key_QuoteLeft, + this, + SLOT(showConsole())); + QMenu* viewMenu = addMenu("View"); addCheckableActionToQMenuAndActionHash(viewMenu, @@ -1195,6 +1202,14 @@ void Menu::toggleChat() { #endif } +void Menu::showConsole() { + QMainWindow* mainWindow = Application::getInstance()->getWindow(); + if (!_jsConsole) { + _jsConsole = new JSConsole(mainWindow); + } + _jsConsole->setVisible(!_jsConsole->isVisible()); +} + void Menu::audioMuteToggled() { QAction *muteAction = _actionHash.value(MenuOption::MuteAudio); muteAction->setChecked(Application::getInstance()->getAudio()->getMuted()); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 230584bf07..b1d33e0a27 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -26,6 +26,7 @@ #include "location/LocationManager.h" #include "ui/PreferencesDialog.h" #include "ui/ChatWindow.h" +#include "ui/JSConsole.h" #include "ui/ScriptEditorWindow.h" const float ADJUST_LOD_DOWN_FPS = 40.0; @@ -187,6 +188,7 @@ private slots: void showMetavoxelEditor(); void showScriptEditor(); void showChat(); + void showConsole(); void toggleChat(); void audioMuteToggled(); void namedLocationCreated(LocationManager::NamedLocationCreateResponse response); @@ -241,6 +243,7 @@ private: QPointer _MetavoxelEditor; QPointer _ScriptEditor; QPointer _chatWindow; + JSConsole* _jsConsole; OctreeStatsDialog* _octreeStatsDialog; LodToolsDialog* _lodToolsDialog; int _maxVoxels; @@ -297,6 +300,7 @@ namespace MenuOption { const QString CollideWithParticles = "Collide With Particles"; const QString CollideWithVoxels = "Collide With Voxels"; const QString Collisions = "Collisions"; + const QString Console = "Console..."; const QString DecreaseAvatarSize = "Decrease Avatar Size"; const QString DecreaseVoxelSize = "Decrease Voxel Size"; const QString DisableAutoAdjustLOD = "Disable Automatically Adjusting LOD"; From 8aa9cea30e76c796ba3cd1bc242dca8d34f1ac0d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 26 May 2014 09:59:02 -0700 Subject: [PATCH 07/45] Add custom evaluation of commands in ScriptEngine --- libraries/script-engine/src/ScriptEngine.cpp | 12 ++++++++++++ libraries/script-engine/src/ScriptEngine.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index be97b37b46..3f92d8426b 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -304,6 +304,18 @@ void ScriptEngine::evaluate() { } } +QScriptValue ScriptEngine::evaluate(const QString& program, const QString& fileName, int lineNumber) { + QScriptValue result = _engine.evaluate(program, fileName, lineNumber); + bool hasUncaughtException = _engine.hasUncaughtException(); + if (hasUncaughtException) { + int line = _engine.uncaughtExceptionLineNumber(); + qDebug() << "Uncaught exception at line" << line << ": " << result.toString(); + } + emit evaluationFinished(result, hasUncaughtException); + _engine.clearExceptions(); + return result; +} + void ScriptEngine::sendAvatarIdentityPacket() { if (_isAvatar && _avatarData) { _avatarData->sendIdentityPacket(); diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 09d41e3e2e..7c9f263694 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -93,6 +93,7 @@ public: public slots: void stop(); + QScriptValue evaluate(const QString& program, const QString& fileName = QString(), int lineNumber = 1); QObject* setInterval(const QScriptValue& function, int intervalMS); QObject* setTimeout(const QScriptValue& function, int timeoutMS); void clearInterval(QObject* timer) { stopTimer(reinterpret_cast(timer)); } @@ -108,6 +109,7 @@ signals: void printedMessage(const QString& message); void errorMessage(const QString& message); void runningStateChanged(); + void evaluationFinished(QScriptValue result, bool isException); protected: QString _scriptContents; From 5a5d5b4983cf182bd4339a9082526b9fd7d5bbf7 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 26 May 2014 09:59:28 -0700 Subject: [PATCH 08/45] Add JSConsole --- interface/src/ui/JSConsole.cpp | 229 +++++++++++++++++++++++++++++++++ interface/src/ui/JSConsole.h | 62 +++++++++ 2 files changed, 291 insertions(+) create mode 100644 interface/src/ui/JSConsole.cpp create mode 100644 interface/src/ui/JSConsole.h diff --git a/interface/src/ui/JSConsole.cpp b/interface/src/ui/JSConsole.cpp new file mode 100644 index 0000000000..d0880cd50b --- /dev/null +++ b/interface/src/ui/JSConsole.cpp @@ -0,0 +1,229 @@ +// +// JSConsole.cpp +// interface/src/ui +// +// Created by Ryan Huffman on 05/12/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 +#include +#include + +#include "Application.h" +#include "ScriptHighlighting.h" + +#include "JSConsole.h" + +const int NO_CURRENT_HISTORY_COMMAND = -1; +const int MAX_HISTORY_SIZE = 64; + +const QString ACTIVE_PROMPT_STYLESHEET = "color: rgb(0, 0, 255);"; +const QString INACTIVE_PROMPT_STYLESHEET = "color: rgba(0, 0, 0, 0.5);"; +const QString COMMAND_STYLE = "color: rgb(30, 141, 255);"; + +const QString RESULT_ERROR_STYLE = "color: rgb(255, 0, 0);"; +const QString RESULT_SUCCESS_STYLE = "color: rgb(160, 160, 160);"; + +const QString GUTTER_ERROR = "
X
"; +const QString GUTTER_PREVIOUS_COMMAND = "
<
"; + +JSConsole::JSConsole(QWidget* parent, ScriptEngine* scriptEngine) : + QDialog(parent, Qt::WindowStaysOnTopHint), + _ui(new Ui::Console), + _currentCommandInHistory(NO_CURRENT_HISTORY_COMMAND), + _commandHistory(), + _scriptEngine(scriptEngine) { + + _ui->setupUi(this); + _ui->promptTextEdit->setLineWrapMode(QTextEdit::NoWrap); + _ui->promptTextEdit->installEventFilter(this); + + connect(_ui->scrollArea->verticalScrollBar(), SIGNAL(rangeChanged(int, int)), this, SLOT(scrollToBottom())); + connect(_ui->promptTextEdit, SIGNAL(textChanged()), this, SLOT(resizeTextInput())); + + + if (_scriptEngine == NULL) { + _scriptEngine = Application::getInstance()->loadScript(); + } + + connect(_scriptEngine, SIGNAL(evaluationFinished(QScriptValue, bool)), + this, SLOT(handleEvalutationFinished(QScriptValue, bool))); + connect(_scriptEngine, SIGNAL(printedMessage(const QString&)), this, SLOT(handlePrint(const QString&))); + + setWindowOpacity(0.95); +} + +JSConsole::~JSConsole() { + delete _ui; +} + +void JSConsole::executeCommand(const QString& command) { + _commandHistory.prepend(command); + if (_commandHistory.length() > MAX_HISTORY_SIZE) { + _commandHistory.removeLast(); + } + + _ui->promptTextEdit->setDisabled(true); + _ui->promptGutterLabel->setStyleSheet(INACTIVE_PROMPT_STYLESHEET); + + appendMessage(">", "
" + command.toHtmlEscaped() + "
"); + + QMetaObject::invokeMethod(_scriptEngine, "evaluate", Q_ARG(const QString&, command)); + + resetCurrentCommandHistory(); +} + +void JSConsole::handleEvalutationFinished(QScriptValue result, bool isException) { + _ui->promptTextEdit->setDisabled(false); + _ui->promptGutterLabel->setStyleSheet(ACTIVE_PROMPT_STYLESHEET); + + // Make sure focus is still on this window - some commands are blocking and can take awhile to execute. + if (window()->isActiveWindow()) { + _ui->promptTextEdit->setFocus(); + } + + QString gutter = (isException || result.isError()) ? GUTTER_ERROR : GUTTER_PREVIOUS_COMMAND; + QString resultColor = (isException || result.isError()) ? RESULT_ERROR_STYLE : RESULT_SUCCESS_STYLE; + QString resultStr = "
" + result.toString().toHtmlEscaped()  + "
"; + appendMessage(gutter, resultStr); +} + +void JSConsole::handlePrint(const QString& message) { + appendMessage("", message); +} + +void JSConsole::mouseReleaseEvent(QMouseEvent* event) { + _ui->promptTextEdit->setFocus(); +} + +void JSConsole::showEvent(QShowEvent* event) { + _ui->promptTextEdit->setFocus(); +} + +bool JSConsole::eventFilter(QObject* sender, QEvent* event) { + if (sender == _ui->promptTextEdit) { + if (event->type() == QEvent::KeyPress) { + QKeyEvent* keyEvent = static_cast(event); + int key = keyEvent->key(); + + if ((key == Qt::Key_Return || key == Qt::Key_Enter)) { + if (keyEvent->modifiers() & Qt::ShiftModifier) { + // If the shift key is being used then treat it as a regular return/enter. If this isn't done, + // a new QTextBlock isn't created. + keyEvent->setModifiers(keyEvent->modifiers() & ~Qt::ShiftModifier); + } else { + QString command = _ui->promptTextEdit->toPlainText().trimmed(); + + if (!command.isEmpty()) { + QTextCursor cursor = _ui->promptTextEdit->textCursor(); + cursor.select(QTextCursor::Document); + cursor.removeSelectedText(); + + executeCommand(command); + } + + return true; + } + } else if (key == Qt::Key_Down) { + // Go to the next command in history if the cursor is at the last line of the current command. + int blockNumber = _ui->promptTextEdit->textCursor().blockNumber(); + int blockCount = _ui->promptTextEdit->document()->blockCount(); + if (blockNumber == blockCount - 1) { + setToNextCommandInHistory(); + return true; + } + } else if (key == Qt::Key_Up) { + // Go to the previous command in history if the cursor is at the first line of the current command. + int blockNumber = _ui->promptTextEdit->textCursor().blockNumber(); + if (blockNumber == 0) { + setToPreviousCommandInHistory(); + return true; + } + } + } + } + return false; +} + +void JSConsole::setToNextCommandInHistory() { + if (_currentCommandInHistory >= 0) { + _currentCommandInHistory--; + if (_currentCommandInHistory == NO_CURRENT_HISTORY_COMMAND) { + setAndSelectCommand(_rootCommand); + } else { + setAndSelectCommand(_commandHistory[_currentCommandInHistory]); + } + } +} + +void JSConsole::setToPreviousCommandInHistory() { + if (_currentCommandInHistory < (_commandHistory.length() - 1)) { + if (_currentCommandInHistory == NO_CURRENT_HISTORY_COMMAND) { + _rootCommand = _ui->promptTextEdit->toPlainText(); + } + _currentCommandInHistory++; + setAndSelectCommand(_commandHistory[_currentCommandInHistory]); + } +} + +void JSConsole::resetCurrentCommandHistory() { + _currentCommandInHistory = NO_CURRENT_HISTORY_COMMAND; +} + +void JSConsole::resizeTextInput() { + _ui->promptTextEdit->setMaximumHeight(_ui->promptTextEdit->document()->size().height()); + _ui->promptTextEdit->updateGeometry(); +} + +void JSConsole::setAndSelectCommand(const QString& text) { + QTextCursor cursor = _ui->promptTextEdit->textCursor(); + cursor.select(QTextCursor::Document); + cursor.deleteChar(); + cursor.insertText(text); + cursor.movePosition(QTextCursor::End); +} + +void JSConsole::scrollToBottom() { + QScrollBar* scrollBar = _ui->scrollArea->verticalScrollBar(); + scrollBar->setValue(scrollBar->maximum()); +} + +void JSConsole::appendMessage(const QString& gutter, const QString& message) { + QWidget* logLine = new QWidget(_ui->logArea); + QHBoxLayout* layout = new QHBoxLayout(logLine); + layout->setMargin(0); + layout->setSpacing(4); + + QLabel* gutterLabel = new QLabel(logLine); + QLabel* messageLabel = new QLabel(logLine); + + gutterLabel->setFixedWidth(16); + gutterLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); + messageLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); + + QFont font("Courier New"); + font.setStyleHint(QFont::Monospace); + gutterLabel->setFont(font); + messageLabel->setFont(font); + + gutterLabel->setText(gutter); + messageLabel->setText(message); + + layout->addWidget(gutterLabel); + layout->addWidget(messageLabel); + logLine->setLayout(layout); + + layout->setAlignment(gutterLabel, Qt::AlignTop); + + layout->setStretch(0, 0); + layout->setStretch(1, 1); + + _ui->logArea->layout()->addWidget(logLine); + + _ui->logArea->updateGeometry(); + scrollToBottom(); +} diff --git a/interface/src/ui/JSConsole.h b/interface/src/ui/JSConsole.h new file mode 100644 index 0000000000..ebc8aeb43b --- /dev/null +++ b/interface/src/ui/JSConsole.h @@ -0,0 +1,62 @@ +// +// JSConsole.h +// interface/src/ui +// +// Created by Ryan Huffman on 05/12/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_JSConsole_h +#define hifi_JSConsole_h + +#include +#include +#include +#include + +#include "ui_console.h" +#include "ScriptEngine.h" + +class JSConsole : public QDialog { + Q_OBJECT +public: + JSConsole(QWidget* parent, ScriptEngine* scriptEngine = NULL); + ~JSConsole(); + +public slots: + void executeCommand(const QString& command); + +signals: + void commandExecuting(const QString& command); + void commandFinished(const QString& result); + +protected: + void setAndSelectCommand(const QString& command); + virtual bool eventFilter(QObject* sender, QEvent* event); + virtual void mouseReleaseEvent(QMouseEvent* event); + virtual void showEvent(QShowEvent* event); + +protected slots: + void scrollToBottom(); + void resizeTextInput(); + void handleEvalutationFinished(QScriptValue result, bool isException); + void handlePrint(const QString& message); + +private: + void appendMessage(const QString& gutter, const QString& message); + void setToNextCommandInHistory(); + void setToPreviousCommandInHistory(); + void resetCurrentCommandHistory(); + + Ui::Console* _ui; + int _currentCommandInHistory; + QList _commandHistory; + QString _rootCommand; + ScriptEngine* _scriptEngine; +}; + + +#endif // hifi_JSConsole_h From 1d7272cbbf5735cda554bffe829549eb6da88199 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 26 May 2014 10:18:04 -0700 Subject: [PATCH 09/45] Add console.ui interface file --- interface/ui/console.ui | 257 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 257 insertions(+) create mode 100644 interface/ui/console.ui diff --git a/interface/ui/console.ui b/interface/ui/console.ui new file mode 100644 index 0000000000..2f5e6d235e --- /dev/null +++ b/interface/ui/console.ui @@ -0,0 +1,257 @@ + + + Console + + + + 0 + 0 + 1018 + 263 + + + + Dialog + + + QDialog { background: white } + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + QFrame::NoFrame + + + Qt::ScrollBarAlwaysOn + + + true + + + + + 0 + 0 + 1003 + 263 + + + + background-color: white; + + + + 4 + + + 4 + + + 4 + + + 4 + + + 4 + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + background-color: white; + + + + 4 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 16 + 0 + + + + + 16 + 16 + + + + + 75 + true + + + + background-color: white; font-weight: bold; color: blue; + + + > + + + + + + + + 0 + 0 + + + + + Courier New + + + + QFrame::NoFrame + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + Qt::TextEditorInteraction + + + + + + + + + + + + + + + + + + + + + From 422c2eac6733ddc83174396fd6d8550c988b70a8 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 27 May 2014 07:29:48 -0700 Subject: [PATCH 10/45] Update showConsole -> toggleConsole and change shortcut --- interface/src/Menu.cpp | 6 +++--- interface/src/Menu.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 7e641fb069..cce8399491 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -229,9 +229,9 @@ Menu::Menu() : addActionToQMenuAndActionHash(toolsMenu, MenuOption::Console, - Qt::CTRL | Qt::Key_QuoteLeft, + Qt::CTRL | Qt::ALT | Qt::Key_J, this, - SLOT(showConsole())); + SLOT(toggleConsole())); QMenu* viewMenu = addMenu("View"); @@ -1230,7 +1230,7 @@ void Menu::toggleChat() { #endif } -void Menu::showConsole() { +void Menu::toggleConsole() { QMainWindow* mainWindow = Application::getInstance()->getWindow(); if (!_jsConsole) { _jsConsole = new JSConsole(mainWindow); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 1aace5d83b..c9577e708e 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -190,7 +190,7 @@ private slots: void showMetavoxelEditor(); void showScriptEditor(); void showChat(); - void showConsole(); + void toggleConsole(); void toggleChat(); void audioMuteToggled(); void namedLocationCreated(LocationManager::NamedLocationCreateResponse response); From b9248e0bbf7bfe9e57590ace44a7664d72207801 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 27 May 2014 08:03:46 -0700 Subject: [PATCH 11/45] Update JSConsole to QWidget --- interface/src/Menu.cpp | 18 +++++++++++++++++- interface/src/Menu.h | 2 +- interface/src/ui/JSConsole.cpp | 2 +- interface/src/ui/JSConsole.h | 2 +- interface/ui/console.ui | 24 +++++++++++++----------- 5 files changed, 33 insertions(+), 15 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index cce8399491..a924528c2b 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -72,6 +72,11 @@ const int ONE_SECOND_OF_FRAMES = 60; const int FIVE_SECONDS_OF_FRAMES = 5 * ONE_SECOND_OF_FRAMES; const float MUTE_RADIUS = 50; +const QString CONSOLE_TITLE = "Scripting Console"; +const float CONSOLE_WINDOW_OPACITY = 0.95; +const int CONSOLE_WIDTH = 800; +const int CONSOLE_HEIGHT = 200; + Menu::Menu() : _actionHash(), _audioJitterBufferSamples(0), @@ -1233,7 +1238,18 @@ void Menu::toggleChat() { void Menu::toggleConsole() { QMainWindow* mainWindow = Application::getInstance()->getWindow(); if (!_jsConsole) { - _jsConsole = new JSConsole(mainWindow); + QDialog* dialog = new QDialog(mainWindow, Qt::WindowStaysOnTopHint); + QVBoxLayout* layout = new QVBoxLayout(dialog); + dialog->setLayout(new QVBoxLayout(dialog)); + + dialog->resize(QSize(CONSOLE_WIDTH, CONSOLE_HEIGHT)); + layout->setMargin(0); + layout->setSpacing(0); + layout->addWidget(new JSConsole(dialog)); + dialog->setWindowOpacity(CONSOLE_WINDOW_OPACITY); + dialog->setWindowTitle(CONSOLE_TITLE); + + _jsConsole = dialog; } _jsConsole->setVisible(!_jsConsole->isVisible()); } diff --git a/interface/src/Menu.h b/interface/src/Menu.h index c9577e708e..6b37791b45 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -245,7 +245,7 @@ private: QPointer _MetavoxelEditor; QPointer _ScriptEditor; QPointer _chatWindow; - JSConsole* _jsConsole; + QDialog* _jsConsole; OctreeStatsDialog* _octreeStatsDialog; LodToolsDialog* _lodToolsDialog; int _maxVoxels; diff --git a/interface/src/ui/JSConsole.cpp b/interface/src/ui/JSConsole.cpp index d0880cd50b..267be0bc6d 100644 --- a/interface/src/ui/JSConsole.cpp +++ b/interface/src/ui/JSConsole.cpp @@ -32,7 +32,7 @@ const QString GUTTER_ERROR = "
X
"; const QString GUTTER_PREVIOUS_COMMAND = "
<
"; JSConsole::JSConsole(QWidget* parent, ScriptEngine* scriptEngine) : - QDialog(parent, Qt::WindowStaysOnTopHint), + QWidget(parent), _ui(new Ui::Console), _currentCommandInHistory(NO_CURRENT_HISTORY_COMMAND), _commandHistory(), diff --git a/interface/src/ui/JSConsole.h b/interface/src/ui/JSConsole.h index ebc8aeb43b..f28132a1f5 100644 --- a/interface/src/ui/JSConsole.h +++ b/interface/src/ui/JSConsole.h @@ -20,7 +20,7 @@ #include "ui_console.h" #include "ScriptEngine.h" -class JSConsole : public QDialog { +class JSConsole : public QWidget { Q_OBJECT public: JSConsole(QWidget* parent, ScriptEngine* scriptEngine = NULL); diff --git a/interface/ui/console.ui b/interface/ui/console.ui index 2f5e6d235e..7c86ab3d8f 100644 --- a/interface/ui/console.ui +++ b/interface/ui/console.ui @@ -1,13 +1,13 @@ Console - + 0 0 - 1018 - 263 + 1055 + 205 @@ -75,8 +75,8 @@ 0 0 - 1003 - 263 + 1040 + 205 @@ -203,14 +203,14 @@ - background-color: white; font-weight: bold; color: blue; + background-color: white; font-weight: bold; color: rgb(169, 187, 195); > - + @@ -220,9 +220,14 @@ - Courier New + Inconsolata,Lucida Console,Andale Mono,Monaco + -1 + + font-family: Inconsolata, Lucida Console, Andale Mono, Monaco; +font-size:14px + QFrame::NoFrame @@ -232,9 +237,6 @@ Qt::ScrollBarAlwaysOff - - Qt::TextEditorInteraction - From 9af0269151c55e07c453ffb2dba9f8ce12a87f44 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 27 May 2014 08:05:56 -0700 Subject: [PATCH 12/45] Update console style --- interface/resources/styles/console.qss | 20 ++++++++++++++ interface/src/ui/JSConsole.cpp | 38 +++++++++++++------------- 2 files changed, 39 insertions(+), 19 deletions(-) create mode 100644 interface/resources/styles/console.qss diff --git a/interface/resources/styles/console.qss b/interface/resources/styles/console.qss new file mode 100644 index 0000000000..c10e429cea --- /dev/null +++ b/interface/resources/styles/console.qss @@ -0,0 +1,20 @@ +* { + font-family: Inconsolata, Lucida Console, Andale Mono, Monaco; + font-size: 14px; +} + +promptTextEdit { + color: rgb(117, 133, 140); +} + +promptTextEdit:!enabled { + color: rgba(0, 0, 0, 0.5); +} + +promptGutterLabel { + color: rgba(117, 133, 140); +} + +promptGutterLabel:!enabled { + color: rgba(0, 0, 0, 0.5); +} diff --git a/interface/src/ui/JSConsole.cpp b/interface/src/ui/JSConsole.cpp index 267be0bc6d..59d2765812 100644 --- a/interface/src/ui/JSConsole.cpp +++ b/interface/src/ui/JSConsole.cpp @@ -21,15 +21,13 @@ const int NO_CURRENT_HISTORY_COMMAND = -1; const int MAX_HISTORY_SIZE = 64; -const QString ACTIVE_PROMPT_STYLESHEET = "color: rgb(0, 0, 255);"; -const QString INACTIVE_PROMPT_STYLESHEET = "color: rgba(0, 0, 0, 0.5);"; -const QString COMMAND_STYLE = "color: rgb(30, 141, 255);"; +const QString COMMAND_STYLE = "color: rgb(38, 106, 155);"; -const QString RESULT_ERROR_STYLE = "color: rgb(255, 0, 0);"; -const QString RESULT_SUCCESS_STYLE = "color: rgb(160, 160, 160);"; +const QString RESULT_SUCCESS_STYLE = "color: rgb(103, 115, 115);"; +const QString RESULT_ERROR_STYLE = "color: rgb(209, 59, 34);"; -const QString GUTTER_ERROR = "
X
"; -const QString GUTTER_PREVIOUS_COMMAND = "
<
"; +const QString GUTTER_PREVIOUS_COMMAND = "<"; +const QString GUTTER_ERROR = "X"; JSConsole::JSConsole(QWidget* parent, ScriptEngine* scriptEngine) : QWidget(parent), @@ -38,8 +36,15 @@ JSConsole::JSConsole(QWidget* parent, ScriptEngine* scriptEngine) : _commandHistory(), _scriptEngine(scriptEngine) { + QFile styleSheet(Application::resourcesPath() + "styles/console.qss"); + if (styleSheet.open(QIODevice::ReadOnly)) { + QDir::setCurrent(Application::resourcesPath()); + setStyleSheet(styleSheet.readAll()); + } + _ui->setupUi(this); _ui->promptTextEdit->setLineWrapMode(QTextEdit::NoWrap); + _ui->promptTextEdit->setWordWrapMode(QTextOption::NoWrap); _ui->promptTextEdit->installEventFilter(this); connect(_ui->scrollArea->verticalScrollBar(), SIGNAL(rangeChanged(int, int)), this, SLOT(scrollToBottom())); @@ -54,7 +59,7 @@ JSConsole::JSConsole(QWidget* parent, ScriptEngine* scriptEngine) : this, SLOT(handleEvalutationFinished(QScriptValue, bool))); connect(_scriptEngine, SIGNAL(printedMessage(const QString&)), this, SLOT(handlePrint(const QString&))); - setWindowOpacity(0.95); + resizeTextInput(); } JSConsole::~JSConsole() { @@ -68,9 +73,8 @@ void JSConsole::executeCommand(const QString& command) { } _ui->promptTextEdit->setDisabled(true); - _ui->promptGutterLabel->setStyleSheet(INACTIVE_PROMPT_STYLESHEET); - appendMessage(">", "
" + command.toHtmlEscaped() + "
"); + appendMessage(">", "" + command.toHtmlEscaped() + ""); QMetaObject::invokeMethod(_scriptEngine, "evaluate", Q_ARG(const QString&, command)); @@ -79,7 +83,6 @@ void JSConsole::executeCommand(const QString& command) { void JSConsole::handleEvalutationFinished(QScriptValue result, bool isException) { _ui->promptTextEdit->setDisabled(false); - _ui->promptGutterLabel->setStyleSheet(ACTIVE_PROMPT_STYLESHEET); // Make sure focus is still on this window - some commands are blocking and can take awhile to execute. if (window()->isActiveWindow()) { @@ -88,7 +91,7 @@ void JSConsole::handleEvalutationFinished(QScriptValue result, bool isException) QString gutter = (isException || result.isError()) ? GUTTER_ERROR : GUTTER_PREVIOUS_COMMAND; QString resultColor = (isException || result.isError()) ? RESULT_ERROR_STYLE : RESULT_SUCCESS_STYLE; - QString resultStr = "
" + result.toString().toHtmlEscaped()  + "
"; + QString resultStr = "" + result.toString().toHtmlEscaped() + ""; appendMessage(gutter, resultStr); } @@ -120,8 +123,7 @@ bool JSConsole::eventFilter(QObject* sender, QEvent* event) { if (!command.isEmpty()) { QTextCursor cursor = _ui->promptTextEdit->textCursor(); - cursor.select(QTextCursor::Document); - cursor.removeSelectedText(); + _ui->promptTextEdit->clear(); executeCommand(command); } @@ -175,7 +177,7 @@ void JSConsole::resetCurrentCommandHistory() { } void JSConsole::resizeTextInput() { - _ui->promptTextEdit->setMaximumHeight(_ui->promptTextEdit->document()->size().height()); + _ui->promptTextEdit->setFixedHeight(_ui->promptTextEdit->document()->size().height()); _ui->promptTextEdit->updateGeometry(); } @@ -205,10 +207,8 @@ void JSConsole::appendMessage(const QString& gutter, const QString& message) { gutterLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); messageLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); - QFont font("Courier New"); - font.setStyleHint(QFont::Monospace); - gutterLabel->setFont(font); - messageLabel->setFont(font); + gutterLabel->setStyleSheet("font-size: 14px; font-family: Inconsolata, Lucida Console, Andale Mono, Monaco;"); + messageLabel->setStyleSheet("font-size: 14px; font-family: Inconsolata, Lucida Console, Andale Mono, Monaco;"); gutterLabel->setText(gutter); messageLabel->setText(message); From 4a0a9f8a3651a5ed6e19cd57eabd7855519f3d4b Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 27 May 2014 08:57:29 -0700 Subject: [PATCH 13/45] Update console style --- interface/resources/styles/console.qss | 8 ++++---- interface/src/ui/JSConsole.cpp | 10 +++++----- interface/ui/console.ui | 17 ++++++++--------- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/interface/resources/styles/console.qss b/interface/resources/styles/console.qss index c10e429cea..9e8a3c0ad4 100644 --- a/interface/resources/styles/console.qss +++ b/interface/resources/styles/console.qss @@ -3,18 +3,18 @@ font-size: 14px; } -promptTextEdit { +#promptTextEdit { color: rgb(117, 133, 140); } -promptTextEdit:!enabled { +#promptTextEdit:!enabled { color: rgba(0, 0, 0, 0.5); } -promptGutterLabel { +#promptGutterLabel { color: rgba(117, 133, 140); } -promptGutterLabel:!enabled { +#promptGutterLabel:!enabled { color: rgba(0, 0, 0, 0.5); } diff --git a/interface/src/ui/JSConsole.cpp b/interface/src/ui/JSConsole.cpp index 59d2765812..87d2fb4860 100644 --- a/interface/src/ui/JSConsole.cpp +++ b/interface/src/ui/JSConsole.cpp @@ -36,17 +36,17 @@ JSConsole::JSConsole(QWidget* parent, ScriptEngine* scriptEngine) : _commandHistory(), _scriptEngine(scriptEngine) { + _ui->setupUi(this); + _ui->promptTextEdit->setLineWrapMode(QTextEdit::NoWrap); + _ui->promptTextEdit->setWordWrapMode(QTextOption::NoWrap); + _ui->promptTextEdit->installEventFilter(this); + QFile styleSheet(Application::resourcesPath() + "styles/console.qss"); if (styleSheet.open(QIODevice::ReadOnly)) { QDir::setCurrent(Application::resourcesPath()); setStyleSheet(styleSheet.readAll()); } - _ui->setupUi(this); - _ui->promptTextEdit->setLineWrapMode(QTextEdit::NoWrap); - _ui->promptTextEdit->setWordWrapMode(QTextOption::NoWrap); - _ui->promptTextEdit->installEventFilter(this); - connect(_ui->scrollArea->verticalScrollBar(), SIGNAL(rangeChanged(int, int)), this, SLOT(scrollToBottom())); connect(_ui->promptTextEdit, SIGNAL(textChanged()), this, SLOT(resizeTextInput())); diff --git a/interface/ui/console.ui b/interface/ui/console.ui index 7c86ab3d8f..d4b0b2bc74 100644 --- a/interface/ui/console.ui +++ b/interface/ui/console.ui @@ -187,27 +187,30 @@ 16 - 0 + 23 16 - 16 + 23 - 75 - true + 50 + false - background-color: white; font-weight: bold; color: rgb(169, 187, 195); + padding: 0px 0 0 0; > + + Qt::PlainText +
@@ -224,10 +227,6 @@ -1 - - font-family: Inconsolata, Lucida Console, Andale Mono, Monaco; -font-size:14px - QFrame::NoFrame From 44c5e56a4bb6484725a34e1ad6251bf30faa6f73 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 27 May 2014 14:09:53 -0700 Subject: [PATCH 14/45] Update JSConsole colors --- interface/resources/styles/console.qss | 8 ++++---- interface/src/ui/JSConsole.cpp | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/interface/resources/styles/console.qss b/interface/resources/styles/console.qss index 9e8a3c0ad4..021d5d84e9 100644 --- a/interface/resources/styles/console.qss +++ b/interface/resources/styles/console.qss @@ -4,17 +4,17 @@ } #promptTextEdit { - color: rgb(117, 133, 140); + color: #425d72; } #promptTextEdit:!enabled { - color: rgba(0, 0, 0, 0.5); + color: #7f7f7f; } #promptGutterLabel { - color: rgba(117, 133, 140); + color: #a9bbc3; } #promptGutterLabel:!enabled { - color: rgba(0, 0, 0, 0.5); + color: #7f7f7f; } diff --git a/interface/src/ui/JSConsole.cpp b/interface/src/ui/JSConsole.cpp index 87d2fb4860..921c571d44 100644 --- a/interface/src/ui/JSConsole.cpp +++ b/interface/src/ui/JSConsole.cpp @@ -21,13 +21,13 @@ const int NO_CURRENT_HISTORY_COMMAND = -1; const int MAX_HISTORY_SIZE = 64; -const QString COMMAND_STYLE = "color: rgb(38, 106, 155);"; +const QString COMMAND_STYLE = "color: #266a9b;"; -const QString RESULT_SUCCESS_STYLE = "color: rgb(103, 115, 115);"; -const QString RESULT_ERROR_STYLE = "color: rgb(209, 59, 34);"; +const QString RESULT_SUCCESS_STYLE = "color: #677373;"; +const QString RESULT_ERROR_STYLE = "color: #d13b22;"; -const QString GUTTER_PREVIOUS_COMMAND = "<"; -const QString GUTTER_ERROR = "X"; +const QString GUTTER_PREVIOUS_COMMAND = "<"; +const QString GUTTER_ERROR = "X"; JSConsole::JSConsole(QWidget* parent, ScriptEngine* scriptEngine) : QWidget(parent), From 6ef802621550b0a3d34bfe0dfcf831997f63f21b Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 27 May 2014 14:10:09 -0700 Subject: [PATCH 15/45] Add console to script editor --- interface/src/ui/ScriptEditorWindow.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/interface/src/ui/ScriptEditorWindow.cpp b/interface/src/ui/ScriptEditorWindow.cpp index 41732d18c6..3f63f0741b 100644 --- a/interface/src/ui/ScriptEditorWindow.cpp +++ b/interface/src/ui/ScriptEditorWindow.cpp @@ -27,6 +27,9 @@ #include "Application.h" #include "FlowLayout.h" +#include "JSConsole.h" + +const int CONSOLE_HEIGHT = 150; ScriptEditorWindow::ScriptEditorWindow() : _ScriptEditorWindowUI(new Ui::ScriptEditorWindow), @@ -48,6 +51,10 @@ ScriptEditorWindow::ScriptEditorWindow() : connect(new QShortcut(QKeySequence("Ctrl+S"), this), &QShortcut::activated, this,&ScriptEditorWindow::saveScriptClicked); connect(new QShortcut(QKeySequence("Ctrl+O"), this), &QShortcut::activated, this, &ScriptEditorWindow::loadScriptClicked); connect(new QShortcut(QKeySequence("F5"), this), &QShortcut::activated, this, &ScriptEditorWindow::toggleRunScriptClicked); + + QWidget* console = new JSConsole(this); + console->setFixedHeight(CONSOLE_HEIGHT); + this->layout()->addWidget(console); } ScriptEditorWindow::~ScriptEditorWindow() { From e89d33dc60f560042c35ec81db4074515ceb2833 Mon Sep 17 00:00:00 2001 From: wangyix Date: Tue, 27 May 2014 18:02:49 -0700 Subject: [PATCH 16/45] added if to not track ParticleErase packets --- .../src/octree/OctreeQueryNode.cpp | 14 +++++++ .../src/octree/OctreeQueryNode.h | 2 + .../src/octree/OctreeSendThread.cpp | 10 ++++- interface/src/Application.cpp | 7 +++- interface/src/voxels/VoxelPacketProcessor.cpp | 3 +- libraries/networking/src/LimitedNodeList.cpp | 38 +++++++++++++++++++ libraries/octree/src/OctreeSceneStats.cpp | 21 ++++++---- libraries/octree/src/OctreeSceneStats.h | 2 +- 8 files changed, 86 insertions(+), 11 deletions(-) diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index ede6dee5e3..f56a96d367 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -365,4 +365,18 @@ void OctreeQueryNode::dumpOutOfView() { void OctreeQueryNode::incrementSequenceNumber() { _sequenceNumber++; +} + +void OctreeQueryNode::updatePacketTimestamp() { + + int numBytesPacketHeader = populatePacketHeader(reinterpret_cast(_octreePacket), _myPacketType); + _octreePacketAt = _octreePacket + numBytesPacketHeader; + _octreePacketAt += sizeof(OCTREE_PACKET_FLAGS); + _octreePacketAt += sizeof(OCTREE_PACKET_SEQUENCE); + + // pack in timestamp + OCTREE_PACKET_SENT_TIME now = usecTimestampNow(); + OCTREE_PACKET_SENT_TIME* timeAt = (OCTREE_PACKET_SENT_TIME*)_octreePacketAt; + *timeAt = now; + } \ No newline at end of file diff --git a/assignment-client/src/octree/OctreeQueryNode.h b/assignment-client/src/octree/OctreeQueryNode.h index 1bb3a72a0c..a1a8aa4a66 100644 --- a/assignment-client/src/octree/OctreeQueryNode.h +++ b/assignment-client/src/octree/OctreeQueryNode.h @@ -101,6 +101,8 @@ public: bool isShuttingDown() const { return _isShuttingDown; } void incrementSequenceNumber(); + + void updatePacketTimestamp(); private slots: void sendThreadFinished(); diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 8d6803adac..c98c8c77b8 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -142,12 +142,18 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes } const unsigned char* messageData = nodeData->getPacket(); +//unsigned char messageData[MAX_PACKET_SIZE]; +//memcpy(messageData, nodeData->getPacket(), MAX_PACKET_SIZE); // DEBUG: make copy of message to send + int numBytesPacketHeader = numBytesForPacketHeader(reinterpret_cast(messageData)); const unsigned char* dataAt = messageData + numBytesPacketHeader; dataAt += sizeof(OCTREE_PACKET_FLAGS); OCTREE_PACKET_SEQUENCE sequence = (*(OCTREE_PACKET_SEQUENCE*)dataAt); dataAt += sizeof(OCTREE_PACKET_SEQUENCE); + OCTREE_PACKET_SENT_TIME timestamp = (*(OCTREE_PACKET_SENT_TIME*)dataAt); + dataAt += sizeof(OCTREE_PACKET_SENT_TIME); + // If we've got a stats message ready to send, then see if we can piggyback them together if (nodeData->stats.isReadyToSend() && !nodeData->isShuttingDown()) { @@ -161,6 +167,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes // copy voxel message to back of stats message memcpy(statsMessage + statsMessageLength, nodeData->getPacket(), nodeData->getPacketLength()); +//memcpy(statsMessage + statsMessageLength, messageData, nodeData->getPacketLength()); statsMessageLength += nodeData->getPacketLength(); // since a stats message is only included on end of scene, don't consider any of these bytes "wasted", since @@ -203,6 +210,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes OctreeServer::didCallWriteDatagram(this); NodeList::getInstance()->writeDatagram((char*) nodeData->getPacket(), nodeData->getPacketLength(), _node); +//NodeList::getInstance()->writeDatagram((char*)messageData, nodeData->getPacketLength(), _node); packetSent = true; @@ -223,6 +231,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes // just send the voxel packet OctreeServer::didCallWriteDatagram(this); NodeList::getInstance()->writeDatagram((char*) nodeData->getPacket(), nodeData->getPacketLength(), _node); +//NodeList::getInstance()->writeDatagram((char*)messageData, nodeData->getPacketLength(), _node); packetSent = true; int thisWastedBytes = MAX_PACKET_SIZE - nodeData->getPacketLength(); @@ -245,7 +254,6 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes nodeData->incrementSequenceNumber(); nodeData->resetOctreePacket(); } - return packetsSent; } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 07309fab85..a8b56f360d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3301,7 +3301,12 @@ void Application::trackIncomingVoxelPacket(const QByteArray& packet, const Share _octreeSceneStatsLock.lockForWrite(); if (_octreeServerSceneStats.find(nodeUUID) != _octreeServerSceneStats.end()) { OctreeSceneStats& stats = _octreeServerSceneStats[nodeUUID]; - stats.trackIncomingOctreePacket(packet, wasStatsPacket, sendingNode->getClockSkewUsec()); + if (stats.trackIncomingOctreePacket(packet, wasStatsPacket, sendingNode->getClockSkewUsec())) { + + // DEBUG! unreasonable flight time + qDebug() << " sending node type: " << NodeType::getNodeTypeName(sendingNode->getType()) << "\n"; + //qDebug() << "\t\t clock skew: " << sendingNode->getClockSkewUsec(); + } } _octreeSceneStatsLock.unlock(); } diff --git a/interface/src/voxels/VoxelPacketProcessor.cpp b/interface/src/voxels/VoxelPacketProcessor.cpp index c0f27264f6..d03eaf0946 100644 --- a/interface/src/voxels/VoxelPacketProcessor.cpp +++ b/interface/src/voxels/VoxelPacketProcessor.cpp @@ -39,7 +39,7 @@ void VoxelPacketProcessor::processPacket(const SharedNodePointer& sendingNode, c } PacketType voxelPacketType = packetTypeForPacket(mutablePacket); - + // note: PacketType_OCTREE_STATS can have PacketType_VOXEL_DATA // immediately following them inside the same packet. So, we process the PacketType_OCTREE_STATS first // then process any remaining bytes as if it was another packet @@ -81,6 +81,7 @@ void VoxelPacketProcessor::processPacket(const SharedNodePointer& sendingNode, c if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) { +if (voxelPacketType != PacketTypeParticleErase) app->trackIncomingVoxelPacket(mutablePacket, sendingNode, wasStatsPacket); if (sendingNode) { diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index c0d7941edf..68255bbd41 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -268,6 +268,44 @@ qint64 LimitedNodeList::writeUnverifiedDatagram(const QByteArray& datagram, cons qint64 LimitedNodeList::writeDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode, const HifiSockAddr& overridenSockAddr) { + /* + QByteArray datagram(data, size); + + qDebug() << "\t writeDatagram()..."; + + PacketType type = packetTypeForPacket(datagram); + if (type != PacketType::PacketTypeParticleErase) { + + qDebug() << "\t\t type: " << (unsigned char)type; + qDebug() << "\t\t UUID: " << uuidFromPacketHeader(datagram); + qDebug() << "\t\t MD5: " << hashFromPacketHeader(datagram); + + + int numBytesPacketHeader = numBytesForPacketHeader(datagram); + const unsigned char* dataAt = reinterpret_cast(datagram.data()) + numBytesPacketHeader; + + unsigned char flags = (*(unsigned char*)(dataAt)); + dataAt += sizeof(unsigned char); + qDebug() << "\t\t flags: " << QString::number(flags, 2); + + uint16_t sequence = (*(uint16_t*)dataAt); + dataAt += sizeof(uint16_t); + qDebug() << "\t\t sequence: " << QString::number(sequence, 16); + + quint64 sentAt = (*(quint64*)dataAt); + dataAt += sizeof(quint64); + qDebug() << "\t\t sent at: " << QString::number(sentAt, 16) << "\n"; + } + else { + qDebug() << "size: " << size; + const char* dataAt = data; + for (int i = 0; i < size; i++) { + unsigned char byte = *((unsigned char*)dataAt); + dataAt += sizeof(unsigned char); + qDebug() << "\t\t " << QString::number(byte, 16); + } + }*/ + return writeDatagram(QByteArray(data, size), destinationNode, overridenSockAddr); } diff --git a/libraries/octree/src/OctreeSceneStats.cpp b/libraries/octree/src/OctreeSceneStats.cpp index c08e723f89..2b04b5652c 100644 --- a/libraries/octree/src/OctreeSceneStats.cpp +++ b/libraries/octree/src/OctreeSceneStats.cpp @@ -839,7 +839,7 @@ const char* OctreeSceneStats::getItemValue(Item item) { return _itemValueBuffer; } -void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, +bool OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, bool wasStatsPacket, int nodeClockSkewUsec) { const bool wantExtraDebugging = false; @@ -857,8 +857,8 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, //bool packetIsColored = oneAtBit(flags, PACKET_IS_COLOR_BIT); //bool packetIsCompressed = oneAtBit(flags, PACKET_IS_COMPRESSED_BIT); - OCTREE_PACKET_SENT_TIME arrivedAt = usecTimestampNow(); - int flightTime = arrivedAt - sentAt + nodeClockSkewUsec; + OCTREE_PACKET_SENT_TIME arrivedAt = usecTimestampNow(); // DEBUG!!! + qint64 flightTime = arrivedAt - sentAt + nodeClockSkewUsec; if (wantExtraDebugging) { qDebug() << "sentAt:" << sentAt << " usecs"; @@ -866,13 +866,20 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, qDebug() << "nodeClockSkewUsec:" << nodeClockSkewUsec << " usecs"; qDebug() << "flightTime:" << flightTime << " usecs"; } - + + +//qDebug() << "\t" << QString::number(sequence, 16) << "\t sentAt:" << QString::number(sentAt, 16) << " usecs"; + // Guard against possible corrupted packets... with bad timestamps const int MAX_RESONABLE_FLIGHT_TIME = 200 * USECS_PER_SECOND; // 200 seconds is more than enough time for a packet to arrive const int MIN_RESONABLE_FLIGHT_TIME = 0; if (flightTime > MAX_RESONABLE_FLIGHT_TIME || flightTime < MIN_RESONABLE_FLIGHT_TIME) { qDebug() << "ignoring unreasonable packet... flightTime:" << flightTime; - return; // ignore any packets that are unreasonable +qDebug() << "\t sentAt:" << QString::number(sentAt, 16) << " usecs"; +qDebug() << "\t arrivedAt:" << QString::number(arrivedAt, 16) << " usecs"; +qDebug() << "\t nodeClockSkewUsec:" << nodeClockSkewUsec << " usecs"; +qDebug() << "\t flightTime:" << flightTime << " usecs"; + return true; // ignore any packets that are unreasonable } // determine our expected sequence number... handle rollover appropriately @@ -884,7 +891,7 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, int sequenceOffset = (sequence - expected); if (sequenceOffset > MAX_RESONABLE_SEQUENCE_OFFSET || sequenceOffset < MIN_RESONABLE_SEQUENCE_OFFSET) { qDebug() << "ignoring unreasonable packet... sequence:" << sequence << "_incomingLastSequence:" << _incomingLastSequence; - return; // ignore any packets that are unreasonable + return false; // ignore any packets that are unreasonable } // track packets here... @@ -985,6 +992,6 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, } } } - + return false; } diff --git a/libraries/octree/src/OctreeSceneStats.h b/libraries/octree/src/OctreeSceneStats.h index ef22fd7c1c..dd0b31b010 100644 --- a/libraries/octree/src/OctreeSceneStats.h +++ b/libraries/octree/src/OctreeSceneStats.h @@ -158,7 +158,7 @@ public: quint64 getLastFullTotalBytes() const { return _lastFullTotalBytes; } // Used in client implementations to track individual octree packets - void trackIncomingOctreePacket(const QByteArray& packet, bool wasStatsPacket, int nodeClockSkewUsec); + bool trackIncomingOctreePacket(const QByteArray& packet, bool wasStatsPacket, int nodeClockSkewUsec); quint32 getIncomingPackets() const { return _incomingPacket; } quint64 getIncomingBytes() const { return _incomingBytes; } From f361b9a8a7b91e44a260e5db450b4e181ba2ad81 Mon Sep 17 00:00:00 2001 From: wangyix Date: Tue, 27 May 2014 18:04:53 -0700 Subject: [PATCH 17/45] removed updatePacketTimestamp() ..from OctreeQueryNode --- assignment-client/src/octree/OctreeQueryNode.cpp | 14 -------------- assignment-client/src/octree/OctreeQueryNode.h | 2 -- 2 files changed, 16 deletions(-) diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index f56a96d367..a5f89dc71b 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -366,17 +366,3 @@ void OctreeQueryNode::dumpOutOfView() { void OctreeQueryNode::incrementSequenceNumber() { _sequenceNumber++; } - -void OctreeQueryNode::updatePacketTimestamp() { - - int numBytesPacketHeader = populatePacketHeader(reinterpret_cast(_octreePacket), _myPacketType); - _octreePacketAt = _octreePacket + numBytesPacketHeader; - _octreePacketAt += sizeof(OCTREE_PACKET_FLAGS); - _octreePacketAt += sizeof(OCTREE_PACKET_SEQUENCE); - - // pack in timestamp - OCTREE_PACKET_SENT_TIME now = usecTimestampNow(); - OCTREE_PACKET_SENT_TIME* timeAt = (OCTREE_PACKET_SENT_TIME*)_octreePacketAt; - *timeAt = now; - -} \ No newline at end of file diff --git a/assignment-client/src/octree/OctreeQueryNode.h b/assignment-client/src/octree/OctreeQueryNode.h index a1a8aa4a66..1bb3a72a0c 100644 --- a/assignment-client/src/octree/OctreeQueryNode.h +++ b/assignment-client/src/octree/OctreeQueryNode.h @@ -101,8 +101,6 @@ public: bool isShuttingDown() const { return _isShuttingDown; } void incrementSequenceNumber(); - - void updatePacketTimestamp(); private slots: void sendThreadFinished(); From 6fd22856f22449bc4c973612cb7d86886050a035 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 28 May 2014 10:24:02 -0700 Subject: [PATCH 18/45] hacking on non-AABox models --- examples/editModelExample.js | 14 ++-- interface/src/models/ModelTreeRenderer.cpp | 87 ++++++++++++++++++++++ libraries/models/src/ModelTreeElement.cpp | 53 ++++++++++++- 3 files changed, 143 insertions(+), 11 deletions(-) diff --git a/examples/editModelExample.js b/examples/editModelExample.js index dbea1419ba..3b23b3ca5a 100644 --- a/examples/editModelExample.js +++ b/examples/editModelExample.js @@ -15,13 +15,13 @@ var count = 0; var moveUntil = 2000; var stopAfter = moveUntil + 100; -var pitch = 90.0; +var pitch = 0.0; var yaw = 0.0; -var roll = 180.0; +var roll = 0.0; var rotation = Quat.fromPitchYawRollDegrees(pitch, yaw, roll) var originalProperties = { - position: { x: 10, + position: { x: 0, y: 0, z: 0 }, @@ -31,12 +31,12 @@ var originalProperties = { green: 255, blue: 0 }, - //modelURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/Feisar_Ship.FBX", + modelURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/Feisar_Ship.FBX", //modelURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/birarda/birarda_head.fbx", //modelURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/pug.fbx", //modelURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/newInvader16x16-large-purple.svo", //modelURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/minotaur/mino_full.fbx", - modelURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/Combat_tank_V01.FBX", + //modelURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/meshes/Combat_tank_V01.FBX", modelRotation: rotation }; @@ -51,8 +51,8 @@ function moveModel(deltaTime) { // delete it... if (count == moveUntil) { - print("calling Models.deleteModel()"); - Models.deleteModel(modelID); + //print("calling Models.deleteModel()"); + //Models.deleteModel(modelID); } // stop it... diff --git a/interface/src/models/ModelTreeRenderer.cpp b/interface/src/models/ModelTreeRenderer.cpp index 68bebd7b99..777459d642 100644 --- a/interface/src/models/ModelTreeRenderer.cpp +++ b/interface/src/models/ModelTreeRenderer.cpp @@ -10,6 +10,7 @@ // #include +#include #include @@ -267,6 +268,92 @@ void ModelTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) glutWireCube(1.0); glPopMatrix(); + + + glPushMatrix(); + { + Extents extents = model->getUnscaledMeshExtents(); + +qDebug() << "original..."; + +qDebug() << " extents.minimum=" << extents.minimum.x << "," << extents.minimum.y << "," << extents.minimum.z; +qDebug() << " extents.maximum=" << extents.maximum.x << "," << extents.maximum.y << "," << extents.maximum.z; + + float maxDimension = glm::distance(extents.maximum, extents.minimum); + float scale = modelItem.getSize() / maxDimension; + +qDebug() << " maxDimension=" << maxDimension; +qDebug() << " modelItem.getSize()=" << modelItem.getSize(); +qDebug() << " modelItem.getSize() [meters]=" << modelItem.getSize() * (float)TREE_SCALE; +qDebug() << " scale=" << scale; + + glm::vec3 halfDimensions = (extents.maximum - extents.minimum) * 0.5f; + glm::vec3 offset = -extents.minimum - halfDimensions; + + extents.minimum += offset; + extents.maximum += offset; + +qDebug() << "after offset..."; + +qDebug() << " extents.minimum=" << extents.minimum.x << "," << extents.minimum.y << "," << extents.minimum.z; +qDebug() << " extents.maximum=" << extents.maximum.x << "," << extents.maximum.y << "," << extents.maximum.z; + + extents.minimum *= (scale * (float)TREE_SCALE); + extents.maximum *= (scale * (float)TREE_SCALE); + +qDebug() << "after scale..."; + +qDebug() << " extents.minimum=" << extents.minimum.x << "," << extents.minimum.y << "," << extents.minimum.z; +qDebug() << " extents.maximum=" << extents.maximum.x << "," << extents.maximum.y << "," << extents.maximum.z; + + // using transform matrix draw spheres at corners + glm::mat4 rotation = glm::mat4_cast(modelItem.getModelRotation()); + glm::vec3 modelPosition = modelItem.getPosition() * (float)TREE_SCALE; + glm::mat4 translation = glm::translate(modelPosition); + glm::mat4 modelToWorldMatrix = translation * rotation; + glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix); + + + glm::vec3 modelOrigin(0); + glm::vec3 modelOriginInWorld = glm::vec3(modelToWorldMatrix * glm::vec4(modelOrigin, 1.0f)); + + glm::vec3 bottomLeftNear = extents.minimum; + glm::vec3 topRightFar = extents.maximum; + + glm::vec3 blnInWorld = glm::vec3(modelToWorldMatrix * glm::vec4(bottomLeftNear, 1.0f)); + glm::vec3 trfInWorld = glm::vec3(modelToWorldMatrix * glm::vec4(topRightFar, 1.0f)); + +//qDebug() << "modelPosition =" << modelPosition.x << "," << modelPosition.y << "," << modelPosition.z; +//qDebug() << "modelOrigin =" << modelOrigin.x << "," << modelOrigin.y << "," << modelOrigin.z; +//qDebug() << "modelOriginInWorld =" << modelOriginInWorld.x << "," << modelOriginInWorld.y << "," << modelOriginInWorld.z; + +qDebug() << " modelPosition =" << modelPosition.x << "," << modelPosition.y << "," << modelPosition.z; +qDebug() << " bottomLeftNear =" << bottomLeftNear.x << "," << bottomLeftNear.y << "," << bottomLeftNear.z; +qDebug() << " blnInWorld =" << blnInWorld.x << "," << blnInWorld.y << "," << blnInWorld.z; + + glPushMatrix(); + glTranslatef(modelOriginInWorld.x, modelOriginInWorld.y, modelOriginInWorld.z); + // draw the orignal bounding cube + glColor3f(0.0f, 1.0f, 0.0f); + glutSolidCube(0.02f); + glPopMatrix(); + + glPushMatrix(); + glTranslatef(blnInWorld.x, blnInWorld.y, blnInWorld.z); + // draw the orignal bounding cube + glColor3f(0.0f, 0.0f, 1.0f); + glutSolidCube(0.02f); + glPopMatrix(); + + glPushMatrix(); + glTranslatef(trfInWorld.x, trfInWorld.y, trfInWorld.z); + // draw the orignal bounding cube + glColor3f(1.0f, 0.0f, 1.0f); + glutSolidCube(0.02f); + glPopMatrix(); + + } + glPopMatrix(); } diff --git a/libraries/models/src/ModelTreeElement.cpp b/libraries/models/src/ModelTreeElement.cpp index dad592f838..12d427aee5 100644 --- a/libraries/models/src/ModelTreeElement.cpp +++ b/libraries/models/src/ModelTreeElement.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include #include @@ -177,15 +179,58 @@ bool ModelTreeElement::findDetailedRayIntersection(const glm::vec3& origin, cons extents.minimum *= scale; extents.maximum *= scale; + + Extents rotatedExtents = extents; - calculateRotatedExtents(extents, model.getModelRotation()); + calculateRotatedExtents(rotatedExtents, model.getModelRotation()); - extents.minimum += model.getPosition(); - extents.maximum += model.getPosition(); + rotatedExtents.minimum += model.getPosition(); + rotatedExtents.maximum += model.getPosition(); - AABox rotatedExtentsBox(extents.minimum, (extents.maximum - extents.minimum)); + + AABox rotatedExtentsBox(rotatedExtents.minimum, (rotatedExtents.maximum - rotatedExtents.minimum)); if (rotatedExtentsBox.findRayIntersection(origin, direction, localDistance, localFace)) { + // if it's in our AABOX for our rotated extents, then check to see if it's in our non-AABox + + glm::mat4 rotation = glm::mat4_cast(model.getModelRotation()); + glm::mat4 translation = glm::translate(model.getPosition()); + glm::mat4 modelToWorldMatrix = rotation; // * translation; + glm::mat4 worldToModelMatrix = modelToWorldMatrix; // glm::inverse(modelToWorldMatrix); + + // Note: reference, to get the point after rotation, take the rotation * the original point + //glm::vec3 rotatedPoint = rotation * originalPoint; + + AABox nonAABox(extents.minimum, (extents.maximum - extents.minimum)); + + glm::vec3 endPoint = origin + direction; + + + glm::vec3 originInModelFrame = glm::vec3(worldToModelMatrix * glm::vec4(origin, 0.0f)); + glm::vec3 endPointInModelFrame = glm::vec3(worldToModelMatrix * glm::vec4(endPoint, 0.0f)); + glm::vec3 directionInModelFrame = endPointInModelFrame - originInModelFrame; + glm::vec3 altDirectionInModelFrame = glm::vec3(worldToModelMatrix * glm::vec4(direction, 0.0f)); + + +qDebug() << "origin =" << origin.x << "," << origin.y << "," << origin.z; +qDebug() << "originInModelFrame =" << originInModelFrame.x << "," << originInModelFrame.y << "," << originInModelFrame.z; + +qDebug() << "endPoint =" << endPoint.x << "," << endPoint.y << "," << endPoint.z; +qDebug() << "endPointInModelFrame =" << endPointInModelFrame.x << "," << endPointInModelFrame.y << "," << endPointInModelFrame.z; + +qDebug() << "direction =" << direction.x << "," << direction.y << "," << direction.z; +qDebug() << "directionInModelFrame =" << directionInModelFrame.x << "," << directionInModelFrame.y << "," << directionInModelFrame.z; +qDebug() << "altDirectionInModelFrame=" << altDirectionInModelFrame.x << "," << altDirectionInModelFrame.y << "," << altDirectionInModelFrame.z; + + float xDistance; + BoxFace xFace; + + if (nonAABox.findRayIntersection(originInModelFrame, directionInModelFrame, xDistance, xFace)) { + qDebug() << "woot! got it! (originInModelFrame, directionInModelFrame) intersects nonAABox!"; + } else { + qDebug() << "NOPE! doesn't (originInModelFrame, directionInModelFrame) intersect nonAABox!"; + } + if (localDistance < distance) { distance = localDistance; face = localFace; From 8b0212dc1eb3ca7c46dc7130819fc7d25fd9850f Mon Sep 17 00:00:00 2001 From: Mohammed Nafees Date: Wed, 28 May 2014 23:19:15 +0530 Subject: [PATCH 19/45] remove all key bindings from running scripts dialog --- interface/src/ui/RunningScriptsWidget.cpp | 34 ++++------------------- interface/ui/runningScriptsWidget.ui | 2 +- 2 files changed, 6 insertions(+), 30 deletions(-) diff --git a/interface/src/ui/RunningScriptsWidget.cpp b/interface/src/ui/RunningScriptsWidget.cpp index 328974dc9d..9bef454829 100644 --- a/interface/src/ui/RunningScriptsWidget.cpp +++ b/interface/src/ui/RunningScriptsWidget.cpp @@ -106,36 +106,12 @@ void RunningScriptsWidget::setRunningScripts(const QStringList& list) { createRecentlyLoadedScriptsTable(); } -void RunningScriptsWidget::keyPressEvent(QKeyEvent* event) -{ - int loadScriptNumber = -1; - switch(event->key()) { - case Qt::Key_Escape: - Application::getInstance()->toggleRunningScriptsWidget(); - break; - - case Qt::Key_1: - case Qt::Key_2: - case Qt::Key_3: - case Qt::Key_4: - case Qt::Key_5: - case Qt::Key_6: - case Qt::Key_7: - case Qt::Key_8: - case Qt::Key_9: - loadScriptNumber = event->key() - Qt::Key_1; - break; - - default: - break; +void RunningScriptsWidget::keyPressEvent(QKeyEvent *keyEvent) { + if (keyEvent->key() == Qt::Key_Escape) { + return; + } else { + FramelessDialog::keyPressEvent(keyEvent); } - if (loadScriptNumber >= 0) { - if (_recentlyLoadedScripts.size() > loadScriptNumber) { - Application::getInstance()->loadScript(_recentlyLoadedScripts.at(loadScriptNumber)); - } - } - - FramelessDialog::keyPressEvent(event); } void RunningScriptsWidget::paintEvent(QPaintEvent* event) { diff --git a/interface/ui/runningScriptsWidget.ui b/interface/ui/runningScriptsWidget.ui index cb0106cd48..6cb23f4c89 100644 --- a/interface/ui/runningScriptsWidget.ui +++ b/interface/ui/runningScriptsWidget.ui @@ -143,7 +143,7 @@ font: bold 14pt; font-size: 14pt; - (click a script or use the 1-9 keys to load and run it) + (click a script to load and run it) true From bebfd7a301be868cd7961004f6dd43dad809c0bb Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 28 May 2014 12:02:22 -0700 Subject: [PATCH 20/45] non-aabox picking working --- interface/src/models/ModelTreeRenderer.cpp | 86 ---------------------- libraries/models/src/ModelTreeElement.cpp | 52 ++++--------- 2 files changed, 14 insertions(+), 124 deletions(-) diff --git a/interface/src/models/ModelTreeRenderer.cpp b/interface/src/models/ModelTreeRenderer.cpp index 777459d642..5f6ac5f21f 100644 --- a/interface/src/models/ModelTreeRenderer.cpp +++ b/interface/src/models/ModelTreeRenderer.cpp @@ -268,92 +268,6 @@ void ModelTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) glutWireCube(1.0); glPopMatrix(); - - - glPushMatrix(); - { - Extents extents = model->getUnscaledMeshExtents(); - -qDebug() << "original..."; - -qDebug() << " extents.minimum=" << extents.minimum.x << "," << extents.minimum.y << "," << extents.minimum.z; -qDebug() << " extents.maximum=" << extents.maximum.x << "," << extents.maximum.y << "," << extents.maximum.z; - - float maxDimension = glm::distance(extents.maximum, extents.minimum); - float scale = modelItem.getSize() / maxDimension; - -qDebug() << " maxDimension=" << maxDimension; -qDebug() << " modelItem.getSize()=" << modelItem.getSize(); -qDebug() << " modelItem.getSize() [meters]=" << modelItem.getSize() * (float)TREE_SCALE; -qDebug() << " scale=" << scale; - - glm::vec3 halfDimensions = (extents.maximum - extents.minimum) * 0.5f; - glm::vec3 offset = -extents.minimum - halfDimensions; - - extents.minimum += offset; - extents.maximum += offset; - -qDebug() << "after offset..."; - -qDebug() << " extents.minimum=" << extents.minimum.x << "," << extents.minimum.y << "," << extents.minimum.z; -qDebug() << " extents.maximum=" << extents.maximum.x << "," << extents.maximum.y << "," << extents.maximum.z; - - extents.minimum *= (scale * (float)TREE_SCALE); - extents.maximum *= (scale * (float)TREE_SCALE); - -qDebug() << "after scale..."; - -qDebug() << " extents.minimum=" << extents.minimum.x << "," << extents.minimum.y << "," << extents.minimum.z; -qDebug() << " extents.maximum=" << extents.maximum.x << "," << extents.maximum.y << "," << extents.maximum.z; - - // using transform matrix draw spheres at corners - glm::mat4 rotation = glm::mat4_cast(modelItem.getModelRotation()); - glm::vec3 modelPosition = modelItem.getPosition() * (float)TREE_SCALE; - glm::mat4 translation = glm::translate(modelPosition); - glm::mat4 modelToWorldMatrix = translation * rotation; - glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix); - - - glm::vec3 modelOrigin(0); - glm::vec3 modelOriginInWorld = glm::vec3(modelToWorldMatrix * glm::vec4(modelOrigin, 1.0f)); - - glm::vec3 bottomLeftNear = extents.minimum; - glm::vec3 topRightFar = extents.maximum; - - glm::vec3 blnInWorld = glm::vec3(modelToWorldMatrix * glm::vec4(bottomLeftNear, 1.0f)); - glm::vec3 trfInWorld = glm::vec3(modelToWorldMatrix * glm::vec4(topRightFar, 1.0f)); - -//qDebug() << "modelPosition =" << modelPosition.x << "," << modelPosition.y << "," << modelPosition.z; -//qDebug() << "modelOrigin =" << modelOrigin.x << "," << modelOrigin.y << "," << modelOrigin.z; -//qDebug() << "modelOriginInWorld =" << modelOriginInWorld.x << "," << modelOriginInWorld.y << "," << modelOriginInWorld.z; - -qDebug() << " modelPosition =" << modelPosition.x << "," << modelPosition.y << "," << modelPosition.z; -qDebug() << " bottomLeftNear =" << bottomLeftNear.x << "," << bottomLeftNear.y << "," << bottomLeftNear.z; -qDebug() << " blnInWorld =" << blnInWorld.x << "," << blnInWorld.y << "," << blnInWorld.z; - - glPushMatrix(); - glTranslatef(modelOriginInWorld.x, modelOriginInWorld.y, modelOriginInWorld.z); - // draw the orignal bounding cube - glColor3f(0.0f, 1.0f, 0.0f); - glutSolidCube(0.02f); - glPopMatrix(); - - glPushMatrix(); - glTranslatef(blnInWorld.x, blnInWorld.y, blnInWorld.z); - // draw the orignal bounding cube - glColor3f(0.0f, 0.0f, 1.0f); - glutSolidCube(0.02f); - glPopMatrix(); - - glPushMatrix(); - glTranslatef(trfInWorld.x, trfInWorld.y, trfInWorld.z); - // draw the orignal bounding cube - glColor3f(1.0f, 0.0f, 1.0f); - glutSolidCube(0.02f); - glPopMatrix(); - - } - glPopMatrix(); } diff --git a/libraries/models/src/ModelTreeElement.cpp b/libraries/models/src/ModelTreeElement.cpp index 12d427aee5..31f786c15c 100644 --- a/libraries/models/src/ModelTreeElement.cpp +++ b/libraries/models/src/ModelTreeElement.cpp @@ -192,51 +192,27 @@ bool ModelTreeElement::findDetailedRayIntersection(const glm::vec3& origin, cons if (rotatedExtentsBox.findRayIntersection(origin, direction, localDistance, localFace)) { // if it's in our AABOX for our rotated extents, then check to see if it's in our non-AABox - + + // extents is the model relative, scaled, centered extents of the model + glm::mat4 rotation = glm::mat4_cast(model.getModelRotation()); glm::mat4 translation = glm::translate(model.getPosition()); - glm::mat4 modelToWorldMatrix = rotation; // * translation; - glm::mat4 worldToModelMatrix = modelToWorldMatrix; // glm::inverse(modelToWorldMatrix); + glm::mat4 modelToWorldMatrix = translation * rotation; + glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix); - // Note: reference, to get the point after rotation, take the rotation * the original point - //glm::vec3 rotatedPoint = rotation * originalPoint; - AABox nonAABox(extents.minimum, (extents.maximum - extents.minimum)); - glm::vec3 endPoint = origin + direction; - + glm::vec3 originInModelFrame = glm::vec3(worldToModelMatrix * glm::vec4(origin, 1.0f)); + glm::vec3 directionInModelFrame = glm::vec3(worldToModelMatrix * glm::vec4(direction, 1.0f)); - glm::vec3 originInModelFrame = glm::vec3(worldToModelMatrix * glm::vec4(origin, 0.0f)); - glm::vec3 endPointInModelFrame = glm::vec3(worldToModelMatrix * glm::vec4(endPoint, 0.0f)); - glm::vec3 directionInModelFrame = endPointInModelFrame - originInModelFrame; - glm::vec3 altDirectionInModelFrame = glm::vec3(worldToModelMatrix * glm::vec4(direction, 0.0f)); - - -qDebug() << "origin =" << origin.x << "," << origin.y << "," << origin.z; -qDebug() << "originInModelFrame =" << originInModelFrame.x << "," << originInModelFrame.y << "," << originInModelFrame.z; - -qDebug() << "endPoint =" << endPoint.x << "," << endPoint.y << "," << endPoint.z; -qDebug() << "endPointInModelFrame =" << endPointInModelFrame.x << "," << endPointInModelFrame.y << "," << endPointInModelFrame.z; - -qDebug() << "direction =" << direction.x << "," << direction.y << "," << direction.z; -qDebug() << "directionInModelFrame =" << directionInModelFrame.x << "," << directionInModelFrame.y << "," << directionInModelFrame.z; -qDebug() << "altDirectionInModelFrame=" << altDirectionInModelFrame.x << "," << altDirectionInModelFrame.y << "," << altDirectionInModelFrame.z; - - float xDistance; - BoxFace xFace; - - if (nonAABox.findRayIntersection(originInModelFrame, directionInModelFrame, xDistance, xFace)) { - qDebug() << "woot! got it! (originInModelFrame, directionInModelFrame) intersects nonAABox!"; - } else { - qDebug() << "NOPE! doesn't (originInModelFrame, directionInModelFrame) intersect nonAABox!"; + if (nonAABox.findRayIntersection(originInModelFrame, directionInModelFrame, localDistance, localFace)) { + if (localDistance < distance) { + distance = localDistance; + face = localFace; + *intersectedObject = (void*)(&model); + somethingIntersected = true; + } } - - if (localDistance < distance) { - distance = localDistance; - face = localFace; - *intersectedObject = (void*)(&model); - somethingIntersected = true; - } } } else if (localDistance < distance) { distance = localDistance; From e3d880248f2be9c1241453a96db8eac67a580c4a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 28 May 2014 12:03:40 -0700 Subject: [PATCH 21/45] tweaks --- examples/editModelExample.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/editModelExample.js b/examples/editModelExample.js index 3b23b3ca5a..83491e2fb1 100644 --- a/examples/editModelExample.js +++ b/examples/editModelExample.js @@ -15,13 +15,13 @@ var count = 0; var moveUntil = 2000; var stopAfter = moveUntil + 100; -var pitch = 0.0; +var pitch = 90.0; var yaw = 0.0; -var roll = 0.0; +var roll = 180.0; var rotation = Quat.fromPitchYawRollDegrees(pitch, yaw, roll) var originalProperties = { - position: { x: 0, + position: { x: 10, y: 0, z: 0 }, @@ -51,8 +51,8 @@ function moveModel(deltaTime) { // delete it... if (count == moveUntil) { - //print("calling Models.deleteModel()"); - //Models.deleteModel(modelID); + print("calling Models.deleteModel()"); + Models.deleteModel(modelID); } // stop it... From d88dd90d79c1ed76165560f9cef7aea7770f0065 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 28 May 2014 12:04:24 -0700 Subject: [PATCH 22/45] revert dead code --- interface/src/models/ModelTreeRenderer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/models/ModelTreeRenderer.cpp b/interface/src/models/ModelTreeRenderer.cpp index 5f6ac5f21f..68bebd7b99 100644 --- a/interface/src/models/ModelTreeRenderer.cpp +++ b/interface/src/models/ModelTreeRenderer.cpp @@ -10,7 +10,6 @@ // #include -#include #include From 574bca38e60f912068bb4e27611e95bc73fdfa76 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 28 May 2014 12:10:51 -0700 Subject: [PATCH 23/45] clean up comments and variable names --- libraries/models/src/ModelTreeElement.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/libraries/models/src/ModelTreeElement.cpp b/libraries/models/src/ModelTreeElement.cpp index 31f786c15c..c655a45b57 100644 --- a/libraries/models/src/ModelTreeElement.cpp +++ b/libraries/models/src/ModelTreeElement.cpp @@ -190,22 +190,23 @@ bool ModelTreeElement::findDetailedRayIntersection(const glm::vec3& origin, cons AABox rotatedExtentsBox(rotatedExtents.minimum, (rotatedExtents.maximum - rotatedExtents.minimum)); + // if it's in our AABOX for our rotated extents, then check to see if it's in our non-AABox if (rotatedExtentsBox.findRayIntersection(origin, direction, localDistance, localFace)) { - // if it's in our AABOX for our rotated extents, then check to see if it's in our non-AABox // extents is the model relative, scaled, centered extents of the model - glm::mat4 rotation = glm::mat4_cast(model.getModelRotation()); glm::mat4 translation = glm::translate(model.getPosition()); glm::mat4 modelToWorldMatrix = translation * rotation; glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix); - AABox nonAABox(extents.minimum, (extents.maximum - extents.minimum)); + AABox modelFrameBox(extents.minimum, (extents.maximum - extents.minimum)); - glm::vec3 originInModelFrame = glm::vec3(worldToModelMatrix * glm::vec4(origin, 1.0f)); - glm::vec3 directionInModelFrame = glm::vec3(worldToModelMatrix * glm::vec4(direction, 1.0f)); + glm::vec3 modelFrameOrigin = glm::vec3(worldToModelMatrix * glm::vec4(origin, 1.0f)); + glm::vec3 modelFrameDirection = glm::vec3(worldToModelMatrix * glm::vec4(direction, 1.0f)); - if (nonAABox.findRayIntersection(originInModelFrame, directionInModelFrame, localDistance, localFace)) { + // we can use the AABox's ray intersection by mapping our origin and direction into the model frame + // and testing intersection there. + if (modelFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, localDistance, localFace)) { if (localDistance < distance) { distance = localDistance; face = localFace; From 9311eeb8f5913619b830bde3158ce4e1b313c4dc Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Wed, 28 May 2014 14:41:30 -0700 Subject: [PATCH 24/45] Fixed compiler warning --- interface/src/Application.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fac0ef154f..570bdb8167 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -162,10 +162,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _bytesPerSecond(0), _nodeBoundsDisplay(this), _previousScriptLocation(), + _applicationOverlay(), _runningScriptsWidget(new RunningScriptsWidget(_window)), _runningScriptsWidgetWasVisible(false), - _trayIcon(new QSystemTrayIcon(_window)), - _applicationOverlay() + _trayIcon(new QSystemTrayIcon(_window)) { // read the ApplicationInfo.ini file for Name/Version/Domain information QSettings applicationInfo(Application::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat); From 13f11e1056a80f2d3b1e6c4fd86ac36d1398b021 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 28 May 2014 14:53:32 -0700 Subject: [PATCH 25/45] Remove "fromBind" arg in Model::setJointRotation It was always set 'true'. --- interface/src/avatar/SkeletonModel.cpp | 10 +++++----- interface/src/renderer/Model.cpp | 5 ++--- interface/src/renderer/Model.h | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 7333bfc395..2001802524 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -45,7 +45,7 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { } int jointIndex = geometry.humanIKJointIndices.at(humanIKJointIndex); if (jointIndex != -1) { - setJointRotation(jointIndex, _rotation * prioVR->getJointRotations().at(i), true, PALM_PRIORITY); + setJointRotation(jointIndex, _rotation * prioVR->getJointRotations().at(i), PALM_PRIORITY); } } return; @@ -188,7 +188,7 @@ void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) { setJointPosition(parentJointIndex, palm.getPosition() + forearmVector * geometry.joints.at(jointIndex).distanceToParent * extractUniformScale(_scale), glm::quat(), false, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY); - setJointRotation(parentJointIndex, palmRotation, true, PALM_PRIORITY); + setJointRotation(parentJointIndex, palmRotation, PALM_PRIORITY); _jointStates[jointIndex].rotation = glm::quat(); } else { @@ -355,12 +355,12 @@ void SkeletonModel::setHandPosition(int jointIndex, const glm::vec3& position, c glm::vec3 forwardVector(rightHand ? -1.0f : 1.0f, 0.0f, 0.0f); glm::quat shoulderRotation = rotationBetween(forwardVector, elbowPosition - shoulderPosition); - setJointRotation(shoulderJointIndex, shoulderRotation, true, PALM_PRIORITY); + setJointRotation(shoulderJointIndex, shoulderRotation, PALM_PRIORITY); setJointRotation(elbowJointIndex, rotationBetween(shoulderRotation * forwardVector, - wristPosition - elbowPosition) * shoulderRotation, true, PALM_PRIORITY); + wristPosition - elbowPosition) * shoulderRotation, PALM_PRIORITY); - setJointRotation(jointIndex, rotation, true, PALM_PRIORITY); + setJointRotation(jointIndex, rotation, PALM_PRIORITY); } bool SkeletonModel::getLeftHandPosition(glm::vec3& position) const { diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 5a93dbcf25..7fff554498 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1231,15 +1231,14 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const return true; } -bool Model::setJointRotation(int jointIndex, const glm::quat& rotation, bool fromBind, float priority) { +bool Model::setJointRotation(int jointIndex, const glm::quat& rotation, float priority) { if (jointIndex == -1 || _jointStates.isEmpty()) { return false; } JointState& state = _jointStates[jointIndex]; if (priority >= state.animationPriority) { state.rotation = state.rotation * glm::inverse(state.combinedRotation) * rotation * - glm::inverse(fromBind ? _geometry->getFBXGeometry().joints.at(jointIndex).inverseBindRotation : - _geometry->getFBXGeometry().joints.at(jointIndex).inverseDefaultRotation); + glm::inverse(_geometry->getFBXGeometry().joints.at(jointIndex).inverseBindRotation); state.animationPriority = priority; } return true; diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index a4e45287dd..75e80fdaa8 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -221,7 +221,7 @@ protected: bool setJointPosition(int jointIndex, const glm::vec3& translation, const glm::quat& rotation = glm::quat(), bool useRotation = false, int lastFreeIndex = -1, bool allIntermediatesFree = false, const glm::vec3& alignment = glm::vec3(0.0f, -1.0f, 0.0f), float priority = 1.0f); - bool setJointRotation(int jointIndex, const glm::quat& rotation, bool fromBind = false, float priority = 1.0f); + bool setJointRotation(int jointIndex, const glm::quat& rotation, float priority = 1.0f); void setJointTranslation(int jointIndex, const glm::vec3& translation); From 8f6ad2faabf0317a1bd1bab3cfb580b1b11f182b Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 28 May 2014 15:27:50 -0700 Subject: [PATCH 26/45] Add 'Load default scripts' button to preferences --- interface/src/Application.cpp | 10 +++- interface/src/Application.h | 1 + interface/src/ui/PreferencesDialog.cpp | 2 + interface/ui/preferencesDialog.ui | 82 ++++++++++++++++++++++++-- 4 files changed, 89 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fac0ef154f..d2b05f2cc4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -105,6 +105,8 @@ const int STARTUP_JITTER_SAMPLES = NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL / 2 const QString CHECK_VERSION_URL = "https://highfidelity.io/latestVersion.xml"; const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/hifi.skipversion"; +const QString DEFAULT_SCRIPTS_JS_URL = "http://public.highfidelity.io/scripts/defaultScripts.js"; + void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) { if (message.size() > 0) { QString dateString = QDateTime::currentDateTime().toTimeSpec(Qt::LocalTime).toString(Qt::ISODate); @@ -362,7 +364,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : qDebug() << "This is a first run..."; // clear the scripts, and set out script to our default scripts clearScriptsBeforeRunning(); - loadScript("http://public.highfidelity.io/scripts/defaultScripts.js"); + loadScript(DEFAULT_SCRIPTS_JS_URL); QMutexLocker locker(&_settingsMutex); _settings->setValue("firstRun",QVariant(false)); @@ -3362,6 +3364,12 @@ void Application::reloadAllScripts() { stopAllScripts(true); } +void Application::loadDefaultScripts() { + if (!_scriptEnginesHash.contains(DEFAULT_SCRIPTS_JS_URL)) { + loadScript(DEFAULT_SCRIPTS_JS_URL); + } +} + void Application::manageRunningScriptsWidgetVisibility(bool shown) { if (_runningScriptsWidgetWasVisible && shown) { _runningScriptsWidget->show(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 0065944611..0d4f1c89d6 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -328,6 +328,7 @@ public slots: void stopAllScripts(bool restart = false); void stopScript(const QString& scriptName); void reloadAllScripts(); + void loadDefaultScripts(); void toggleRunningScriptsWidget(); void uploadHead(); diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index ed2d7097db..d5c6079d4b 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -29,6 +29,8 @@ PreferencesDialog::PreferencesDialog(QWidget* parent, Qt::WindowFlags flags) : F connect(ui.buttonBrowseHead, &QPushButton::clicked, this, &PreferencesDialog::openHeadModelBrowser); connect(ui.buttonBrowseBody, &QPushButton::clicked, this, &PreferencesDialog::openBodyModelBrowser); connect(ui.buttonBrowseLocation, &QPushButton::clicked, this, &PreferencesDialog::openSnapshotLocationBrowser); + connect(ui.buttonReloadDefaultScripts, &QPushButton::clicked, + Application::getInstance(), &Application::loadDefaultScripts); } void PreferencesDialog::accept() { diff --git a/interface/ui/preferencesDialog.ui b/interface/ui/preferencesDialog.ui index bab431160d..a1c2073ab6 100644 --- a/interface/ui/preferencesDialog.ui +++ b/interface/ui/preferencesDialog.ui @@ -134,8 +134,8 @@ color: #0e7077 0 30 - 615 - 491 + 494 + 384 @@ -154,9 +154,9 @@ color: #0e7077 0 - -271 - 598 - 1018 + -204 + 494 + 1091 @@ -612,6 +612,78 @@ color: #0e7077 + + + + + 0 + 0 + + + + + 0 + 40 + + + + + Arial + 20 + 50 + false + + + + color: #0e7077 + + + Scripts + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + + + + + + 0 + 0 + + + + background: #0e7077; +color: #fff; +border-radius: 4px; +font: bold 14pt; +padding: 10px;margin-top:10px + + + Load Default Scripts + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + From e6d12bf239f3abec108abbab45aafc3f073abd7a Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Wed, 28 May 2014 15:56:14 -0700 Subject: [PATCH 27/45] Disabled overlay for oculus. We still have to call applicationOverlay.renderOverlay(true) or prioVR cant calibrate. --- interface/src/devices/OculusManager.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 8f71d38bdb..af18db4006 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -83,7 +83,9 @@ void OculusManager::display(Camera& whichCamera) { #ifdef HAVE_LIBOVR ApplicationOverlay& applicationOverlay = Application::getInstance()->getApplicationOverlay(); // We only need to render the overlays to a texture once, then we just render the texture as a quad + // PrioVR will only work if renderOverlay is called, calibration is connected to Application::renderingOverlay() applicationOverlay.renderOverlay(true); + const bool displayOverlays = false; Application::getInstance()->getGlowEffect()->prepare(); @@ -104,7 +106,9 @@ void OculusManager::display(Camera& whichCamera) { Application::getInstance()->displaySide(whichCamera); - applicationOverlay.displayOverlayTextureOculus(whichCamera); + if (displayOverlays) { + applicationOverlay.displayOverlayTextureOculus(whichCamera); + } // and the right eye to the right side const StereoEyeParams& rightEyeParams = _stereoConfig.GetEyeRenderParams(StereoEye_Right); @@ -121,7 +125,9 @@ void OculusManager::display(Camera& whichCamera) { Application::getInstance()->displaySide(whichCamera); - applicationOverlay.displayOverlayTextureOculus(whichCamera); + if (displayOverlays) { + applicationOverlay.displayOverlayTextureOculus(whichCamera); + } glPopMatrix(); From 9f2a4ae6260b0f24a43ab3137a246166f10175e8 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 28 May 2014 16:49:39 -0700 Subject: [PATCH 28/45] Make JointState a proper class JointState gets a pointer to its corresponding FBXJoint --- interface/src/avatar/FaceModel.cpp | 12 +- interface/src/avatar/SkeletonModel.cpp | 22 ++-- interface/src/renderer/Model.cpp | 157 +++++++++++++------------ interface/src/renderer/Model.h | 25 ++-- 4 files changed, 115 insertions(+), 101 deletions(-) diff --git a/interface/src/avatar/FaceModel.cpp b/interface/src/avatar/FaceModel.cpp index 2cf2f70068..6ecc45e1e3 100644 --- a/interface/src/avatar/FaceModel.cpp +++ b/interface/src/avatar/FaceModel.cpp @@ -49,9 +49,9 @@ void FaceModel::simulate(float deltaTime, bool fullUpdate) { void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) { // get the rotation axes in joint space and use them to adjust the rotation glm::mat3 axes = glm::mat3_cast(_rotation); - glm::mat3 inverse = glm::mat3(glm::inverse(parentState.transform * glm::translate(state.translation) * + glm::mat3 inverse = glm::mat3(glm::inverse(parentState._transform * glm::translate(state._translation) * joint.preTransform * glm::mat4_cast(joint.preRotation))); - state.rotation = glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalRoll(), glm::normalize(inverse * axes[2])) + state._rotation = glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalRoll(), glm::normalize(inverse * axes[2])) * glm::angleAxis(RADIANS_PER_DEGREE * _owningHead->getFinalYaw(), glm::normalize(inverse * axes[1])) * glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalPitch(), glm::normalize(inverse * axes[0])) * joint.rotation; @@ -59,23 +59,23 @@ void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBX void FaceModel::maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) { // likewise with the eye joints - glm::mat4 inverse = glm::inverse(parentState.transform * glm::translate(state.translation) * + glm::mat4 inverse = glm::inverse(parentState._transform * glm::translate(state._translation) * joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation)); glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getFinalOrientation() * IDENTITY_FRONT, 0.0f)); glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(_owningHead->getLookAtPosition() + _owningHead->getSaccade() - _translation, 1.0f)); glm::quat between = rotationBetween(front, lookAt); const float MAX_ANGLE = 30.0f * RADIANS_PER_DEGREE; - state.rotation = glm::angleAxis(glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE), glm::axis(between)) * + state._rotation = glm::angleAxis(glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE), glm::axis(between)) * joint.rotation; } void FaceModel::updateJointState(int index) { JointState& state = _jointStates[index]; - const FBXGeometry& geometry = _geometry->getFBXGeometry(); - const FBXJoint& joint = geometry.joints.at(index); + const FBXJoint& joint = state.getFBXJoint(); if (joint.parentIndex != -1) { const JointState& parentState = _jointStates.at(joint.parentIndex); + const FBXGeometry& geometry = _geometry->getFBXGeometry(); if (index == geometry.neckJointIndex) { maybeUpdateNeckRotation(parentState, joint, state); diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 2001802524..3586e525ae 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -189,7 +189,7 @@ void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) { geometry.joints.at(jointIndex).distanceToParent * extractUniformScale(_scale), glm::quat(), false, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY); setJointRotation(parentJointIndex, palmRotation, PALM_PRIORITY); - _jointStates[jointIndex].rotation = glm::quat(); + _jointStates[jointIndex]._rotation = glm::quat(); } else { setJointPosition(jointIndex, palm.getPosition(), palmRotation, @@ -199,10 +199,10 @@ void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) { void SkeletonModel::updateJointState(int index) { JointState& state = _jointStates[index]; - const FBXGeometry& geometry = _geometry->getFBXGeometry(); - const FBXJoint& joint = geometry.joints.at(index); + const FBXJoint& joint = state.getFBXJoint(); if (joint.parentIndex != -1) { const JointState& parentState = _jointStates.at(joint.parentIndex); + const FBXGeometry& geometry = _geometry->getFBXGeometry(); if (index == geometry.leanJointIndex) { maybeUpdateLeanRotation(parentState, joint, state); @@ -217,9 +217,9 @@ void SkeletonModel::updateJointState(int index) { Model::updateJointState(index); if (index == _geometry->getFBXGeometry().rootJointIndex) { - state.transform[3][0] = 0.0f; - state.transform[3][1] = 0.0f; - state.transform[3][2] = 0.0f; + state._transform[3][0] = 0.0f; + state._transform[3][1] = 0.0f; + state._transform[3][2] = 0.0f; } } @@ -229,9 +229,9 @@ void SkeletonModel::maybeUpdateLeanRotation(const JointState& parentState, const } // get the rotation axes in joint space and use them to adjust the rotation glm::mat3 axes = glm::mat3_cast(_rotation); - glm::mat3 inverse = glm::mat3(glm::inverse(parentState.transform * glm::translate(state.translation) * + glm::mat3 inverse = glm::mat3(glm::inverse(parentState._transform * glm::translate(state._translation) * joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation))); - state.rotation = glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanSideways(), + state._rotation = glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanSideways(), glm::normalize(inverse * axes[2])) * glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanForward(), glm::normalize(inverse * axes[0])) * joint.rotation; } @@ -255,11 +255,11 @@ void SkeletonModel::renderJointConstraints(int jointIndex) { do { const FBXJoint& joint = geometry.joints.at(jointIndex); const JointState& jointState = _jointStates.at(jointIndex); - glm::vec3 position = extractTranslation(jointState.transform) + _translation; + glm::vec3 position = extractTranslation(jointState._transform) + _translation; glPushMatrix(); glTranslatef(position.x, position.y, position.z); - glm::quat parentRotation = (joint.parentIndex == -1) ? _rotation : _jointStates.at(joint.parentIndex).combinedRotation; + glm::quat parentRotation = (joint.parentIndex == -1) ? _rotation : _jointStates.at(joint.parentIndex)._combinedRotation; glm::vec3 rotationAxis = glm::axis(parentRotation); glRotatef(glm::degrees(glm::angle(parentRotation)), rotationAxis.x, rotationAxis.y, rotationAxis.z); float fanScale = directionSize * 0.75f; @@ -292,7 +292,7 @@ void SkeletonModel::renderJointConstraints(int jointIndex) { } glPopMatrix(); - renderOrientationDirections(position, jointState.combinedRotation, directionSize); + renderOrientationDirections(position, jointState._combinedRotation, directionSize); jointIndex = joint.parentIndex; } while (jointIndex != -1 && geometry.joints.at(jointIndex).isFree); diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index a8914feb79..648a748f01 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -135,13 +135,14 @@ void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locati program.release(); } -QVector Model::createJointStates(const FBXGeometry& geometry) { +QVector Model::createJointStates(const FBXGeometry& geometry) { QVector jointStates; foreach (const FBXJoint& joint, geometry.joints) { JointState state; - state.translation = joint.translation; - state.rotation = joint.rotation; - state.animationPriority = 0.0f; + state._translation = joint.translation; + state._rotation = joint.rotation; + state._animationPriority = 0.0f; + state.setFBXJoint(joint); jointStates.append(state); } @@ -160,23 +161,23 @@ QVector Model::createJointStates(const FBXGeometry& geometry) continue; } JointState& state = jointStates[i]; - const FBXJoint& joint = geometry.joints[i]; + const FBXJoint& joint = state.getFBXJoint(); int parentIndex = joint.parentIndex; if (parentIndex == -1) { _rootIndex = i; glm::mat4 baseTransform = glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset); - glm::quat combinedRotation = joint.preRotation * state.rotation * joint.postRotation; - state.transform = baseTransform * geometry.offset * glm::translate(state.translation) * joint.preTransform * + glm::quat combinedRotation = joint.preRotation * state._rotation * joint.postRotation; + state._transform = baseTransform * geometry.offset * glm::translate(state._translation) * joint.preTransform * glm::mat4_cast(combinedRotation) * joint.postTransform; - state.combinedRotation = _rotation * combinedRotation; + state._combinedRotation = _rotation * combinedRotation; ++numJointsSet; jointIsSet[i] = true; } else if (jointIsSet[parentIndex]) { const JointState& parentState = jointStates.at(parentIndex); - glm::quat combinedRotation = joint.preRotation * state.rotation * joint.postRotation; - state.transform = parentState.transform * glm::translate(state.translation) * joint.preTransform * + glm::quat combinedRotation = joint.preRotation * state._rotation * joint.postRotation; + state._transform = parentState._transform * glm::translate(state._translation) * joint.preTransform * glm::mat4_cast(combinedRotation) * joint.postTransform; - state.combinedRotation = parentState.combinedRotation * combinedRotation; + state._combinedRotation = parentState._combinedRotation * combinedRotation; ++numJointsSet; jointIsSet[i] = true; } @@ -372,7 +373,7 @@ void Model::reset() { } const FBXGeometry& geometry = _geometry->getFBXGeometry(); for (int i = 0; i < _jointStates.size(); i++) { - _jointStates[i].rotation = geometry.joints.at(i).rotation; + _jointStates[i]._rotation = geometry.joints.at(i).rotation; } } @@ -582,7 +583,7 @@ bool Model::getJointState(int index, glm::quat& rotation) const { if (index == -1 || index >= _jointStates.size()) { return false; } - rotation = _jointStates.at(index).rotation; + rotation = _jointStates.at(index)._rotation; const glm::quat& defaultRotation = _geometry->getFBXGeometry().joints.at(index).rotation; return glm::abs(rotation.x - defaultRotation.x) >= EPSILON || glm::abs(rotation.y - defaultRotation.y) >= EPSILON || @@ -593,13 +594,13 @@ bool Model::getJointState(int index, glm::quat& rotation) const { void Model::setJointState(int index, bool valid, const glm::quat& rotation, float priority) { if (index != -1 && index < _jointStates.size()) { JointState& state = _jointStates[index]; - if (priority >= state.animationPriority) { + if (priority >= state._animationPriority) { if (valid) { - state.rotation = rotation; - state.animationPriority = priority; - } else if (priority == state.animationPriority) { - state.rotation = _geometry->getFBXGeometry().joints.at(index).rotation; - state.animationPriority = 0.0f; + state._rotation = rotation; + state._animationPriority = priority; + } else if (priority == state._animationPriority) { + state._rotation = _geometry->getFBXGeometry().joints.at(index).rotation; + state._animationPriority = 0.0f; } } } @@ -632,7 +633,7 @@ bool Model::getJointPosition(int jointIndex, glm::vec3& position) const { if (jointIndex == -1 || _jointStates.isEmpty()) { return false; } - position = _translation + extractTranslation(_jointStates[jointIndex].transform); + position = _translation + extractTranslation(_jointStates[jointIndex]._transform); return true; } @@ -640,7 +641,7 @@ bool Model::getJointRotation(int jointIndex, glm::quat& rotation, bool fromBind) if (jointIndex == -1 || _jointStates.isEmpty()) { return false; } - rotation = _jointStates[jointIndex].combinedRotation * + rotation = _jointStates[jointIndex]._combinedRotation * (fromBind ? _geometry->getFBXGeometry().joints[jointIndex].inverseBindRotation : _geometry->getFBXGeometry().joints[jointIndex].inverseDefaultRotation); return true; @@ -858,11 +859,11 @@ void Model::updateShapePositions() { for (int i = 0; i < _jointStates.size(); i++) { const FBXJoint& joint = geometry.joints[i]; // shape position and rotation need to be in world-frame - glm::vec3 jointToShapeOffset = uniformScale * (_jointStates[i].combinedRotation * joint.shapePosition); - glm::vec3 worldPosition = extractTranslation(_jointStates[i].transform) + jointToShapeOffset + _translation; + glm::vec3 jointToShapeOffset = uniformScale * (_jointStates[i]._combinedRotation * joint.shapePosition); + glm::vec3 worldPosition = extractTranslation(_jointStates[i]._transform) + jointToShapeOffset + _translation; Shape* shape = _jointShapes[i]; shape->setPosition(worldPosition); - shape->setRotation(_jointStates[i].combinedRotation * joint.shapeRotation); + shape->setRotation(_jointStates[i]._combinedRotation * joint.shapeRotation); float distance = glm::distance(worldPosition, _translation) + shape->getBoundingRadius(); if (distance > _boundingRadius) { _boundingRadius = distance; @@ -884,12 +885,12 @@ bool Model::findRayIntersection(const glm::vec3& origin, const glm::vec3& direct float radiusScale = extractUniformScale(_scale); for (int i = 0; i < _jointStates.size(); i++) { const FBXJoint& joint = geometry.joints[i]; - glm::vec3 end = extractTranslation(_jointStates[i].transform); + glm::vec3 end = extractTranslation(_jointStates[i]._transform); float endRadius = joint.boneRadius * radiusScale; glm::vec3 start = end; float startRadius = joint.boneRadius * radiusScale; if (joint.parentIndex != -1) { - start = extractTranslation(_jointStates[joint.parentIndex].transform); + start = extractTranslation(_jointStates[joint.parentIndex]._transform); startRadius = geometry.joints[joint.parentIndex].boneRadius * radiusScale; } // for now, use average of start and end radii @@ -1115,7 +1116,7 @@ void Model::simulateInternal(float deltaTime) { const FBXMesh& mesh = geometry.meshes.at(i); for (int j = 0; j < mesh.clusters.size(); j++) { const FBXCluster& cluster = mesh.clusters.at(j); - state.clusterMatrices[j] = _jointStates[cluster.jointIndex].transform * cluster.inverseBindMatrix; + state.clusterMatrices[j] = _jointStates[cluster.jointIndex]._transform * cluster.inverseBindMatrix; } } @@ -1127,21 +1128,21 @@ void Model::simulateInternal(float deltaTime) { void Model::updateJointState(int index) { JointState& state = _jointStates[index]; - const FBXGeometry& geometry = _geometry->getFBXGeometry(); - const FBXJoint& joint = geometry.joints.at(index); + const FBXJoint& joint = state.getFBXJoint(); if (joint.parentIndex == -1) { + const FBXGeometry& geometry = _geometry->getFBXGeometry(); glm::mat4 baseTransform = glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset); - glm::quat combinedRotation = joint.preRotation * state.rotation * joint.postRotation; - state.transform = baseTransform * geometry.offset * glm::translate(state.translation) * joint.preTransform * + glm::quat combinedRotation = joint.preRotation * state._rotation * joint.postRotation; + state._transform = baseTransform * geometry.offset * glm::translate(state._translation) * joint.preTransform * glm::mat4_cast(combinedRotation) * joint.postTransform; - state.combinedRotation = _rotation * combinedRotation; + state._combinedRotation = _rotation * combinedRotation; } else { const JointState& parentState = _jointStates.at(joint.parentIndex); - glm::quat combinedRotation = joint.preRotation * state.rotation * joint.postRotation; - state.transform = parentState.transform * glm::translate(state.translation) * joint.preTransform * + glm::quat combinedRotation = joint.preRotation * state._rotation * joint.postRotation; + state._transform = parentState._transform * glm::translate(state._translation) * joint.preTransform * glm::mat4_cast(combinedRotation) * joint.postTransform; - state.combinedRotation = parentState.combinedRotation * combinedRotation; + state._combinedRotation = parentState._combinedRotation * combinedRotation; } } @@ -1174,17 +1175,17 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const } // then, we go from the joint upwards, rotating the end as close as possible to the target - glm::vec3 endPosition = extractTranslation(_jointStates[jointIndex].transform); + glm::vec3 endPosition = extractTranslation(_jointStates[jointIndex]._transform); for (int j = 1; freeLineage.at(j - 1) != lastFreeIndex; j++) { int index = freeLineage.at(j); - const FBXJoint& joint = geometry.joints.at(index); + JointState& state = _jointStates[index]; + const FBXJoint& joint = state.getFBXJoint(); if (!(joint.isFree || allIntermediatesFree)) { continue; } - JointState& state = _jointStates[index]; - glm::vec3 jointPosition = extractTranslation(state.transform); + glm::vec3 jointPosition = extractTranslation(state._transform); glm::vec3 jointVector = endPosition - jointPosition; - glm::quat oldCombinedRotation = state.combinedRotation; + glm::quat oldCombinedRotation = state._combinedRotation; glm::quat combinedDelta; float combinedWeight; if (useRotation) { @@ -1202,7 +1203,7 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const for (int k = j - 1; k > 0; k--) { int index = freeLineage.at(k); updateJointState(index); - positionSum += extractTranslation(_jointStates.at(index).transform); + positionSum += extractTranslation(_jointStates.at(index)._transform); } glm::vec3 projectedCenterOfMass = glm::cross(jointVector, glm::cross(positionSum / (j - 1.0f) - jointPosition, jointVector)); @@ -1214,7 +1215,7 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const } } applyRotationDelta(index, combinedDelta, true, priority); - glm::quat actualDelta = state.combinedRotation * glm::inverse(oldCombinedRotation); + glm::quat actualDelta = state._combinedRotation * glm::inverse(oldCombinedRotation); endPosition = actualDelta * jointVector + jointPosition; if (useRotation) { endRotation = actualDelta * endRotation; @@ -1236,29 +1237,29 @@ bool Model::setJointRotation(int jointIndex, const glm::quat& rotation, float pr return false; } JointState& state = _jointStates[jointIndex]; - if (priority >= state.animationPriority) { - state.rotation = state.rotation * glm::inverse(state.combinedRotation) * rotation * + if (priority >= state._animationPriority) { + state._rotation = state._rotation * glm::inverse(state._combinedRotation) * rotation * glm::inverse(_geometry->getFBXGeometry().joints.at(jointIndex).inverseBindRotation); - state.animationPriority = priority; + state._animationPriority = priority; } return true; } void Model::setJointTranslation(int jointIndex, const glm::vec3& translation) { - const FBXGeometry& geometry = _geometry->getFBXGeometry(); - const FBXJoint& joint = geometry.joints.at(jointIndex); + JointState& state = _jointStates[jointIndex]; + const FBXJoint& joint = state.getFBXJoint(); glm::mat4 parentTransform; if (joint.parentIndex == -1) { + const FBXGeometry& geometry = _geometry->getFBXGeometry(); parentTransform = glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset) * geometry.offset; } else { - parentTransform = _jointStates.at(joint.parentIndex).transform; + parentTransform = _jointStates.at(joint.parentIndex)._transform; } - JointState& state = _jointStates[jointIndex]; glm::vec3 preTranslation = extractTranslation(joint.preTransform * glm::mat4_cast(joint.preRotation * - state.rotation * joint.postRotation) * joint.postTransform); - state.translation = glm::vec3(glm::inverse(parentTransform) * glm::vec4(translation, 1.0f)) - preTranslation; + state._rotation * joint.postRotation) * joint.postTransform); + state._translation = glm::vec3(glm::inverse(parentTransform) * glm::vec4(translation, 1.0f)) - preTranslation; } bool Model::restoreJointPosition(int jointIndex, float percent, float priority) { @@ -1270,11 +1271,11 @@ bool Model::restoreJointPosition(int jointIndex, float percent, float priority) foreach (int index, freeLineage) { JointState& state = _jointStates[index]; - if (priority == state.animationPriority) { + if (priority == state._animationPriority) { const FBXJoint& joint = geometry.joints.at(index); - state.rotation = safeMix(state.rotation, joint.rotation, percent); - state.translation = glm::mix(state.translation, joint.translation, percent); - state.animationPriority = 0.0f; + state._rotation = safeMix(state._rotation, joint.rotation, percent); + state._translation = glm::mix(state._translation, joint.translation, percent); + state._animationPriority = 0.0f; } } return true; @@ -1296,23 +1297,23 @@ float Model::getLimbLength(int jointIndex) const { void Model::applyRotationDelta(int jointIndex, const glm::quat& delta, bool constrain, float priority) { JointState& state = _jointStates[jointIndex]; - if (priority < state.animationPriority) { + if (priority < state._animationPriority) { return; } - state.animationPriority = priority; - const FBXJoint& joint = _geometry->getFBXGeometry().joints[jointIndex]; + state._animationPriority = priority; + const FBXJoint& joint = state.getFBXJoint(); if (!constrain || (joint.rotationMin == glm::vec3(-PI, -PI, -PI) && joint.rotationMax == glm::vec3(PI, PI, PI))) { // no constraints - state.rotation = state.rotation * glm::inverse(state.combinedRotation) * delta * state.combinedRotation; - state.combinedRotation = delta * state.combinedRotation; + state._rotation = state._rotation * glm::inverse(state._combinedRotation) * delta * state._combinedRotation; + state._combinedRotation = delta * state._combinedRotation; return; } - glm::quat targetRotation = delta * state.combinedRotation; - glm::vec3 eulers = safeEulerAngles(state.rotation * glm::inverse(state.combinedRotation) * targetRotation); + glm::quat targetRotation = delta * state._combinedRotation; + glm::vec3 eulers = safeEulerAngles(state._rotation * glm::inverse(state._combinedRotation) * targetRotation); glm::quat newRotation = glm::quat(glm::clamp(eulers, joint.rotationMin, joint.rotationMax)); - state.combinedRotation = state.combinedRotation * glm::inverse(state.rotation) * newRotation; - state.rotation = newRotation; + state._combinedRotation = state._combinedRotation * glm::inverse(state._rotation) * newRotation; + state._rotation = newRotation; } const int BALL_SUBDIVISIONS = 10; @@ -1850,10 +1851,10 @@ void AnimationHandle::simulate(float deltaTime) { for (int i = 0; i < _jointMappings.size(); i++) { int mapping = _jointMappings.at(i); if (mapping != -1) { - Model::JointState& state = _model->_jointStates[mapping]; - if (_priority >= state.animationPriority) { - state.rotation = frame.rotations.at(i); - state.animationPriority = _priority; + JointState& state = _model->_jointStates[mapping]; + if (_priority >= state._animationPriority) { + state._rotation = frame.rotations.at(i); + state._animationPriority = _priority; } } } @@ -1874,10 +1875,10 @@ void AnimationHandle::simulate(float deltaTime) { for (int i = 0; i < _jointMappings.size(); i++) { int mapping = _jointMappings.at(i); if (mapping != -1) { - Model::JointState& state = _model->_jointStates[mapping]; - if (_priority >= state.animationPriority) { - state.rotation = safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction); - state.animationPriority = _priority; + JointState& state = _model->_jointStates[mapping]; + if (_priority >= state._animationPriority) { + state._rotation = safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction); + state._animationPriority = _priority; } } } @@ -1887,10 +1888,16 @@ void AnimationHandle::replaceMatchingPriorities(float newPriority) { for (int i = 0; i < _jointMappings.size(); i++) { int mapping = _jointMappings.at(i); if (mapping != -1) { - Model::JointState& state = _model->_jointStates[mapping]; - if (_priority == state.animationPriority) { - state.animationPriority = newPriority; + JointState& state = _model->_jointStates[mapping]; + if (_priority == state._animationPriority) { + state._animationPriority = newPriority; } } } } + +JointState::JointState() : + _translation(0.0f), + _animationPriority(0.0f), + _fbxJoint(NULL) { +} diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 75e80fdaa8..69d584f267 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -30,6 +30,22 @@ class Shape; typedef QSharedPointer AnimationHandlePointer; typedef QWeakPointer WeakAnimationHandlePointer; + +class JointState { +public: + JointState(); + glm::vec3 _translation; // translation relative to parent + glm::quat _rotation; // rotation relative to parent + glm::mat4 _transform; // rotation to world frame + translation in model frame + glm::quat _combinedRotation; // rotation from joint local to world frame + float _animationPriority; // the priority of the animation affecting this joint + + void setFBXJoint(const FBXJoint& joint) { _fbxJoint = &joint; } + const FBXJoint& getFBXJoint() const { return *_fbxJoint; } + +private: + const FBXJoint* _fbxJoint; // JointState does not own its FBXJoint +}; /// A generic 3D model displaying geometry loaded from a URL. class Model : public QObject { @@ -182,15 +198,6 @@ protected: bool _snappedToCenter; /// are we currently snapped to center int _rootIndex; - class JointState { - public: - glm::vec3 translation; // translation relative to parent - glm::quat rotation; // rotation relative to parent - glm::mat4 transform; // rotation to world frame + translation in model frame - glm::quat combinedRotation; // rotation from joint local to world frame - float animationPriority; // the priority of the animation affecting this joint - }; - bool _shapesAreDirty; QVector _jointStates; QVector _jointShapes; From 81ed0d99f77e0377a596e8e779569ce8d83e3f80 Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Wed, 28 May 2014 17:13:59 -0700 Subject: [PATCH 29/45] Added prediction for Oculus rift to reduce apparent latency. --- interface/src/devices/OculusManager.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index af18db4006..c8b2d0dcbc 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -50,7 +50,8 @@ void OculusManager::connect() { _sensorDevice = *_hmdDevice->GetSensor(); _sensorFusion = new SensorFusion; _sensorFusion->AttachToSensor(_sensorDevice); - + _sensorFusion->SetPredictionEnabled(true); + HMDInfo info; _hmdDevice->GetDeviceInfo(&info); _stereoConfig.SetHMDInfo(info); @@ -201,7 +202,7 @@ void OculusManager::reset() { void OculusManager::getEulerAngles(float& yaw, float& pitch, float& roll) { #ifdef HAVE_LIBOVR - _sensorFusion->GetOrientation().GetEulerAngles(&yaw, &pitch, &roll); + _sensorFusion->GetPredictedOrientation().GetEulerAngles(&yaw, &pitch, &roll); #endif } From c7990773790e4f00fd02e30e8eb13b7ea0171508 Mon Sep 17 00:00:00 2001 From: wangyix Date: Wed, 28 May 2014 17:20:10 -0700 Subject: [PATCH 30/45] added flag,seq,ts to ParticleErase and ModelErase ... this fixes unreasonable flight-time issue --- assignment-client/src/models/ModelServer.cpp | 5 +-- assignment-client/src/models/ModelServer.h | 2 +- .../src/octree/OctreeQueryNode.cpp | 11 ++++--- .../src/octree/OctreeQueryNode.h | 6 ++-- .../src/octree/OctreeSendThread.cpp | 20 ++++++------ .../src/octree/OctreeSendThread.h | 2 ++ assignment-client/src/octree/OctreeServer.h | 2 +- .../src/particles/ParticleServer.cpp | 5 +-- .../src/particles/ParticleServer.h | 2 +- assignment-client/src/voxels/VoxelServer.cpp | 5 ++- assignment-client/src/voxels/VoxelServer.h | 2 +- interface/src/voxels/VoxelPacketProcessor.cpp | 2 +- libraries/models/src/ModelTree.cpp | 29 +++++++++++++++-- libraries/models/src/ModelTree.h | 2 +- libraries/networking/src/LimitedNodeList.cpp | 32 +++++++++---------- libraries/octree/src/OctreeSceneStats.cpp | 2 +- libraries/particles/src/ParticleTree.cpp | 27 ++++++++++++++-- libraries/particles/src/ParticleTree.h | 2 +- 18 files changed, 106 insertions(+), 52 deletions(-) diff --git a/assignment-client/src/models/ModelServer.cpp b/assignment-client/src/models/ModelServer.cpp index a71c98ed83..8f322e4c82 100644 --- a/assignment-client/src/models/ModelServer.cpp +++ b/assignment-client/src/models/ModelServer.cpp @@ -86,7 +86,7 @@ bool ModelServer::hasSpecialPacketToSend(const SharedNodePointer& node) { return shouldSendDeletedModels; } -int ModelServer::sendSpecialPacket(const SharedNodePointer& node) { +int ModelServer::sendSpecialPacket(OCTREE_PACKET_SEQUENCE& sequenceNumber, const SharedNodePointer& node) { unsigned char outputBuffer[MAX_PACKET_SIZE]; size_t packetLength = 0; @@ -100,12 +100,13 @@ int ModelServer::sendSpecialPacket(const SharedNodePointer& node) { // TODO: is it possible to send too many of these packets? what if you deleted 1,000,000 models? while (hasMoreToSend) { - hasMoreToSend = tree->encodeModelsDeletedSince(deletedModelsSentAt, + hasMoreToSend = tree->encodeModelsDeletedSince(sequenceNumber, deletedModelsSentAt, outputBuffer, MAX_PACKET_SIZE, packetLength); //qDebug() << "sending PacketType_MODEL_ERASE packetLength:" << packetLength; NodeList::getInstance()->writeDatagram((char*) outputBuffer, packetLength, SharedNodePointer(node)); + sequenceNumber++; } nodeData->setLastDeletedModelsSentAt(deletePacketSentAt); diff --git a/assignment-client/src/models/ModelServer.h b/assignment-client/src/models/ModelServer.h index c2ca6d1f5b..35cb79d8cf 100644 --- a/assignment-client/src/models/ModelServer.h +++ b/assignment-client/src/models/ModelServer.h @@ -37,7 +37,7 @@ public: // subclass may implement these method virtual void beforeRun(); virtual bool hasSpecialPacketToSend(const SharedNodePointer& node); - virtual int sendSpecialPacket(const SharedNodePointer& node); + virtual int sendSpecialPacket(OCTREE_PACKET_SEQUENCE& sequenceNumber, const SharedNodePointer& node); virtual void modelCreated(const ModelItem& newModel, const SharedNodePointer& senderNode); diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index a5f89dc71b..ea15770f9e 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -38,7 +38,7 @@ OctreeQueryNode::OctreeQueryNode() : _lastClientOctreeSizeScale(DEFAULT_OCTREE_SIZE_SCALE), _lodChanged(false), _lodInitialized(false), - _sequenceNumber(0), + //_sequenceNumber(0), _lastRootTimestamp(0), _myPacketType(PacketTypeUnknown), _isShuttingDown(false) @@ -158,11 +158,11 @@ bool OctreeQueryNode::shouldSuppressDuplicatePacket() { void OctreeQueryNode::init() { _myPacketType = getMyPacketType(); - resetOctreePacket(); // don't bump sequence + resetOctreePacket(0); // don't bump sequence } -void OctreeQueryNode::resetOctreePacket() { +void OctreeQueryNode::resetOctreePacket(OCTREE_PACKET_SEQUENCE sequenceNumber) { // if shutting down, return immediately if (_isShuttingDown) { return; @@ -200,7 +200,7 @@ void OctreeQueryNode::resetOctreePacket() { // pack in sequence number OCTREE_PACKET_SEQUENCE* sequenceAt = (OCTREE_PACKET_SEQUENCE*)_octreePacketAt; - *sequenceAt = _sequenceNumber; + *sequenceAt = sequenceNumber; _octreePacketAt += sizeof(OCTREE_PACKET_SEQUENCE); _octreePacketAvailableBytes -= sizeof(OCTREE_PACKET_SEQUENCE); @@ -362,7 +362,8 @@ void OctreeQueryNode::dumpOutOfView() { } } } - +/* void OctreeQueryNode::incrementSequenceNumber() { _sequenceNumber++; } +*/ diff --git a/assignment-client/src/octree/OctreeQueryNode.h b/assignment-client/src/octree/OctreeQueryNode.h index 1bb3a72a0c..af293189a4 100644 --- a/assignment-client/src/octree/OctreeQueryNode.h +++ b/assignment-client/src/octree/OctreeQueryNode.h @@ -35,7 +35,7 @@ public: void init(); // called after creation to set up some virtual items virtual PacketType getMyPacketType() const = 0; - void resetOctreePacket(); // resets octree packet to after "V" header + void resetOctreePacket(OCTREE_PACKET_SEQUENCE sequenceNumber); // resets octree packet to after "V" header void writeToPacket(const unsigned char* buffer, unsigned int bytes); // writes to end of packet @@ -100,7 +100,7 @@ public: void forceNodeShutdown(); bool isShuttingDown() const { return _isShuttingDown; } - void incrementSequenceNumber(); + //void incrementSequenceNumber(); private slots: void sendThreadFinished(); @@ -138,7 +138,7 @@ private: bool _lodChanged; bool _lodInitialized; - OCTREE_PACKET_SEQUENCE _sequenceNumber; + //OCTREE_PACKET_SEQUENCE _sequenceNumber; quint64 _lastRootTimestamp; diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index c98c8c77b8..dca18026a1 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -28,7 +28,8 @@ OctreeSendThread::OctreeSendThread(const SharedAssignmentPointer& myAssignment, _nodeUUID(node->getUUID()), _packetData(), _nodeMissingCount(0), - _isShuttingDown(false) + _isShuttingDown(false), + _sequenceNumber(0) { QString safeServerName("Octree"); if (_myServer) { @@ -137,7 +138,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes // obscure the packet and not send it. This allows the callers and upper level logic to not need to know about // this rate control savings. if (nodeData->shouldSuppressDuplicatePacket()) { - nodeData->resetOctreePacket(); // we still need to reset it though! + nodeData->resetOctreePacket(_sequenceNumber); // we still need to reset it though! return packetsSent; // without sending... } @@ -163,11 +164,10 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes int piggyBackSize = nodeData->getPacketLength() + statsMessageLength; // If the size of the stats message and the voxel message will fit in a packet, then piggyback them - if (piggyBackSize < MAX_PACKET_SIZE) { +if (piggyBackSize < MAX_PACKET_SIZE && false) { // copy voxel message to back of stats message memcpy(statsMessage + statsMessageLength, nodeData->getPacket(), nodeData->getPacketLength()); -//memcpy(statsMessage + statsMessageLength, messageData, nodeData->getPacketLength()); statsMessageLength += nodeData->getPacketLength(); // since a stats message is only included on end of scene, don't consider any of these bytes "wasted", since @@ -210,7 +210,6 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes OctreeServer::didCallWriteDatagram(this); NodeList::getInstance()->writeDatagram((char*) nodeData->getPacket(), nodeData->getPacketLength(), _node); -//NodeList::getInstance()->writeDatagram((char*)messageData, nodeData->getPacketLength(), _node); packetSent = true; @@ -231,7 +230,6 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes // just send the voxel packet OctreeServer::didCallWriteDatagram(this); NodeList::getInstance()->writeDatagram((char*) nodeData->getPacket(), nodeData->getPacketLength(), _node); -//NodeList::getInstance()->writeDatagram((char*)messageData, nodeData->getPacketLength(), _node); packetSent = true; int thisWastedBytes = MAX_PACKET_SIZE - nodeData->getPacketLength(); @@ -251,8 +249,8 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes trueBytesSent += nodeData->getPacketLength(); truePacketsSent++; packetsSent++; - nodeData->incrementSequenceNumber(); - nodeData->resetOctreePacket(); + _sequenceNumber++; + nodeData->resetOctreePacket(_sequenceNumber); } return packetsSent; } @@ -291,7 +289,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus if (nodeData->isPacketWaiting()) { packetsSentThisInterval += handlePacketSend(nodeData, trueBytesSent, truePacketsSent); } else { - nodeData->resetOctreePacket(); + nodeData->resetOctreePacket(_sequenceNumber); } int targetSize = MAX_OCTREE_PACKET_DATA_SIZE; if (wantCompression) { @@ -537,7 +535,9 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus // send the environment packet // TODO: should we turn this into a while loop to better handle sending multiple special packets if (_myServer->hasSpecialPacketToSend(_node) && !nodeData->isShuttingDown()) { - trueBytesSent += _myServer->sendSpecialPacket(_node); +qDebug() << "sending special packet..."; + trueBytesSent += _myServer->sendSpecialPacket(_sequenceNumber, _node); + nodeData->resetOctreePacket(_sequenceNumber); // because _sequenceNumber has changed truePacketsSent++; packetsSentThisInterval++; } diff --git a/assignment-client/src/octree/OctreeSendThread.h b/assignment-client/src/octree/OctreeSendThread.h index d8eed27802..9dcf266cd8 100644 --- a/assignment-client/src/octree/OctreeSendThread.h +++ b/assignment-client/src/octree/OctreeSendThread.h @@ -55,6 +55,8 @@ private: int _nodeMissingCount; bool _isShuttingDown; + + OCTREE_PACKET_SEQUENCE _sequenceNumber; }; #endif // hifi_OctreeSendThread_h diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index ff62561c58..df8519e200 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -72,7 +72,7 @@ public: // subclass may implement these method virtual void beforeRun() { }; virtual bool hasSpecialPacketToSend(const SharedNodePointer& node) { return false; } - virtual int sendSpecialPacket(const SharedNodePointer& node) { return 0; } + virtual int sendSpecialPacket(OCTREE_PACKET_SEQUENCE& sequenceNumber, const SharedNodePointer& node) { return 0; } static void attachQueryNodeToNode(Node* newNode); diff --git a/assignment-client/src/particles/ParticleServer.cpp b/assignment-client/src/particles/ParticleServer.cpp index 649ee0cff9..e752900059 100644 --- a/assignment-client/src/particles/ParticleServer.cpp +++ b/assignment-client/src/particles/ParticleServer.cpp @@ -86,7 +86,7 @@ bool ParticleServer::hasSpecialPacketToSend(const SharedNodePointer& node) { return shouldSendDeletedParticles; } -int ParticleServer::sendSpecialPacket(const SharedNodePointer& node) { +int ParticleServer::sendSpecialPacket(OCTREE_PACKET_SEQUENCE& sequenceNumber, const SharedNodePointer& node) { unsigned char outputBuffer[MAX_PACKET_SIZE]; size_t packetLength = 0; @@ -100,12 +100,13 @@ int ParticleServer::sendSpecialPacket(const SharedNodePointer& node) { // TODO: is it possible to send too many of these packets? what if you deleted 1,000,000 particles? while (hasMoreToSend) { - hasMoreToSend = tree->encodeParticlesDeletedSince(deletedParticlesSentAt, + hasMoreToSend = tree->encodeParticlesDeletedSince(sequenceNumber, deletedParticlesSentAt, outputBuffer, MAX_PACKET_SIZE, packetLength); //qDebug() << "sending PacketType_PARTICLE_ERASE packetLength:" << packetLength; NodeList::getInstance()->writeDatagram((char*) outputBuffer, packetLength, SharedNodePointer(node)); + sequenceNumber++; } nodeData->setLastDeletedParticlesSentAt(deletePacketSentAt); diff --git a/assignment-client/src/particles/ParticleServer.h b/assignment-client/src/particles/ParticleServer.h index 1e0bb1b967..cb8e128475 100644 --- a/assignment-client/src/particles/ParticleServer.h +++ b/assignment-client/src/particles/ParticleServer.h @@ -37,7 +37,7 @@ public: // subclass may implement these method virtual void beforeRun(); virtual bool hasSpecialPacketToSend(const SharedNodePointer& node); - virtual int sendSpecialPacket(const SharedNodePointer& node); + virtual int sendSpecialPacket(OCTREE_PACKET_SEQUENCE& sequenceNumber, const SharedNodePointer& node); virtual void particleCreated(const Particle& newParticle, const SharedNodePointer& senderNode); diff --git a/assignment-client/src/voxels/VoxelServer.cpp b/assignment-client/src/voxels/VoxelServer.cpp index 7747b8336b..1251358320 100644 --- a/assignment-client/src/voxels/VoxelServer.cpp +++ b/assignment-client/src/voxels/VoxelServer.cpp @@ -40,7 +40,10 @@ bool VoxelServer::hasSpecialPacketToSend(const SharedNodePointer& node) { return shouldSendEnvironments; } -int VoxelServer::sendSpecialPacket(const SharedNodePointer& node) { +int VoxelServer::sendSpecialPacket(OCTREE_PACKET_SEQUENCE& sequence, const SharedNodePointer& node) { + + // TODO: add flags, seq, timestamp to packet + int numBytesPacketHeader = populatePacketHeader(reinterpret_cast(_tempOutputBuffer), PacketTypeEnvironmentData); int envPacketLength = numBytesPacketHeader; int environmentsToSend = getSendMinimalEnvironment() ? 1 : getEnvironmentDataCount(); diff --git a/assignment-client/src/voxels/VoxelServer.h b/assignment-client/src/voxels/VoxelServer.h index bec60cadfe..8fba2e9d69 100644 --- a/assignment-client/src/voxels/VoxelServer.h +++ b/assignment-client/src/voxels/VoxelServer.h @@ -46,7 +46,7 @@ public: // subclass may implement these method virtual void beforeRun(); virtual bool hasSpecialPacketToSend(const SharedNodePointer& node); - virtual int sendSpecialPacket(const SharedNodePointer& node); + virtual int sendSpecialPacket(OCTREE_PACKET_SEQUENCE& sequence, const SharedNodePointer& node); private: bool _sendEnvironments; diff --git a/interface/src/voxels/VoxelPacketProcessor.cpp b/interface/src/voxels/VoxelPacketProcessor.cpp index d03eaf0946..11e62b0fe3 100644 --- a/interface/src/voxels/VoxelPacketProcessor.cpp +++ b/interface/src/voxels/VoxelPacketProcessor.cpp @@ -81,7 +81,7 @@ void VoxelPacketProcessor::processPacket(const SharedNodePointer& sendingNode, c if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) { -if (voxelPacketType != PacketTypeParticleErase) +//if (voxelPacketType != PacketTypeParticleErase) app->trackIncomingVoxelPacket(mutablePacket, sendingNode, wasStatsPacket); if (sendingNode) { diff --git a/libraries/models/src/ModelTree.cpp b/libraries/models/src/ModelTree.cpp index 637079560b..44f1c60ac7 100644 --- a/libraries/models/src/ModelTree.cpp +++ b/libraries/models/src/ModelTree.cpp @@ -545,8 +545,8 @@ bool ModelTree::hasModelsDeletedSince(quint64 sinceTime) { } // sinceTime is an in/out parameter - it will be side effected with the last time sent out -bool ModelTree::encodeModelsDeletedSince(quint64& sinceTime, unsigned char* outputBuffer, size_t maxLength, - size_t& outputLength) { +bool ModelTree::encodeModelsDeletedSince(OCTREE_PACKET_SEQUENCE sequenceNumber, quint64& sinceTime, unsigned char* outputBuffer, + size_t maxLength, size_t& outputLength) { bool hasMoreToSend = true; @@ -555,6 +555,26 @@ bool ModelTree::encodeModelsDeletedSince(quint64& sinceTime, unsigned char* outp copyAt += numBytesPacketHeader; outputLength = numBytesPacketHeader; +// pack in flags +OCTREE_PACKET_FLAGS flags = 0; +OCTREE_PACKET_FLAGS* flagsAt = (OCTREE_PACKET_FLAGS*)copyAt; +*flagsAt = flags; +copyAt += sizeof(OCTREE_PACKET_FLAGS); +outputLength += sizeof(OCTREE_PACKET_FLAGS); + +// pack in sequence number +OCTREE_PACKET_SEQUENCE* sequenceAt = (OCTREE_PACKET_SEQUENCE*)copyAt; +*sequenceAt = sequenceNumber; +copyAt += sizeof(OCTREE_PACKET_SEQUENCE); +outputLength += sizeof(OCTREE_PACKET_SEQUENCE); + +// pack in timestamp +OCTREE_PACKET_SENT_TIME now = usecTimestampNow(); +OCTREE_PACKET_SENT_TIME* timeAt = (OCTREE_PACKET_SENT_TIME*)copyAt; +*timeAt = now; +copyAt += sizeof(OCTREE_PACKET_SENT_TIME); +outputLength += sizeof(OCTREE_PACKET_SENT_TIME); + uint16_t numberOfIds = 0; // placeholder for now unsigned char* numberOfIDsAt = copyAt; memcpy(copyAt, &numberOfIds, sizeof(numberOfIds)); @@ -642,8 +662,13 @@ void ModelTree::processEraseMessage(const QByteArray& dataByteArray, const Share size_t processedBytes = numBytesPacketHeader; dataAt += numBytesPacketHeader; +dataAt += sizeof(OCTREE_PACKET_FLAGS); +dataAt += sizeof(OCTREE_PACKET_SEQUENCE); +dataAt += sizeof(OCTREE_PACKET_SENT_TIME); + uint16_t numberOfIds = 0; // placeholder for now memcpy(&numberOfIds, dataAt, sizeof(numberOfIds)); +qDebug() << "\t\t\t numberOfIds: " << numberOfIds; dataAt += sizeof(numberOfIds); processedBytes += sizeof(numberOfIds); diff --git a/libraries/models/src/ModelTree.h b/libraries/models/src/ModelTree.h index b8df1c1a22..df45ae9c15 100644 --- a/libraries/models/src/ModelTree.h +++ b/libraries/models/src/ModelTree.h @@ -69,7 +69,7 @@ public: bool hasAnyDeletedModels() const { return _recentlyDeletedModelItemIDs.size() > 0; } bool hasModelsDeletedSince(quint64 sinceTime); - bool encodeModelsDeletedSince(quint64& sinceTime, unsigned char* packetData, size_t maxLength, size_t& outputLength); + bool encodeModelsDeletedSince(OCTREE_PACKET_SEQUENCE sequenceNumber, quint64& sinceTime, unsigned char* packetData, size_t maxLength, size_t& outputLength); void forgetModelsDeletedBefore(quint64 sinceTime); void processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode); diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 68255bbd41..ed5ea579e0 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -268,21 +268,22 @@ qint64 LimitedNodeList::writeUnverifiedDatagram(const QByteArray& datagram, cons qint64 LimitedNodeList::writeDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode, const HifiSockAddr& overridenSockAddr) { - /* + QByteArray datagram(data, size); qDebug() << "\t writeDatagram()..."; + int numBytesPacketHeader = numBytesForPacketHeader(datagram); + const unsigned char* dataAt = reinterpret_cast(datagram.data()) + numBytesPacketHeader; + PacketType type = packetTypeForPacket(datagram); - if (type != PacketType::PacketTypeParticleErase) { - - qDebug() << "\t\t type: " << (unsigned char)type; - qDebug() << "\t\t UUID: " << uuidFromPacketHeader(datagram); - qDebug() << "\t\t MD5: " << hashFromPacketHeader(datagram); + qDebug() << "\t\t type: " << (unsigned char)type; - int numBytesPacketHeader = numBytesForPacketHeader(datagram); - const unsigned char* dataAt = reinterpret_cast(datagram.data()) + numBytesPacketHeader; + if (type != PacketTypeOctreeStats) { + + //qDebug() << "\t\t UUID: " << uuidFromPacketHeader(datagram); + //qDebug() << "\t\t MD5: " << hashFromPacketHeader(datagram); unsigned char flags = (*(unsigned char*)(dataAt)); dataAt += sizeof(unsigned char); @@ -296,15 +297,12 @@ qint64 LimitedNodeList::writeDatagram(const char* data, qint64 size, const Share dataAt += sizeof(quint64); qDebug() << "\t\t sent at: " << QString::number(sentAt, 16) << "\n"; } - else { - qDebug() << "size: " << size; - const char* dataAt = data; - for (int i = 0; i < size; i++) { - unsigned char byte = *((unsigned char*)dataAt); - dataAt += sizeof(unsigned char); - qDebug() << "\t\t " << QString::number(byte, 16); - } - }*/ + + if (type == PacketTypeParticleErase || type==PacketTypeModelErase) { + uint16_t ids = *((uint16_t*)dataAt); + dataAt += sizeof(uint16_t); + qDebug() << "\t\t\t ids: " << ids; + } return writeDatagram(QByteArray(data, size), destinationNode, overridenSockAddr); } diff --git a/libraries/octree/src/OctreeSceneStats.cpp b/libraries/octree/src/OctreeSceneStats.cpp index 2b04b5652c..4ca2237b43 100644 --- a/libraries/octree/src/OctreeSceneStats.cpp +++ b/libraries/octree/src/OctreeSceneStats.cpp @@ -868,7 +868,7 @@ bool OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, } -//qDebug() << "\t" << QString::number(sequence, 16) << "\t sentAt:" << QString::number(sentAt, 16) << " usecs"; +qDebug() << "\t" << QString::number(sequence, 16) << "\t sentAt:" << QString::number(sentAt, 16) << " usecs"; // Guard against possible corrupted packets... with bad timestamps const int MAX_RESONABLE_FLIGHT_TIME = 200 * USECS_PER_SECOND; // 200 seconds is more than enough time for a packet to arrive diff --git a/libraries/particles/src/ParticleTree.cpp b/libraries/particles/src/ParticleTree.cpp index dd8cb6e618..a597c76bd9 100644 --- a/libraries/particles/src/ParticleTree.cpp +++ b/libraries/particles/src/ParticleTree.cpp @@ -511,8 +511,8 @@ bool ParticleTree::hasParticlesDeletedSince(quint64 sinceTime) { } // sinceTime is an in/out parameter - it will be side effected with the last time sent out -bool ParticleTree::encodeParticlesDeletedSince(quint64& sinceTime, unsigned char* outputBuffer, size_t maxLength, - size_t& outputLength) { +bool ParticleTree::encodeParticlesDeletedSince(OCTREE_PACKET_SEQUENCE sequenceNumber, quint64& sinceTime, unsigned char* outputBuffer, + size_t maxLength, size_t& outputLength) { bool hasMoreToSend = true; @@ -521,6 +521,24 @@ bool ParticleTree::encodeParticlesDeletedSince(quint64& sinceTime, unsigned char copyAt += numBytesPacketHeader; outputLength = numBytesPacketHeader; +// pack in flags +OCTREE_PACKET_FLAGS flags = 0; +memcpy(copyAt, &flags, sizeof(OCTREE_PACKET_FLAGS)); +copyAt += sizeof(OCTREE_PACKET_FLAGS); +outputLength += sizeof(OCTREE_PACKET_FLAGS); + +// pack in sequence number +memcpy(copyAt, &sequenceNumber, sizeof(OCTREE_PACKET_SEQUENCE)); +copyAt += sizeof(OCTREE_PACKET_SEQUENCE); +outputLength += sizeof(OCTREE_PACKET_SEQUENCE); + +// pack in timestamp +OCTREE_PACKET_SENT_TIME now = usecTimestampNow(); +memcpy(copyAt, &now, sizeof(OCTREE_PACKET_SENT_TIME)); +copyAt += sizeof(OCTREE_PACKET_SENT_TIME); +outputLength += sizeof(OCTREE_PACKET_SENT_TIME); + + uint16_t numberOfIds = 0; // placeholder for now unsigned char* numberOfIDsAt = copyAt; memcpy(copyAt, &numberOfIds, sizeof(numberOfIds)); @@ -609,8 +627,13 @@ void ParticleTree::processEraseMessage(const QByteArray& dataByteArray, const Sh size_t processedBytes = numBytesPacketHeader; dataAt += numBytesPacketHeader; +dataAt += sizeof(OCTREE_PACKET_FLAGS); +dataAt += sizeof(OCTREE_PACKET_SEQUENCE); +dataAt += sizeof(OCTREE_PACKET_SENT_TIME); + uint16_t numberOfIds = 0; // placeholder for now memcpy(&numberOfIds, dataAt, sizeof(numberOfIds)); +qDebug() << "\t\t\t numberOfIds: " << numberOfIds; dataAt += sizeof(numberOfIds); processedBytes += sizeof(numberOfIds); diff --git a/libraries/particles/src/ParticleTree.h b/libraries/particles/src/ParticleTree.h index 0a2ac285b7..88cff94249 100644 --- a/libraries/particles/src/ParticleTree.h +++ b/libraries/particles/src/ParticleTree.h @@ -67,7 +67,7 @@ public: bool hasAnyDeletedParticles() const { return _recentlyDeletedParticleIDs.size() > 0; } bool hasParticlesDeletedSince(quint64 sinceTime); - bool encodeParticlesDeletedSince(quint64& sinceTime, unsigned char* packetData, size_t maxLength, size_t& outputLength); + bool encodeParticlesDeletedSince(OCTREE_PACKET_SEQUENCE sequenceNumber, quint64& sinceTime, unsigned char* packetData, size_t maxLength, size_t& outputLength); void forgetParticlesDeletedBefore(quint64 sinceTime); void processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode); From b15b0fd96cb30c199715673d972c7394a13529f7 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 28 May 2014 17:31:07 -0700 Subject: [PATCH 31/45] cleaner initialization of JointState --- interface/src/renderer/Model.cpp | 13 ++++++++++--- interface/src/renderer/Model.h | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 648a748f01..7e21bbb90f 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -139,9 +139,6 @@ QVector Model::createJointStates(const FBXGeometry& geometry) { QVector jointStates; foreach (const FBXJoint& joint, geometry.joints) { JointState state; - state._translation = joint.translation; - state._rotation = joint.rotation; - state._animationPriority = 0.0f; state.setFBXJoint(joint); jointStates.append(state); } @@ -1896,8 +1893,18 @@ void AnimationHandle::replaceMatchingPriorities(float newPriority) { } } +// ---------------------------------------------------------------------------- +// JointState TODO: move this class to its own files +// ---------------------------------------------------------------------------- JointState::JointState() : _translation(0.0f), _animationPriority(0.0f), _fbxJoint(NULL) { } + +void JointState::setFBXJoint(const FBXJoint& joint) { + assert(&joint != NULL); + _translation = joint.translation; + _rotation = joint.rotation; + _fbxJoint = &joint; +} diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 69d584f267..be58a1d7f2 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -40,7 +40,7 @@ public: glm::quat _combinedRotation; // rotation from joint local to world frame float _animationPriority; // the priority of the animation affecting this joint - void setFBXJoint(const FBXJoint& joint) { _fbxJoint = &joint; } + void setFBXJoint(const FBXJoint& joint); const FBXJoint& getFBXJoint() const { return *_fbxJoint; } private: From 5d4b0df1088b9700cc8ecb8600845b15797dc4b6 Mon Sep 17 00:00:00 2001 From: wangyix Date: Wed, 28 May 2014 17:41:38 -0700 Subject: [PATCH 32/45] added flag,seq,st to EnvironmentData, untested removed/commented out debug prints --- assignment-client/src/voxels/VoxelServer.cpp | 30 ++++++++++++++++++-- assignment-client/src/voxels/VoxelServer.h | 2 +- interface/src/Environment.cpp | 5 ++++ libraries/models/src/ModelTree.cpp | 1 - libraries/networking/src/LimitedNodeList.cpp | 4 +-- libraries/octree/src/OctreeSceneStats.cpp | 3 +- libraries/particles/src/ParticleTree.cpp | 1 - 7 files changed, 38 insertions(+), 8 deletions(-) diff --git a/assignment-client/src/voxels/VoxelServer.cpp b/assignment-client/src/voxels/VoxelServer.cpp index 1251358320..181a51ebc9 100644 --- a/assignment-client/src/voxels/VoxelServer.cpp +++ b/assignment-client/src/voxels/VoxelServer.cpp @@ -40,12 +40,36 @@ bool VoxelServer::hasSpecialPacketToSend(const SharedNodePointer& node) { return shouldSendEnvironments; } -int VoxelServer::sendSpecialPacket(OCTREE_PACKET_SEQUENCE& sequence, const SharedNodePointer& node) { +int VoxelServer::sendSpecialPacket(OCTREE_PACKET_SEQUENCE& sequenceNumber, const SharedNodePointer& node) { - // TODO: add flags, seq, timestamp to packet +unsigned char* copyAt = _tempOutputBuffer; int numBytesPacketHeader = populatePacketHeader(reinterpret_cast(_tempOutputBuffer), PacketTypeEnvironmentData); +copyAt += numBytesPacketHeader; int envPacketLength = numBytesPacketHeader; + + +// pack in flags +OCTREE_PACKET_FLAGS flags = 0; +OCTREE_PACKET_FLAGS* flagsAt = (OCTREE_PACKET_FLAGS*)copyAt; +*flagsAt = flags; +copyAt += sizeof(OCTREE_PACKET_FLAGS); +envPacketLength += sizeof(OCTREE_PACKET_FLAGS); + +// pack in sequence number +OCTREE_PACKET_SEQUENCE* sequenceAt = (OCTREE_PACKET_SEQUENCE*)copyAt; +*sequenceAt = sequenceNumber; +copyAt += sizeof(OCTREE_PACKET_SEQUENCE); +envPacketLength += sizeof(OCTREE_PACKET_SEQUENCE); + +// pack in timestamp +OCTREE_PACKET_SENT_TIME now = usecTimestampNow(); +OCTREE_PACKET_SENT_TIME* timeAt = (OCTREE_PACKET_SENT_TIME*)copyAt; +*timeAt = now; +copyAt += sizeof(OCTREE_PACKET_SENT_TIME); +envPacketLength += sizeof(OCTREE_PACKET_SENT_TIME); + + int environmentsToSend = getSendMinimalEnvironment() ? 1 : getEnvironmentDataCount(); for (int i = 0; i < environmentsToSend; i++) { @@ -53,6 +77,8 @@ int VoxelServer::sendSpecialPacket(OCTREE_PACKET_SEQUENCE& sequence, const Share } NodeList::getInstance()->writeDatagram((char*) _tempOutputBuffer, envPacketLength, SharedNodePointer(node)); + sequenceNumber++; + return envPacketLength; } diff --git a/assignment-client/src/voxels/VoxelServer.h b/assignment-client/src/voxels/VoxelServer.h index 8fba2e9d69..b9277fed0c 100644 --- a/assignment-client/src/voxels/VoxelServer.h +++ b/assignment-client/src/voxels/VoxelServer.h @@ -46,7 +46,7 @@ public: // subclass may implement these method virtual void beforeRun(); virtual bool hasSpecialPacketToSend(const SharedNodePointer& node); - virtual int sendSpecialPacket(OCTREE_PACKET_SEQUENCE& sequence, const SharedNodePointer& node); + virtual int sendSpecialPacket(OCTREE_PACKET_SEQUENCE& sequenceNumber, const SharedNodePointer& node); private: bool _sendEnvironments; diff --git a/interface/src/Environment.cpp b/interface/src/Environment.cpp index 1ba2f0501c..c302907cd7 100644 --- a/interface/src/Environment.cpp +++ b/interface/src/Environment.cpp @@ -160,6 +160,11 @@ bool Environment::findCapsulePenetration(const glm::vec3& start, const glm::vec3 int Environment::parseData(const HifiSockAddr& senderAddress, const QByteArray& packet) { // push past the packet header int bytesRead = numBytesForPacketHeader(packet); + +// push past flags, sequence, timestamp +bytesRead += sizeof(OCTREE_PACKET_FLAGS); +bytesRead += sizeof(OCTREE_PACKET_SEQUENCE); +bytesRead += sizeof(OCTREE_PACKET_SENT_TIME); // get the lock for the duration of the call QMutexLocker locker(&_mutex); diff --git a/libraries/models/src/ModelTree.cpp b/libraries/models/src/ModelTree.cpp index 44f1c60ac7..8b249411ba 100644 --- a/libraries/models/src/ModelTree.cpp +++ b/libraries/models/src/ModelTree.cpp @@ -668,7 +668,6 @@ dataAt += sizeof(OCTREE_PACKET_SENT_TIME); uint16_t numberOfIds = 0; // placeholder for now memcpy(&numberOfIds, dataAt, sizeof(numberOfIds)); -qDebug() << "\t\t\t numberOfIds: " << numberOfIds; dataAt += sizeof(numberOfIds); processedBytes += sizeof(numberOfIds); diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index ed5ea579e0..743cbe949a 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -268,7 +268,7 @@ qint64 LimitedNodeList::writeUnverifiedDatagram(const QByteArray& datagram, cons qint64 LimitedNodeList::writeDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode, const HifiSockAddr& overridenSockAddr) { - + /* QByteArray datagram(data, size); qDebug() << "\t writeDatagram()..."; @@ -303,7 +303,7 @@ qint64 LimitedNodeList::writeDatagram(const char* data, qint64 size, const Share dataAt += sizeof(uint16_t); qDebug() << "\t\t\t ids: " << ids; } - + */ return writeDatagram(QByteArray(data, size), destinationNode, overridenSockAddr); } diff --git a/libraries/octree/src/OctreeSceneStats.cpp b/libraries/octree/src/OctreeSceneStats.cpp index 4ca2237b43..3659c8bd24 100644 --- a/libraries/octree/src/OctreeSceneStats.cpp +++ b/libraries/octree/src/OctreeSceneStats.cpp @@ -868,13 +868,14 @@ bool OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, } -qDebug() << "\t" << QString::number(sequence, 16) << "\t sentAt:" << QString::number(sentAt, 16) << " usecs"; +//qDebug() << "\t" << QString::number(sequence, 16) << "\t sentAt:" << QString::number(sentAt, 16) << " usecs"; // Guard against possible corrupted packets... with bad timestamps const int MAX_RESONABLE_FLIGHT_TIME = 200 * USECS_PER_SECOND; // 200 seconds is more than enough time for a packet to arrive const int MIN_RESONABLE_FLIGHT_TIME = 0; if (flightTime > MAX_RESONABLE_FLIGHT_TIME || flightTime < MIN_RESONABLE_FLIGHT_TIME) { qDebug() << "ignoring unreasonable packet... flightTime:" << flightTime; +qDebug() << "\t sequence:" << QString::number(sequence, 16); qDebug() << "\t sentAt:" << QString::number(sentAt, 16) << " usecs"; qDebug() << "\t arrivedAt:" << QString::number(arrivedAt, 16) << " usecs"; qDebug() << "\t nodeClockSkewUsec:" << nodeClockSkewUsec << " usecs"; diff --git a/libraries/particles/src/ParticleTree.cpp b/libraries/particles/src/ParticleTree.cpp index a597c76bd9..50f9ea1090 100644 --- a/libraries/particles/src/ParticleTree.cpp +++ b/libraries/particles/src/ParticleTree.cpp @@ -633,7 +633,6 @@ dataAt += sizeof(OCTREE_PACKET_SENT_TIME); uint16_t numberOfIds = 0; // placeholder for now memcpy(&numberOfIds, dataAt, sizeof(numberOfIds)); -qDebug() << "\t\t\t numberOfIds: " << numberOfIds; dataAt += sizeof(numberOfIds); processedBytes += sizeof(numberOfIds); From ec25982a58256442dda8b434710cdd297d002888 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 28 May 2014 17:51:17 -0700 Subject: [PATCH 33/45] add JointState::updateWorldTransform() --- interface/src/renderer/Model.cpp | 30 ++++++++++++------------------ interface/src/renderer/Model.h | 9 ++++++--- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 7e21bbb90f..215678dedc 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -162,19 +162,13 @@ QVector Model::createJointStates(const FBXGeometry& geometry) { int parentIndex = joint.parentIndex; if (parentIndex == -1) { _rootIndex = i; - glm::mat4 baseTransform = glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset); - glm::quat combinedRotation = joint.preRotation * state._rotation * joint.postRotation; - state._transform = baseTransform * geometry.offset * glm::translate(state._translation) * joint.preTransform * - glm::mat4_cast(combinedRotation) * joint.postTransform; - state._combinedRotation = _rotation * combinedRotation; + glm::mat4 baseTransform = glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset) * geometry.offset; + state.updateWorldTransform(baseTransform, _rotation); ++numJointsSet; jointIsSet[i] = true; } else if (jointIsSet[parentIndex]) { const JointState& parentState = jointStates.at(parentIndex); - glm::quat combinedRotation = joint.preRotation * state._rotation * joint.postRotation; - state._transform = parentState._transform * glm::translate(state._translation) * joint.preTransform * - glm::mat4_cast(combinedRotation) * joint.postTransform; - state._combinedRotation = parentState._combinedRotation * combinedRotation; + state.updateWorldTransform(parentState._transform, parentState._combinedRotation); ++numJointsSet; jointIsSet[i] = true; } @@ -1129,17 +1123,11 @@ void Model::updateJointState(int index) { if (joint.parentIndex == -1) { const FBXGeometry& geometry = _geometry->getFBXGeometry(); - glm::mat4 baseTransform = glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset); - glm::quat combinedRotation = joint.preRotation * state._rotation * joint.postRotation; - state._transform = baseTransform * geometry.offset * glm::translate(state._translation) * joint.preTransform * - glm::mat4_cast(combinedRotation) * joint.postTransform; - state._combinedRotation = _rotation * combinedRotation; + glm::mat4 baseTransform = glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset) * geometry.offset; + state.updateWorldTransform(baseTransform, _rotation); } else { const JointState& parentState = _jointStates.at(joint.parentIndex); - glm::quat combinedRotation = joint.preRotation * state._rotation * joint.postRotation; - state._transform = parentState._transform * glm::translate(state._translation) * joint.preTransform * - glm::mat4_cast(combinedRotation) * joint.postTransform; - state._combinedRotation = parentState._combinedRotation * combinedRotation; + state.updateWorldTransform(parentState._transform, parentState._combinedRotation); } } @@ -1908,3 +1896,9 @@ void JointState::setFBXJoint(const FBXJoint& joint) { _rotation = joint.rotation; _fbxJoint = &joint; } + +void JointState::updateWorldTransform(const glm::mat4& baseTransform, const glm::quat& parentRotation) { + glm::quat combinedRotation = _fbxJoint->preRotation * _rotation * _fbxJoint->postRotation; + _transform = baseTransform * glm::translate(_translation) * _fbxJoint->preTransform * glm::mat4_cast(combinedRotation) * _fbxJoint->postTransform; + _combinedRotation = parentRotation * combinedRotation; +} diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index be58a1d7f2..349e8305c4 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -34,15 +34,18 @@ typedef QWeakPointer WeakAnimationHandlePointer; class JointState { public: JointState(); + + void setFBXJoint(const FBXJoint& joint); + const FBXJoint& getFBXJoint() const { return *_fbxJoint; } + + void updateWorldTransform(const glm::mat4& baseTransform, const glm::quat& parentRotation); + glm::vec3 _translation; // translation relative to parent glm::quat _rotation; // rotation relative to parent glm::mat4 _transform; // rotation to world frame + translation in model frame glm::quat _combinedRotation; // rotation from joint local to world frame float _animationPriority; // the priority of the animation affecting this joint - void setFBXJoint(const FBXJoint& joint); - const FBXJoint& getFBXJoint() const { return *_fbxJoint; } - private: const FBXJoint* _fbxJoint; // JointState does not own its FBXJoint }; From cfe176c60e139c743c6a95018fbc607a2ad7afed Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 28 May 2014 20:50:39 -0700 Subject: [PATCH 34/45] Add locationsMenu.js --- examples/locationsMenu.js | 302 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 302 insertions(+) create mode 100644 examples/locationsMenu.js diff --git a/examples/locationsMenu.js b/examples/locationsMenu.js new file mode 100644 index 0000000000..6f4a28fe38 --- /dev/null +++ b/examples/locationsMenu.js @@ -0,0 +1,302 @@ +// +// locationsMenu.js +// examples +// +// Created by Ryan Huffman on 5/28/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 +// + +var scriptUrl = "https://script.google.com/macros/s/AKfycbwIo4lmF-qUwX1Z-9eA_P-g2gse9oFhNcjVyyksGukyDDEFXgU/exec?action=listOwners&domain=alpha.highfidelity.io"; + +var LocationMenu = function(opts) { + var self = this; + + var pageSize = opts.pageSize || 10; + var menuWidth = opts.menuWidth || 150; + var menuHeight = opts.menuItemHeight || 24; + + var inactiveColor = { red: 51, green: 102, blue: 102 }; + var activeColor = { red: 18, green: 66, blue: 66 }; + var prevNextColor = { red: 192, green: 192, blue: 192 }; + var disabledColor = { red: 64, green: 64, blue: 64}; + var position = { x: 0, y: 0 }; + + var locationIconUrl = "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/tools/location.svg"; + var toolHeight = 50; + var toolWidth = 50; + var visible = false; + var menuItemOffset = { + x: 55, + y: 0, + }; + var menuItemPadding = 5; + var margin = 7; + var fullMenuHeight = (2 * menuItemOffset.y) + (menuHeight * (pageSize + 1)); + var menuOffset = -fullMenuHeight + toolHeight; + + var windowDimensions = Controller.getViewportDimensions(); + + this.locations = []; + this.numPages = 1; + this.page = 0; + + this.menuToggleButton = Overlays.addOverlay("image", { + x: position.x, + y: position.y, + width: toolWidth, height: toolHeight, + subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight }, + imageURL: locationIconUrl, + alpha: 0.9 + }); + + this.background = Overlays.addOverlay("text", { + x: 0, + y: 0, + width: menuWidth + 10, + height: (menuHeight * (pageSize + 1)) + 10, + color: { red: 0, green: 0, blue: 0}, + topMargin: 4, + leftMargin: 4, + text: "", + visible: visible, + }); + + this.menuItems = []; + for (var i = 0; i < pageSize; i++) { + var menuItem = Overlays.addOverlay("text", { + x: 0, + y: 0, + width: menuWidth, + height: menuHeight, + color: inactiveColor, + topMargin: margin, + leftMargin: margin, + text: (i == 0) ? "Loading..." : "", + visible: visible, + }); + this.menuItems.push({ overlay: menuItem, location: null }); + } + + this.previousButton = Overlays.addOverlay("text", { + x: 0, + y: 0, + width: menuWidth / 2, + height: menuHeight, + color: disabledColor, + topMargin: margin, + leftMargin: margin, + text: "Previous", + visible: visible, + }); + + this.nextButton = Overlays.addOverlay("text", { + x: 0, + y: 0, + width: menuWidth / 2, + height: menuHeight, + color: disabledColor, + topMargin: margin, + leftMargin: margin, + text: "Next", + visible: visible, + }); + + this.reposition = function(force) { + var newWindowDimensions = Controller.getViewportDimensions(); + if (force || newWindowDimensions.y != windowDimensions.y) { + windowDimensions = newWindowDimensions; + + position.x = 8; + position.y = Math.floor(windowDimensions.y / 2) + 25 + 50 + 8; + + Overlays.editOverlay(self.menuToggleButton, { + x: position.x, + y: position.y, + }); + Overlays.editOverlay(self.background, { + x: position.x + menuItemOffset.x, + y: position.y + menuItemOffset.y - 2 * menuItemPadding + menuOffset, + }); + for (var i = 0; i < pageSize; i++) { + Overlays.editOverlay(self.menuItems[i].overlay, { + x: position.x + menuItemOffset.x + menuItemPadding, + y: position.y + menuItemOffset.y - menuItemPadding + (i * menuHeight) + menuOffset, + }); + } + Overlays.editOverlay(self.previousButton, { + x: position.x + menuItemOffset.x + menuItemPadding, + y: position.y + menuItemOffset.y - menuItemPadding + (pageSize * menuHeight) + menuOffset, + }); + Overlays.editOverlay(self.nextButton, { + x: position.x + menuItemOffset.x + menuItemPadding + (menuWidth / 2), + y: position.y + menuItemOffset.y - menuItemPadding + (pageSize * menuHeight) + menuOffset, + }); + } + } + + this.updateLocations = function(locations) { + this.locations = locations; + this.numPages = Math.ceil(locations.length / pageSize); + this.goToPage(0); + } + + this.setError = function() { + Overlays.editOverlay(this.menuItems[0].overlay, { text: "Error loading data" }); + } + + this.toggleMenu = function() { + visible = !visible; + for (var i = 0; i < this.menuItems.length; i++) { + Overlays.editOverlay(this.menuItems[i].overlay, { visible: visible}); + } + Overlays.editOverlay(this.previousButton, { visible: visible}); + Overlays.editOverlay(this.nextButton, { visible: visible}); + Overlays.editOverlay(this.background, { visible: visible}); + if (visible) { + Overlays.editOverlay(this.menuToggleButton, { subImage: { x: 0, y: 0, width: toolWidth, height: toolHeight } }), + } else { + Overlays.editOverlay(this.menuToggleButton, { subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight } }), + } + } + + this.goToPage = function(pageNumber) { + if (pageNumber < 0 || pageNumber >= this.numPages) { + return; + } + + this.page = pageNumber; + var start = pageNumber * pageSize; + for (var i = 0; i < pageSize; i++) { + var update = {}; + var location = null; + if (start + i < this.locations.length) { + location = this.locations[start + i]; + update.text = (start + i + 1) + ". " + location.username; + update.color = inactiveColor; + } else { + update.text = ""; + update.color = disabledColor; + } + Overlays.editOverlay(this.menuItems[i].overlay, update); + this.menuItems[i].location = location; + } + + this.previousEnabled = pageNumber > 0; + this.nextEnabled = pageNumber < (this.numPages - 1); + + Overlays.editOverlay(this.previousButton, { color: this.previousEnabled ? prevNextColor : disabledColor}); + Overlays.editOverlay(this.nextButton, { color: this.nextEnabled ? prevNextColor : disabledColor }); + } + + this.mousePressEvent = function(event) { + var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); + + if (clickedOverlay == self.menuToggleButton) { + self.toggleMenu(); + } else if (clickedOverlay == self.previousButton) { + if (self.previousEnabled) { + Overlays.editOverlay(clickedOverlay, { color: activeColor }); + } + } else if (clickedOverlay == self.nextButton) { + if (self.nextEnabled) { + Overlays.editOverlay(clickedOverlay, { color: activeColor }); + } + } else { + for (var i = 0; i < self.menuItems.length; i++) { + if (clickedOverlay == self.menuItems[i].overlay) { + if (self.menuItems[i].location != null) { + Overlays.editOverlay(clickedOverlay, { color: activeColor }); + } + break; + } + } + } + } + + this.mouseReleaseEvent = function(event) { + var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); + + if (clickedOverlay == self.previousButton) { + if (self.previousEnabled) { + Overlays.editOverlay(clickedOverlay, { color: inactiveColor }); + self.goToPage(self.page - 1); + } + } else if (clickedOverlay == self.nextButton) { + if (self.nextEnabled) { + Overlays.editOverlay(clickedOverlay, { color: inactiveColor }); + self.goToPage(self.page + 1); + } + } else { + for (var i = 0; i < self.menuItems.length; i++) { + if (clickedOverlay == self.menuItems[i].overlay) { + if (self.menuItems[i].location != null) { + Overlays.editOverlay(clickedOverlay, { color: inactiveColor }); + var location = self.menuItems[i].location; + Window.location = "hifi://" + location.domain + "/" + + location.x + "," + location.y + "," + location.z; + } + break; + } + } + } + } + + this.cleanup = function() { + for (var i = 0; i < self.menuItems.length; i++) { + Overlays.deleteOverlay(self.menuItems[i].overlay); + } + Overlays.deleteOverlay(self.menuToggleButton); + Overlays.deleteOverlay(self.previousButton); + Overlays.deleteOverlay(self.nextButton); + Overlays.deleteOverlay(self.background); + } + + Controller.mousePressEvent.connect(this.mousePressEvent); + Controller.mouseReleaseEvent.connect(this.mouseReleaseEvent); + Script.update.connect(this.reposition); + Script.scriptEnding.connect(this.cleanup); + + this.reposition(true); +}; + +var locationMenu = new LocationMenu({ pageSize: 8 }); + +print("Loading strip data from " + scriptUrl); + +var req = new XMLHttpRequest(); +req.responseType = 'json'; + +req.onreadystatechange = function() { + if (req.readyState == req.DONE) { + if (req.status == 200 && req.response != null) { + for (var domain in req.response) { + var locations = req.response[domain]; + var users = []; + for (var i = 0; i < locations.length; i++) { + var loc = locations[i]; + var x1 = loc[1], + x2 = loc[2], + y1 = loc[3], + y2 = loc[4]; + users.push({ + domain: domain, + username: loc[0], + x: x1, + y: 300, + z: y1, + }); + } + locationMenu.updateLocations(users); + } + } else { + print("Error loading data: " + req.status + " " + req.statusText + ", " + req.errorCode + ": " + req.responseText); + locationMenu.setError(); + } + } +} + +req.open("GET", scriptUrl); +req.send(); From e0d68607cd5f154af7609455f926d5900ef5887a Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 28 May 2014 21:02:33 -0700 Subject: [PATCH 35/45] Set max voxel size of 16 meters in script for voxel creation --- examples/editVoxels.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/examples/editVoxels.js b/examples/editVoxels.js index 9040306bf6..14bea50bb0 100644 --- a/examples/editVoxels.js +++ b/examples/editVoxels.js @@ -28,7 +28,7 @@ var NEW_VOXEL_SIZE = 1.0; var NEW_VOXEL_DISTANCE_FROM_CAMERA = 3.0; var PIXELS_PER_EXTRUDE_VOXEL = 16; var WHEEL_PIXELS_PER_SCALE_CHANGE = 100; -var MAX_VOXEL_SCALE = 1.0; +var MAX_VOXEL_SCALE = 16.0; var MIN_VOXEL_SCALE = 1.0 / Math.pow(2.0, 8.0); var WHITE_COLOR = { red: 255, green: 255, blue: 255 }; @@ -394,6 +394,9 @@ function ScaleSelector() { if (this.power < 13) { ++this.power; this.scale *= 2.0; + if (this.scale > MAX_VOXEL_SCALE) { + this.scale = MAX_VOXEL_SCALE; + } this.update(); rescaleImport(); resizeVoxelSound.play(voxelSizePlus); @@ -1056,6 +1059,9 @@ function mousePressEvent(event) { lastVoxelPosition = { x: voxelDetails.x, y: voxelDetails.y, z: voxelDetails.z }; lastVoxelColor = { red: newColor.red, green: newColor.green, blue: newColor.blue }; lastVoxelScale = voxelDetails.s; + if (lastVoxelScale > MAX_VOXEL_SCALE) { + lastVoxelScale = MAX_VOXEL_SCALE; + } addVoxelSound.playRandom(); From 86d6fd45de95962b23d2c30c33da242666e838fb Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 29 May 2014 08:19:43 -0700 Subject: [PATCH 36/45] safe copy of JointState data --- interface/src/renderer/Model.cpp | 26 +++++++++++++++++++------- interface/src/renderer/Model.h | 6 ++++-- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 215678dedc..1a857ff811 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -138,8 +138,9 @@ void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locati QVector Model::createJointStates(const FBXGeometry& geometry) { QVector jointStates; foreach (const FBXJoint& joint, geometry.joints) { + // NOTE: the state keeps a pointer to an FBXJoint JointState state; - state.setFBXJoint(joint); + state.setFBXJoint(&joint); jointStates.append(state); } @@ -408,7 +409,7 @@ bool Model::updateGeometry() { int oldIndex = it.value() - 1; int newIndex = newGeometry.getJointIndex(it.key()); if (newIndex != -1) { - newJointStates[newIndex] = _jointStates.at(oldIndex); + newJointStates[newIndex].copyState(_jointStates[oldIndex]); } } } @@ -1890,15 +1891,26 @@ JointState::JointState() : _fbxJoint(NULL) { } -void JointState::setFBXJoint(const FBXJoint& joint) { - assert(&joint != NULL); - _translation = joint.translation; - _rotation = joint.rotation; - _fbxJoint = &joint; +void JointState::setFBXJoint(const FBXJoint* joint) { + assert(joint != NULL); + _translation = joint->translation; + _rotation = joint->rotation; + // NOTE: JointState does not own the FBXJoint to which it points. + _fbxJoint = joint; } void JointState::updateWorldTransform(const glm::mat4& baseTransform, const glm::quat& parentRotation) { + assert(_fbxJoint != NULL); glm::quat combinedRotation = _fbxJoint->preRotation * _rotation * _fbxJoint->postRotation; _transform = baseTransform * glm::translate(_translation) * _fbxJoint->preTransform * glm::mat4_cast(combinedRotation) * _fbxJoint->postTransform; _combinedRotation = parentRotation * combinedRotation; } + +void JointState::copyState(const JointState& state) { + _translation = state._translation; + _rotation = state._rotation; + _transform = state._transform; + _combinedRotation = state._combinedRotation; + _animationPriority = state._animationPriority; + // DO NOT copy _fbxJoint +} diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 349e8305c4..b8a5de5902 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -35,11 +35,13 @@ class JointState { public: JointState(); - void setFBXJoint(const FBXJoint& joint); + void setFBXJoint(const FBXJoint* joint); const FBXJoint& getFBXJoint() const { return *_fbxJoint; } void updateWorldTransform(const glm::mat4& baseTransform, const glm::quat& parentRotation); + void copyState(const JointState& state); + glm::vec3 _translation; // translation relative to parent glm::quat _rotation; // rotation relative to parent glm::mat4 _transform; // rotation to world frame + translation in model frame @@ -47,7 +49,7 @@ public: float _animationPriority; // the priority of the animation affecting this joint private: - const FBXJoint* _fbxJoint; // JointState does not own its FBXJoint + const FBXJoint* _fbxJoint; // JointState does NOT own its FBXJoint }; /// A generic 3D model displaying geometry loaded from a URL. From 425632e072fe64196d7f917f1a0bb30027d31423 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 29 May 2014 08:48:22 -0700 Subject: [PATCH 37/45] Add 'f' to end of const float to follow coding standard --- interface/src/Menu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index a924528c2b..c21214bed5 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -73,7 +73,7 @@ const int FIVE_SECONDS_OF_FRAMES = 5 * ONE_SECOND_OF_FRAMES; const float MUTE_RADIUS = 50; const QString CONSOLE_TITLE = "Scripting Console"; -const float CONSOLE_WINDOW_OPACITY = 0.95; +const float CONSOLE_WINDOW_OPACITY = 0.95f; const int CONSOLE_WIDTH = 800; const int CONSOLE_HEIGHT = 200; From c87c4748771376d6d63cbfb9e0903f03565fa6d3 Mon Sep 17 00:00:00 2001 From: wangyix Date: Thu, 29 May 2014 10:39:40 -0700 Subject: [PATCH 38/45] removed debug info, cleaned code for pull req --- .../src/octree/OctreeSendThread.cpp | 1 - assignment-client/src/voxels/VoxelServer.cpp | 38 +++++++++--------- interface/src/Application.cpp | 7 +--- interface/src/Environment.cpp | 8 ++-- interface/src/voxels/VoxelPacketProcessor.cpp | 2 +- libraries/models/src/ModelTree.cpp | 40 +++++++++---------- libraries/networking/src/LimitedNodeList.cpp | 36 ----------------- libraries/octree/src/OctreeSceneStats.cpp | 16 ++------ libraries/octree/src/OctreeSceneStats.h | 2 +- libraries/particles/src/ParticleTree.cpp | 34 ++++++++-------- 10 files changed, 67 insertions(+), 117 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index dca18026a1..b91c4c4761 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -535,7 +535,6 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus // send the environment packet // TODO: should we turn this into a while loop to better handle sending multiple special packets if (_myServer->hasSpecialPacketToSend(_node) && !nodeData->isShuttingDown()) { -qDebug() << "sending special packet..."; trueBytesSent += _myServer->sendSpecialPacket(_sequenceNumber, _node); nodeData->resetOctreePacket(_sequenceNumber); // because _sequenceNumber has changed truePacketsSent++; diff --git a/assignment-client/src/voxels/VoxelServer.cpp b/assignment-client/src/voxels/VoxelServer.cpp index 181a51ebc9..9a4da4d611 100644 --- a/assignment-client/src/voxels/VoxelServer.cpp +++ b/assignment-client/src/voxels/VoxelServer.cpp @@ -42,32 +42,32 @@ bool VoxelServer::hasSpecialPacketToSend(const SharedNodePointer& node) { int VoxelServer::sendSpecialPacket(OCTREE_PACKET_SEQUENCE& sequenceNumber, const SharedNodePointer& node) { -unsigned char* copyAt = _tempOutputBuffer; + unsigned char* copyAt = _tempOutputBuffer; int numBytesPacketHeader = populatePacketHeader(reinterpret_cast(_tempOutputBuffer), PacketTypeEnvironmentData); -copyAt += numBytesPacketHeader; + copyAt += numBytesPacketHeader; int envPacketLength = numBytesPacketHeader; -// pack in flags -OCTREE_PACKET_FLAGS flags = 0; -OCTREE_PACKET_FLAGS* flagsAt = (OCTREE_PACKET_FLAGS*)copyAt; -*flagsAt = flags; -copyAt += sizeof(OCTREE_PACKET_FLAGS); -envPacketLength += sizeof(OCTREE_PACKET_FLAGS); + // pack in flags + OCTREE_PACKET_FLAGS flags = 0; + OCTREE_PACKET_FLAGS* flagsAt = (OCTREE_PACKET_FLAGS*)copyAt; + *flagsAt = flags; + copyAt += sizeof(OCTREE_PACKET_FLAGS); + envPacketLength += sizeof(OCTREE_PACKET_FLAGS); -// pack in sequence number -OCTREE_PACKET_SEQUENCE* sequenceAt = (OCTREE_PACKET_SEQUENCE*)copyAt; -*sequenceAt = sequenceNumber; -copyAt += sizeof(OCTREE_PACKET_SEQUENCE); -envPacketLength += sizeof(OCTREE_PACKET_SEQUENCE); + // pack in sequence number + OCTREE_PACKET_SEQUENCE* sequenceAt = (OCTREE_PACKET_SEQUENCE*)copyAt; + *sequenceAt = sequenceNumber; + copyAt += sizeof(OCTREE_PACKET_SEQUENCE); + envPacketLength += sizeof(OCTREE_PACKET_SEQUENCE); -// pack in timestamp -OCTREE_PACKET_SENT_TIME now = usecTimestampNow(); -OCTREE_PACKET_SENT_TIME* timeAt = (OCTREE_PACKET_SENT_TIME*)copyAt; -*timeAt = now; -copyAt += sizeof(OCTREE_PACKET_SENT_TIME); -envPacketLength += sizeof(OCTREE_PACKET_SENT_TIME); + // pack in timestamp + OCTREE_PACKET_SENT_TIME now = usecTimestampNow(); + OCTREE_PACKET_SENT_TIME* timeAt = (OCTREE_PACKET_SENT_TIME*)copyAt; + *timeAt = now; + copyAt += sizeof(OCTREE_PACKET_SENT_TIME); + envPacketLength += sizeof(OCTREE_PACKET_SENT_TIME); int environmentsToSend = getSendMinimalEnvironment() ? 1 : getEnvironmentDataCount(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7ad3409f8e..4ee15bc949 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3142,12 +3142,7 @@ void Application::trackIncomingVoxelPacket(const QByteArray& packet, const Share _octreeSceneStatsLock.lockForWrite(); if (_octreeServerSceneStats.find(nodeUUID) != _octreeServerSceneStats.end()) { OctreeSceneStats& stats = _octreeServerSceneStats[nodeUUID]; - if (stats.trackIncomingOctreePacket(packet, wasStatsPacket, sendingNode->getClockSkewUsec())) { - - // DEBUG! unreasonable flight time - qDebug() << " sending node type: " << NodeType::getNodeTypeName(sendingNode->getType()) << "\n"; - //qDebug() << "\t\t clock skew: " << sendingNode->getClockSkewUsec(); - } + stats.trackIncomingOctreePacket(packet, wasStatsPacket, sendingNode->getClockSkewUsec()); } _octreeSceneStatsLock.unlock(); } diff --git a/interface/src/Environment.cpp b/interface/src/Environment.cpp index c302907cd7..67337f963c 100644 --- a/interface/src/Environment.cpp +++ b/interface/src/Environment.cpp @@ -161,10 +161,10 @@ int Environment::parseData(const HifiSockAddr& senderAddress, const QByteArray& // push past the packet header int bytesRead = numBytesForPacketHeader(packet); -// push past flags, sequence, timestamp -bytesRead += sizeof(OCTREE_PACKET_FLAGS); -bytesRead += sizeof(OCTREE_PACKET_SEQUENCE); -bytesRead += sizeof(OCTREE_PACKET_SENT_TIME); + // push past flags, sequence, timestamp + bytesRead += sizeof(OCTREE_PACKET_FLAGS); + bytesRead += sizeof(OCTREE_PACKET_SEQUENCE); + bytesRead += sizeof(OCTREE_PACKET_SENT_TIME); // get the lock for the duration of the call QMutexLocker locker(&_mutex); diff --git a/interface/src/voxels/VoxelPacketProcessor.cpp b/interface/src/voxels/VoxelPacketProcessor.cpp index 11e62b0fe3..095c378c04 100644 --- a/interface/src/voxels/VoxelPacketProcessor.cpp +++ b/interface/src/voxels/VoxelPacketProcessor.cpp @@ -81,7 +81,7 @@ void VoxelPacketProcessor::processPacket(const SharedNodePointer& sendingNode, c if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) { -//if (voxelPacketType != PacketTypeParticleErase) + app->trackIncomingVoxelPacket(mutablePacket, sendingNode, wasStatsPacket); if (sendingNode) { diff --git a/libraries/models/src/ModelTree.cpp b/libraries/models/src/ModelTree.cpp index 279508bf29..e88a969061 100644 --- a/libraries/models/src/ModelTree.cpp +++ b/libraries/models/src/ModelTree.cpp @@ -555,25 +555,25 @@ bool ModelTree::encodeModelsDeletedSince(OCTREE_PACKET_SEQUENCE sequenceNumber, copyAt += numBytesPacketHeader; outputLength = numBytesPacketHeader; -// pack in flags -OCTREE_PACKET_FLAGS flags = 0; -OCTREE_PACKET_FLAGS* flagsAt = (OCTREE_PACKET_FLAGS*)copyAt; -*flagsAt = flags; -copyAt += sizeof(OCTREE_PACKET_FLAGS); -outputLength += sizeof(OCTREE_PACKET_FLAGS); + // pack in flags + OCTREE_PACKET_FLAGS flags = 0; + OCTREE_PACKET_FLAGS* flagsAt = (OCTREE_PACKET_FLAGS*)copyAt; + *flagsAt = flags; + copyAt += sizeof(OCTREE_PACKET_FLAGS); + outputLength += sizeof(OCTREE_PACKET_FLAGS); -// pack in sequence number -OCTREE_PACKET_SEQUENCE* sequenceAt = (OCTREE_PACKET_SEQUENCE*)copyAt; -*sequenceAt = sequenceNumber; -copyAt += sizeof(OCTREE_PACKET_SEQUENCE); -outputLength += sizeof(OCTREE_PACKET_SEQUENCE); + // pack in sequence number + OCTREE_PACKET_SEQUENCE* sequenceAt = (OCTREE_PACKET_SEQUENCE*)copyAt; + *sequenceAt = sequenceNumber; + copyAt += sizeof(OCTREE_PACKET_SEQUENCE); + outputLength += sizeof(OCTREE_PACKET_SEQUENCE); -// pack in timestamp -OCTREE_PACKET_SENT_TIME now = usecTimestampNow(); -OCTREE_PACKET_SENT_TIME* timeAt = (OCTREE_PACKET_SENT_TIME*)copyAt; -*timeAt = now; -copyAt += sizeof(OCTREE_PACKET_SENT_TIME); -outputLength += sizeof(OCTREE_PACKET_SENT_TIME); + // pack in timestamp + OCTREE_PACKET_SENT_TIME now = usecTimestampNow(); + OCTREE_PACKET_SENT_TIME* timeAt = (OCTREE_PACKET_SENT_TIME*)copyAt; + *timeAt = now; + copyAt += sizeof(OCTREE_PACKET_SENT_TIME); + outputLength += sizeof(OCTREE_PACKET_SENT_TIME); uint16_t numberOfIds = 0; // placeholder for now unsigned char* numberOfIDsAt = copyAt; @@ -662,9 +662,9 @@ void ModelTree::processEraseMessage(const QByteArray& dataByteArray, const Share size_t processedBytes = numBytesPacketHeader; dataAt += numBytesPacketHeader; -dataAt += sizeof(OCTREE_PACKET_FLAGS); -dataAt += sizeof(OCTREE_PACKET_SEQUENCE); -dataAt += sizeof(OCTREE_PACKET_SENT_TIME); + dataAt += sizeof(OCTREE_PACKET_FLAGS); + dataAt += sizeof(OCTREE_PACKET_SEQUENCE); + dataAt += sizeof(OCTREE_PACKET_SENT_TIME); uint16_t numberOfIds = 0; // placeholder for now memcpy(&numberOfIds, dataAt, sizeof(numberOfIds)); diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 743cbe949a..c0d7941edf 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -268,42 +268,6 @@ qint64 LimitedNodeList::writeUnverifiedDatagram(const QByteArray& datagram, cons qint64 LimitedNodeList::writeDatagram(const char* data, qint64 size, const SharedNodePointer& destinationNode, const HifiSockAddr& overridenSockAddr) { - /* - QByteArray datagram(data, size); - - qDebug() << "\t writeDatagram()..."; - - int numBytesPacketHeader = numBytesForPacketHeader(datagram); - const unsigned char* dataAt = reinterpret_cast(datagram.data()) + numBytesPacketHeader; - - PacketType type = packetTypeForPacket(datagram); - qDebug() << "\t\t type: " << (unsigned char)type; - - - if (type != PacketTypeOctreeStats) { - - //qDebug() << "\t\t UUID: " << uuidFromPacketHeader(datagram); - //qDebug() << "\t\t MD5: " << hashFromPacketHeader(datagram); - - unsigned char flags = (*(unsigned char*)(dataAt)); - dataAt += sizeof(unsigned char); - qDebug() << "\t\t flags: " << QString::number(flags, 2); - - uint16_t sequence = (*(uint16_t*)dataAt); - dataAt += sizeof(uint16_t); - qDebug() << "\t\t sequence: " << QString::number(sequence, 16); - - quint64 sentAt = (*(quint64*)dataAt); - dataAt += sizeof(quint64); - qDebug() << "\t\t sent at: " << QString::number(sentAt, 16) << "\n"; - } - - if (type == PacketTypeParticleErase || type==PacketTypeModelErase) { - uint16_t ids = *((uint16_t*)dataAt); - dataAt += sizeof(uint16_t); - qDebug() << "\t\t\t ids: " << ids; - } - */ return writeDatagram(QByteArray(data, size), destinationNode, overridenSockAddr); } diff --git a/libraries/octree/src/OctreeSceneStats.cpp b/libraries/octree/src/OctreeSceneStats.cpp index 3659c8bd24..269b64559f 100644 --- a/libraries/octree/src/OctreeSceneStats.cpp +++ b/libraries/octree/src/OctreeSceneStats.cpp @@ -839,7 +839,7 @@ const char* OctreeSceneStats::getItemValue(Item item) { return _itemValueBuffer; } -bool OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, +void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, bool wasStatsPacket, int nodeClockSkewUsec) { const bool wantExtraDebugging = false; @@ -866,21 +866,13 @@ bool OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, qDebug() << "nodeClockSkewUsec:" << nodeClockSkewUsec << " usecs"; qDebug() << "flightTime:" << flightTime << " usecs"; } - - -//qDebug() << "\t" << QString::number(sequence, 16) << "\t sentAt:" << QString::number(sentAt, 16) << " usecs"; // Guard against possible corrupted packets... with bad timestamps const int MAX_RESONABLE_FLIGHT_TIME = 200 * USECS_PER_SECOND; // 200 seconds is more than enough time for a packet to arrive const int MIN_RESONABLE_FLIGHT_TIME = 0; if (flightTime > MAX_RESONABLE_FLIGHT_TIME || flightTime < MIN_RESONABLE_FLIGHT_TIME) { qDebug() << "ignoring unreasonable packet... flightTime:" << flightTime; -qDebug() << "\t sequence:" << QString::number(sequence, 16); -qDebug() << "\t sentAt:" << QString::number(sentAt, 16) << " usecs"; -qDebug() << "\t arrivedAt:" << QString::number(arrivedAt, 16) << " usecs"; -qDebug() << "\t nodeClockSkewUsec:" << nodeClockSkewUsec << " usecs"; -qDebug() << "\t flightTime:" << flightTime << " usecs"; - return true; // ignore any packets that are unreasonable + return; } // determine our expected sequence number... handle rollover appropriately @@ -892,7 +884,7 @@ qDebug() << "\t flightTime:" << flightTime << " usecs"; int sequenceOffset = (sequence - expected); if (sequenceOffset > MAX_RESONABLE_SEQUENCE_OFFSET || sequenceOffset < MIN_RESONABLE_SEQUENCE_OFFSET) { qDebug() << "ignoring unreasonable packet... sequence:" << sequence << "_incomingLastSequence:" << _incomingLastSequence; - return false; // ignore any packets that are unreasonable + return; // ignore any packets that are unreasonable } // track packets here... @@ -993,6 +985,6 @@ qDebug() << "\t flightTime:" << flightTime << " usecs"; } } } - return false; + return; } diff --git a/libraries/octree/src/OctreeSceneStats.h b/libraries/octree/src/OctreeSceneStats.h index dd0b31b010..ef22fd7c1c 100644 --- a/libraries/octree/src/OctreeSceneStats.h +++ b/libraries/octree/src/OctreeSceneStats.h @@ -158,7 +158,7 @@ public: quint64 getLastFullTotalBytes() const { return _lastFullTotalBytes; } // Used in client implementations to track individual octree packets - bool trackIncomingOctreePacket(const QByteArray& packet, bool wasStatsPacket, int nodeClockSkewUsec); + void trackIncomingOctreePacket(const QByteArray& packet, bool wasStatsPacket, int nodeClockSkewUsec); quint32 getIncomingPackets() const { return _incomingPacket; } quint64 getIncomingBytes() const { return _incomingBytes; } diff --git a/libraries/particles/src/ParticleTree.cpp b/libraries/particles/src/ParticleTree.cpp index c36e029ce1..cd79ff303e 100644 --- a/libraries/particles/src/ParticleTree.cpp +++ b/libraries/particles/src/ParticleTree.cpp @@ -521,22 +521,22 @@ bool ParticleTree::encodeParticlesDeletedSince(OCTREE_PACKET_SEQUENCE sequenceNu copyAt += numBytesPacketHeader; outputLength = numBytesPacketHeader; -// pack in flags -OCTREE_PACKET_FLAGS flags = 0; -memcpy(copyAt, &flags, sizeof(OCTREE_PACKET_FLAGS)); -copyAt += sizeof(OCTREE_PACKET_FLAGS); -outputLength += sizeof(OCTREE_PACKET_FLAGS); + // pack in flags + OCTREE_PACKET_FLAGS flags = 0; + memcpy(copyAt, &flags, sizeof(OCTREE_PACKET_FLAGS)); + copyAt += sizeof(OCTREE_PACKET_FLAGS); + outputLength += sizeof(OCTREE_PACKET_FLAGS); -// pack in sequence number -memcpy(copyAt, &sequenceNumber, sizeof(OCTREE_PACKET_SEQUENCE)); -copyAt += sizeof(OCTREE_PACKET_SEQUENCE); -outputLength += sizeof(OCTREE_PACKET_SEQUENCE); + // pack in sequence number + memcpy(copyAt, &sequenceNumber, sizeof(OCTREE_PACKET_SEQUENCE)); + copyAt += sizeof(OCTREE_PACKET_SEQUENCE); + outputLength += sizeof(OCTREE_PACKET_SEQUENCE); -// pack in timestamp -OCTREE_PACKET_SENT_TIME now = usecTimestampNow(); -memcpy(copyAt, &now, sizeof(OCTREE_PACKET_SENT_TIME)); -copyAt += sizeof(OCTREE_PACKET_SENT_TIME); -outputLength += sizeof(OCTREE_PACKET_SENT_TIME); + // pack in timestamp + OCTREE_PACKET_SENT_TIME now = usecTimestampNow(); + memcpy(copyAt, &now, sizeof(OCTREE_PACKET_SENT_TIME)); + copyAt += sizeof(OCTREE_PACKET_SENT_TIME); + outputLength += sizeof(OCTREE_PACKET_SENT_TIME); uint16_t numberOfIds = 0; // placeholder for now @@ -627,9 +627,9 @@ void ParticleTree::processEraseMessage(const QByteArray& dataByteArray, const Sh size_t processedBytes = numBytesPacketHeader; dataAt += numBytesPacketHeader; -dataAt += sizeof(OCTREE_PACKET_FLAGS); -dataAt += sizeof(OCTREE_PACKET_SEQUENCE); -dataAt += sizeof(OCTREE_PACKET_SENT_TIME); + dataAt += sizeof(OCTREE_PACKET_FLAGS); + dataAt += sizeof(OCTREE_PACKET_SEQUENCE); + dataAt += sizeof(OCTREE_PACKET_SENT_TIME); uint16_t numberOfIds = 0; // placeholder for now memcpy(&numberOfIds, dataAt, sizeof(numberOfIds)); From fe1a0e45654a59beadcf19a8d5c75882734f9b8d Mon Sep 17 00:00:00 2001 From: wangyix Date: Thu, 29 May 2014 11:27:14 -0700 Subject: [PATCH 39/45] removed debug stuff i missed --- assignment-client/src/octree/OctreeQueryNode.cpp | 6 ------ assignment-client/src/octree/OctreeQueryNode.h | 4 ---- assignment-client/src/octree/OctreeSendThread.cpp | 5 ++--- assignment-client/src/voxels/VoxelServer.cpp | 2 -- libraries/octree/src/OctreeSceneStats.cpp | 6 +++--- 5 files changed, 5 insertions(+), 18 deletions(-) diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index ea15770f9e..f7b293dfa8 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -38,7 +38,6 @@ OctreeQueryNode::OctreeQueryNode() : _lastClientOctreeSizeScale(DEFAULT_OCTREE_SIZE_SCALE), _lodChanged(false), _lodInitialized(false), - //_sequenceNumber(0), _lastRootTimestamp(0), _myPacketType(PacketTypeUnknown), _isShuttingDown(false) @@ -362,8 +361,3 @@ void OctreeQueryNode::dumpOutOfView() { } } } -/* -void OctreeQueryNode::incrementSequenceNumber() { - _sequenceNumber++; -} -*/ diff --git a/assignment-client/src/octree/OctreeQueryNode.h b/assignment-client/src/octree/OctreeQueryNode.h index af293189a4..eeea98699c 100644 --- a/assignment-client/src/octree/OctreeQueryNode.h +++ b/assignment-client/src/octree/OctreeQueryNode.h @@ -99,8 +99,6 @@ public: void nodeKilled(); void forceNodeShutdown(); bool isShuttingDown() const { return _isShuttingDown; } - - //void incrementSequenceNumber(); private slots: void sendThreadFinished(); @@ -138,8 +136,6 @@ private: bool _lodChanged; bool _lodInitialized; - //OCTREE_PACKET_SEQUENCE _sequenceNumber; - quint64 _lastRootTimestamp; PacketType _myPacketType; diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index b91c4c4761..a396e1170c 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -143,8 +143,6 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes } const unsigned char* messageData = nodeData->getPacket(); -//unsigned char messageData[MAX_PACKET_SIZE]; -//memcpy(messageData, nodeData->getPacket(), MAX_PACKET_SIZE); // DEBUG: make copy of message to send int numBytesPacketHeader = numBytesForPacketHeader(reinterpret_cast(messageData)); const unsigned char* dataAt = messageData + numBytesPacketHeader; @@ -164,7 +162,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes int piggyBackSize = nodeData->getPacketLength() + statsMessageLength; // If the size of the stats message and the voxel message will fit in a packet, then piggyback them -if (piggyBackSize < MAX_PACKET_SIZE && false) { + if (piggyBackSize < MAX_PACKET_SIZE) { // copy voxel message to back of stats message memcpy(statsMessage + statsMessageLength, nodeData->getPacket(), nodeData->getPacketLength()); @@ -252,6 +250,7 @@ if (piggyBackSize < MAX_PACKET_SIZE && false) { _sequenceNumber++; nodeData->resetOctreePacket(_sequenceNumber); } + return packetsSent; } diff --git a/assignment-client/src/voxels/VoxelServer.cpp b/assignment-client/src/voxels/VoxelServer.cpp index 9a4da4d611..43d01f1c77 100644 --- a/assignment-client/src/voxels/VoxelServer.cpp +++ b/assignment-client/src/voxels/VoxelServer.cpp @@ -48,7 +48,6 @@ int VoxelServer::sendSpecialPacket(OCTREE_PACKET_SEQUENCE& sequenceNumber, const copyAt += numBytesPacketHeader; int envPacketLength = numBytesPacketHeader; - // pack in flags OCTREE_PACKET_FLAGS flags = 0; OCTREE_PACKET_FLAGS* flagsAt = (OCTREE_PACKET_FLAGS*)copyAt; @@ -69,7 +68,6 @@ int VoxelServer::sendSpecialPacket(OCTREE_PACKET_SEQUENCE& sequenceNumber, const copyAt += sizeof(OCTREE_PACKET_SENT_TIME); envPacketLength += sizeof(OCTREE_PACKET_SENT_TIME); - int environmentsToSend = getSendMinimalEnvironment() ? 1 : getEnvironmentDataCount(); for (int i = 0; i < environmentsToSend; i++) { diff --git a/libraries/octree/src/OctreeSceneStats.cpp b/libraries/octree/src/OctreeSceneStats.cpp index 269b64559f..9580ae6d13 100644 --- a/libraries/octree/src/OctreeSceneStats.cpp +++ b/libraries/octree/src/OctreeSceneStats.cpp @@ -857,7 +857,7 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, //bool packetIsColored = oneAtBit(flags, PACKET_IS_COLOR_BIT); //bool packetIsCompressed = oneAtBit(flags, PACKET_IS_COMPRESSED_BIT); - OCTREE_PACKET_SENT_TIME arrivedAt = usecTimestampNow(); // DEBUG!!! + OCTREE_PACKET_SENT_TIME arrivedAt = usecTimestampNow(); qint64 flightTime = arrivedAt - sentAt + nodeClockSkewUsec; if (wantExtraDebugging) { @@ -872,7 +872,7 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, const int MIN_RESONABLE_FLIGHT_TIME = 0; if (flightTime > MAX_RESONABLE_FLIGHT_TIME || flightTime < MIN_RESONABLE_FLIGHT_TIME) { qDebug() << "ignoring unreasonable packet... flightTime:" << flightTime; - return; + return; // ignore any packets that are unreasonable } // determine our expected sequence number... handle rollover appropriately @@ -985,6 +985,6 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, } } } - return; + } From 65508b2016d1688a6beba885aa2efed8bc920b15 Mon Sep 17 00:00:00 2001 From: wangyix Date: Thu, 29 May 2014 11:42:35 -0700 Subject: [PATCH 40/45] updated packet type version numbers --- libraries/networking/src/PacketHeaders.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index 0f0b57635c..c56dba9cf1 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -52,7 +52,7 @@ PacketVersion versionForPacketType(PacketType type) { case PacketTypeAvatarIdentity: return 1; case PacketTypeEnvironmentData: - return 1; + return 2; case PacketTypeDomainList: case PacketTypeDomainListRequest: return 3; @@ -66,8 +66,12 @@ PacketVersion versionForPacketType(PacketType type) { return 1; case PacketTypeParticleData: return 1; + case PacketTypeParticleErase: + return 1; case PacketTypeModelData: - return 2; + return 2; + case PacketTypeModelErase: + return 1; default: return 0; } From e6966c2155e0561cf34d343047776f98da7ff35a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 29 May 2014 12:12:23 -0700 Subject: [PATCH 41/45] add improved detailed rendering and FPS debugging stats --- interface/src/Application.cpp | 129 ++++++++++++++++++++------ interface/src/Menu.cpp | 9 +- interface/src/Menu.h | 5 + interface/src/renderer/GlowEffect.cpp | 4 + interface/src/ui/Stats.cpp | 73 ++++++++++++++- interface/src/ui/Stats.h | 1 + libraries/shared/src/PerfStat.cpp | 18 ++++ libraries/shared/src/PerfStat.h | 37 ++++++++ 8 files changed, 245 insertions(+), 31 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4ee15bc949..db6333acee 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -554,6 +554,8 @@ void Application::initializeGL() { } void Application::paintGL() { + PerformanceTimer perfTimer("paintGL"); + PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings)); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::paintGL()"); @@ -648,7 +650,10 @@ void Application::paintGL() { _rearMirrorTools->render(true); } - _applicationOverlay.renderOverlay(); + { + PerformanceTimer perfTimer("paintGL/renderOverlay"); + _applicationOverlay.renderOverlay(); + } } _frameCount++; @@ -1288,11 +1293,13 @@ void Application::timer() { } void Application::idle() { + PerformanceTimer perfTimer("idle"); + // Normally we check PipelineWarnings, but since idle will often take more than 10ms we only show these idle timing // details if we're in ExtraDebugging mode. However, the ::update() and it's subcomponents will show their timing // details normally. bool showWarnings = getLogger()->extraDebugging(); - PerformanceWarning warn(showWarnings, "Application::idle()"); + PerformanceWarning warn(showWarnings, "idle()"); // Only run simulation code if more than IDLE_SIMULATE_MSECS have passed since last time we ran @@ -1300,15 +1307,18 @@ void Application::idle() { if (timeSinceLastUpdate > IDLE_SIMULATE_MSECS) { _lastTimeUpdated.start(); { + PerformanceTimer perfTimer("idle/update"); PerformanceWarning warn(showWarnings, "Application::idle()... update()"); const float BIGGEST_DELTA_TIME_SECS = 0.25f; update(glm::clamp((float)timeSinceLastUpdate / 1000.f, 0.f, BIGGEST_DELTA_TIME_SECS)); } { + PerformanceTimer perfTimer("idle/updateGL"); PerformanceWarning warn(showWarnings, "Application::idle()... updateGL()"); _glWidget->updateGL(); } { + PerformanceTimer perfTimer("idle/rest"); PerformanceWarning warn(showWarnings, "Application::idle()... rest of it"); _idleLoopStdev.addValue(timeSinceLastUpdate); @@ -1320,14 +1330,16 @@ void Application::idle() { } if (Menu::getInstance()->isOptionChecked(MenuOption::BuckyBalls)) { + PerformanceTimer perfTimer("idle/rest/_buckyBalls"); _buckyBalls.simulate(timeSinceLastUpdate / 1000.f, Application::getInstance()->getAvatar()->getHandData()); } // After finishing all of the above work, restart the idle timer, allowing 2ms to process events. idleTimer->start(2); - } - if (_numChangedSettings > 0) { - saveSettings(); + + if (_numChangedSettings > 0) { + saveSettings(); + } } } } @@ -1729,6 +1741,7 @@ bool Application::isLookingAtMyAvatar(Avatar* avatar) { } void Application::updateLOD() { + PerformanceTimer perfTimer("idle/update/updateLOD"); // adjust it unless we were asked to disable this feature, or if we're currently in throttleRendering mode if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableAutoAdjustLOD) && !isThrottleRendering()) { Menu::getInstance()->autoAdjustLOD(_fps); @@ -1738,6 +1751,7 @@ void Application::updateLOD() { } void Application::updateMouseRay() { + PerformanceTimer perfTimer("idle/update/updateMouseRay"); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateMouseRay()"); @@ -1770,6 +1784,7 @@ void Application::updateMouseRay() { } void Application::updateFaceshift() { + PerformanceTimer perfTimer("idle/update/updateFaceshift"); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateFaceshift()"); @@ -1784,6 +1799,7 @@ void Application::updateFaceshift() { } void Application::updateVisage() { + PerformanceTimer perfTimer("idle/update/updateVisage"); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateVisage()"); @@ -1793,6 +1809,7 @@ void Application::updateVisage() { } void Application::updateMyAvatarLookAtPosition() { + PerformanceTimer perfTimer("idle/update/updateMyAvatarLookAtPosition"); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateMyAvatarLookAtPosition()"); @@ -1858,6 +1875,7 @@ void Application::updateMyAvatarLookAtPosition() { } void Application::updateThreads(float deltaTime) { + PerformanceTimer perfTimer("idle/update/updateThreads"); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateThreads()"); @@ -1872,6 +1890,7 @@ void Application::updateThreads(float deltaTime) { } void Application::updateMetavoxels(float deltaTime) { + PerformanceTimer perfTimer("idle/update/updateMetavoxels"); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateMetavoxels()"); @@ -1901,6 +1920,7 @@ void Application::cameraMenuChanged() { } void Application::updateCamera(float deltaTime) { + PerformanceTimer perfTimer("idle/update/updateCamera"); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateCamera()"); @@ -1918,6 +1938,7 @@ void Application::updateCamera(float deltaTime) { } void Application::updateDialogs(float deltaTime) { + PerformanceTimer perfTimer("idle/update/updateDialogs"); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateDialogs()"); @@ -1934,6 +1955,7 @@ void Application::updateDialogs(float deltaTime) { } void Application::updateCursor(float deltaTime) { + PerformanceTimer perfTimer("idle/update/updateCursor"); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateCursor()"); @@ -1958,41 +1980,66 @@ void Application::updateCursor(float deltaTime) { } void Application::update(float deltaTime) { + //PerformanceTimer perfTimer("idle/update"); // NOTE: we track this above in Application::idle() + bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::update()"); updateLOD(); - - // check what's under the mouse and update the mouse voxel - updateMouseRay(); - + updateMouseRay(); // check what's under the mouse and update the mouse voxel updateFaceshift(); updateVisage(); - _myAvatar->updateLookAtTargetAvatar(); + + { + PerformanceTimer perfTimer("idle/update/updateLookAtTargetAvatar"); + _myAvatar->updateLookAtTargetAvatar(); + } updateMyAvatarLookAtPosition(); - _sixenseManager.update(deltaTime); - _joystickManager.update(); - _prioVR.update(deltaTime); + { + PerformanceTimer perfTimer("idle/update/sixense,joystick,prioVR"); + _sixenseManager.update(deltaTime); + _joystickManager.update(); + _prioVR.update(deltaTime); + } updateMyAvatar(deltaTime); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process... - _avatarManager.updateOtherAvatars(deltaTime); //loop through all the other avatars and simulate them... + { + PerformanceTimer perfTimer("idle/update/_avatarManager"); + _avatarManager.updateOtherAvatars(deltaTime); //loop through all the other avatars and simulate them... + } updateMetavoxels(deltaTime); // update metavoxels updateCamera(deltaTime); // handle various camera tweaks like off axis projection updateDialogs(deltaTime); // update various stats dialogs if present updateCursor(deltaTime); // Handle cursor updates - _particles.update(); // update the particles... - _particleCollisionSystem.update(); // collide the particles... + { + PerformanceTimer perfTimer("idle/update/_particles"); + _particles.update(); // update the particles... + } + { + PerformanceTimer perfTimer("idle/update/_particleCollisionSystem"); + _particleCollisionSystem.update(); // collide the particles... + } - _models.update(); // update the models... + { + PerformanceTimer perfTimer("idle/update/_models"); + _models.update(); // update the models... + } - _overlays.update(deltaTime); + { + PerformanceTimer perfTimer("idle/update/_overlays"); + _overlays.update(deltaTime); + } - // let external parties know we're updating - emit simulating(deltaTime); + { + PerformanceTimer perfTimer("idle/update/emit simulating"); + // let external parties know we're updating + emit simulating(deltaTime); + } } void Application::updateMyAvatar(float deltaTime) { + PerformanceTimer perfTimer("idle/update/updateMyAvatar"); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateMyAvatar()"); @@ -2253,6 +2300,7 @@ glm::vec3 Application::getSunDirection() { } void Application::updateShadowMap() { + PerformanceTimer perfTimer("pintGL/updateShadowMap"); QOpenGLFramebufferObject* fbo = _textureCache.getShadowFramebufferObject(); fbo->bind(); glEnable(GL_DEPTH_TEST); @@ -2392,6 +2440,7 @@ QImage Application::renderAvatarBillboard() { } void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { + PerformanceTimer perfTimer("paintGL/displaySide"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide()"); // transform by eye offset @@ -2424,9 +2473,13 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { glTranslatef(_viewMatrixTranslation.x, _viewMatrixTranslation.y, _viewMatrixTranslation.z); // Setup 3D lights (after the camera transform, so that they are positioned in world space) - setupWorldLight(); + { + PerformanceTimer perfTimer("paintGL/displaySide/setupWorldLight"); + setupWorldLight(); + } if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Stars)) { + PerformanceTimer perfTimer("paintGL/displaySide/stars"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide() ... stars..."); if (!_stars.isStarsLoaded()) { @@ -2455,6 +2508,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { // draw the sky dome if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) { + PerformanceTimer perfTimer("paintGL/displaySide/atmosphere"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide() ... atmosphere..."); _environment.renderAtmospheres(whichCamera); @@ -2474,10 +2528,14 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { glMaterialfv(GL_FRONT, GL_SPECULAR, NO_SPECULAR_COLOR); // draw the audio reflector overlay - _audioReflector.render(); - + { + PerformanceTimer perfTimer("paintGL/displaySide/audioReflector"); + _audioReflector.render(); + } + // Draw voxels if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) { + PerformanceTimer perfTimer("paintGL/displaySide/voxels"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide() ... voxels..."); _voxels.render(); @@ -2485,12 +2543,14 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { // also, metavoxels if (Menu::getInstance()->isOptionChecked(MenuOption::Metavoxels)) { + PerformanceTimer perfTimer("paintGL/displaySide/metavoxels"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide() ... metavoxels..."); _metavoxels.render(); } if (Menu::getInstance()->isOptionChecked(MenuOption::BuckyBalls)) { + PerformanceTimer perfTimer("paintGL/displaySide/buckyBalls"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide() ... bucky balls..."); _buckyBalls.render(); @@ -2498,6 +2558,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { // render particles... if (Menu::getInstance()->isOptionChecked(MenuOption::Particles)) { + PerformanceTimer perfTimer("paintGL/displaySide/particles"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide() ... particles..."); _particles.render(); @@ -2505,6 +2566,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { // render models... if (Menu::getInstance()->isOptionChecked(MenuOption::Models)) { + PerformanceTimer perfTimer("paintGL/displaySide/models"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide() ... models..."); _models.render(); @@ -2512,6 +2574,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { // render the ambient occlusion effect if enabled if (Menu::getInstance()->isOptionChecked(MenuOption::AmbientOcclusion)) { + PerformanceTimer perfTimer("paintGL/displaySide/AmbientOcclusion"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide() ... AmbientOcclusion..."); _ambientOcclusionEffect.render(); @@ -2525,16 +2588,21 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { } bool mirrorMode = (whichCamera.getInterpolatedMode() == CAMERA_MODE_MIRROR); - _avatarManager.renderAvatars(mirrorMode ? Avatar::MIRROR_RENDER_MODE : Avatar::NORMAL_RENDER_MODE, selfAvatarOnly); + { + PerformanceTimer perfTimer("paintGL/displaySide/renderAvatars"); + _avatarManager.renderAvatars(mirrorMode ? Avatar::MIRROR_RENDER_MODE : Avatar::NORMAL_RENDER_MODE, selfAvatarOnly); + } if (!selfAvatarOnly) { // Render the world box if (whichCamera.getMode() != CAMERA_MODE_MIRROR && Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { + PerformanceTimer perfTimer("paintGL/displaySide/renderWorldBox"); renderWorldBox(); } - // brad's frustum for debugging + // view frustum for debugging if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayFrustum) && whichCamera.getMode() != CAMERA_MODE_MIRROR) { + PerformanceTimer perfTimer("paintGL/displaySide/ViewFrustum"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide() ... renderViewFrustum..."); renderViewFrustum(_viewFrustum); @@ -2542,6 +2610,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { // render voxel fades if they exist if (_voxelFades.size() > 0) { + PerformanceTimer perfTimer("paintGL/displaySide/voxel fades"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide() ... voxel fades..."); _voxelFadesLock.lockForWrite(); @@ -2557,10 +2626,16 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { } // give external parties a change to hook in - emit renderingInWorldInterface(); + { + PerformanceTimer perfTimer("paintGL/displaySide/inWorldInterface"); + emit renderingInWorldInterface(); + } // render JS/scriptable overlays - _overlays.render3D(); + { + PerformanceTimer perfTimer("paintGL/displaySide/3dOverlays"); + _overlays.render3D(); + } } } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 7fd8f26006..25bf65d18e 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -386,8 +386,15 @@ Menu::Menu() : addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::AlternateIK, 0, false); addDisabledActionAndSeparator(developerMenu, "Testing"); - + QMenu* timingMenu = developerMenu->addMenu("Timing and Statistics Tools"); + QMenu* perfTimerMenu = timingMenu->addMenu("Performance Timer"); + addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::DisplayTimingDetails, 0, true); + addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandDisplaySideTiming, 0, false); + addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandIdleTiming, 0, false); + addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandPaintGLTiming, 0, false); + addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandUpdateTiming, 0, false); + addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::TestPing, 0, true); addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::FrameTimer); addActionToQMenuAndActionHash(timingMenu, MenuOption::RunTimingTests, 0, this, SLOT(runTests())); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 50e59320b9..c1a9e4274b 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -321,10 +321,15 @@ namespace MenuOption { const QString DisplayModelBounds = "Display Model Bounds"; const QString DisplayModelElementProxy = "Display Model Element Bounds"; const QString DisplayModelElementChildProxies = "Display Model Element Children"; + const QString DisplayTimingDetails = "Display Timing Details"; const QString DontFadeOnVoxelServerChanges = "Don't Fade In/Out on Voxel Server Changes"; const QString EchoLocalAudio = "Echo Local Audio"; const QString EchoServerAudio = "Echo Server Audio"; const QString Enable3DTVMode = "Enable 3DTV Mode"; + const QString ExpandDisplaySideTiming = "Expand Display Side Timing"; + const QString ExpandIdleTiming = "Expand Idle Timing"; + const QString ExpandPaintGLTiming = "Expand PaintGL Timing"; + const QString ExpandUpdateTiming = "Expand Update Timing"; const QString Faceplus = "Faceplus"; const QString Faceshift = "Faceshift"; const QString FilterSixense = "Smooth Sixense Movement"; diff --git a/interface/src/renderer/GlowEffect.cpp b/interface/src/renderer/GlowEffect.cpp index 1eceb71752..262a632df0 100644 --- a/interface/src/renderer/GlowEffect.cpp +++ b/interface/src/renderer/GlowEffect.cpp @@ -14,6 +14,8 @@ #include +#include + #include "Application.h" #include "GlowEffect.h" #include "ProgramObject.h" @@ -119,6 +121,8 @@ static void maybeRelease(QOpenGLFramebufferObject* fbo) { } QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { + PerformanceTimer perfTimer("paintGL/glowEffect"); + QOpenGLFramebufferObject* primaryFBO = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject(); primaryFBO->release(); glBindTexture(GL_TEXTURE_2D, primaryFBO->texture()); diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index a391ed239c..d7ca0152fd 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -18,6 +18,8 @@ #include #include +#include + #include "Stats.h" #include "InterfaceConfig.h" #include "Menu.h" @@ -158,6 +160,33 @@ void Stats::drawBackground(unsigned int rgba, int x, int y, int width, int heigh glColor4f(1, 1, 1, 1); } +bool Stats::includeTimingRecord(const QString& name) { + bool included = false; + if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayTimingDetails)) { + + if (name == "idle/update") { + included = Menu::getInstance()->isOptionChecked(MenuOption::ExpandUpdateTiming) || + Menu::getInstance()->isOptionChecked(MenuOption::ExpandIdleTiming); + } else if (name == "idle/updateGL") { + included = Menu::getInstance()->isOptionChecked(MenuOption::ExpandIdleTiming); + } else if (name.startsWith("idle/update")) { + included = Menu::getInstance()->isOptionChecked(MenuOption::ExpandUpdateTiming); + } else if (name.startsWith("idle/")) { + included = Menu::getInstance()->isOptionChecked(MenuOption::ExpandIdleTiming); + } else if (name == "paintGL/displaySide") { + included = Menu::getInstance()->isOptionChecked(MenuOption::ExpandDisplaySideTiming) || + Menu::getInstance()->isOptionChecked(MenuOption::ExpandPaintGLTiming); + } else if (name.startsWith("paintGL/displaySide/")) { + included = Menu::getInstance()->isOptionChecked(MenuOption::ExpandDisplaySideTiming); + } else if (name.startsWith("paintGL/")) { + included = Menu::getInstance()->isOptionChecked(MenuOption::ExpandPaintGLTiming); + } else { + included = true; // include everything else + } + } + return included; +} + // display expanded or contracted stats void Stats::display( const float* color, @@ -190,6 +219,9 @@ void Stats::display( int totalServers = NodeList::getInstance()->size(); lines = _expanded ? 5 : 3; + + + drawBackground(backgroundColor, horizontalOffset, 0, _generalStatsWidth, lines * STATS_PELS_PER_LINE + 10); horizontalOffset += 5; @@ -345,11 +377,25 @@ void Stats::display( VoxelSystem* voxels = Application::getInstance()->getVoxels(); - lines = _expanded ? 12 : 3; + lines = _expanded ? 11 : 3; if (_expanded && Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessing)) { lines += 9; // spatial audio processing adds 1 spacing line and 8 extra lines of info } + if (_expanded && Menu::getInstance()->isOptionChecked(MenuOption::DisplayTimingDetails)) { + // we will also include room for 1 line per timing record and a header + lines += 1; + + const QMap& allRecords = PerformanceTimer::getAllTimerRecords(); + QMapIterator i(allRecords); + while (i.hasNext()) { + i.next(); + if (includeTimingRecord(i.key())) { + lines++; + } + } + } + drawBackground(backgroundColor, horizontalOffset, 0, glWidget->width() - horizontalOffset, lines * STATS_PELS_PER_LINE + 10); horizontalOffset += 5; @@ -454,8 +500,6 @@ void Stats::display( } } - verticalOffset += (_expanded ? STATS_PELS_PER_LINE : 0); - QString serversTotalString = locale.toString((uint)totalNodes); // consider adding: .rightJustified(10, ' '); // Server Voxels @@ -508,6 +552,29 @@ void Stats::display( drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color); } + // TODO: the display of these timing details should all be moved to JavaScript + if (_expanded && Menu::getInstance()->isOptionChecked(MenuOption::DisplayTimingDetails)) { + // Timing details... + const int TIMER_OUTPUT_LINE_LENGTH = 300; + char perfLine[TIMER_OUTPUT_LINE_LENGTH]; + verticalOffset += STATS_PELS_PER_LINE; + drawText(horizontalOffset, verticalOffset, scale, rotation, font, + "---------------- Function --------------- --msecs- -calls--", color); + + const QMap& allRecords = PerformanceTimer::getAllTimerRecords(); + QMapIterator i(allRecords); + while (i.hasNext()) { + i.next(); + if (includeTimingRecord(i.key())) { + sprintf(perfLine, "%40s: %8.4f [%6llu]", qPrintable(i.key()), + (float)i.value().getMovingAverage() / (float)USECS_PER_MSEC, + i.value().getCount()); + + verticalOffset += STATS_PELS_PER_LINE; + drawText(horizontalOffset, verticalOffset, scale, rotation, font, perfLine, color); + } + } + } if (_expanded && Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessing)) { verticalOffset += STATS_PELS_PER_LINE; // space one line... diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index 1ce0807ee8..66d6ec99f0 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -30,6 +30,7 @@ public: void checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseDragStartedY, int horizontalOffset); void resetWidth(int width, int horizontalOffset); void display(const float* color, int horizontalOffset, float fps, int packetsPerSecond, int bytesPerSecond, int voxelPacketsToProcess); + bool includeTimingRecord(const QString& name); private: static Stats* _sharedInstance; diff --git a/libraries/shared/src/PerfStat.cpp b/libraries/shared/src/PerfStat.cpp index 9235cb3f25..4dca3f3d49 100644 --- a/libraries/shared/src/PerfStat.cpp +++ b/libraries/shared/src/PerfStat.cpp @@ -52,4 +52,22 @@ PerformanceWarning::~PerformanceWarning() { } }; +QMap PerformanceTimer::_records; + +PerformanceTimer::~PerformanceTimer() { + quint64 end = usecTimestampNow(); + quint64 elapsedusec = (end - _start); + PerformanceTimerRecord& namedRecord = _records[_name]; + namedRecord.recordResult(elapsedusec); +} + +void PerformanceTimer::dumpAllTimerRecords() { + QMapIterator i(_records); + while (i.hasNext()) { + i.next(); + qDebug() << i.key() << ": average " << i.value().getAverage() + << " [" << i.value().getMovingAverage() << "]" + << "usecs over" << i.value().getCount() << "calls"; + } +} diff --git a/libraries/shared/src/PerfStat.h b/libraries/shared/src/PerfStat.h index 22cf14f207..f849fb844c 100644 --- a/libraries/shared/src/PerfStat.h +++ b/libraries/shared/src/PerfStat.h @@ -17,6 +17,7 @@ #include #include "SharedUtil.h" +#include "SimpleMovingAverage.h" #include #include @@ -49,5 +50,41 @@ public: static void setSuppressShortTimings(bool suppressShortTimings) { _suppressShortTimings = suppressShortTimings; } }; +class PerformanceTimerRecord { +public: + PerformanceTimerRecord() : _runningTotal(0), _totalCalls(0) {} + + void recordResult(quint64 elapsed) { _runningTotal += elapsed; _totalCalls++; _movingAverage.updateAverage(elapsed); } + quint64 getAverage() const { return (_totalCalls == 0) ? 0 : _runningTotal / _totalCalls; } + quint64 getMovingAverage() const { return (_totalCalls == 0) ? 0 : _movingAverage.getAverage(); } + quint64 getCount() const { return _totalCalls; } + +private: + quint64 _runningTotal; + quint64 _totalCalls; + SimpleMovingAverage _movingAverage; +}; + +class PerformanceTimer { +public: + + PerformanceTimer(const QString& name) : + _start(usecTimestampNow()), + _name(name) { } + + quint64 elapsed() const { return (usecTimestampNow() - _start); }; + + ~PerformanceTimer(); + + static const PerformanceTimerRecord& getTimerRecord(const QString& name) { return _records[name]; }; + static const QMap& getAllTimerRecords() { return _records; }; + static void dumpAllTimerRecords(); + +private: + quint64 _start; + QString _name; + static QMap _records; +}; + #endif // hifi_PerfStat_h From f82be105e8056f9835e3cbba34561455e3207393 Mon Sep 17 00:00:00 2001 From: wangyix Date: Thu, 29 May 2014 12:54:34 -0700 Subject: [PATCH 42/45] moved _sequenceNumber back to OctreeQueryNode --- assignment-client/src/models/ModelServer.cpp | 6 +++--- assignment-client/src/models/ModelServer.h | 2 +- assignment-client/src/octree/OctreeQueryNode.cpp | 15 ++++++++++++--- assignment-client/src/octree/OctreeQueryNode.h | 8 +++++++- assignment-client/src/octree/OctreeSendThread.cpp | 10 +++++----- assignment-client/src/octree/OctreeServer.h | 2 +- .../src/particles/ParticleServer.cpp | 6 +++--- assignment-client/src/particles/ParticleServer.h | 2 +- assignment-client/src/voxels/VoxelServer.cpp | 6 +++--- assignment-client/src/voxels/VoxelServer.h | 2 +- 10 files changed, 37 insertions(+), 22 deletions(-) diff --git a/assignment-client/src/models/ModelServer.cpp b/assignment-client/src/models/ModelServer.cpp index 8f322e4c82..ff2367ec6e 100644 --- a/assignment-client/src/models/ModelServer.cpp +++ b/assignment-client/src/models/ModelServer.cpp @@ -86,7 +86,7 @@ bool ModelServer::hasSpecialPacketToSend(const SharedNodePointer& node) { return shouldSendDeletedModels; } -int ModelServer::sendSpecialPacket(OCTREE_PACKET_SEQUENCE& sequenceNumber, const SharedNodePointer& node) { +int ModelServer::sendSpecialPacket(OctreeQueryNode* queryNode, const SharedNodePointer& node) { unsigned char outputBuffer[MAX_PACKET_SIZE]; size_t packetLength = 0; @@ -100,13 +100,13 @@ int ModelServer::sendSpecialPacket(OCTREE_PACKET_SEQUENCE& sequenceNumber, const // TODO: is it possible to send too many of these packets? what if you deleted 1,000,000 models? while (hasMoreToSend) { - hasMoreToSend = tree->encodeModelsDeletedSince(sequenceNumber, deletedModelsSentAt, + hasMoreToSend = tree->encodeModelsDeletedSince(queryNode->getSequenceNumber(), deletedModelsSentAt, outputBuffer, MAX_PACKET_SIZE, packetLength); //qDebug() << "sending PacketType_MODEL_ERASE packetLength:" << packetLength; NodeList::getInstance()->writeDatagram((char*) outputBuffer, packetLength, SharedNodePointer(node)); - sequenceNumber++; + queryNode->incrementSequenceNumber(); } nodeData->setLastDeletedModelsSentAt(deletePacketSentAt); diff --git a/assignment-client/src/models/ModelServer.h b/assignment-client/src/models/ModelServer.h index 35cb79d8cf..7e7f239f2a 100644 --- a/assignment-client/src/models/ModelServer.h +++ b/assignment-client/src/models/ModelServer.h @@ -37,7 +37,7 @@ public: // subclass may implement these method virtual void beforeRun(); virtual bool hasSpecialPacketToSend(const SharedNodePointer& node); - virtual int sendSpecialPacket(OCTREE_PACKET_SEQUENCE& sequenceNumber, const SharedNodePointer& node); + virtual int sendSpecialPacket(OctreeQueryNode* queryNode, const SharedNodePointer& node); virtual void modelCreated(const ModelItem& newModel, const SharedNodePointer& senderNode); diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index f7b293dfa8..30df4373f5 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -38,6 +38,7 @@ OctreeQueryNode::OctreeQueryNode() : _lastClientOctreeSizeScale(DEFAULT_OCTREE_SIZE_SCALE), _lodChanged(false), _lodInitialized(false), + _sequenceNumber(0), _lastRootTimestamp(0), _myPacketType(PacketTypeUnknown), _isShuttingDown(false) @@ -157,11 +158,11 @@ bool OctreeQueryNode::shouldSuppressDuplicatePacket() { void OctreeQueryNode::init() { _myPacketType = getMyPacketType(); - resetOctreePacket(0); // don't bump sequence + resetOctreePacket(); // don't bump sequence } -void OctreeQueryNode::resetOctreePacket(OCTREE_PACKET_SEQUENCE sequenceNumber) { +void OctreeQueryNode::resetOctreePacket() { // if shutting down, return immediately if (_isShuttingDown) { return; @@ -199,7 +200,7 @@ void OctreeQueryNode::resetOctreePacket(OCTREE_PACKET_SEQUENCE sequenceNumber) { // pack in sequence number OCTREE_PACKET_SEQUENCE* sequenceAt = (OCTREE_PACKET_SEQUENCE*)_octreePacketAt; - *sequenceAt = sequenceNumber; + *sequenceAt = _sequenceNumber; _octreePacketAt += sizeof(OCTREE_PACKET_SEQUENCE); _octreePacketAvailableBytes -= sizeof(OCTREE_PACKET_SEQUENCE); @@ -361,3 +362,11 @@ void OctreeQueryNode::dumpOutOfView() { } } } + +void OctreeQueryNode::incrementSequenceNumber() { + _sequenceNumber++; +} + +OCTREE_PACKET_SEQUENCE OctreeQueryNode::getSequenceNumber() { + return _sequenceNumber; +} \ No newline at end of file diff --git a/assignment-client/src/octree/OctreeQueryNode.h b/assignment-client/src/octree/OctreeQueryNode.h index eeea98699c..f60634f33d 100644 --- a/assignment-client/src/octree/OctreeQueryNode.h +++ b/assignment-client/src/octree/OctreeQueryNode.h @@ -35,7 +35,7 @@ public: void init(); // called after creation to set up some virtual items virtual PacketType getMyPacketType() const = 0; - void resetOctreePacket(OCTREE_PACKET_SEQUENCE sequenceNumber); // resets octree packet to after "V" header + void resetOctreePacket(); // resets octree packet to after "V" header void writeToPacket(const unsigned char* buffer, unsigned int bytes); // writes to end of packet @@ -99,6 +99,10 @@ public: void nodeKilled(); void forceNodeShutdown(); bool isShuttingDown() const { return _isShuttingDown; } + + void incrementSequenceNumber(); + + OCTREE_PACKET_SEQUENCE getSequenceNumber(); private slots: void sendThreadFinished(); @@ -136,6 +140,8 @@ private: bool _lodChanged; bool _lodInitialized; + OCTREE_PACKET_SEQUENCE _sequenceNumber; + quint64 _lastRootTimestamp; PacketType _myPacketType; diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index a396e1170c..d8aebd0cdf 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -138,7 +138,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes // obscure the packet and not send it. This allows the callers and upper level logic to not need to know about // this rate control savings. if (nodeData->shouldSuppressDuplicatePacket()) { - nodeData->resetOctreePacket(_sequenceNumber); // we still need to reset it though! + nodeData->resetOctreePacket(); // we still need to reset it though! return packetsSent; // without sending... } @@ -248,7 +248,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes truePacketsSent++; packetsSent++; _sequenceNumber++; - nodeData->resetOctreePacket(_sequenceNumber); + nodeData->resetOctreePacket(); } return packetsSent; @@ -288,7 +288,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus if (nodeData->isPacketWaiting()) { packetsSentThisInterval += handlePacketSend(nodeData, trueBytesSent, truePacketsSent); } else { - nodeData->resetOctreePacket(_sequenceNumber); + nodeData->resetOctreePacket(); } int targetSize = MAX_OCTREE_PACKET_DATA_SIZE; if (wantCompression) { @@ -534,8 +534,8 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus // send the environment packet // TODO: should we turn this into a while loop to better handle sending multiple special packets if (_myServer->hasSpecialPacketToSend(_node) && !nodeData->isShuttingDown()) { - trueBytesSent += _myServer->sendSpecialPacket(_sequenceNumber, _node); - nodeData->resetOctreePacket(_sequenceNumber); // because _sequenceNumber has changed + trueBytesSent += _myServer->sendSpecialPacket(nodeData, _node); + nodeData->resetOctreePacket(); // because nodeData's _sequenceNumber has changed truePacketsSent++; packetsSentThisInterval++; } diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index df8519e200..f0db93feb3 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -72,7 +72,7 @@ public: // subclass may implement these method virtual void beforeRun() { }; virtual bool hasSpecialPacketToSend(const SharedNodePointer& node) { return false; } - virtual int sendSpecialPacket(OCTREE_PACKET_SEQUENCE& sequenceNumber, const SharedNodePointer& node) { return 0; } + virtual int sendSpecialPacket(OctreeQueryNode* queryNode, const SharedNodePointer& node) { return 0; } static void attachQueryNodeToNode(Node* newNode); diff --git a/assignment-client/src/particles/ParticleServer.cpp b/assignment-client/src/particles/ParticleServer.cpp index e752900059..1dd65f11f3 100644 --- a/assignment-client/src/particles/ParticleServer.cpp +++ b/assignment-client/src/particles/ParticleServer.cpp @@ -86,7 +86,7 @@ bool ParticleServer::hasSpecialPacketToSend(const SharedNodePointer& node) { return shouldSendDeletedParticles; } -int ParticleServer::sendSpecialPacket(OCTREE_PACKET_SEQUENCE& sequenceNumber, const SharedNodePointer& node) { +int ParticleServer::sendSpecialPacket(OctreeQueryNode* queryNode, const SharedNodePointer& node) { unsigned char outputBuffer[MAX_PACKET_SIZE]; size_t packetLength = 0; @@ -100,13 +100,13 @@ int ParticleServer::sendSpecialPacket(OCTREE_PACKET_SEQUENCE& sequenceNumber, co // TODO: is it possible to send too many of these packets? what if you deleted 1,000,000 particles? while (hasMoreToSend) { - hasMoreToSend = tree->encodeParticlesDeletedSince(sequenceNumber, deletedParticlesSentAt, + hasMoreToSend = tree->encodeParticlesDeletedSince(queryNode->getSequenceNumber(), deletedParticlesSentAt, outputBuffer, MAX_PACKET_SIZE, packetLength); //qDebug() << "sending PacketType_PARTICLE_ERASE packetLength:" << packetLength; NodeList::getInstance()->writeDatagram((char*) outputBuffer, packetLength, SharedNodePointer(node)); - sequenceNumber++; + queryNode->incrementSequenceNumber(); } nodeData->setLastDeletedParticlesSentAt(deletePacketSentAt); diff --git a/assignment-client/src/particles/ParticleServer.h b/assignment-client/src/particles/ParticleServer.h index cb8e128475..3066c5fa98 100644 --- a/assignment-client/src/particles/ParticleServer.h +++ b/assignment-client/src/particles/ParticleServer.h @@ -37,7 +37,7 @@ public: // subclass may implement these method virtual void beforeRun(); virtual bool hasSpecialPacketToSend(const SharedNodePointer& node); - virtual int sendSpecialPacket(OCTREE_PACKET_SEQUENCE& sequenceNumber, const SharedNodePointer& node); + virtual int sendSpecialPacket(OctreeQueryNode* queryNode, const SharedNodePointer& node); virtual void particleCreated(const Particle& newParticle, const SharedNodePointer& senderNode); diff --git a/assignment-client/src/voxels/VoxelServer.cpp b/assignment-client/src/voxels/VoxelServer.cpp index 43d01f1c77..8f4a8bab36 100644 --- a/assignment-client/src/voxels/VoxelServer.cpp +++ b/assignment-client/src/voxels/VoxelServer.cpp @@ -40,7 +40,7 @@ bool VoxelServer::hasSpecialPacketToSend(const SharedNodePointer& node) { return shouldSendEnvironments; } -int VoxelServer::sendSpecialPacket(OCTREE_PACKET_SEQUENCE& sequenceNumber, const SharedNodePointer& node) { +int VoxelServer::sendSpecialPacket(OctreeQueryNode* queryNode, const SharedNodePointer& node) { unsigned char* copyAt = _tempOutputBuffer; @@ -57,7 +57,7 @@ int VoxelServer::sendSpecialPacket(OCTREE_PACKET_SEQUENCE& sequenceNumber, const // pack in sequence number OCTREE_PACKET_SEQUENCE* sequenceAt = (OCTREE_PACKET_SEQUENCE*)copyAt; - *sequenceAt = sequenceNumber; + *sequenceAt = queryNode->getSequenceNumber(); copyAt += sizeof(OCTREE_PACKET_SEQUENCE); envPacketLength += sizeof(OCTREE_PACKET_SEQUENCE); @@ -75,7 +75,7 @@ int VoxelServer::sendSpecialPacket(OCTREE_PACKET_SEQUENCE& sequenceNumber, const } NodeList::getInstance()->writeDatagram((char*) _tempOutputBuffer, envPacketLength, SharedNodePointer(node)); - sequenceNumber++; + queryNode->incrementSequenceNumber(); return envPacketLength; } diff --git a/assignment-client/src/voxels/VoxelServer.h b/assignment-client/src/voxels/VoxelServer.h index b9277fed0c..4e04c48cfd 100644 --- a/assignment-client/src/voxels/VoxelServer.h +++ b/assignment-client/src/voxels/VoxelServer.h @@ -46,7 +46,7 @@ public: // subclass may implement these method virtual void beforeRun(); virtual bool hasSpecialPacketToSend(const SharedNodePointer& node); - virtual int sendSpecialPacket(OCTREE_PACKET_SEQUENCE& sequenceNumber, const SharedNodePointer& node); + virtual int sendSpecialPacket(OctreeQueryNode* queryNode, const SharedNodePointer& node); private: bool _sendEnvironments; From d8b0b03e591f1a1471cf4128e2f4f1beb925cc86 Mon Sep 17 00:00:00 2001 From: wangyix Date: Thu, 29 May 2014 13:39:57 -0700 Subject: [PATCH 43/45] removed _sequenceNumber from OctreeSendThread inlined getSequenceNumber and incrementSequenceNumber --- assignment-client/src/octree/OctreeQueryNode.h | 4 ++-- assignment-client/src/octree/OctreeSendThread.cpp | 5 ++--- assignment-client/src/octree/OctreeSendThread.h | 2 -- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/assignment-client/src/octree/OctreeQueryNode.h b/assignment-client/src/octree/OctreeQueryNode.h index f60634f33d..eb420039e6 100644 --- a/assignment-client/src/octree/OctreeQueryNode.h +++ b/assignment-client/src/octree/OctreeQueryNode.h @@ -100,9 +100,9 @@ public: void forceNodeShutdown(); bool isShuttingDown() const { return _isShuttingDown; } - void incrementSequenceNumber(); + void incrementSequenceNumber() { _sequenceNumber++; } - OCTREE_PACKET_SEQUENCE getSequenceNumber(); + OCTREE_PACKET_SEQUENCE getSequenceNumber() const { return _sequenceNumber; } private slots: void sendThreadFinished(); diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index d8aebd0cdf..fab9be24d3 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -28,8 +28,7 @@ OctreeSendThread::OctreeSendThread(const SharedAssignmentPointer& myAssignment, _nodeUUID(node->getUUID()), _packetData(), _nodeMissingCount(0), - _isShuttingDown(false), - _sequenceNumber(0) + _isShuttingDown(false) { QString safeServerName("Octree"); if (_myServer) { @@ -247,7 +246,7 @@ int OctreeSendThread::handlePacketSend(OctreeQueryNode* nodeData, int& trueBytes trueBytesSent += nodeData->getPacketLength(); truePacketsSent++; packetsSent++; - _sequenceNumber++; + nodeData->incrementSequenceNumber(); nodeData->resetOctreePacket(); } diff --git a/assignment-client/src/octree/OctreeSendThread.h b/assignment-client/src/octree/OctreeSendThread.h index 9dcf266cd8..d8eed27802 100644 --- a/assignment-client/src/octree/OctreeSendThread.h +++ b/assignment-client/src/octree/OctreeSendThread.h @@ -55,8 +55,6 @@ private: int _nodeMissingCount; bool _isShuttingDown; - - OCTREE_PACKET_SEQUENCE _sequenceNumber; }; #endif // hifi_OctreeSendThread_h From 4c4ff45f318f8b31079d6b5b2922cd837bbf599e Mon Sep 17 00:00:00 2001 From: wangyix Date: Thu, 29 May 2014 14:31:40 -0700 Subject: [PATCH 44/45] removed duplicate function bodies --- assignment-client/src/octree/OctreeQueryNode.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index 30df4373f5..6acd85bff6 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -362,11 +362,3 @@ void OctreeQueryNode::dumpOutOfView() { } } } - -void OctreeQueryNode::incrementSequenceNumber() { - _sequenceNumber++; -} - -OCTREE_PACKET_SEQUENCE OctreeQueryNode::getSequenceNumber() { - return _sequenceNumber; -} \ No newline at end of file From 7e3ef34e6c2ddb053843bc98e8fed8d902c28437 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 29 May 2014 15:34:20 -0700 Subject: [PATCH 45/45] CR feedback --- interface/src/ui/Stats.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index d7ca0152fd..42eae260c7 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -219,9 +219,6 @@ void Stats::display( int totalServers = NodeList::getInstance()->size(); lines = _expanded ? 5 : 3; - - - drawBackground(backgroundColor, horizontalOffset, 0, _generalStatsWidth, lines * STATS_PELS_PER_LINE + 10); horizontalOffset += 5;