From 38623e108a621fe55e193e4d87108c358697874c Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 11 Jul 2014 15:37:59 -0700 Subject: [PATCH 01/10] Delete persister when its thread finishes, copy metavoxel nodes on subdivision so that we'll know that they changed. --- .../src/metavoxels/MetavoxelServer.cpp | 1 + .../metavoxels/src/AttributeRegistry.cpp | 6 ++- libraries/metavoxels/src/MetavoxelData.cpp | 46 +++++++++++++------ libraries/metavoxels/src/MetavoxelData.h | 7 +-- 4 files changed, 43 insertions(+), 17 deletions(-) diff --git a/assignment-client/src/metavoxels/MetavoxelServer.cpp b/assignment-client/src/metavoxels/MetavoxelServer.cpp index 4d9c45ed6c..598d8ea722 100644 --- a/assignment-client/src/metavoxels/MetavoxelServer.cpp +++ b/assignment-client/src/metavoxels/MetavoxelServer.cpp @@ -55,6 +55,7 @@ void MetavoxelServer::run() { _persister = new MetavoxelPersister(this); QThread* persistenceThread = new QThread(this); _persister->moveToThread(persistenceThread); + _persister->connect(persistenceThread, SIGNAL(finished()), SLOT(deleteLater())); persistenceThread->start(); // queue up the load diff --git a/libraries/metavoxels/src/AttributeRegistry.cpp b/libraries/metavoxels/src/AttributeRegistry.cpp index 64b2646261..670f0be389 100644 --- a/libraries/metavoxels/src/AttributeRegistry.cpp +++ b/libraries/metavoxels/src/AttributeRegistry.cpp @@ -213,7 +213,11 @@ void Attribute::writeMetavoxelDelta(const MetavoxelNode& root, const MetavoxelNo } void Attribute::readMetavoxelSubdivision(MetavoxelData& data, MetavoxelStreamState& state) { - data.getRoot(state.attribute)->readSubdivision(state); + // copy if changed + MetavoxelNode* root = data.getRoot(state.attribute); + if (root->readSubdivision(state)) { + data.setRoot(state.attribute, new MetavoxelNode(state.attribute, root)); + } } void Attribute::writeMetavoxelSubdivision(const MetavoxelNode& root, MetavoxelStreamState& state) { diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp index 1362731a8a..72d5392a39 100644 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ b/libraries/metavoxels/src/MetavoxelData.cpp @@ -603,12 +603,18 @@ void MetavoxelData::writeDelta(const MetavoxelData& reference, const MetavoxelLO } } -MetavoxelNode* MetavoxelData::createRoot(const AttributePointer& attribute) { - MetavoxelNode*& root = _roots[attribute]; - if (root) { - root->decrementReferenceCount(attribute); +void MetavoxelData::setRoot(const AttributePointer& attribute, MetavoxelNode* root) { + MetavoxelNode*& rootReference = _roots[attribute]; + if (rootReference) { + rootReference->decrementReferenceCount(attribute); } - return root = new MetavoxelNode(attribute); + rootReference = root; +} + +MetavoxelNode* MetavoxelData::createRoot(const AttributePointer& attribute) { + MetavoxelNode* root = new MetavoxelNode(attribute); + setRoot(attribute, root); + return root; } bool MetavoxelData::deepEquals(const MetavoxelData& other, const MetavoxelLOD& lod) const { @@ -843,10 +849,12 @@ void MetavoxelNode::readDelta(const MetavoxelNode& reference, MetavoxelStreamSta _children[i] = new MetavoxelNode(state.attribute); _children[i]->readDelta(*reference._children[i], nextState); } else { - _children[i] = reference._children[i]; - _children[i]->incrementReferenceCount(); - if (nextState.becameSubdivided()) { - _children[i]->readSubdivision(nextState); + if (nextState.becameSubdivided() && reference._children[i]->readSubdivision(nextState)) { + _children[i] = new MetavoxelNode(state.attribute, reference._children[i]); + + } else { + _children[i] = reference._children[i]; + _children[i]->incrementReferenceCount(); } } } @@ -888,7 +896,7 @@ void MetavoxelNode::writeDelta(const MetavoxelNode& reference, MetavoxelStreamSt } } -void MetavoxelNode::readSubdivision(MetavoxelStreamState& state) { +bool MetavoxelNode::readSubdivision(MetavoxelStreamState& state) { bool leaf; bool subdivideReference = state.shouldSubdivideReference(); if (!subdivideReference) { @@ -897,7 +905,7 @@ void MetavoxelNode::readSubdivision(MetavoxelStreamState& state) { leaf = isLeaf(); } if (leaf) { - clearChildren(state.attribute); + return clearChildren(state.attribute); } else { MetavoxelStreamState nextState = { glm::vec3(), state.size * 0.5f, state.attribute, @@ -909,13 +917,22 @@ void MetavoxelNode::readSubdivision(MetavoxelStreamState& state) { _children[i] = new MetavoxelNode(state.attribute); _children[i]->read(nextState); } + return true; + } else { + bool changed = false; for (int i = 0; i < CHILD_COUNT; i++) { nextState.setMinimum(state.minimum, i); if (nextState.becameSubdivided()) { - _children[i]->readSubdivision(nextState); + if (_children[i]->readSubdivision(nextState)) { + MetavoxelNode* oldNode = _children[i]; + _children[i] = new MetavoxelNode(state.attribute, oldNode); + oldNode->decrementReferenceCount(state.attribute); + changed = true; + } } } + return changed; } } } @@ -1042,13 +1059,16 @@ void MetavoxelNode::destroy(const AttributePointer& attribute) { } } -void MetavoxelNode::clearChildren(const AttributePointer& attribute) { +bool MetavoxelNode::clearChildren(const AttributePointer& attribute) { + bool cleared = false; for (int i = 0; i < CHILD_COUNT; i++) { if (_children[i]) { _children[i]->decrementReferenceCount(attribute); _children[i] = NULL; + cleared = true; } } + return cleared; } bool MetavoxelNode::deepEquals(const AttributePointer& attribute, const MetavoxelNode& other, diff --git a/libraries/metavoxels/src/MetavoxelData.h b/libraries/metavoxels/src/MetavoxelData.h index f558bf8e80..ac8f0cc023 100644 --- a/libraries/metavoxels/src/MetavoxelData.h +++ b/libraries/metavoxels/src/MetavoxelData.h @@ -118,7 +118,8 @@ public: void writeDelta(const MetavoxelData& reference, const MetavoxelLOD& referenceLOD, Bitstream& out, const MetavoxelLOD& lod) const; - MetavoxelNode* getRoot(const AttributePointer& attribute) const { return _roots.value(attribute); } + void setRoot(const AttributePointer& attribute, MetavoxelNode* root); + MetavoxelNode* getRoot(const AttributePointer& attribute) const { return _roots.value(attribute); } MetavoxelNode* createRoot(const AttributePointer& attribute); /// Performs a deep comparison between this data and the specified other (as opposed to the == operator, which does a @@ -200,7 +201,7 @@ public: void readDelta(const MetavoxelNode& reference, MetavoxelStreamState& state); void writeDelta(const MetavoxelNode& reference, MetavoxelStreamState& state) const; - void readSubdivision(MetavoxelStreamState& state); + bool readSubdivision(MetavoxelStreamState& state); void writeSubdivision(MetavoxelStreamState& state) const; void writeSpanners(MetavoxelStreamState& state) const; @@ -216,7 +217,7 @@ public: void destroy(const AttributePointer& attribute); - void clearChildren(const AttributePointer& attribute); + bool clearChildren(const AttributePointer& attribute); /// Performs a deep comparison between this and the specified other node. bool deepEquals(const AttributePointer& attribute, const MetavoxelNode& other, From 5e34bcc4233b8caec3442fcc47c8e25e26915c5b Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 11 Jul 2014 15:51:36 -0700 Subject: [PATCH 02/10] Some additional comments. --- libraries/metavoxels/src/DatagramSequencer.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/metavoxels/src/DatagramSequencer.h b/libraries/metavoxels/src/DatagramSequencer.h index 4a01679c68..9a1f5a4ae0 100644 --- a/libraries/metavoxels/src/DatagramSequencer.h +++ b/libraries/metavoxels/src/DatagramSequencer.h @@ -426,9 +426,9 @@ private: int _writePositionResetPacketNumber; SpanList _acknowledged; bool _messagesEnabled; - int _messageLengthPlaceholder; - int _messageReceivedOffset; - int _messageSize; + int _messageLengthPlaceholder; ///< the location in the buffer of the message length for the current message + int _messageReceivedOffset; ///< when reached, indicates that the most recent sent message has been received + int _messageSize; ///< the size of the most recent sent message; only valid when _messageReceivedOffset has been set }; #endif // hifi_DatagramSequencer_h From e32bab5b0469a741e73da94f279f26c50d419031 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 14 Jul 2014 14:32:55 -0700 Subject: [PATCH 03/10] Beginnings of some metavoxel scriptability, to create some test landscapes. --- interface/src/Application.cpp | 1 + libraries/metavoxels/src/Bitstream.cpp | 7 +++++++ libraries/metavoxels/src/Bitstream.h | 5 +++++ .../metavoxels/src/MetavoxelClientManager.cpp | 19 +++++++++++++++++++ .../metavoxels/src/MetavoxelClientManager.h | 4 ++++ 5 files changed, 36 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f13a92bba0..7219a019d4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3641,6 +3641,7 @@ ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScript scriptEngine->registerGlobalObject("AnimationCache", &_animationCache); scriptEngine->registerGlobalObject("AudioReflector", &_audioReflector); scriptEngine->registerGlobalObject("Account", AccountScriptingInterface::getInstance()); + scriptEngine->registerGlobalObject("Metavoxels", &_metavoxels); #ifdef HAVE_RTMIDI scriptEngine->registerGlobalObject("MIDI", &MIDIManager::getInstance()); diff --git a/libraries/metavoxels/src/Bitstream.cpp b/libraries/metavoxels/src/Bitstream.cpp index 0d4f8a52b4..2e9e641d88 100644 --- a/libraries/metavoxels/src/Bitstream.cpp +++ b/libraries/metavoxels/src/Bitstream.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -128,6 +129,12 @@ QList Bitstream::getMetaObjectSubClasses(const QMetaObject* return getMetaObjectSubClasses().values(metaObject); } +void Bitstream::configureScriptEngine(QScriptEngine* engine) { + foreach (const QMetaObject* metaObject, getMetaObjects()) { + engine->globalObject().setProperty(metaObject->className(), engine->newQMetaObject(metaObject)); + } +} + Bitstream::Bitstream(QDataStream& underlying, MetadataType metadataType, GenericsMode genericsMode, QObject* parent) : QObject(parent), _underlying(underlying), diff --git a/libraries/metavoxels/src/Bitstream.h b/libraries/metavoxels/src/Bitstream.h index dacfeb2ee9..04b4dc97fc 100644 --- a/libraries/metavoxels/src/Bitstream.h +++ b/libraries/metavoxels/src/Bitstream.h @@ -32,6 +32,7 @@ class QByteArray; class QColor; class QDataStream; +class QScriptEngine; class QScriptValue; class QUrl; @@ -320,6 +321,10 @@ public: /// subclasses. static QList getMetaObjectSubClasses(const QMetaObject* metaObject); + /// Configures the supplied script engine with our registered meta-objects, allowing all of them to be instantiated from + /// scripts. + static void configureScriptEngine(QScriptEngine* engine); + enum MetadataType { NO_METADATA, HASH_METADATA, FULL_METADATA }; enum GenericsMode { NO_GENERICS, FALLBACK_GENERICS, ALL_GENERICS }; diff --git a/libraries/metavoxels/src/MetavoxelClientManager.cpp b/libraries/metavoxels/src/MetavoxelClientManager.cpp index f3ea1ae8c5..ff02398b85 100644 --- a/libraries/metavoxels/src/MetavoxelClientManager.cpp +++ b/libraries/metavoxels/src/MetavoxelClientManager.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include "MetavoxelClientManager.h" #include "MetavoxelMessages.h" @@ -53,7 +55,24 @@ SharedObjectPointer MetavoxelClientManager::findFirstRaySpannerIntersection(cons return closestSpanner; } +void MetavoxelClientManager::setSphere(const glm::vec3& center, float radius, QRgb color) { + Sphere* sphere = new Sphere(); + sphere->setTranslation(center); + sphere->setScale(radius); + sphere->setColor(color); + setSpanner(sphere); +} + +void MetavoxelClientManager::setSpanner(const SharedObjectPointer& object, bool reliable) { + MetavoxelEditMessage edit = { QVariant::fromValue(SetSpannerEdit(object)) }; + applyEdit(edit, reliable); +} + void MetavoxelClientManager::applyEdit(const MetavoxelEditMessage& edit, bool reliable) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "applyEdit", Q_ARG(const MetavoxelEditMessage&, edit), Q_ARG(bool, reliable)); + return; + } foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { if (node->getType() == NodeType::MetavoxelServer) { QMutexLocker locker(&node->getMutex()); diff --git a/libraries/metavoxels/src/MetavoxelClientManager.h b/libraries/metavoxels/src/MetavoxelClientManager.h index ad6c86c8fc..7537d7f971 100644 --- a/libraries/metavoxels/src/MetavoxelClientManager.h +++ b/libraries/metavoxels/src/MetavoxelClientManager.h @@ -28,6 +28,10 @@ public: SharedObjectPointer findFirstRaySpannerIntersection(const glm::vec3& origin, const glm::vec3& direction, const AttributePointer& attribute, float& distance); + + Q_INVOKABLE void setSphere(const glm::vec3& center, float radius, QRgb color = 0x808080); + + Q_INVOKABLE void setSpanner(const SharedObjectPointer& object, bool reliable = false); Q_INVOKABLE void applyEdit(const MetavoxelEditMessage& edit, bool reliable = false); From 9d5510008797e288ffa4f79620a1fc2059e2b1de Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 15 Jul 2014 09:31:23 -0700 Subject: [PATCH 04/10] Merge (but don't clear redundant nodes) after reading subdivisions. --- libraries/metavoxels/src/MetavoxelData.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp index 72d5392a39..fdce323708 100644 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ b/libraries/metavoxels/src/MetavoxelData.cpp @@ -767,7 +767,7 @@ void MetavoxelNode::mergeChildren(const AttributePointer& attribute, bool postRe childValues[i] = _children[i]->_attributeValue; allLeaves &= _children[i]->isLeaf(); } - if (attribute->merge(_attributeValue, childValues, postRead) && allLeaves) { + if (attribute->merge(_attributeValue, childValues, postRead) && allLeaves && !postRead) { clearChildren(attribute); } } @@ -917,6 +917,7 @@ bool MetavoxelNode::readSubdivision(MetavoxelStreamState& state) { _children[i] = new MetavoxelNode(state.attribute); _children[i]->read(nextState); } + mergeChildren(state.attribute, true); return true; } else { @@ -932,6 +933,9 @@ bool MetavoxelNode::readSubdivision(MetavoxelStreamState& state) { } } } + if (changed) { + mergeChildren(state.attribute, true); + } return changed; } } From e2c8bdbdbed6468d4c72b056d54faf36ca707e1a Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 15 Jul 2014 13:22:50 -0700 Subject: [PATCH 05/10] Create new nodes on subdivision. --- .../metavoxels/src/AttributeRegistry.cpp | 7 +- libraries/metavoxels/src/MetavoxelData.cpp | 97 +++++++++---------- libraries/metavoxels/src/MetavoxelData.h | 2 +- 3 files changed, 53 insertions(+), 53 deletions(-) diff --git a/libraries/metavoxels/src/AttributeRegistry.cpp b/libraries/metavoxels/src/AttributeRegistry.cpp index 670f0be389..1cd41500fc 100644 --- a/libraries/metavoxels/src/AttributeRegistry.cpp +++ b/libraries/metavoxels/src/AttributeRegistry.cpp @@ -214,9 +214,10 @@ void Attribute::writeMetavoxelDelta(const MetavoxelNode& root, const MetavoxelNo void Attribute::readMetavoxelSubdivision(MetavoxelData& data, MetavoxelStreamState& state) { // copy if changed - MetavoxelNode* root = data.getRoot(state.attribute); - if (root->readSubdivision(state)) { - data.setRoot(state.attribute, new MetavoxelNode(state.attribute, root)); + MetavoxelNode* oldRoot = data.getRoot(state.attribute); + MetavoxelNode* newRoot = oldRoot->readSubdivision(state); + if (newRoot != oldRoot) { + data.setRoot(state.attribute, newRoot); } } diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp index fdce323708..a3ea5ca189 100644 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ b/libraries/metavoxels/src/MetavoxelData.cpp @@ -849,9 +849,11 @@ void MetavoxelNode::readDelta(const MetavoxelNode& reference, MetavoxelStreamSta _children[i] = new MetavoxelNode(state.attribute); _children[i]->readDelta(*reference._children[i], nextState); } else { - if (nextState.becameSubdivided() && reference._children[i]->readSubdivision(nextState)) { - _children[i] = new MetavoxelNode(state.attribute, reference._children[i]); - + if (nextState.becameSubdivided()) { + _children[i] = reference._children[i]->readSubdivision(nextState); + if (_children[i] == reference._children[i]) { + _children[i]->incrementReferenceCount(); + } } else { _children[i] = reference._children[i]; _children[i]->incrementReferenceCount(); @@ -896,71 +898,68 @@ void MetavoxelNode::writeDelta(const MetavoxelNode& reference, MetavoxelStreamSt } } -bool MetavoxelNode::readSubdivision(MetavoxelStreamState& state) { - bool leaf; - bool subdivideReference = state.shouldSubdivideReference(); - if (!subdivideReference) { +MetavoxelNode* MetavoxelNode::readSubdivision(MetavoxelStreamState& state) { + if (!state.shouldSubdivideReference()) { + bool leaf; state.stream >> leaf; - } else { - leaf = isLeaf(); - } - if (leaf) { - return clearChildren(state.attribute); - - } else { - MetavoxelStreamState nextState = { glm::vec3(), state.size * 0.5f, state.attribute, - state.stream, state.lod, state.referenceLOD }; - if (!subdivideReference) { - clearChildren(state.attribute); - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - _children[i] = new MetavoxelNode(state.attribute); - _children[i]->read(nextState); - } - mergeChildren(state.attribute, true); - return true; + if (leaf) { + return isLeaf() ? this : new MetavoxelNode(getAttributeValue(state.attribute)); } else { - bool changed = false; + MetavoxelNode* newNode = new MetavoxelNode(getAttributeValue(state.attribute)); + MetavoxelStreamState nextState = { glm::vec3(), state.size * 0.5f, state.attribute, + state.stream, state.lod, state.referenceLOD }; for (int i = 0; i < CHILD_COUNT; i++) { nextState.setMinimum(state.minimum, i); - if (nextState.becameSubdivided()) { - if (_children[i]->readSubdivision(nextState)) { - MetavoxelNode* oldNode = _children[i]; - _children[i] = new MetavoxelNode(state.attribute, oldNode); - oldNode->decrementReferenceCount(state.attribute); - changed = true; + newNode->_children[i] = new MetavoxelNode(state.attribute); + newNode->_children[i]->read(nextState); + } + return newNode; + } + } else if (!isLeaf()) { + MetavoxelNode* node = this; + MetavoxelStreamState nextState = { glm::vec3(), state.size * 0.5f, state.attribute, + state.stream, state.lod, state.referenceLOD }; + for (int i = 0; i < CHILD_COUNT; i++) { + nextState.setMinimum(state.minimum, i); + if (nextState.becameSubdivided()) { + MetavoxelNode* child = _children[i]->readSubdivision(nextState); + if (child != _children[i]) { + if (node == this) { + node = new MetavoxelNode(state.attribute, this); } + node->_children[i] = child; + _children[i]->decrementReferenceCount(state.attribute); } } - if (changed) { - mergeChildren(state.attribute, true); - } - return changed; } + if (node != this) { + node->mergeChildren(state.attribute, true); + } + return node; } + return this; } void MetavoxelNode::writeSubdivision(MetavoxelStreamState& state) const { bool leaf = isLeaf(); - bool subdivideReference = state.shouldSubdivideReference(); - if (!subdivideReference) { + if (!state.shouldSubdivideReference()) { state.stream << leaf; - } - if (!leaf) { - MetavoxelStreamState nextState = { glm::vec3(), state.size * 0.5f, state.attribute, - state.stream, state.lod, state.referenceLOD }; - if (!subdivideReference) { + if (!leaf) { + MetavoxelStreamState nextState = { glm::vec3(), state.size * 0.5f, state.attribute, + state.stream, state.lod, state.referenceLOD }; for (int i = 0; i < CHILD_COUNT; i++) { nextState.setMinimum(state.minimum, i); _children[i]->write(nextState); } - } else { - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - if (nextState.becameSubdivided()) { - _children[i]->writeSubdivision(nextState); - } + } + } else if (!leaf) { + MetavoxelStreamState nextState = { glm::vec3(), state.size * 0.5f, state.attribute, + state.stream, state.lod, state.referenceLOD }; + for (int i = 0; i < CHILD_COUNT; i++) { + nextState.setMinimum(state.minimum, i); + if (nextState.becameSubdivided()) { + _children[i]->writeSubdivision(nextState); } } } diff --git a/libraries/metavoxels/src/MetavoxelData.h b/libraries/metavoxels/src/MetavoxelData.h index ac8f0cc023..eeab5bd0f4 100644 --- a/libraries/metavoxels/src/MetavoxelData.h +++ b/libraries/metavoxels/src/MetavoxelData.h @@ -201,7 +201,7 @@ public: void readDelta(const MetavoxelNode& reference, MetavoxelStreamState& state); void writeDelta(const MetavoxelNode& reference, MetavoxelStreamState& state) const; - bool readSubdivision(MetavoxelStreamState& state); + MetavoxelNode* readSubdivision(MetavoxelStreamState& state); void writeSubdivision(MetavoxelStreamState& state) const; void writeSpanners(MetavoxelStreamState& state) const; From ebcb8d00d61c2ddf99afbac30dd82f9f5fe94c73 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 15 Jul 2014 15:47:31 -0700 Subject: [PATCH 06/10] Unfortunately, the early test for subdivision doesn't work, which means that, for now, we need to traverse the entire tree to find subdivided nodes. To be revisited. --- libraries/metavoxels/src/MetavoxelData.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp index a3ea5ca189..41cf2b2a20 100644 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ b/libraries/metavoxels/src/MetavoxelData.cpp @@ -47,13 +47,8 @@ bool MetavoxelLOD::becameSubdivided(const glm::vec3& minimum, float size, if (!shouldSubdivide(minimum, size, multiplier)) { return false; // this one must be subdivided } - // the general check is whether we've gotten closer (as multiplied by the threshold) to any point in the volume, - // which we approximate as a sphere for simplicity - float halfSize = size * 0.5f; - glm::vec3 center = minimum + glm::vec3(halfSize, halfSize, halfSize); - float radius = sqrtf(3 * halfSize * halfSize); - return qMax(0.0f, glm::distance(position, center) - radius) * threshold <= - qMax(0.0f, glm::distance(reference.position, center) - radius) * reference.threshold; + // TODO: find some way of culling subtrees that can't possibly contain subdivided nodes + return true; } MetavoxelData::MetavoxelData() : _size(1.0f) { From 469e31cc051ff84c40c78f244e46c2859d32e7f9 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 15 Jul 2014 16:44:02 -0700 Subject: [PATCH 07/10] Script bindings for QColor. --- .../metavoxels/src/MetavoxelClientManager.cpp | 2 +- .../metavoxels/src/MetavoxelClientManager.h | 2 +- libraries/shared/src/RegisteredMetaTypes.cpp | 26 +++++++++++++++++++ libraries/shared/src/RegisteredMetaTypes.h | 5 ++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/libraries/metavoxels/src/MetavoxelClientManager.cpp b/libraries/metavoxels/src/MetavoxelClientManager.cpp index ff02398b85..0b9e3f3d8c 100644 --- a/libraries/metavoxels/src/MetavoxelClientManager.cpp +++ b/libraries/metavoxels/src/MetavoxelClientManager.cpp @@ -55,7 +55,7 @@ SharedObjectPointer MetavoxelClientManager::findFirstRaySpannerIntersection(cons return closestSpanner; } -void MetavoxelClientManager::setSphere(const glm::vec3& center, float radius, QRgb color) { +void MetavoxelClientManager::setSphere(const glm::vec3& center, float radius, const QColor& color) { Sphere* sphere = new Sphere(); sphere->setTranslation(center); sphere->setScale(radius); diff --git a/libraries/metavoxels/src/MetavoxelClientManager.h b/libraries/metavoxels/src/MetavoxelClientManager.h index 7537d7f971..191af794f7 100644 --- a/libraries/metavoxels/src/MetavoxelClientManager.h +++ b/libraries/metavoxels/src/MetavoxelClientManager.h @@ -29,7 +29,7 @@ public: SharedObjectPointer findFirstRaySpannerIntersection(const glm::vec3& origin, const glm::vec3& direction, const AttributePointer& attribute, float& distance); - Q_INVOKABLE void setSphere(const glm::vec3& center, float radius, QRgb color = 0x808080); + Q_INVOKABLE void setSphere(const glm::vec3& center, float radius, const QColor& color = QColor(Qt::gray)); Q_INVOKABLE void setSpanner(const SharedObjectPointer& object, bool reliable = false); diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index 3e21a72fd5..afc439c586 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include "RegisteredMetaTypes.h" static int vec4MetaTypeId = qRegisterMetaType(); @@ -25,6 +27,7 @@ void registerMetaTypes(QScriptEngine* engine) { qScriptRegisterMetaType(engine, vec2toScriptValue, vec2FromScriptValue); qScriptRegisterMetaType(engine, quatToScriptValue, quatFromScriptValue); qScriptRegisterMetaType(engine, xColorToScriptValue, xColorFromScriptValue); + qScriptRegisterMetaType(engine, qColorToScriptValue, qColorFromScriptValue); qScriptRegisterMetaType(engine, pickRayToScriptValue, pickRayFromScriptValue); qScriptRegisterMetaType(engine, collisionToScriptValue, collisionFromScriptValue); } @@ -101,6 +104,29 @@ void xColorFromScriptValue(const QScriptValue &object, xColor& color) { color.blue = object.property("blue").toVariant().toInt(); } +QScriptValue qColorToScriptValue(QScriptEngine* engine, const QColor& color) { + QScriptValue object = engine->newObject(); + object.setProperty("red", color.red()); + object.setProperty("green", color.green()); + object.setProperty("blue", color.blue()); + object.setProperty("alpha", color.alpha()); + return object; +} + +void qColorFromScriptValue(const QScriptValue& object, QColor& color) { + if (object.isNumber()) { + color.setRgb(object.toUInt32()); + + } else if (object.isString()) { + color.setNamedColor(object.toString()); + + } else { + QScriptValue alphaValue = object.property("alpha"); + color.setRgb(object.property("red").toInt32(), object.property("green").toInt32(), object.property("blue").toInt32(), + alphaValue.isNumber() ? alphaValue.toInt32() : 255); + } +} + QScriptValue pickRayToScriptValue(QScriptEngine* engine, const PickRay& pickRay) { QScriptValue obj = engine->newObject(); QScriptValue origin = vec3toScriptValue(engine, pickRay.origin); diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index d876965723..b925639e8a 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -19,6 +19,8 @@ #include "CollisionInfo.h" #include "SharedUtil.h" +class QColor; + Q_DECLARE_METATYPE(glm::vec4) Q_DECLARE_METATYPE(glm::vec3) Q_DECLARE_METATYPE(glm::vec2) @@ -42,6 +44,9 @@ void quatFromScriptValue(const QScriptValue &object, glm::quat& quat); QScriptValue xColorToScriptValue(QScriptEngine* engine, const xColor& color); void xColorFromScriptValue(const QScriptValue &object, xColor& color); +QScriptValue qColorToScriptValue(QScriptEngine* engine, const QColor& color); +void qColorFromScriptValue(const QScriptValue& object, QColor& color); + class PickRay { public: PickRay() : origin(0), direction(0) { }; From ce0210bf0428c135f4684713db5161d8fc954475 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 15 Jul 2014 16:52:17 -0700 Subject: [PATCH 08/10] The weak shared object hash can be accessed by multiple threads, so it must be locked. --- libraries/metavoxels/src/SharedObject.cpp | 5 +++++ libraries/metavoxels/src/SharedObject.h | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/libraries/metavoxels/src/SharedObject.cpp b/libraries/metavoxels/src/SharedObject.cpp index d0a1842d31..fc72218e2e 100644 --- a/libraries/metavoxels/src/SharedObject.cpp +++ b/libraries/metavoxels/src/SharedObject.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include "Bitstream.h" #include "MetavoxelUtil.h" @@ -27,10 +28,12 @@ SharedObject::SharedObject() : _remoteID(0), _remoteOriginID(0) { + QWriteLocker locker(&_weakHashLock); _weakHash.insert(_id, this); } void SharedObject::setID(int id) { + QWriteLocker locker(&_weakHashLock); _weakHash.remove(_id); _weakHash.insert(_id = id, this); } @@ -41,6 +44,7 @@ void SharedObject::incrementReferenceCount() { void SharedObject::decrementReferenceCount() { if (!_referenceCount.deref()) { + QWriteLocker locker(&_weakHashLock); _weakHash.remove(_id); delete this; } @@ -127,6 +131,7 @@ void SharedObject::dump(QDebug debug) const { int SharedObject::_lastID = 0; WeakSharedObjectHash SharedObject::_weakHash; +QReadWriteLock SharedObject::_weakHashLock; void pruneWeakSharedObjectHash(WeakSharedObjectHash& hash) { for (WeakSharedObjectHash::iterator it = hash.begin(); it != hash.end(); ) { diff --git a/libraries/metavoxels/src/SharedObject.h b/libraries/metavoxels/src/SharedObject.h index ba643b449c..5ff5aa9680 100644 --- a/libraries/metavoxels/src/SharedObject.h +++ b/libraries/metavoxels/src/SharedObject.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,9 @@ public: /// Returns the weak hash under which all local shared objects are registered. static const WeakSharedObjectHash& getWeakHash() { return _weakHash; } + /// Returns a reference to the weak hash lock. + static QReadWriteLock& getWeakHashLock() { return _weakHashLock; } + Q_INVOKABLE SharedObject(); /// Returns the unique local ID for this object. @@ -85,6 +89,7 @@ private: static int _lastID; static WeakSharedObjectHash _weakHash; + static QReadWriteLock _weakHashLock; }; /// Removes the null references from the supplied hash. From a13d8559e6083191f05cb717c3a322a7b5fb3066 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 15 Jul 2014 16:55:52 -0700 Subject: [PATCH 09/10] Better scoping. --- libraries/metavoxels/src/SharedObject.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/metavoxels/src/SharedObject.cpp b/libraries/metavoxels/src/SharedObject.cpp index fc72218e2e..efc6aa4be6 100644 --- a/libraries/metavoxels/src/SharedObject.cpp +++ b/libraries/metavoxels/src/SharedObject.cpp @@ -44,8 +44,10 @@ void SharedObject::incrementReferenceCount() { void SharedObject::decrementReferenceCount() { if (!_referenceCount.deref()) { - QWriteLocker locker(&_weakHashLock); - _weakHash.remove(_id); + { + QWriteLocker locker(&_weakHashLock); + _weakHash.remove(_id); + } delete this; } } From 2d4134afafdb629ff01f9b4c1de5375ab9cdb75a Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 15 Jul 2014 17:58:31 -0700 Subject: [PATCH 10/10] Provide basic conversions to/from SharedObjectPointer (still have to work out how to handle reference counting correctly). --- libraries/metavoxels/src/Bitstream.cpp | 11 ++++++++++- libraries/metavoxels/src/Bitstream.h | 2 +- libraries/script-engine/src/ScriptEngine.cpp | 2 ++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/libraries/metavoxels/src/Bitstream.cpp b/libraries/metavoxels/src/Bitstream.cpp index 2e9e641d88..f49ae1c04f 100644 --- a/libraries/metavoxels/src/Bitstream.cpp +++ b/libraries/metavoxels/src/Bitstream.cpp @@ -129,10 +129,19 @@ QList Bitstream::getMetaObjectSubClasses(const QMetaObject* return getMetaObjectSubClasses().values(metaObject); } -void Bitstream::configureScriptEngine(QScriptEngine* engine) { +QScriptValue sharedObjectPointerToScriptValue(QScriptEngine* engine, const SharedObjectPointer& pointer) { + return pointer ? engine->newQObject(pointer.data()) : engine->nullValue(); +} + +void sharedObjectPointerFromScriptValue(const QScriptValue& object, SharedObjectPointer& pointer) { + pointer = qobject_cast(object.toQObject()); +} + +void Bitstream::registerTypes(QScriptEngine* engine) { foreach (const QMetaObject* metaObject, getMetaObjects()) { engine->globalObject().setProperty(metaObject->className(), engine->newQMetaObject(metaObject)); } + qScriptRegisterMetaType(engine, sharedObjectPointerToScriptValue, sharedObjectPointerFromScriptValue); } Bitstream::Bitstream(QDataStream& underlying, MetadataType metadataType, GenericsMode genericsMode, QObject* parent) : diff --git a/libraries/metavoxels/src/Bitstream.h b/libraries/metavoxels/src/Bitstream.h index 04b4dc97fc..7602424ded 100644 --- a/libraries/metavoxels/src/Bitstream.h +++ b/libraries/metavoxels/src/Bitstream.h @@ -323,7 +323,7 @@ public: /// Configures the supplied script engine with our registered meta-objects, allowing all of them to be instantiated from /// scripts. - static void configureScriptEngine(QScriptEngine* engine); + static void registerTypes(QScriptEngine* engine); enum MetadataType { NO_METADATA, HASH_METADATA, FULL_METADATA }; diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index cd7c2670ec..c5d5019b1f 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -229,6 +230,7 @@ void ScriptEngine::init() { registerMenuItemProperties(&_engine); registerAnimationTypes(&_engine); registerAvatarTypes(&_engine); + Bitstream::registerTypes(&_engine); qScriptRegisterMetaType(&_engine, ParticlePropertiesToScriptValue, ParticlePropertiesFromScriptValue); qScriptRegisterMetaType(&_engine, ParticleIDtoScriptValue, ParticleIDfromScriptValue);