From 1ea9b0ccbcf4141fd9ab6988d6a00fb569570fa0 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 29 Jul 2014 19:13:43 -0700 Subject: [PATCH] Working on heightfield encoding. --- interface/src/MetavoxelSystem.cpp | 13 +++-- interface/src/MetavoxelSystem.h | 12 +++- interface/src/ui/MetavoxelEditor.cpp | 28 +++++++++- interface/src/ui/MetavoxelEditor.h | 1 + .../metavoxels/src/AttributeRegistry.cpp | 55 +++++++++++++++++++ libraries/metavoxels/src/AttributeRegistry.h | 11 ++++ 6 files changed, 112 insertions(+), 8 deletions(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index c090edcbef..e1479f8f02 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -255,11 +255,12 @@ void PointBuffer::render() { } HeightfieldBuffer::HeightfieldBuffer(const glm::vec3& translation, float scale, - const QByteArray& height, const QByteArray& color) : + const QByteArray& height, const QByteArray& color, bool clearAfterLoading) : _translation(translation), _scale(scale), _height(height), _color(color), + _clearAfterLoading(clearAfterLoading), _heightTexture(QOpenGLTexture::Target2D), _colorTexture(QOpenGLTexture::Target2D) { } @@ -281,8 +282,9 @@ void HeightfieldBuffer::render() { _heightTexture.setFormat(QOpenGLTexture::LuminanceFormat); _heightTexture.allocateStorage(); _heightTexture.setData(QOpenGLTexture::Luminance, QOpenGLTexture::UInt8, _height.data()); - _height.clear(); - + if (_clearAfterLoading) { + _height.clear(); + } if (!_color.isEmpty()) { int colorSize = glm::sqrt(_color.size() / 3); _colorTexture.setSize(colorSize, colorSize); @@ -294,8 +296,9 @@ void HeightfieldBuffer::render() { _colorTexture.allocateStorage(); if (!_color.isEmpty()) { _colorTexture.setData(QOpenGLTexture::RGB, QOpenGLTexture::UInt8, _color.data()); - _color.clear(); - + if (_clearAfterLoading) { + _color.clear(); + } } else { const quint8 WHITE_COLOR[] = { 255, 255, 255 }; _colorTexture.setData(QOpenGLTexture::RGB, QOpenGLTexture::UInt8, const_cast(WHITE_COLOR)); diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h index 1ee037f8c0..89ea7dcbda 100644 --- a/interface/src/MetavoxelSystem.h +++ b/interface/src/MetavoxelSystem.h @@ -125,7 +125,15 @@ private: class HeightfieldBuffer : public BufferData { public: - HeightfieldBuffer(const glm::vec3& translation, float scale, const QByteArray& height, const QByteArray& color); + /// Creates a new heightfield buffer. + /// \param clearAfterLoading if true, clear the data arrays after we load them into textures in order to reclaim the space + HeightfieldBuffer(const glm::vec3& translation, float scale, const QByteArray& height, const QByteArray& color, + bool clearAfterLoading = true); + + const glm::vec3& getTranslation() const { return _translation; } + + const QByteArray& getHeight() const { return _height; } + const QByteArray& getColor() const { return _color; } virtual void render(); @@ -135,6 +143,7 @@ private: float _scale; QByteArray _height; QByteArray _color; + bool _clearAfterLoading; QOpenGLTexture _heightTexture; QOpenGLTexture _colorTexture; @@ -147,6 +156,7 @@ class HeightfieldPreview { public: void setBuffers(const QVector& buffers) { _buffers = buffers; } + const QVector& getBuffers() const { return _buffers; } void render(const glm::vec3& translation, float scale) const; diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index 70573b02c7..3f3198116f 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -908,11 +908,15 @@ ImportHeightfieldTool::ImportHeightfieldTool(MetavoxelEditor* editor) : _scale->setMinimum(-FLT_MAX); _scale->setMaximum(FLT_MAX); _scale->setPrefix("2^"); - _scale->setValue(1.0); + _scale->setValue(3.0); form->addRow("Height:", _height = new QPushButton()); connect(_height, &QAbstractButton::clicked, this, &ImportHeightfieldTool::selectHeightFile); form->addRow("Color:", _color = new QPushButton()); connect(_color, &QAbstractButton::clicked, this, &ImportHeightfieldTool::selectColorFile); + + QPushButton* applyButton = new QPushButton("Apply"); + layout()->addWidget(applyButton); + connect(applyButton, &QAbstractButton::clicked, this, &ImportHeightfieldTool::apply); } bool ImportHeightfieldTool::appliesTo(const AttributePointer& attribute) const { @@ -955,6 +959,26 @@ void ImportHeightfieldTool::selectColorFile() { updatePreview(); } +void ImportHeightfieldTool::apply() { + float scale = pow(2.0, _scale->value()); + foreach (const BufferDataPointer& bufferData, _preview.getBuffers()) { + HeightfieldBuffer* buffer = static_cast(bufferData.data()); + MetavoxelData data; + data.setSize(scale); + HeightfieldDataPointer heightPointer(new HeightfieldData(buffer->getHeight())); + data.setRoot(AttributeRegistry::getInstance()->getHeightfieldAttribute(), new MetavoxelNode(AttributeValue( + AttributeRegistry::getInstance()->getHeightfieldAttribute(), encodeInline(heightPointer)))); + if (!buffer->getColor().isEmpty()) { + HeightfieldDataPointer colorPointer(new HeightfieldData(buffer->getColor())); + data.setRoot(AttributeRegistry::getInstance()->getHeightfieldColorAttribute(), new MetavoxelNode(AttributeValue( + AttributeRegistry::getInstance()->getHeightfieldColorAttribute(), encodeInline(colorPointer)))); + } + MetavoxelEditMessage message = { QVariant::fromValue(SetDataEdit( + _translation->getValue() + buffer->getTranslation() * scale, data)) }; + Application::getInstance()->getMetavoxels()->applyEdit(message, true); + } +} + const int BLOCK_SIZE = 32; const int BLOCK_ADVANCEMENT = BLOCK_SIZE - 1; @@ -988,7 +1012,7 @@ void ImportHeightfieldTool::updatePreview() { _colorImage.scanLine(i + y) + j * BYTES_PER_COLOR, columns * BYTES_PER_COLOR); } } - buffers.append(BufferDataPointer(new HeightfieldBuffer(glm::vec3(x, 0.0f, z), 1.0f, height, color))); + buffers.append(BufferDataPointer(new HeightfieldBuffer(glm::vec3(x, 0.0f, z), 1.0f, height, color, false))); } } } diff --git a/interface/src/ui/MetavoxelEditor.h b/interface/src/ui/MetavoxelEditor.h index bc9dfdf741..2545ff57ba 100644 --- a/interface/src/ui/MetavoxelEditor.h +++ b/interface/src/ui/MetavoxelEditor.h @@ -241,6 +241,7 @@ private slots: void selectHeightFile(); void selectColorFile(); + void apply(); private: diff --git a/libraries/metavoxels/src/AttributeRegistry.cpp b/libraries/metavoxels/src/AttributeRegistry.cpp index 4f4da7adf2..fefbbc3cd8 100644 --- a/libraries/metavoxels/src/AttributeRegistry.cpp +++ b/libraries/metavoxels/src/AttributeRegistry.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include +#include #include #include #include @@ -459,10 +461,49 @@ HeightfieldData::HeightfieldData(const QByteArray& contents) : _contents(contents) { } +void HeightfieldData::write(Bitstream& out, bool color) { + QMutexLocker locker(&_encodedMutex); + if (_encoded.isEmpty()) { + QImage image; + const int BYTES_PER_PIXEL = 3; + if (color) { + int size = glm::sqrt(_contents.size() / (double)BYTES_PER_PIXEL); + image = QImage((uchar*)_contents.data(), size, size, QImage::Format_RGB888); + } else { + int size = glm::sqrt((double)_contents.size()); + image = QImage(size, size, QImage::Format_RGB888); + uchar* dest = image.bits(); + for (const char* src = _contents.constData(), *end = src + _contents.size(); src != end; src++) { + *dest++ = *src; + *dest++ = *src; + *dest++ = *src; + } + } + QBuffer buffer(&_encoded); + buffer.open(QIODevice::WriteOnly); + image.save(&buffer, "JPG"); + } + +} + HeightfieldAttribute::HeightfieldAttribute(const QString& name) : InlineAttribute(name) { } +void HeightfieldAttribute::read(Bitstream& in, void*& value, bool isLeaf) const { + if (isLeaf) { + } +} + +void HeightfieldAttribute::write(Bitstream& out, void* value, bool isLeaf) const { + if (isLeaf) { + HeightfieldDataPointer data = decodeInline(value); + if (data) { + data->write(out, false); + } + } +} + bool HeightfieldAttribute::merge(void*& parent, void* children[], bool postRead) const { return false; } @@ -471,6 +512,20 @@ HeightfieldColorAttribute::HeightfieldColorAttribute(const QString& name) : InlineAttribute(name) { } +void HeightfieldColorAttribute::read(Bitstream& in, void*& value, bool isLeaf) const { + if (isLeaf) { + } +} + +void HeightfieldColorAttribute::write(Bitstream& out, void* value, bool isLeaf) const { + if (isLeaf) { + HeightfieldDataPointer data = decodeInline(value); + if (data) { + data->write(out, true); + } + } +} + bool HeightfieldColorAttribute::merge(void*& parent, void* children[], bool postRead) const { return false; } diff --git a/libraries/metavoxels/src/AttributeRegistry.h b/libraries/metavoxels/src/AttributeRegistry.h index 262ef89462..3ef37646d6 100644 --- a/libraries/metavoxels/src/AttributeRegistry.h +++ b/libraries/metavoxels/src/AttributeRegistry.h @@ -13,6 +13,7 @@ #define hifi_AttributeRegistry_h #include +#include #include #include #include @@ -424,9 +425,13 @@ public: const QByteArray& getContents() const { return _contents; } + void write(Bitstream& out, bool color); + private: QByteArray _contents; + QByteArray _encoded; + QMutex _encodedMutex; }; typedef QExplicitlySharedDataPointer HeightfieldDataPointer; @@ -439,6 +444,9 @@ public: Q_INVOKABLE HeightfieldAttribute(const QString& name = QString()); + virtual void read(Bitstream& in, void*& value, bool isLeaf) const; + virtual void write(Bitstream& out, void* value, bool isLeaf) const; + virtual bool merge(void*& parent, void* children[], bool postRead = false) const; }; @@ -450,6 +458,9 @@ public: Q_INVOKABLE HeightfieldColorAttribute(const QString& name = QString()); + virtual void read(Bitstream& in, void*& value, bool isLeaf) const; + virtual void write(Bitstream& out, void* value, bool isLeaf) const; + virtual bool merge(void*& parent, void* children[], bool postRead = false) const; };