Working on ability to set a region of the metavoxel data directly.

This commit is contained in:
Andrzej Kapolka 2014-04-02 12:40:01 -07:00
parent 7f6dc7ac2f
commit 40844d2000
6 changed files with 139 additions and 6 deletions

View file

@ -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 };

View file

@ -920,6 +920,13 @@ public:
_Pragma(STRINGIFY(unused(_TypePtr##X)))
#endif
/// Registers a simple type and its streamer.
template<class T> int registerSimpleMetaType() {
int type = qRegisterMetaType<T>();
Bitstream::registerTypeStreamer(type, new SimpleTypeStreamer<T>());
return type;
}
/// Registers a streamable type and its streamer.
template<class T> int registerStreamableMetaType() {
int type = qRegisterMetaType<T>();

View file

@ -24,6 +24,8 @@ REGISTER_META_OBJECT(Spanner)
REGISTER_META_OBJECT(Sphere)
REGISTER_META_OBJECT(StaticModel)
static int metavoxelDataTypeId = registerSimpleMetaType<MetavoxelData>();
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<AttributePointer, MetavoxelNode*>::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<AttributePointer, MetavoxelNode*>::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 {

View file

@ -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<AttributePointer, MetavoxelNode*> _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:

View file

@ -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);
}

View file

@ -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__) */