mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 15:59:57 +02:00
Working on heightfield encoding.
This commit is contained in:
parent
496f4a184e
commit
1ea9b0ccbc
6 changed files with 112 additions and 8 deletions
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -241,6 +241,7 @@ private slots:
|
|||
|
||||
void selectHeightFile();
|
||||
void selectColorFile();
|
||||
void apply();
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue