Working on heightfield encoding.

This commit is contained in:
Andrzej Kapolka 2014-07-29 19:13:43 -07:00
parent 496f4a184e
commit 1ea9b0ccbc
6 changed files with 112 additions and 8 deletions

View file

@ -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<quint8*>(WHITE_COLOR));

View file

@ -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<BufferDataPointer>& buffers) { _buffers = buffers; }
const QVector<BufferDataPointer>& getBuffers() const { return _buffers; }
void render(const glm::vec3& translation, float scale) const;

View file

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

View file

@ -241,6 +241,7 @@ private slots:
void selectHeightFile();
void selectColorFile();
void apply();
private:

View file

@ -9,6 +9,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QBuffer>
#include <QMutexLocker>
#include <QReadLocker>
#include <QScriptEngine>
#include <QWriteLocker>
@ -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<HeightfieldDataPointer>(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<HeightfieldDataPointer>(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<HeightfieldDataPointer>(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<HeightfieldDataPointer>(value);
if (data) {
data->write(out, true);
}
}
}
bool HeightfieldColorAttribute::merge(void*& parent, void* children[], bool postRead) const {
return false;
}

View file

@ -13,6 +13,7 @@
#define hifi_AttributeRegistry_h
#include <QHash>
#include <QMutex>
#include <QObject>
#include <QReadWriteLock>
#include <QSharedPointer>
@ -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<HeightfieldData> 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;
};