From ef9ff0fa7401a38241da2e5043fc502d93914faa Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 3 Mar 2014 16:46:25 -0800 Subject: [PATCH] Put initialization and deletion of localVoxelSystems on render thread --- examples/localVoxelsExample.js | 38 +++++- interface/src/Application.cpp | 2 + interface/src/VoxelSystem.h | 2 +- interface/src/ui/LocalVoxelsOverlay.cpp | 148 ++++++++++------------- interface/src/ui/LocalVoxelsOverlay.h | 27 +++-- interface/src/ui/Overlay.cpp | 1 + interface/src/ui/Overlay.h | 4 + interface/src/ui/Overlays.cpp | 48 +++++++- interface/src/ui/Overlays.h | 4 +- libraries/voxels/src/LocalVoxelsList.cpp | 12 +- 10 files changed, 170 insertions(+), 116 deletions(-) diff --git a/examples/localVoxelsExample.js b/examples/localVoxelsExample.js index 4892f656d5..dd192d4c82 100644 --- a/examples/localVoxelsExample.js +++ b/examples/localVoxelsExample.js @@ -1,7 +1,35 @@ -function test() { - var tree = LocalVoxels("tree"); - tree.setVoxel(0, 0, 0, 1, 128, 128, 128); +var tree = LocalVoxels("tree"); +tree.setVoxel(0, 0, 0, 0.5, 255, 0, 0); +tree.setVoxel(0.5, 0.5, 0.5, 0.5, 0, 255, 0); + +var overlay1 = Overlays.addOverlay("localvoxels", { + position: {x: 1, y: 1, z: 1}, + size: 1, + name: "tree" + }); +var overlay2 = Overlays.addOverlay("localvoxels", { + position: {x: 1, y: 2, z: 1}, + size: 1, + name: "tree" + }); +var overlay3 = Overlays.addOverlay("localvoxels", { + position: {x: 1, y: 3, z: 1}, + size: 1, + name: "tree" + }); +var overlay4 = Overlays.addOverlay("localvoxels", { + position: {x: 1, y: 4, z: 1}, + size: 1, + name: "tree" + }); + + +// When our script shuts down, we should clean up all of our overlays +function scriptEnding() { + Overlays.deleteOverlay(overlay1); + Overlays.deleteOverlay(overlay2); + Overlays.deleteOverlay(overlay3); + Overlays.deleteOverlay(overlay4); } - -test(); \ No newline at end of file +Script.scriptEnding.connect(scriptEnding); \ No newline at end of file diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 75e9065ce0..1fb32e1989 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1920,6 +1920,8 @@ void Application::update(float deltaTime) { _particles.update(); // update the particles... _particleCollisionSystem.update(); // collide the particles... + _overlays.update(deltaTime); + // let external parties know we're updating emit simulating(deltaTime); } diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index a261d6aa53..ade4ed9b4e 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -53,8 +53,8 @@ public: int parseData(const QByteArray& packet); + bool isInitialized() { return _initialized; } virtual void init(); - void simulate(float deltaTime) { } void render(); void changeTree(VoxelTree* newTree); diff --git a/interface/src/ui/LocalVoxelsOverlay.cpp b/interface/src/ui/LocalVoxelsOverlay.cpp index 8a6be8cd82..b14db72d99 100644 --- a/interface/src/ui/LocalVoxelsOverlay.cpp +++ b/interface/src/ui/LocalVoxelsOverlay.cpp @@ -6,106 +6,80 @@ // Copyright (c) 2014 High Fidelity, Inc. All rights reserved. // // +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + +#include +#include -#include #include +#include #include "LocalVoxelsOverlay.h" -struct OverlayElement { - QString treeName; - StrongVoxelTreePointer tree; // so that the tree doesn't get freed - glm::vec3 position; - float scale; - bool wantDisplay; - StrongVoxelSystemPointer voxelSystem; -}; +QMap LocalVoxelsOverlay::_voxelSystemMap; - -LocalVoxelsOverlay::LocalVoxelsOverlay() { +LocalVoxelsOverlay::LocalVoxelsOverlay() : + Volume3DOverlay(), + _voxelCount(0) +{ + _wantDeleteOnRenderThread = true; } LocalVoxelsOverlay::~LocalVoxelsOverlay() { + _voxelSystem->changeTree(new VoxelTree()); + _voxelSystem.clear(); + if (_voxelSystemMap.value(_treeName).isNull()) { + _voxelSystemMap.remove(_treeName); + } + _tree.clear(); + LocalVoxelsList::getInstance()->remove(_treeName); +} + +void LocalVoxelsOverlay::update(float deltatime) { + if (!_voxelSystem->isInitialized()) { + _voxelSystem->init(); + } + + if (_voxelCount != _tree->getOctreeElementsCount()) { + _voxelCount = _tree->getOctreeElementsCount(); + _voxelSystem->forceRedrawEntireTree(); + } } void LocalVoxelsOverlay::render() { - QMap::iterator i; - for (i = _overlayMap.begin(); i != _overlayMap.end(); ++i) { - if (i->wantDisplay && i->scale > 0) { - glPushMatrix(); - glTranslatef(i->position.x, i->position.y, i->position.z); - glScalef(i->scale, i->scale, i->scale); - i->voxelSystem->render(); - glPopMatrix(); + if (_visible && _size > 0 && _voxelSystem && _voxelSystem->isInitialized()) { + glPushMatrix(); { + glTranslatef(_position.x, _position.y, _position.z); + glScalef(_size, _size, _size); + _voxelSystem->render(); + } glPopMatrix(); + } +} + +void LocalVoxelsOverlay::setProperties(const QScriptValue &properties) { + Volume3DOverlay::setProperties(properties); + + QScriptValue treeName = properties.property("name"); + // if "end" property was not there, check to see if they included aliases: endPoint, or p2 + if (treeName.isValid()) { + if ((_treeName = treeName.toString()) == DOMAIN_TREE_NAME) { + qDebug() << "addOverlay(): Can't create overlay from domain tree"; + return; + } + _tree = LocalVoxelsList::getInstance()->getTree(_treeName); + if (_tree.isNull()) { + qDebug() << "addOverlay(): Invalid tree name"; + return; + } + + _voxelSystem = _voxelSystemMap[_treeName]; + if (_voxelSystem.isNull()) { + _voxelSystem = StrongVoxelSystemPointer(new VoxelSystem(1, + DEFAULT_MAX_VOXELS_PER_SYSTEM, + _tree.data())); + _voxelSystemMap.insert(_treeName, _voxelSystem); } } } -void LocalVoxelsOverlay::addOverlay(QString overlayName, QString treeName) { - if (treeName == DOMAIN_TREE_NAME) { - qDebug() << "addOverlay(): Can't create overlay from domain tree"; - return; - } - if (_overlayMap.contains(overlayName)) { - qDebug() << "addOverlay(): Overlay name elready in use"; - return; - } - - StrongVoxelTreePointer tree = LocalVoxelsList::getInstance()->getTree(treeName); - if (tree.isNull()) { - qDebug() << "addOverlay(): Invalid tree name"; - return; - } - StrongVoxelSystemPointer voxelSystem = _voxelSystemMap[treeName]; - if (voxelSystem.isNull()) { - voxelSystem = StrongVoxelSystemPointer(new VoxelSystem(TREE_SCALE, - DEFAULT_MAX_VOXELS_PER_SYSTEM, - tree.data())); - _voxelSystemMap.insert(treeName, voxelSystem); - } - - OverlayElement element = { - treeName, - tree, - glm::vec3(0, 0, 0), - 0, - false, - voxelSystem - }; - _overlayMap.insert(overlayName, element); -} - -void LocalVoxelsOverlay::setPosition(QString overlayName, float x, float y, float z) { - if (_overlayMap.contains(overlayName)) { - _overlayMap[overlayName].position = glm::vec3(x, y, z); - } -} - -void LocalVoxelsOverlay::setScale(QString overlayName, float scale) { - if (_overlayMap.contains(overlayName)) { - _overlayMap[overlayName].scale = scale; - } -} - -void LocalVoxelsOverlay::display(QString overlayName, bool wantDisplay) { - if (_overlayMap.contains(overlayName)) { - _overlayMap[overlayName].wantDisplay = wantDisplay; - } -} - -void LocalVoxelsOverlay::removeOverlay(QString overlayName) { - if (_overlayMap.contains(overlayName)) { - QString treeName = _overlayMap.take(overlayName).treeName; - - if (_voxelSystemMap.value(treeName).isNull()) { - _voxelSystemMap.remove(treeName); - } - } -} - - - - - - - diff --git a/interface/src/ui/LocalVoxelsOverlay.h b/interface/src/ui/LocalVoxelsOverlay.h index 28ce6c909f..c5582a54eb 100644 --- a/interface/src/ui/LocalVoxelsOverlay.h +++ b/interface/src/ui/LocalVoxelsOverlay.h @@ -11,13 +11,19 @@ #ifndef __hifi__LocalVoxelsOverlay__ #define __hifi__LocalVoxelsOverlay__ -#include "Volume3DOverlay.h" +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" +#include +#include #include #include #include -struct OverlayElement; +#include + +#include "Volume3DOverlay.h" + typedef QSharedPointer StrongVoxelSystemPointer; typedef QWeakPointer WeakVoxelSystemPointer; @@ -27,19 +33,18 @@ public: LocalVoxelsOverlay(); ~LocalVoxelsOverlay(); + virtual void update(float deltatime); virtual void render(); - void addOverlay(QString overlayName, QString treeName); - void setPosition(QString overlayName, float x, float y, float z); - void setScale(QString overlayName, float scale); - void update(QString overlayName); - void display(QString overlayName, bool wantDisplay); - void removeOverlay(QString overlayName); - + virtual void setProperties(const QScriptValue& properties); private: - QMap _overlayMap; // overlayName/overlayElement - QMap _voxelSystemMap; // treeName/voxelSystem + static QMap _voxelSystemMap; // treeName/voxelSystem + + QString _treeName; + StrongVoxelTreePointer _tree; // so that the tree doesn't get freed + int _voxelCount; + StrongVoxelSystemPointer _voxelSystem; }; #endif /* defined(__hifi__LocalVoxelsOverlay__) */ diff --git a/interface/src/ui/Overlay.cpp b/interface/src/ui/Overlay.cpp index 40da2253f4..61c0ee36c0 100644 --- a/interface/src/ui/Overlay.cpp +++ b/interface/src/ui/Overlay.cpp @@ -18,6 +18,7 @@ Overlay::Overlay() : _parent(NULL), + _wantDeleteOnRenderThread(false), _alpha(DEFAULT_ALPHA), _color(DEFAULT_BACKGROUND_COLOR), _visible(true) diff --git a/interface/src/ui/Overlay.h b/interface/src/ui/Overlay.h index df898ec741..95d4bf7541 100644 --- a/interface/src/ui/Overlay.h +++ b/interface/src/ui/Overlay.h @@ -28,9 +28,11 @@ public: Overlay(); ~Overlay(); void init(QGLWidget* parent); + virtual void update(float deltatime) {} virtual void render() = 0; // getters + bool deleteOnRenderThread() { return _wantDeleteOnRenderThread; } bool getVisible() const { return _visible; } const xColor& getColor() const { return _color; } float getAlpha() const { return _alpha; } @@ -44,6 +46,8 @@ public: protected: QGLWidget* _parent; + bool _wantDeleteOnRenderThread; + float _alpha; xColor _color; bool _visible; // should the overlay be drawn at all diff --git a/interface/src/ui/Overlays.cpp b/interface/src/ui/Overlays.cpp index 84944332f1..a57970b797 100644 --- a/interface/src/ui/Overlays.cpp +++ b/interface/src/ui/Overlays.cpp @@ -13,19 +13,41 @@ #include "Sphere3DOverlay.h" #include "TextOverlay.h" #include "ClipboardOverlay.h" +#include "LocalVoxelsOverlay.h" -unsigned int Overlays::_nextOverlayID = 1; - -Overlays::Overlays() { +Overlays::Overlays() : _nextOverlayID(1) { } Overlays::~Overlays() { + QMap::iterator it; + for (it = _overlays2D.begin(); it != _overlays2D.end(); ++it) { + delete _overlays2D.take(it.key()); + } + for (it = _overlays3D.begin(); it != _overlays3D.end(); ++it) { + delete _overlays3D.take(it.key()); + } + while (!_overlaysToDelete.isEmpty()) { + delete _overlaysToDelete.takeLast(); + } } void Overlays::init(QGLWidget* parent) { _parent = parent; } +void Overlays::update(float deltatime) { + foreach (Overlay* thisOverlay, _overlays2D) { + thisOverlay->update(deltatime); + } + foreach (Overlay* thisOverlay, _overlays3D) { + thisOverlay->update(deltatime); + } + while (!_overlaysToDelete.isEmpty()) { + delete _overlaysToDelete.takeLast(); + } + +} + void Overlays::render2D() { foreach(Overlay* thisOverlay, _overlays2D) { thisOverlay->render(); @@ -79,6 +101,12 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope thisOverlay->setProperties(properties); created = true; is3D = true; + } else if (type == "localvoxels") { + thisOverlay = new LocalVoxelsOverlay(); + thisOverlay->init(_parent); + thisOverlay->setProperties(properties); + created = true; + is3D = true; } if (created) { @@ -111,11 +139,21 @@ bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) { // TODO: make multi-threaded safe void Overlays::deleteOverlay(unsigned int id) { + Overlay* overlayToDelete; if (_overlays2D.contains(id)) { - _overlays2D.erase(_overlays2D.find(id)); + overlayToDelete = _overlays2D.take(id); } else if (_overlays3D.contains(id)) { - _overlays3D.erase(_overlays3D.find(id)); + overlayToDelete = _overlays3D.take(id); + } else { + return; } + + if (overlayToDelete->deleteOnRenderThread()) { + _overlaysToDelete.push_back(overlayToDelete); + } else { + delete overlayToDelete; + } + } unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) { diff --git a/interface/src/ui/Overlays.h b/interface/src/ui/Overlays.h index cfd84fd44b..c28f3ab83b 100644 --- a/interface/src/ui/Overlays.h +++ b/interface/src/ui/Overlays.h @@ -18,6 +18,7 @@ public: Overlays(); ~Overlays(); void init(QGLWidget* parent); + void update(float deltatime); void render3D(); void render2D(); @@ -38,7 +39,8 @@ public slots: private: QMap _overlays2D; QMap _overlays3D; - static unsigned int _nextOverlayID; + QList _overlaysToDelete; + unsigned int _nextOverlayID; QGLWidget* _parent; }; diff --git a/libraries/voxels/src/LocalVoxelsList.cpp b/libraries/voxels/src/LocalVoxelsList.cpp index 16f72483de..e8f5a09d6d 100644 --- a/libraries/voxels/src/LocalVoxelsList.cpp +++ b/libraries/voxels/src/LocalVoxelsList.cpp @@ -37,28 +37,28 @@ void LocalVoxelsList::addPersistantTree(QString treeName, VoxelTree* tree) { StrongVoxelTreePointer treePtr(tree, doNothing); _persistantTrees.push_back(treePtr); _trees.insert(treeName, treePtr); - qDebug() << "[DEBUG] LocalVoxelsList : added persistant tree (" << treeName << ")" << endl; + qDebug() << "[DEBUG] LocalVoxelsList : added persistant tree (" << treeName << ")"; } void LocalVoxelsList::insert(QString treeName, StrongVoxelTreePointer& tree) { // If the key don't already exist or the value is null if (!_trees.contains(treeName) || !_trees.value(treeName)) { _trees.insert(treeName, tree); - qDebug() << "[DEBUG] LocalVoxelsList : added local tree (" << treeName << ")" << endl; + qDebug() << "[DEBUG] LocalVoxelsList : added local tree (" << treeName << ")"; } else { // if not we replace the tree created by the user with the existing one tree = _trees.value(treeName); - qDebug() << "[DEBUG] LocalVoxelsList : local tree already exist (" << treeName << ")"<< endl; + qDebug() << "[DEBUG] LocalVoxelsList : local tree already exist (" << treeName << ")"; } } void LocalVoxelsList::remove(QString treeName) { // if the tree is not used anymore (no strong pointer) - if (!_trees.value(treeName, StrongVoxelTreePointer(NULL))) { + if (!_trees.value(treeName)) { // then remove it from the list - qDebug() << "[DEBUG] LocalVoxelsList : removed unused tree (" << treeName << ")" << endl; + qDebug() << "[DEBUG] LocalVoxelsList : removed unused tree (" << treeName << ")"; _trees.remove(treeName); } else { - qDebug() << "[DEBUG] LocalVoxelsList : tree still in use (" << treeName << ")" << endl; + qDebug() << "[DEBUG] LocalVoxelsList : tree still in use (" << treeName << ")"; } } \ No newline at end of file