From 40844d2000ede56d4ac04f6de713e2def80935d7 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 2 Apr 2014 12:40:01 -0700 Subject: [PATCH] Working on ability to set a region of the metavoxel data directly. --- .../src/metavoxels/MetavoxelServer.cpp | 2 + libraries/metavoxels/src/Bitstream.h | 7 ++ libraries/metavoxels/src/MetavoxelData.cpp | 92 ++++++++++++++++++- libraries/metavoxels/src/MetavoxelData.h | 18 +++- .../metavoxels/src/MetavoxelMessages.cpp | 9 ++ libraries/metavoxels/src/MetavoxelMessages.h | 17 ++++ 6 files changed, 139 insertions(+), 6 deletions(-) diff --git a/assignment-client/src/metavoxels/MetavoxelServer.cpp b/assignment-client/src/metavoxels/MetavoxelServer.cpp index 98c91d44e7..23c8f2189c 100644 --- a/assignment-client/src/metavoxels/MetavoxelServer.cpp +++ b/assignment-client/src/metavoxels/MetavoxelServer.cpp @@ -95,6 +95,8 @@ MetavoxelSession::MetavoxelSession(MetavoxelServer* server, const SharedNodePoin connect(&_sequencer, SIGNAL(readyToRead(Bitstream&)), SLOT(readPacket(Bitstream&))); connect(&_sequencer, SIGNAL(sendAcknowledged(int)), SLOT(clearSendRecordsBefore(int))); connect(&_sequencer, SIGNAL(receivedHighPriorityMessage(const QVariant&)), SLOT(handleMessage(const QVariant&))); + connect(_sequencer.getReliableInputChannel(), SIGNAL(receivedMessage(const QVariant&)), + SLOT(handleMessage(const QVariant&))); // insert the baseline send record SendRecord record = { 0 }; diff --git a/libraries/metavoxels/src/Bitstream.h b/libraries/metavoxels/src/Bitstream.h index 760154a928..8f36ce9a08 100644 --- a/libraries/metavoxels/src/Bitstream.h +++ b/libraries/metavoxels/src/Bitstream.h @@ -920,6 +920,13 @@ public: _Pragma(STRINGIFY(unused(_TypePtr##X))) #endif +/// Registers a simple type and its streamer. +template int registerSimpleMetaType() { + int type = qRegisterMetaType(); + Bitstream::registerTypeStreamer(type, new SimpleTypeStreamer()); + return type; +} + /// Registers a streamable type and its streamer. template int registerStreamableMetaType() { int type = qRegisterMetaType(); diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp index e548de46c7..c89967b3a0 100644 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ b/libraries/metavoxels/src/MetavoxelData.cpp @@ -24,6 +24,8 @@ REGISTER_META_OBJECT(Spanner) REGISTER_META_OBJECT(Sphere) REGISTER_META_OBJECT(StaticModel) +static int metavoxelDataTypeId = registerSimpleMetaType(); + MetavoxelLOD::MetavoxelLOD(const glm::vec3& position, float threshold) : position(position), threshold(threshold) { @@ -327,6 +329,67 @@ const int Y_MAXIMUM_FLAG = 2; const int Z_MAXIMUM_FLAG = 4; const int MAXIMUM_FLAG_MASK = X_MAXIMUM_FLAG | Y_MAXIMUM_FLAG | Z_MAXIMUM_FLAG; +static glm::vec3 getNextMinimum(const glm::vec3& minimum, float nextSize, int index) { + return minimum + glm::vec3( + (index & X_MAXIMUM_FLAG) ? nextSize : 0.0f, + (index & Y_MAXIMUM_FLAG) ? nextSize : 0.0f, + (index & Z_MAXIMUM_FLAG) ? nextSize : 0.0f); +} + +static void setNode(const AttributePointer& attribute, MetavoxelNode*& node, MetavoxelNode* other) { + if (node) { + node->decrementReferenceCount(attribute); + } + (node = other)->incrementReferenceCount(); +} + +static void setNode(const AttributeValue& value, MetavoxelNode*& node, const glm::vec3& minimum, float size, + MetavoxelNode* other, const glm::vec3& otherMinimum, float otherSize) { + if (otherSize >= size) { + setNode(value.getAttribute(), node, other); + return; + } + if (!node) { + node = new MetavoxelNode(value); + } + int index = 0; + float otherHalfSize = otherSize * 0.5f; + float nextSize = size * 0.5f; + if (otherMinimum.x + otherHalfSize >= minimum.x + nextSize) { + index |= X_MAXIMUM_FLAG; + } + if (otherMinimum.y + otherHalfSize >= minimum.y + nextSize) { + index |= Y_MAXIMUM_FLAG; + } + if (otherMinimum.z + otherHalfSize >= minimum.z + nextSize) { + index |= Z_MAXIMUM_FLAG; + } + if (node->isLeaf()) { + for (int i = 1; i < MetavoxelNode::CHILD_COUNT; i++) { + node->setChild((index + i) % MetavoxelNode::CHILD_COUNT, new MetavoxelNode( + node->getAttributeValue(value.getAttribute()))); + } + } + MetavoxelNode* nextNode = node->getChild(index); + setNode(node->getAttributeValue(value.getAttribute()), nextNode, getNextMinimum(minimum, nextSize, index), + nextSize, other, otherMinimum, otherSize); + node->setChild(index, nextNode); +} + +void MetavoxelData::set(const glm::vec3& minimum, const MetavoxelData& data) { + // expand to fit the entire data + Box bounds = minimum + glm::vec3(data.getSize(), data.getSize(), data.getSize()); + while (!getBounds().contains(bounds)) { + expand(); + } + + // set each attribute separately + for (QHash::const_iterator it = data._roots.constBegin(); + it != data._roots.constEnd(); it++) { + setNode(it.key(), _roots[it.key()], getMinimum(), getSize(), it.value(), minimum, data.getSize()); + } +} + static int getOppositeIndex(int index) { return index ^ MAXIMUM_FLAG_MASK; } @@ -511,6 +574,14 @@ MetavoxelNode* MetavoxelData::createRoot(const AttributePointer& attribute) { return root = new MetavoxelNode(attribute); } +bool MetavoxelData::operator==(const MetavoxelData& other) const { + return _size == other._size && _roots == other._roots; +} + +bool MetavoxelData::operator!=(const MetavoxelData& other) const { + return _size != other._size || _roots != other._roots; +} + void MetavoxelData::incrementRootReferenceCounts() { for (QHash::const_iterator it = _roots.constBegin(); it != _roots.constEnd(); it++) { it.value()->incrementReferenceCount(); @@ -523,11 +594,22 @@ void MetavoxelData::decrementRootReferenceCounts() { } } -static glm::vec3 getNextMinimum(const glm::vec3& minimum, float nextSize, int index) { - return minimum + glm::vec3( - (index & X_MAXIMUM_FLAG) ? nextSize : 0.0f, - (index & Y_MAXIMUM_FLAG) ? nextSize : 0.0f, - (index & Z_MAXIMUM_FLAG) ? nextSize : 0.0f); +Bitstream& operator<<(Bitstream& out, const MetavoxelData& data) { + data.write(out); + return out; +} + +Bitstream& operator>>(Bitstream& in, MetavoxelData& data) { + data.read(in); + return in; +} + +template<> void Bitstream::writeDelta(const MetavoxelData& value, const MetavoxelData& reference) { + value.writeDelta(reference, MetavoxelLOD(), *this, MetavoxelLOD()); +} + +template<> void Bitstream::readDelta(MetavoxelData& value, const MetavoxelData& reference) { + value.readDelta(reference, MetavoxelLOD(), *this, MetavoxelLOD()); } bool MetavoxelStreamState::shouldSubdivide() const { diff --git a/libraries/metavoxels/src/MetavoxelData.h b/libraries/metavoxels/src/MetavoxelData.h index fa408aafb7..4db2e919b4 100644 --- a/libraries/metavoxels/src/MetavoxelData.h +++ b/libraries/metavoxels/src/MetavoxelData.h @@ -90,6 +90,9 @@ public: SharedObjectPointer findFirstRaySpannerIntersection(const glm::vec3& origin, const glm::vec3& direction, const AttributePointer& attribute, float& distance, const MetavoxelLOD& lod = MetavoxelLOD()); + /// Sets part of the data. + void set(const glm::vec3& minimum, const MetavoxelData& data); + /// Expands the tree, increasing its capacity in all dimensions. void expand(); @@ -103,6 +106,9 @@ public: MetavoxelNode* getRoot(const AttributePointer& attribute) const { return _roots.value(attribute); } MetavoxelNode* createRoot(const AttributePointer& attribute); + bool operator==(const MetavoxelData& other) const; + bool operator!=(const MetavoxelData& other) const; + private: friend class MetavoxelVisitation; @@ -114,6 +120,16 @@ private: QHash _roots; }; +Bitstream& operator<<(Bitstream& out, const MetavoxelData& data); + +Bitstream& operator>>(Bitstream& in, MetavoxelData& data); + +template<> void Bitstream::writeDelta(const MetavoxelData& value, const MetavoxelData& reference); + +template<> void Bitstream::readDelta(MetavoxelData& value, const MetavoxelData& reference); + +Q_DECLARE_METATYPE(MetavoxelData) + /// Holds the state used in streaming metavoxel data. class MetavoxelStreamState { public: @@ -592,7 +608,7 @@ public: const QUrl& getURL() const { return _url; } virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - const glm::vec3& clipMinimum, float clipSize,float& distance) const; + const glm::vec3& clipMinimum, float clipSize, float& distance) const; signals: diff --git a/libraries/metavoxels/src/MetavoxelMessages.cpp b/libraries/metavoxels/src/MetavoxelMessages.cpp index ce0d01ccf2..7bf10467f6 100644 --- a/libraries/metavoxels/src/MetavoxelMessages.cpp +++ b/libraries/metavoxels/src/MetavoxelMessages.cpp @@ -305,3 +305,12 @@ void SetSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& obje setIntersectingMasked(spanner->getBounds(), data); } + +SetDataEdit::SetDataEdit(const glm::vec3& minimum, const MetavoxelData& data) : + minimum(minimum), + data(data) { +} + +void SetDataEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const { + data.set(minimum, this->data); +} diff --git a/libraries/metavoxels/src/MetavoxelMessages.h b/libraries/metavoxels/src/MetavoxelMessages.h index 25db8e5464..309439812d 100644 --- a/libraries/metavoxels/src/MetavoxelMessages.h +++ b/libraries/metavoxels/src/MetavoxelMessages.h @@ -176,4 +176,21 @@ public: DECLARE_STREAMABLE_METATYPE(SetSpannerEdit) +/// An edit that directly sets part of the metavoxel data. +class SetDataEdit : public MetavoxelEdit { + STREAMABLE + +public: + + STREAM glm::vec3 minimum; + + STREAM MetavoxelData data; + + SetDataEdit(const glm::vec3& minimum = glm::vec3(), const MetavoxelData& data = MetavoxelData()); + + virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const; +}; + +DECLARE_STREAMABLE_METATYPE(SetDataEdit) + #endif /* defined(__interface__MetavoxelMessages__) */