mirror of
https://github.com/overte-org/overte.git
synced 2025-04-25 21:36:12 +02:00
Rather than using a boolean to indicate "colorness," use a different class.
More texture bits.
This commit is contained in:
parent
23a4c21ce1
commit
e854656a7f
9 changed files with 465 additions and 287 deletions
|
@ -1011,7 +1011,7 @@ int HeightfieldFetchVisitor::visit(MetavoxelInfo& info) {
|
||||||
if (!info.isLeaf && info.size > _buffer->getScale()) {
|
if (!info.isLeaf && info.size > _buffer->getScale()) {
|
||||||
return DEFAULT_ORDER;
|
return DEFAULT_ORDER;
|
||||||
}
|
}
|
||||||
HeightfieldDataPointer height = info.inputValues.at(0).getInlineValue<HeightfieldDataPointer>();
|
HeightfieldHeightDataPointer height = info.inputValues.at(0).getInlineValue<HeightfieldHeightDataPointer>();
|
||||||
if (!height) {
|
if (!height) {
|
||||||
return STOP_RECURSION;
|
return STOP_RECURSION;
|
||||||
}
|
}
|
||||||
|
@ -1067,7 +1067,7 @@ int HeightfieldFetchVisitor::visit(MetavoxelInfo& info) {
|
||||||
if (colorSize == 0) {
|
if (colorSize == 0) {
|
||||||
return STOP_RECURSION;
|
return STOP_RECURSION;
|
||||||
}
|
}
|
||||||
HeightfieldDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldDataPointer>();
|
HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldColorDataPointer>();
|
||||||
if (!color) {
|
if (!color) {
|
||||||
return STOP_RECURSION;
|
return STOP_RECURSION;
|
||||||
}
|
}
|
||||||
|
@ -1149,14 +1149,14 @@ int HeightfieldRegionVisitor::visit(MetavoxelInfo& info) {
|
||||||
return DEFAULT_ORDER;
|
return DEFAULT_ORDER;
|
||||||
}
|
}
|
||||||
HeightfieldBuffer* buffer = NULL;
|
HeightfieldBuffer* buffer = NULL;
|
||||||
HeightfieldDataPointer height = info.inputValues.at(0).getInlineValue<HeightfieldDataPointer>();
|
HeightfieldHeightDataPointer height = info.inputValues.at(0).getInlineValue<HeightfieldHeightDataPointer>();
|
||||||
if (height) {
|
if (height) {
|
||||||
const QByteArray& heightContents = height->getContents();
|
const QByteArray& heightContents = height->getContents();
|
||||||
int size = glm::sqrt(heightContents.size());
|
int size = glm::sqrt(heightContents.size());
|
||||||
int extendedSize = size + HeightfieldBuffer::HEIGHT_EXTENSION;
|
int extendedSize = size + HeightfieldBuffer::HEIGHT_EXTENSION;
|
||||||
int heightContentsSize = extendedSize * extendedSize;
|
int heightContentsSize = extendedSize * extendedSize;
|
||||||
|
|
||||||
HeightfieldDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldDataPointer>();
|
HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldColorDataPointer>();
|
||||||
int colorContentsSize = 0;
|
int colorContentsSize = 0;
|
||||||
if (color) {
|
if (color) {
|
||||||
const QByteArray& colorContents = color->getContents();
|
const QByteArray& colorContents = color->getContents();
|
||||||
|
|
|
@ -957,14 +957,28 @@ void ImportHeightfieldTool::apply() {
|
||||||
HeightfieldBuffer* buffer = static_cast<HeightfieldBuffer*>(bufferData.data());
|
HeightfieldBuffer* buffer = static_cast<HeightfieldBuffer*>(bufferData.data());
|
||||||
MetavoxelData data;
|
MetavoxelData data;
|
||||||
data.setSize(scale);
|
data.setSize(scale);
|
||||||
HeightfieldDataPointer heightPointer(new HeightfieldData(buffer->getUnextendedHeight()));
|
|
||||||
|
QByteArray height = buffer->getUnextendedHeight();
|
||||||
|
HeightfieldHeightDataPointer heightPointer(new HeightfieldHeightData(height));
|
||||||
data.setRoot(AttributeRegistry::getInstance()->getHeightfieldAttribute(), new MetavoxelNode(AttributeValue(
|
data.setRoot(AttributeRegistry::getInstance()->getHeightfieldAttribute(), new MetavoxelNode(AttributeValue(
|
||||||
AttributeRegistry::getInstance()->getHeightfieldAttribute(), encodeInline(heightPointer))));
|
AttributeRegistry::getInstance()->getHeightfieldAttribute(), encodeInline(heightPointer))));
|
||||||
if (!buffer->getColor().isEmpty()) {
|
|
||||||
HeightfieldDataPointer colorPointer(new HeightfieldData(buffer->getUnextendedColor()));
|
QByteArray color;
|
||||||
data.setRoot(AttributeRegistry::getInstance()->getHeightfieldColorAttribute(), new MetavoxelNode(AttributeValue(
|
if (buffer->getColor().isEmpty()) {
|
||||||
AttributeRegistry::getInstance()->getHeightfieldColorAttribute(), encodeInline(colorPointer))));
|
const int WHITE_VALUE = 0xFF;
|
||||||
|
color = QByteArray(height.size() * HeightfieldData::COLOR_BYTES, WHITE_VALUE);
|
||||||
|
} else {
|
||||||
|
color = buffer->getUnextendedColor();
|
||||||
}
|
}
|
||||||
|
HeightfieldColorDataPointer colorPointer(new HeightfieldColorData(color));
|
||||||
|
data.setRoot(AttributeRegistry::getInstance()->getHeightfieldColorAttribute(), new MetavoxelNode(AttributeValue(
|
||||||
|
AttributeRegistry::getInstance()->getHeightfieldColorAttribute(), encodeInline(colorPointer))));
|
||||||
|
|
||||||
|
QByteArray texture(height.size(), 0);
|
||||||
|
HeightfieldDataPointer texturePointer(new HeightfieldData(texture));
|
||||||
|
data.setRoot(AttributeRegistry::getInstance()->getHeightfieldTextureAttribute(), new MetavoxelNode(AttributeValue(
|
||||||
|
AttributeRegistry::getInstance()->getHeightfieldTextureAttribute(), encodeInline(texturePointer))));
|
||||||
|
|
||||||
MetavoxelEditMessage message = { QVariant::fromValue(SetDataEdit(
|
MetavoxelEditMessage message = { QVariant::fromValue(SetDataEdit(
|
||||||
_translation->getValue() + buffer->getTranslation() * scale, data)) };
|
_translation->getValue() + buffer->getTranslation() * scale, data)) };
|
||||||
Application::getInstance()->getMetavoxels()->applyEdit(message, true);
|
Application::getInstance()->getMetavoxels()->applyEdit(message, true);
|
||||||
|
@ -1165,20 +1179,20 @@ QVariant HeightfieldColorBrushTool::createEdit(bool alternate) {
|
||||||
HeightfieldTextureBrushTool::HeightfieldTextureBrushTool(MetavoxelEditor* editor) :
|
HeightfieldTextureBrushTool::HeightfieldTextureBrushTool(MetavoxelEditor* editor) :
|
||||||
HeightfieldBrushTool(editor, "Texture Brush") {
|
HeightfieldBrushTool(editor, "Texture Brush") {
|
||||||
|
|
||||||
_form->addRow("URL:", _url = new QUrlEditor(this));
|
_form->addRow(_textureEditor = new SharedObjectEditor(&HeightfieldTexture::staticMetaObject, false));
|
||||||
_url->setURL(QUrl());
|
connect(_textureEditor, &SharedObjectEditor::objectChanged, this, &HeightfieldTextureBrushTool::updateTexture);
|
||||||
connect(_url, &QUrlEditor::urlChanged, this, &HeightfieldTextureBrushTool::updateTexture);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant HeightfieldTextureBrushTool::createEdit(bool alternate) {
|
QVariant HeightfieldTextureBrushTool::createEdit(bool alternate) {
|
||||||
if (alternate) {
|
if (alternate) {
|
||||||
return QVariant::fromValue(PaintHeightfieldTextureEdit(_position, _radius->value(), QUrl(), QColor()));
|
return QVariant::fromValue(PaintHeightfieldTextureEdit(_position, _radius->value(), SharedObjectPointer(), QColor()));
|
||||||
} else {
|
} else {
|
||||||
return QVariant::fromValue(PaintHeightfieldTextureEdit(_position, _radius->value(), _url->getURL(),
|
return QVariant::fromValue(PaintHeightfieldTextureEdit(_position, _radius->value(), _textureEditor->getObject(),
|
||||||
_texture ? _texture->getAverageColor() : QColor()));
|
_texture ? _texture->getAverageColor() : QColor()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeightfieldTextureBrushTool::updateTexture() {
|
void HeightfieldTextureBrushTool::updateTexture() {
|
||||||
_texture = Application::getInstance()->getTextureCache()->getTexture(_url->getURL());
|
HeightfieldTexture* texture = static_cast<HeightfieldTexture*>(_textureEditor->getObject().data());
|
||||||
|
_texture = Application::getInstance()->getTextureCache()->getTexture(texture->getURL());
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,9 +26,9 @@ class QListWidget;
|
||||||
class QPushButton;
|
class QPushButton;
|
||||||
class QScrollArea;
|
class QScrollArea;
|
||||||
class QSpinBox;
|
class QSpinBox;
|
||||||
class QUrlEditor;
|
|
||||||
|
|
||||||
class MetavoxelTool;
|
class MetavoxelTool;
|
||||||
|
class SharedObjectEditor;
|
||||||
class Vec3Editor;
|
class Vec3Editor;
|
||||||
|
|
||||||
/// Allows editing metavoxels.
|
/// Allows editing metavoxels.
|
||||||
|
@ -380,7 +380,7 @@ private slots:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
QUrlEditor* _url;
|
SharedObjectEditor* _textureEditor;
|
||||||
QSharedPointer<NetworkTexture> _texture;
|
QSharedPointer<NetworkTexture> _texture;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ REGISTER_META_OBJECT(QRgbAttribute)
|
||||||
REGISTER_META_OBJECT(PackedNormalAttribute)
|
REGISTER_META_OBJECT(PackedNormalAttribute)
|
||||||
REGISTER_META_OBJECT(SpannerQRgbAttribute)
|
REGISTER_META_OBJECT(SpannerQRgbAttribute)
|
||||||
REGISTER_META_OBJECT(SpannerPackedNormalAttribute)
|
REGISTER_META_OBJECT(SpannerPackedNormalAttribute)
|
||||||
|
REGISTER_META_OBJECT(HeightfieldTexture)
|
||||||
REGISTER_META_OBJECT(HeightfieldAttribute)
|
REGISTER_META_OBJECT(HeightfieldAttribute)
|
||||||
REGISTER_META_OBJECT(HeightfieldColorAttribute)
|
REGISTER_META_OBJECT(HeightfieldColorAttribute)
|
||||||
REGISTER_META_OBJECT(HeightfieldTextureAttribute)
|
REGISTER_META_OBJECT(HeightfieldTextureAttribute)
|
||||||
|
@ -502,8 +503,7 @@ HeightfieldData::HeightfieldData(const QByteArray& contents) :
|
||||||
_contents(contents) {
|
_contents(contents) {
|
||||||
}
|
}
|
||||||
|
|
||||||
HeightfieldData::HeightfieldData(Bitstream& in, int bytes, bool color) {
|
HeightfieldData::~HeightfieldData() {
|
||||||
read(in, bytes, color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum HeightfieldImage { NULL_HEIGHTFIELD_IMAGE, NORMAL_HEIGHTFIELD_IMAGE, DEFLATED_HEIGHTFIELD_IMAGE };
|
enum HeightfieldImage { NULL_HEIGHTFIELD_IMAGE, NORMAL_HEIGHTFIELD_IMAGE, DEFLATED_HEIGHTFIELD_IMAGE };
|
||||||
|
@ -549,51 +549,48 @@ const QImage decodeHeightfieldImage(const QByteArray& data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HeightfieldData::HeightfieldData(Bitstream& in, int bytes, const HeightfieldDataPointer& reference, bool color) {
|
HeightfieldHeightData::HeightfieldHeightData(const QByteArray& contents) :
|
||||||
|
HeightfieldData(contents) {
|
||||||
|
}
|
||||||
|
|
||||||
|
HeightfieldHeightData::HeightfieldHeightData(Bitstream& in, int bytes) {
|
||||||
|
read(in, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
HeightfieldHeightData::HeightfieldHeightData(Bitstream& in, int bytes, const HeightfieldHeightDataPointer& reference) {
|
||||||
if (!reference) {
|
if (!reference) {
|
||||||
read(in, bytes, color);
|
read(in, bytes);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QMutexLocker locker(&reference->_encodedDeltaMutex);
|
QMutexLocker locker(&reference->getEncodedDeltaMutex());
|
||||||
reference->_encodedDelta = in.readAligned(bytes);
|
reference->setEncodedDelta(in.readAligned(bytes));
|
||||||
reference->_deltaData = this;
|
reference->setDeltaData(HeightfieldDataPointer(this));
|
||||||
_contents = reference->_contents;
|
_contents = reference->getContents();
|
||||||
QImage image = decodeHeightfieldImage(reference->_encodedDelta);
|
QImage image = decodeHeightfieldImage(reference->getEncodedDelta());
|
||||||
if (image.isNull()) {
|
if (image.isNull()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QPoint offset = image.offset();
|
QPoint offset = image.offset();
|
||||||
image = image.convertToFormat(QImage::Format_RGB888);
|
image = image.convertToFormat(QImage::Format_RGB888);
|
||||||
if (offset.x() == 0) {
|
if (offset.x() == 0) {
|
||||||
set(image, color);
|
set(image);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int minX = offset.x() - 1;
|
int minX = offset.x() - 1;
|
||||||
int minY = offset.y() - 1;
|
int minY = offset.y() - 1;
|
||||||
if (color) {
|
int size = glm::sqrt((float)_contents.size());
|
||||||
int size = glm::sqrt(_contents.size() / (float)COLOR_BYTES);
|
char* lineDest = _contents.data() + minY * size + minX;
|
||||||
char* dest = _contents.data() + (minY * size + minX) * COLOR_BYTES;
|
for (int y = 0; y < image.height(); y++) {
|
||||||
int destStride = size * COLOR_BYTES;
|
const uchar* src = image.constScanLine(y);
|
||||||
int srcStride = image.width() * COLOR_BYTES;
|
for (char* dest = lineDest, *end = dest + image.width(); dest != end; dest++, src += COLOR_BYTES) {
|
||||||
for (int y = 0; y < image.height(); y++) {
|
*dest = *src;
|
||||||
memcpy(dest, image.constScanLine(y), srcStride);
|
|
||||||
dest += destStride;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int size = glm::sqrt((float)_contents.size());
|
|
||||||
char* lineDest = _contents.data() + minY * size + minX;
|
|
||||||
for (int y = 0; y < image.height(); y++) {
|
|
||||||
const uchar* src = image.constScanLine(y);
|
|
||||||
for (char* dest = lineDest, *end = dest + image.width(); dest != end; dest++, src += COLOR_BYTES) {
|
|
||||||
*dest = *src;
|
|
||||||
}
|
|
||||||
lineDest += size;
|
|
||||||
}
|
}
|
||||||
|
lineDest += size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HeightfieldData::HeightfieldData(Bitstream& in, int bytes, const HeightfieldDataPointer& ancestor,
|
HeightfieldHeightData::HeightfieldHeightData(Bitstream& in, int bytes, const HeightfieldHeightDataPointer& ancestor,
|
||||||
const glm::vec3& minimum, float size, bool color) {
|
const glm::vec3& minimum, float size) {
|
||||||
QMutexLocker locker(&_encodedSubdivisionsMutex);
|
QMutexLocker locker(&_encodedSubdivisionsMutex);
|
||||||
int index = (int)glm::round(glm::log(size) / glm::log(0.5f)) - 1;
|
int index = (int)glm::round(glm::log(size) / glm::log(0.5f)) - 1;
|
||||||
if (_encodedSubdivisions.size() <= index) {
|
if (_encodedSubdivisions.size() <= index) {
|
||||||
|
@ -610,61 +607,35 @@ HeightfieldData::HeightfieldData(Bitstream& in, int bytes, const HeightfieldData
|
||||||
int destSize = image.width();
|
int destSize = image.width();
|
||||||
const uchar* src = image.constBits();
|
const uchar* src = image.constBits();
|
||||||
const QByteArray& ancestorContents = ancestor->getContents();
|
const QByteArray& ancestorContents = ancestor->getContents();
|
||||||
if (color) {
|
|
||||||
int ancestorSize = glm::sqrt(ancestorContents.size() / (float)COLOR_BYTES);
|
|
||||||
float ancestorY = minimum.z * ancestorSize;
|
|
||||||
float ancestorIncrement = size * ancestorSize / destSize;
|
|
||||||
int ancestorStride = ancestorSize * COLOR_BYTES;
|
|
||||||
|
|
||||||
_contents = QByteArray(destSize * destSize * COLOR_BYTES, 0);
|
int ancestorSize = glm::sqrt((float)ancestorContents.size());
|
||||||
char* dest = _contents.data();
|
float ancestorY = minimum.z * ancestorSize;
|
||||||
int stride = image.width() * COLOR_BYTES;
|
float ancestorIncrement = size * ancestorSize / destSize;
|
||||||
|
|
||||||
for (int y = 0; y < destSize; y++, ancestorY += ancestorIncrement) {
|
_contents = QByteArray(destSize * destSize, 0);
|
||||||
const uchar* lineRef = (const uchar*)ancestorContents.constData() + (int)ancestorY * ancestorStride;
|
char* dest = _contents.data();
|
||||||
float ancestorX = minimum.x * ancestorSize;
|
|
||||||
for (char* end = dest + stride; dest != end; ancestorX += ancestorIncrement) {
|
|
||||||
const uchar* ref = lineRef + (int)ancestorX * COLOR_BYTES;
|
|
||||||
*dest++ = *ref++ + *src++;
|
|
||||||
*dest++ = *ref++ + *src++;
|
|
||||||
*dest++ = *ref++ + *src++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int ancestorSize = glm::sqrt((float)ancestorContents.size());
|
|
||||||
float ancestorY = minimum.z * ancestorSize;
|
|
||||||
float ancestorIncrement = size * ancestorSize / destSize;
|
|
||||||
|
|
||||||
_contents = QByteArray(destSize * destSize, 0);
|
for (int y = 0; y < destSize; y++, ancestorY += ancestorIncrement) {
|
||||||
char* dest = _contents.data();
|
const uchar* lineRef = (const uchar*)ancestorContents.constData() + (int)ancestorY * ancestorSize;
|
||||||
|
float ancestorX = minimum.x * ancestorSize;
|
||||||
for (int y = 0; y < destSize; y++, ancestorY += ancestorIncrement) {
|
for (char* end = dest + destSize; dest != end; src += COLOR_BYTES, ancestorX += ancestorIncrement) {
|
||||||
const uchar* lineRef = (const uchar*)ancestorContents.constData() + (int)ancestorY * ancestorSize;
|
const uchar* ref = lineRef + (int)ancestorX;
|
||||||
float ancestorX = minimum.x * ancestorSize;
|
*dest++ = *ref++ + *src;
|
||||||
for (char* end = dest + destSize; dest != end; src += COLOR_BYTES, ancestorX += ancestorIncrement) {
|
|
||||||
const uchar* ref = lineRef + (int)ancestorX;
|
|
||||||
*dest++ = *ref++ + *src;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeightfieldData::write(Bitstream& out, bool color) {
|
void HeightfieldHeightData::write(Bitstream& out) {
|
||||||
QMutexLocker locker(&_encodedMutex);
|
QMutexLocker locker(&_encodedMutex);
|
||||||
if (_encoded.isEmpty()) {
|
if (_encoded.isEmpty()) {
|
||||||
QImage image;
|
QImage image;
|
||||||
if (color) {
|
int size = glm::sqrt((float)_contents.size());
|
||||||
int size = glm::sqrt(_contents.size() / (float)COLOR_BYTES);
|
image = QImage(size, size, QImage::Format_RGB888);
|
||||||
image = QImage((uchar*)_contents.data(), size, size, QImage::Format_RGB888);
|
uchar* dest = image.bits();
|
||||||
} else {
|
for (const char* src = _contents.constData(), *end = src + _contents.size(); src != end; src++) {
|
||||||
int size = glm::sqrt((float)_contents.size());
|
*dest++ = *src;
|
||||||
image = QImage(size, size, QImage::Format_RGB888);
|
*dest++ = *src;
|
||||||
uchar* dest = image.bits();
|
*dest++ = *src;
|
||||||
for (const char* src = _contents.constData(), *end = src + _contents.size(); src != end; src++) {
|
|
||||||
*dest++ = *src;
|
|
||||||
*dest++ = *src;
|
|
||||||
*dest++ = *src;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_encoded = encodeHeightfieldImage(image);
|
_encoded = encodeHeightfieldImage(image);
|
||||||
}
|
}
|
||||||
|
@ -672,95 +643,58 @@ void HeightfieldData::write(Bitstream& out, bool color) {
|
||||||
out.writeAligned(_encoded);
|
out.writeAligned(_encoded);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeightfieldData::writeDelta(Bitstream& out, const HeightfieldDataPointer& reference, bool color) {
|
void HeightfieldHeightData::writeDelta(Bitstream& out, const HeightfieldHeightDataPointer& reference) {
|
||||||
if (!reference || reference->getContents().size() != _contents.size()) {
|
if (!reference || reference->getContents().size() != _contents.size()) {
|
||||||
write(out, color);
|
write(out);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QMutexLocker locker(&reference->_encodedDeltaMutex);
|
QMutexLocker locker(&reference->getEncodedDeltaMutex());
|
||||||
if (reference->_encodedDelta.isEmpty() || reference->_deltaData != this) {
|
if (reference->getEncodedDelta().isEmpty() || reference->getDeltaData() != this) {
|
||||||
QImage image;
|
QImage image;
|
||||||
int minX, minY;
|
int size = glm::sqrt((float)_contents.size());
|
||||||
if (color) {
|
int minX = size, minY = size;
|
||||||
int size = glm::sqrt(_contents.size() / (float)COLOR_BYTES);
|
int maxX = -1, maxY = -1;
|
||||||
minX = size;
|
const char* src = _contents.constData();
|
||||||
minY = size;
|
const char* ref = reference->getContents().constData();
|
||||||
int maxX = -1, maxY = -1;
|
for (int y = 0; y < size; y++) {
|
||||||
const char* src = _contents.constData();
|
bool difference = false;
|
||||||
const char* ref = reference->_contents.constData();
|
for (int x = 0; x < size; x++) {
|
||||||
for (int y = 0; y < size; y++) {
|
if (*src++ != *ref++) {
|
||||||
bool difference = false;
|
minX = qMin(minX, x);
|
||||||
for (int x = 0; x < size; x++, src += COLOR_BYTES, ref += COLOR_BYTES) {
|
maxX = qMax(maxX, x);
|
||||||
if (src[0] != ref[0] || src[1] != ref[1] || src[2] != ref[2]) {
|
difference = true;
|
||||||
minX = qMin(minX, x);
|
|
||||||
maxX = qMax(maxX, x);
|
|
||||||
difference = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (difference) {
|
|
||||||
minY = qMin(minY, y);
|
|
||||||
maxY = qMax(maxY, y);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (maxX >= minX) {
|
if (difference) {
|
||||||
int width = maxX - minX + 1;
|
minY = qMin(minY, y);
|
||||||
int height = maxY - minY + 1;
|
maxY = qMax(maxY, y);
|
||||||
image = QImage(width, height, QImage::Format_RGB888);
|
|
||||||
src = _contents.constData() + (minY * size + minX) * COLOR_BYTES;
|
|
||||||
int srcStride = size * COLOR_BYTES;
|
|
||||||
int destStride = width * COLOR_BYTES;
|
|
||||||
for (int y = 0; y < height; y++) {
|
|
||||||
memcpy(image.scanLine(y), src, destStride);
|
|
||||||
src += srcStride;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
int size = glm::sqrt((float)_contents.size());
|
if (maxX >= minX) {
|
||||||
minX = size;
|
int width = qMax(maxX - minX + 1, 0);
|
||||||
minY = size;
|
int height = qMax(maxY - minY + 1, 0);
|
||||||
int maxX = -1, maxY = -1;
|
image = QImage(width, height, QImage::Format_RGB888);
|
||||||
const char* src = _contents.constData();
|
const uchar* lineSrc = (const uchar*)_contents.constData() + minY * size + minX;
|
||||||
const char* ref = reference->_contents.constData();
|
for (int y = 0; y < height; y++) {
|
||||||
for (int y = 0; y < size; y++) {
|
uchar* dest = image.scanLine(y);
|
||||||
bool difference = false;
|
for (const uchar* src = lineSrc, *end = src + width; src != end; src++) {
|
||||||
for (int x = 0; x < size; x++) {
|
*dest++ = *src;
|
||||||
if (*src++ != *ref++) {
|
*dest++ = *src;
|
||||||
minX = qMin(minX, x);
|
*dest++ = *src;
|
||||||
maxX = qMax(maxX, x);
|
|
||||||
difference = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (difference) {
|
|
||||||
minY = qMin(minY, y);
|
|
||||||
maxY = qMax(maxY, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (maxX >= minX) {
|
|
||||||
int width = qMax(maxX - minX + 1, 0);
|
|
||||||
int height = qMax(maxY - minY + 1, 0);
|
|
||||||
image = QImage(width, height, QImage::Format_RGB888);
|
|
||||||
const uchar* lineSrc = (const uchar*)_contents.constData() + minY * size + minX;
|
|
||||||
for (int y = 0; y < height; y++) {
|
|
||||||
uchar* dest = image.scanLine(y);
|
|
||||||
for (const uchar* src = lineSrc, *end = src + width; src != end; src++) {
|
|
||||||
*dest++ = *src;
|
|
||||||
*dest++ = *src;
|
|
||||||
*dest++ = *src;
|
|
||||||
}
|
|
||||||
lineSrc += size;
|
|
||||||
}
|
}
|
||||||
|
lineSrc += size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
image.setOffset(QPoint(minX + 1, minY + 1));
|
image.setOffset(QPoint(minX + 1, minY + 1));
|
||||||
reference->_encodedDelta = encodeHeightfieldImage(image);
|
reference->setEncodedDelta(encodeHeightfieldImage(image));
|
||||||
reference->_deltaData = this;
|
reference->setDeltaData(HeightfieldDataPointer(this));
|
||||||
}
|
}
|
||||||
out << reference->_encodedDelta.size();
|
out << reference->getEncodedDelta().size();
|
||||||
out.writeAligned(reference->_encodedDelta);
|
out.writeAligned(reference->getEncodedDelta());
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeightfieldData::writeSubdivided(Bitstream& out, const HeightfieldDataPointer& ancestor,
|
void HeightfieldHeightData::writeSubdivided(Bitstream& out, const HeightfieldHeightDataPointer& ancestor,
|
||||||
const glm::vec3& minimum, float size, bool color) {
|
const glm::vec3& minimum, float size) {
|
||||||
QMutexLocker locker(&_encodedSubdivisionsMutex);
|
QMutexLocker locker(&_encodedSubdivisionsMutex);
|
||||||
int index = (int)glm::round(glm::log(size) / glm::log(0.5f)) - 1;
|
int index = (int)glm::round(glm::log(size) / glm::log(0.5f)) - 1;
|
||||||
if (_encodedSubdivisions.size() <= index) {
|
if (_encodedSubdivisions.size() <= index) {
|
||||||
|
@ -771,46 +705,24 @@ void HeightfieldData::writeSubdivided(Bitstream& out, const HeightfieldDataPoint
|
||||||
QImage image;
|
QImage image;
|
||||||
const QByteArray& ancestorContents = ancestor->getContents();
|
const QByteArray& ancestorContents = ancestor->getContents();
|
||||||
const uchar* src = (const uchar*)_contents.constData();
|
const uchar* src = (const uchar*)_contents.constData();
|
||||||
if (color) {
|
|
||||||
int destSize = glm::sqrt(_contents.size() / (float)COLOR_BYTES);
|
|
||||||
image = QImage(destSize, destSize, QImage::Format_RGB888);
|
|
||||||
uchar* dest = image.bits();
|
|
||||||
int stride = destSize * COLOR_BYTES;
|
|
||||||
|
|
||||||
int ancestorSize = glm::sqrt(ancestorContents.size() / (float)COLOR_BYTES);
|
int destSize = glm::sqrt((float)_contents.size());
|
||||||
float ancestorY = minimum.z * ancestorSize;
|
image = QImage(destSize, destSize, QImage::Format_RGB888);
|
||||||
float ancestorIncrement = size * ancestorSize / destSize;
|
uchar* dest = image.bits();
|
||||||
int ancestorStride = ancestorSize * COLOR_BYTES;
|
|
||||||
|
|
||||||
for (int y = 0; y < destSize; y++, ancestorY += ancestorIncrement) {
|
int ancestorSize = glm::sqrt((float)ancestorContents.size());
|
||||||
const uchar* lineRef = (const uchar*)ancestorContents.constData() + (int)ancestorY * ancestorStride;
|
float ancestorY = minimum.z * ancestorSize;
|
||||||
float ancestorX = minimum.x * ancestorSize;
|
float ancestorIncrement = size * ancestorSize / destSize;
|
||||||
for (const uchar* end = src + stride; src != end; ancestorX += ancestorIncrement) {
|
|
||||||
const uchar* ref = lineRef + (int)ancestorX * COLOR_BYTES;
|
|
||||||
*dest++ = *src++ - *ref++;
|
|
||||||
*dest++ = *src++ - *ref++;
|
|
||||||
*dest++ = *src++ - *ref++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int destSize = glm::sqrt((float)_contents.size());
|
|
||||||
image = QImage(destSize, destSize, QImage::Format_RGB888);
|
|
||||||
uchar* dest = image.bits();
|
|
||||||
|
|
||||||
int ancestorSize = glm::sqrt((float)ancestorContents.size());
|
for (int y = 0; y < destSize; y++, ancestorY += ancestorIncrement) {
|
||||||
float ancestorY = minimum.z * ancestorSize;
|
const uchar* lineRef = (const uchar*)ancestorContents.constData() + (int)ancestorY * ancestorSize;
|
||||||
float ancestorIncrement = size * ancestorSize / destSize;
|
float ancestorX = minimum.x * ancestorSize;
|
||||||
|
for (const uchar* end = src + destSize; src != end; ancestorX += ancestorIncrement) {
|
||||||
for (int y = 0; y < destSize; y++, ancestorY += ancestorIncrement) {
|
const uchar* ref = lineRef + (int)ancestorX;
|
||||||
const uchar* lineRef = (const uchar*)ancestorContents.constData() + (int)ancestorY * ancestorSize;
|
uchar difference = *src++ - *ref;
|
||||||
float ancestorX = minimum.x * ancestorSize;
|
*dest++ = difference;
|
||||||
for (const uchar* end = src + destSize; src != end; ancestorX += ancestorIncrement) {
|
*dest++ = difference;
|
||||||
const uchar* ref = lineRef + (int)ancestorX;
|
*dest++ = difference;
|
||||||
uchar difference = *src++ - *ref;
|
|
||||||
*dest++ = difference;
|
|
||||||
*dest++ = difference;
|
|
||||||
*dest++ = difference;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
subdivision.data = encodeHeightfieldImage(image, true);
|
subdivision.data = encodeHeightfieldImage(image, true);
|
||||||
|
@ -820,27 +732,211 @@ void HeightfieldData::writeSubdivided(Bitstream& out, const HeightfieldDataPoint
|
||||||
out.writeAligned(subdivision.data);
|
out.writeAligned(subdivision.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeightfieldData::read(Bitstream& in, int bytes, bool color) {
|
void HeightfieldHeightData::read(Bitstream& in, int bytes) {
|
||||||
set(decodeHeightfieldImage(_encoded = in.readAligned(bytes)).convertToFormat(QImage::Format_RGB888), color);
|
set(decodeHeightfieldImage(_encoded = in.readAligned(bytes)).convertToFormat(QImage::Format_RGB888));
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeightfieldData::set(const QImage& image, bool color) {
|
void HeightfieldHeightData::set(const QImage& image) {
|
||||||
if (color) {
|
_contents.resize(image.width() * image.height());
|
||||||
_contents.resize(image.width() * image.height() * COLOR_BYTES);
|
char* dest = _contents.data();
|
||||||
memcpy(_contents.data(), image.constBits(), _contents.size());
|
for (const uchar* src = image.constBits(), *end = src + _contents.size() * COLOR_BYTES;
|
||||||
|
src != end; src += COLOR_BYTES) {
|
||||||
|
*dest++ = *src;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
HeightfieldColorData::HeightfieldColorData(const QByteArray& contents) :
|
||||||
_contents.resize(image.width() * image.height());
|
HeightfieldData(contents) {
|
||||||
char* dest = _contents.data();
|
}
|
||||||
for (const uchar* src = image.constBits(), *end = src + _contents.size() * COLOR_BYTES;
|
|
||||||
src != end; src += COLOR_BYTES) {
|
HeightfieldColorData::HeightfieldColorData(Bitstream& in, int bytes) {
|
||||||
*dest++ = *src;
|
read(in, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
HeightfieldColorData::HeightfieldColorData(Bitstream& in, int bytes, const HeightfieldColorDataPointer& reference) {
|
||||||
|
if (!reference) {
|
||||||
|
read(in, bytes);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QMutexLocker locker(&reference->getEncodedDeltaMutex());
|
||||||
|
reference->setEncodedDelta(in.readAligned(bytes));
|
||||||
|
reference->setDeltaData(HeightfieldDataPointer(this));
|
||||||
|
_contents = reference->getContents();
|
||||||
|
QImage image = decodeHeightfieldImage(reference->getEncodedDelta());
|
||||||
|
if (image.isNull()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QPoint offset = image.offset();
|
||||||
|
image = image.convertToFormat(QImage::Format_RGB888);
|
||||||
|
if (offset.x() == 0) {
|
||||||
|
set(image);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int minX = offset.x() - 1;
|
||||||
|
int minY = offset.y() - 1;
|
||||||
|
int size = glm::sqrt(_contents.size() / (float)COLOR_BYTES);
|
||||||
|
char* dest = _contents.data() + (minY * size + minX) * COLOR_BYTES;
|
||||||
|
int destStride = size * COLOR_BYTES;
|
||||||
|
int srcStride = image.width() * COLOR_BYTES;
|
||||||
|
for (int y = 0; y < image.height(); y++) {
|
||||||
|
memcpy(dest, image.constScanLine(y), srcStride);
|
||||||
|
dest += destStride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HeightfieldColorData::HeightfieldColorData(Bitstream& in, int bytes, const HeightfieldColorDataPointer& ancestor,
|
||||||
|
const glm::vec3& minimum, float size) {
|
||||||
|
QMutexLocker locker(&_encodedSubdivisionsMutex);
|
||||||
|
int index = (int)glm::round(glm::log(size) / glm::log(0.5f)) - 1;
|
||||||
|
if (_encodedSubdivisions.size() <= index) {
|
||||||
|
_encodedSubdivisions.resize(index + 1);
|
||||||
|
}
|
||||||
|
EncodedSubdivision& subdivision = _encodedSubdivisions[index];
|
||||||
|
subdivision.data = in.readAligned(bytes);
|
||||||
|
subdivision.ancestor = ancestor;
|
||||||
|
QImage image = decodeHeightfieldImage(subdivision.data);
|
||||||
|
if (image.isNull()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
image = image.convertToFormat(QImage::Format_RGB888);
|
||||||
|
int destSize = image.width();
|
||||||
|
const uchar* src = image.constBits();
|
||||||
|
const QByteArray& ancestorContents = ancestor->getContents();
|
||||||
|
|
||||||
|
int ancestorSize = glm::sqrt(ancestorContents.size() / (float)COLOR_BYTES);
|
||||||
|
float ancestorY = minimum.z * ancestorSize;
|
||||||
|
float ancestorIncrement = size * ancestorSize / destSize;
|
||||||
|
int ancestorStride = ancestorSize * COLOR_BYTES;
|
||||||
|
|
||||||
|
_contents = QByteArray(destSize * destSize * COLOR_BYTES, 0);
|
||||||
|
char* dest = _contents.data();
|
||||||
|
int stride = image.width() * COLOR_BYTES;
|
||||||
|
|
||||||
|
for (int y = 0; y < destSize; y++, ancestorY += ancestorIncrement) {
|
||||||
|
const uchar* lineRef = (const uchar*)ancestorContents.constData() + (int)ancestorY * ancestorStride;
|
||||||
|
float ancestorX = minimum.x * ancestorSize;
|
||||||
|
for (char* end = dest + stride; dest != end; ancestorX += ancestorIncrement) {
|
||||||
|
const uchar* ref = lineRef + (int)ancestorX * COLOR_BYTES;
|
||||||
|
*dest++ = *ref++ + *src++;
|
||||||
|
*dest++ = *ref++ + *src++;
|
||||||
|
*dest++ = *ref++ + *src++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HeightfieldColorData::write(Bitstream& out) {
|
||||||
|
QMutexLocker locker(&_encodedMutex);
|
||||||
|
if (_encoded.isEmpty()) {
|
||||||
|
QImage image;
|
||||||
|
int size = glm::sqrt(_contents.size() / (float)COLOR_BYTES);
|
||||||
|
image = QImage((uchar*)_contents.data(), size, size, QImage::Format_RGB888);
|
||||||
|
_encoded = encodeHeightfieldImage(image);
|
||||||
|
}
|
||||||
|
out << _encoded.size();
|
||||||
|
out.writeAligned(_encoded);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeightfieldColorData::writeDelta(Bitstream& out, const HeightfieldColorDataPointer& reference) {
|
||||||
|
if (!reference || reference->getContents().size() != _contents.size()) {
|
||||||
|
write(out);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QMutexLocker locker(&reference->getEncodedDeltaMutex());
|
||||||
|
if (reference->getEncodedDelta().isEmpty() || reference->getDeltaData() != this) {
|
||||||
|
QImage image;
|
||||||
|
int size = glm::sqrt(_contents.size() / (float)COLOR_BYTES);
|
||||||
|
int minX = size, minY = size;
|
||||||
|
int maxX = -1, maxY = -1;
|
||||||
|
const char* src = _contents.constData();
|
||||||
|
const char* ref = reference->getContents().constData();
|
||||||
|
for (int y = 0; y < size; y++) {
|
||||||
|
bool difference = false;
|
||||||
|
for (int x = 0; x < size; x++, src += COLOR_BYTES, ref += COLOR_BYTES) {
|
||||||
|
if (src[0] != ref[0] || src[1] != ref[1] || src[2] != ref[2]) {
|
||||||
|
minX = qMin(minX, x);
|
||||||
|
maxX = qMax(maxX, x);
|
||||||
|
difference = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (difference) {
|
||||||
|
minY = qMin(minY, y);
|
||||||
|
maxY = qMax(maxY, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (maxX >= minX) {
|
||||||
|
int width = maxX - minX + 1;
|
||||||
|
int height = maxY - minY + 1;
|
||||||
|
image = QImage(width, height, QImage::Format_RGB888);
|
||||||
|
src = _contents.constData() + (minY * size + minX) * COLOR_BYTES;
|
||||||
|
int srcStride = size * COLOR_BYTES;
|
||||||
|
int destStride = width * COLOR_BYTES;
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
memcpy(image.scanLine(y), src, destStride);
|
||||||
|
src += srcStride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
image.setOffset(QPoint(minX + 1, minY + 1));
|
||||||
|
reference->setEncodedDelta(encodeHeightfieldImage(image));
|
||||||
|
reference->setDeltaData(HeightfieldDataPointer(this));
|
||||||
|
}
|
||||||
|
out << reference->getEncodedDelta().size();
|
||||||
|
out.writeAligned(reference->getEncodedDelta());
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeightfieldColorData::writeSubdivided(Bitstream& out, const HeightfieldColorDataPointer& ancestor,
|
||||||
|
const glm::vec3& minimum, float size) {
|
||||||
|
QMutexLocker locker(&_encodedSubdivisionsMutex);
|
||||||
|
int index = (int)glm::round(glm::log(size) / glm::log(0.5f)) - 1;
|
||||||
|
if (_encodedSubdivisions.size() <= index) {
|
||||||
|
_encodedSubdivisions.resize(index + 1);
|
||||||
|
}
|
||||||
|
EncodedSubdivision& subdivision = _encodedSubdivisions[index];
|
||||||
|
if (subdivision.data.isEmpty() || subdivision.ancestor != ancestor) {
|
||||||
|
QImage image;
|
||||||
|
const QByteArray& ancestorContents = ancestor->getContents();
|
||||||
|
const uchar* src = (const uchar*)_contents.constData();
|
||||||
|
|
||||||
|
int destSize = glm::sqrt(_contents.size() / (float)COLOR_BYTES);
|
||||||
|
image = QImage(destSize, destSize, QImage::Format_RGB888);
|
||||||
|
uchar* dest = image.bits();
|
||||||
|
int stride = destSize * COLOR_BYTES;
|
||||||
|
|
||||||
|
int ancestorSize = glm::sqrt(ancestorContents.size() / (float)COLOR_BYTES);
|
||||||
|
float ancestorY = minimum.z * ancestorSize;
|
||||||
|
float ancestorIncrement = size * ancestorSize / destSize;
|
||||||
|
int ancestorStride = ancestorSize * COLOR_BYTES;
|
||||||
|
|
||||||
|
for (int y = 0; y < destSize; y++, ancestorY += ancestorIncrement) {
|
||||||
|
const uchar* lineRef = (const uchar*)ancestorContents.constData() + (int)ancestorY * ancestorStride;
|
||||||
|
float ancestorX = minimum.x * ancestorSize;
|
||||||
|
for (const uchar* end = src + stride; src != end; ancestorX += ancestorIncrement) {
|
||||||
|
const uchar* ref = lineRef + (int)ancestorX * COLOR_BYTES;
|
||||||
|
*dest++ = *src++ - *ref++;
|
||||||
|
*dest++ = *src++ - *ref++;
|
||||||
|
*dest++ = *src++ - *ref++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
subdivision.data = encodeHeightfieldImage(image, true);
|
||||||
|
subdivision.ancestor = ancestor;
|
||||||
|
}
|
||||||
|
out << subdivision.data.size();
|
||||||
|
out.writeAligned(subdivision.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeightfieldColorData::read(Bitstream& in, int bytes) {
|
||||||
|
set(decodeHeightfieldImage(_encoded = in.readAligned(bytes)).convertToFormat(QImage::Format_RGB888));
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeightfieldColorData::set(const QImage& image) {
|
||||||
|
_contents.resize(image.width() * image.height() * COLOR_BYTES);
|
||||||
|
memcpy(_contents.data(), image.constBits(), _contents.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
HeightfieldTexture::HeightfieldTexture() {
|
||||||
|
}
|
||||||
|
|
||||||
HeightfieldAttribute::HeightfieldAttribute(const QString& name) :
|
HeightfieldAttribute::HeightfieldAttribute(const QString& name) :
|
||||||
InlineAttribute<HeightfieldDataPointer>(name) {
|
InlineAttribute<HeightfieldHeightDataPointer>(name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeightfieldAttribute::read(Bitstream& in, void*& value, bool isLeaf) const {
|
void HeightfieldAttribute::read(Bitstream& in, void*& value, bool isLeaf) const {
|
||||||
|
@ -850,9 +946,9 @@ void HeightfieldAttribute::read(Bitstream& in, void*& value, bool isLeaf) const
|
||||||
int size;
|
int size;
|
||||||
in >> size;
|
in >> size;
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
*(HeightfieldDataPointer*)&value = HeightfieldDataPointer();
|
*(HeightfieldHeightDataPointer*)&value = HeightfieldHeightDataPointer();
|
||||||
} else {
|
} else {
|
||||||
*(HeightfieldDataPointer*)&value = HeightfieldDataPointer(new HeightfieldData(in, size, false));
|
*(HeightfieldHeightDataPointer*)&value = HeightfieldHeightDataPointer(new HeightfieldHeightData(in, size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -860,9 +956,9 @@ void HeightfieldAttribute::write(Bitstream& out, void* value, bool isLeaf) const
|
||||||
if (!isLeaf) {
|
if (!isLeaf) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HeightfieldDataPointer data = decodeInline<HeightfieldDataPointer>(value);
|
HeightfieldHeightDataPointer data = decodeInline<HeightfieldHeightDataPointer>(value);
|
||||||
if (data) {
|
if (data) {
|
||||||
data->write(out, false);
|
data->write(out);
|
||||||
} else {
|
} else {
|
||||||
out << 0;
|
out << 0;
|
||||||
}
|
}
|
||||||
|
@ -875,10 +971,10 @@ void HeightfieldAttribute::readDelta(Bitstream& in, void*& value, void* referenc
|
||||||
int size;
|
int size;
|
||||||
in >> size;
|
in >> size;
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
*(HeightfieldDataPointer*)&value = HeightfieldDataPointer();
|
*(HeightfieldHeightDataPointer*)&value = HeightfieldHeightDataPointer();
|
||||||
} else {
|
} else {
|
||||||
*(HeightfieldDataPointer*)&value = HeightfieldDataPointer(new HeightfieldData(
|
*(HeightfieldHeightDataPointer*)&value = HeightfieldHeightDataPointer(new HeightfieldHeightData(
|
||||||
in, size, decodeInline<HeightfieldDataPointer>(reference), false));
|
in, size, decodeInline<HeightfieldHeightDataPointer>(reference)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -886,9 +982,9 @@ void HeightfieldAttribute::writeDelta(Bitstream& out, void* value, void* referen
|
||||||
if (!isLeaf) {
|
if (!isLeaf) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HeightfieldDataPointer data = decodeInline<HeightfieldDataPointer>(value);
|
HeightfieldHeightDataPointer data = decodeInline<HeightfieldHeightDataPointer>(value);
|
||||||
if (data) {
|
if (data) {
|
||||||
data->writeDelta(out, decodeInline<HeightfieldDataPointer>(reference), false);
|
data->writeDelta(out, decodeInline<HeightfieldHeightDataPointer>(reference));
|
||||||
} else {
|
} else {
|
||||||
out << 0;
|
out << 0;
|
||||||
}
|
}
|
||||||
|
@ -897,20 +993,20 @@ void HeightfieldAttribute::writeDelta(Bitstream& out, void* value, void* referen
|
||||||
bool HeightfieldAttribute::merge(void*& parent, void* children[], bool postRead) const {
|
bool HeightfieldAttribute::merge(void*& parent, void* children[], bool postRead) const {
|
||||||
int maxSize = 0;
|
int maxSize = 0;
|
||||||
for (int i = 0; i < MERGE_COUNT; i++) {
|
for (int i = 0; i < MERGE_COUNT; i++) {
|
||||||
HeightfieldDataPointer pointer = decodeInline<HeightfieldDataPointer>(children[i]);
|
HeightfieldHeightDataPointer pointer = decodeInline<HeightfieldHeightDataPointer>(children[i]);
|
||||||
if (pointer) {
|
if (pointer) {
|
||||||
maxSize = qMax(maxSize, pointer->getContents().size());
|
maxSize = qMax(maxSize, pointer->getContents().size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (maxSize == 0) {
|
if (maxSize == 0) {
|
||||||
*(HeightfieldDataPointer*)&parent = HeightfieldDataPointer();
|
*(HeightfieldHeightDataPointer*)&parent = HeightfieldHeightDataPointer();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
int size = glm::sqrt((float)maxSize);
|
int size = glm::sqrt((float)maxSize);
|
||||||
QByteArray contents(size * size, 0);
|
QByteArray contents(size * size, 0);
|
||||||
int halfSize = size / 2;
|
int halfSize = size / 2;
|
||||||
for (int i = 0; i < MERGE_COUNT; i++) {
|
for (int i = 0; i < MERGE_COUNT; i++) {
|
||||||
HeightfieldDataPointer child = decodeInline<HeightfieldDataPointer>(children[i]);
|
HeightfieldHeightDataPointer child = decodeInline<HeightfieldHeightDataPointer>(children[i]);
|
||||||
if (!child) {
|
if (!child) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -920,7 +1016,7 @@ bool HeightfieldAttribute::merge(void*& parent, void* children[], bool postRead)
|
||||||
int xIndex = i & INDEX_MASK;
|
int xIndex = i & INDEX_MASK;
|
||||||
const int Y_SHIFT = 1;
|
const int Y_SHIFT = 1;
|
||||||
int yIndex = (i >> Y_SHIFT) & INDEX_MASK;
|
int yIndex = (i >> Y_SHIFT) & INDEX_MASK;
|
||||||
if (yIndex == 0 && decodeInline<HeightfieldDataPointer>(children[i | (1 << Y_SHIFT)])) {
|
if (yIndex == 0 && decodeInline<HeightfieldHeightDataPointer>(children[i | (1 << Y_SHIFT)])) {
|
||||||
continue; // bottom is overriden by top
|
continue; // bottom is overriden by top
|
||||||
}
|
}
|
||||||
const int HALF_RANGE = 128;
|
const int HALF_RANGE = 128;
|
||||||
|
@ -959,12 +1055,12 @@ bool HeightfieldAttribute::merge(void*& parent, void* children[], bool postRead)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*(HeightfieldDataPointer*)&parent = HeightfieldDataPointer(new HeightfieldData(contents));
|
*(HeightfieldHeightDataPointer*)&parent = HeightfieldHeightDataPointer(new HeightfieldHeightData(contents));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
HeightfieldColorAttribute::HeightfieldColorAttribute(const QString& name) :
|
HeightfieldColorAttribute::HeightfieldColorAttribute(const QString& name) :
|
||||||
InlineAttribute<HeightfieldDataPointer>(name) {
|
InlineAttribute<HeightfieldColorDataPointer>(name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeightfieldColorAttribute::read(Bitstream& in, void*& value, bool isLeaf) const {
|
void HeightfieldColorAttribute::read(Bitstream& in, void*& value, bool isLeaf) const {
|
||||||
|
@ -974,9 +1070,9 @@ void HeightfieldColorAttribute::read(Bitstream& in, void*& value, bool isLeaf) c
|
||||||
int size;
|
int size;
|
||||||
in >> size;
|
in >> size;
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
*(HeightfieldDataPointer*)&value = HeightfieldDataPointer();
|
*(HeightfieldColorDataPointer*)&value = HeightfieldColorDataPointer();
|
||||||
} else {
|
} else {
|
||||||
*(HeightfieldDataPointer*)&value = HeightfieldDataPointer(new HeightfieldData(in, size, true));
|
*(HeightfieldColorDataPointer*)&value = HeightfieldColorDataPointer(new HeightfieldColorData(in, size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -984,9 +1080,9 @@ void HeightfieldColorAttribute::write(Bitstream& out, void* value, bool isLeaf)
|
||||||
if (!isLeaf) {
|
if (!isLeaf) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HeightfieldDataPointer data = decodeInline<HeightfieldDataPointer>(value);
|
HeightfieldColorDataPointer data = decodeInline<HeightfieldColorDataPointer>(value);
|
||||||
if (data) {
|
if (data) {
|
||||||
data->write(out, true);
|
data->write(out);
|
||||||
} else {
|
} else {
|
||||||
out << 0;
|
out << 0;
|
||||||
}
|
}
|
||||||
|
@ -999,10 +1095,10 @@ void HeightfieldColorAttribute::readDelta(Bitstream& in, void*& value, void* ref
|
||||||
int size;
|
int size;
|
||||||
in >> size;
|
in >> size;
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
*(HeightfieldDataPointer*)&value = HeightfieldDataPointer();
|
*(HeightfieldColorDataPointer*)&value = HeightfieldColorDataPointer();
|
||||||
} else {
|
} else {
|
||||||
*(HeightfieldDataPointer*)&value = HeightfieldDataPointer(new HeightfieldData(
|
*(HeightfieldColorDataPointer*)&value = HeightfieldColorDataPointer(new HeightfieldColorData(
|
||||||
in, size, decodeInline<HeightfieldDataPointer>(reference), true));
|
in, size, decodeInline<HeightfieldColorDataPointer>(reference)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1010,9 +1106,9 @@ void HeightfieldColorAttribute::writeDelta(Bitstream& out, void* value, void* re
|
||||||
if (!isLeaf) {
|
if (!isLeaf) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HeightfieldDataPointer data = decodeInline<HeightfieldDataPointer>(value);
|
HeightfieldColorDataPointer data = decodeInline<HeightfieldColorDataPointer>(value);
|
||||||
if (data) {
|
if (data) {
|
||||||
data->writeDelta(out, decodeInline<HeightfieldDataPointer>(reference), true);
|
data->writeDelta(out, decodeInline<HeightfieldColorDataPointer>(reference));
|
||||||
} else {
|
} else {
|
||||||
out << 0;
|
out << 0;
|
||||||
}
|
}
|
||||||
|
@ -1021,20 +1117,20 @@ void HeightfieldColorAttribute::writeDelta(Bitstream& out, void* value, void* re
|
||||||
bool HeightfieldColorAttribute::merge(void*& parent, void* children[], bool postRead) const {
|
bool HeightfieldColorAttribute::merge(void*& parent, void* children[], bool postRead) const {
|
||||||
int maxSize = 0;
|
int maxSize = 0;
|
||||||
for (int i = 0; i < MERGE_COUNT; i++) {
|
for (int i = 0; i < MERGE_COUNT; i++) {
|
||||||
HeightfieldDataPointer pointer = decodeInline<HeightfieldDataPointer>(children[i]);
|
HeightfieldColorDataPointer pointer = decodeInline<HeightfieldColorDataPointer>(children[i]);
|
||||||
if (pointer) {
|
if (pointer) {
|
||||||
maxSize = qMax(maxSize, pointer->getContents().size());
|
maxSize = qMax(maxSize, pointer->getContents().size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (maxSize == 0) {
|
if (maxSize == 0) {
|
||||||
*(HeightfieldDataPointer*)&parent = HeightfieldDataPointer();
|
*(HeightfieldColorDataPointer*)&parent = HeightfieldColorDataPointer();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
int size = glm::sqrt(maxSize / (float)HeightfieldData::COLOR_BYTES);
|
int size = glm::sqrt(maxSize / (float)HeightfieldData::COLOR_BYTES);
|
||||||
QByteArray contents(size * size * HeightfieldData::COLOR_BYTES, 0);
|
QByteArray contents(size * size * HeightfieldData::COLOR_BYTES, 0);
|
||||||
int halfSize = size / 2;
|
int halfSize = size / 2;
|
||||||
for (int i = 0; i < MERGE_COUNT; i++) {
|
for (int i = 0; i < MERGE_COUNT; i++) {
|
||||||
HeightfieldDataPointer child = decodeInline<HeightfieldDataPointer>(children[i]);
|
HeightfieldColorDataPointer child = decodeInline<HeightfieldColorDataPointer>(children[i]);
|
||||||
if (!child) {
|
if (!child) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1044,7 +1140,7 @@ bool HeightfieldColorAttribute::merge(void*& parent, void* children[], bool post
|
||||||
int xIndex = i & INDEX_MASK;
|
int xIndex = i & INDEX_MASK;
|
||||||
const int Y_SHIFT = 1;
|
const int Y_SHIFT = 1;
|
||||||
int yIndex = (i >> Y_SHIFT) & INDEX_MASK;
|
int yIndex = (i >> Y_SHIFT) & INDEX_MASK;
|
||||||
if (yIndex == 0 && decodeInline<HeightfieldDataPointer>(children[i | (1 << Y_SHIFT)])) {
|
if (yIndex == 0 && decodeInline<HeightfieldColorDataPointer>(children[i | (1 << Y_SHIFT)])) {
|
||||||
continue; // bottom is overriden by top
|
continue; // bottom is overriden by top
|
||||||
}
|
}
|
||||||
int Z_SHIFT = 2;
|
int Z_SHIFT = 2;
|
||||||
|
@ -1098,7 +1194,7 @@ bool HeightfieldColorAttribute::merge(void*& parent, void* children[], bool post
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*(HeightfieldDataPointer*)&parent = HeightfieldDataPointer(new HeightfieldData(contents));
|
*(HeightfieldColorDataPointer*)&parent = HeightfieldColorDataPointer(new HeightfieldColorData(contents));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <QReadWriteLock>
|
#include <QReadWriteLock>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <QUrl>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
#include "Bitstream.h"
|
#include "Bitstream.h"
|
||||||
|
@ -28,7 +29,9 @@ class QScriptEngine;
|
||||||
class QScriptValue;
|
class QScriptValue;
|
||||||
|
|
||||||
class Attribute;
|
class Attribute;
|
||||||
|
class HeightfieldColorData;
|
||||||
class HeightfieldData;
|
class HeightfieldData;
|
||||||
|
class HeightfieldHeightData;
|
||||||
class MetavoxelData;
|
class MetavoxelData;
|
||||||
class MetavoxelLOD;
|
class MetavoxelLOD;
|
||||||
class MetavoxelNode;
|
class MetavoxelNode;
|
||||||
|
@ -439,23 +442,20 @@ public:
|
||||||
|
|
||||||
static const int COLOR_BYTES = 3;
|
static const int COLOR_BYTES = 3;
|
||||||
|
|
||||||
HeightfieldData(const QByteArray& contents);
|
HeightfieldData(const QByteArray& contents = QByteArray());
|
||||||
HeightfieldData(Bitstream& in, int bytes, bool color);
|
virtual ~HeightfieldData();
|
||||||
HeightfieldData(Bitstream& in, int bytes, const HeightfieldDataPointer& reference, bool color);
|
|
||||||
HeightfieldData(Bitstream& in, int bytes, const HeightfieldDataPointer& ancestor,
|
|
||||||
const glm::vec3& minimum, float size, bool color);
|
|
||||||
|
|
||||||
const QByteArray& getContents() const { return _contents; }
|
const QByteArray& getContents() const { return _contents; }
|
||||||
|
|
||||||
void write(Bitstream& out, bool color);
|
void setDeltaData(const HeightfieldDataPointer& deltaData) { _deltaData = deltaData; }
|
||||||
void writeDelta(Bitstream& out, const HeightfieldDataPointer& reference, bool color);
|
const HeightfieldDataPointer& getDeltaData() const { return _deltaData; }
|
||||||
void writeSubdivided(Bitstream& out, const HeightfieldDataPointer& ancestor,
|
|
||||||
const glm::vec3& minimum, float size, bool color);
|
|
||||||
|
|
||||||
private:
|
void setEncodedDelta(const QByteArray& encodedDelta) { _encodedDelta = encodedDelta; }
|
||||||
|
const QByteArray& getEncodedDelta() const { return _encodedDelta; }
|
||||||
|
|
||||||
void read(Bitstream& in, int bytes, bool color);
|
QMutex& getEncodedDeltaMutex() { return _encodedDeltaMutex; }
|
||||||
void set(const QImage& image, bool color);
|
|
||||||
|
protected:
|
||||||
|
|
||||||
QByteArray _contents;
|
QByteArray _contents;
|
||||||
QByteArray _encoded;
|
QByteArray _encoded;
|
||||||
|
@ -474,8 +474,70 @@ private:
|
||||||
QMutex _encodedSubdivisionsMutex;
|
QMutex _encodedSubdivisionsMutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef QExplicitlySharedDataPointer<HeightfieldHeightData> HeightfieldHeightDataPointer;
|
||||||
|
|
||||||
|
/// Contains a block of heightfield height data.
|
||||||
|
class HeightfieldHeightData : public HeightfieldData {
|
||||||
|
public:
|
||||||
|
|
||||||
|
HeightfieldHeightData(const QByteArray& contents);
|
||||||
|
HeightfieldHeightData(Bitstream& in, int bytes);
|
||||||
|
HeightfieldHeightData(Bitstream& in, int bytes, const HeightfieldHeightDataPointer& reference);
|
||||||
|
HeightfieldHeightData(Bitstream& in, int bytes, const HeightfieldHeightDataPointer& ancestor,
|
||||||
|
const glm::vec3& minimum, float size);
|
||||||
|
|
||||||
|
void write(Bitstream& out);
|
||||||
|
void writeDelta(Bitstream& out, const HeightfieldHeightDataPointer& reference);
|
||||||
|
void writeSubdivided(Bitstream& out, const HeightfieldHeightDataPointer& ancestor,
|
||||||
|
const glm::vec3& minimum, float size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void read(Bitstream& in, int bytes);
|
||||||
|
void set(const QImage& image);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef QExplicitlySharedDataPointer<HeightfieldColorData> HeightfieldColorDataPointer;
|
||||||
|
|
||||||
|
/// Contains a block of heightfield color data.
|
||||||
|
class HeightfieldColorData : public HeightfieldData {
|
||||||
|
public:
|
||||||
|
|
||||||
|
HeightfieldColorData(const QByteArray& contents);
|
||||||
|
HeightfieldColorData(Bitstream& in, int bytes);
|
||||||
|
HeightfieldColorData(Bitstream& in, int bytes, const HeightfieldColorDataPointer& reference);
|
||||||
|
HeightfieldColorData(Bitstream& in, int bytes, const HeightfieldColorDataPointer& ancestor,
|
||||||
|
const glm::vec3& minimum, float size);
|
||||||
|
|
||||||
|
void write(Bitstream& out);
|
||||||
|
void writeDelta(Bitstream& out, const HeightfieldColorDataPointer& reference);
|
||||||
|
void writeSubdivided(Bitstream& out, const HeightfieldColorDataPointer& ancestor,
|
||||||
|
const glm::vec3& minimum, float size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void read(Bitstream& in, int bytes);
|
||||||
|
void set(const QImage& image);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Contains the description of a heightfield texture.
|
||||||
|
class HeightfieldTexture : public SharedObject {
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QUrl url MEMBER _url)
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Q_INVOKABLE HeightfieldTexture();
|
||||||
|
|
||||||
|
const QUrl& getURL() const { return _url; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
QUrl _url;
|
||||||
|
};
|
||||||
|
|
||||||
/// An attribute that stores heightfield data.
|
/// An attribute that stores heightfield data.
|
||||||
class HeightfieldAttribute : public InlineAttribute<HeightfieldDataPointer> {
|
class HeightfieldAttribute : public InlineAttribute<HeightfieldHeightDataPointer> {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -492,7 +554,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
/// An attribute that stores heightfield colors.
|
/// An attribute that stores heightfield colors.
|
||||||
class HeightfieldColorAttribute : public InlineAttribute<HeightfieldDataPointer> {
|
class HeightfieldColorAttribute : public InlineAttribute<HeightfieldColorDataPointer> {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -354,7 +354,7 @@ int PaintHeightfieldHeightEditVisitor::visit(MetavoxelInfo& info) {
|
||||||
if (!info.isLeaf) {
|
if (!info.isLeaf) {
|
||||||
return DEFAULT_ORDER;
|
return DEFAULT_ORDER;
|
||||||
}
|
}
|
||||||
HeightfieldDataPointer pointer = info.inputValues.at(0).getInlineValue<HeightfieldDataPointer>();
|
HeightfieldHeightDataPointer pointer = info.inputValues.at(0).getInlineValue<HeightfieldHeightDataPointer>();
|
||||||
if (!pointer) {
|
if (!pointer) {
|
||||||
return STOP_RECURSION;
|
return STOP_RECURSION;
|
||||||
}
|
}
|
||||||
|
@ -396,8 +396,8 @@ int PaintHeightfieldHeightEditVisitor::visit(MetavoxelInfo& info) {
|
||||||
lineDest += size;
|
lineDest += size;
|
||||||
}
|
}
|
||||||
if (changed) {
|
if (changed) {
|
||||||
HeightfieldDataPointer newPointer(new HeightfieldData(contents));
|
HeightfieldHeightDataPointer newPointer(new HeightfieldHeightData(contents));
|
||||||
info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline<HeightfieldDataPointer>(newPointer));
|
info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline<HeightfieldHeightDataPointer>(newPointer));
|
||||||
}
|
}
|
||||||
return STOP_RECURSION;
|
return STOP_RECURSION;
|
||||||
}
|
}
|
||||||
|
@ -442,7 +442,7 @@ int PaintHeightfieldColorEditVisitor::visit(MetavoxelInfo& info) {
|
||||||
if (!info.isLeaf) {
|
if (!info.isLeaf) {
|
||||||
return DEFAULT_ORDER;
|
return DEFAULT_ORDER;
|
||||||
}
|
}
|
||||||
HeightfieldDataPointer pointer = info.inputValues.at(0).getInlineValue<HeightfieldDataPointer>();
|
HeightfieldColorDataPointer pointer = info.inputValues.at(0).getInlineValue<HeightfieldColorDataPointer>();
|
||||||
if (!pointer) {
|
if (!pointer) {
|
||||||
return STOP_RECURSION;
|
return STOP_RECURSION;
|
||||||
}
|
}
|
||||||
|
@ -481,8 +481,8 @@ int PaintHeightfieldColorEditVisitor::visit(MetavoxelInfo& info) {
|
||||||
lineDest += stride;
|
lineDest += stride;
|
||||||
}
|
}
|
||||||
if (changed) {
|
if (changed) {
|
||||||
HeightfieldDataPointer newPointer(new HeightfieldData(contents));
|
HeightfieldColorDataPointer newPointer(new HeightfieldColorData(contents));
|
||||||
info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline<HeightfieldDataPointer>(newPointer));
|
info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline<HeightfieldColorDataPointer>(newPointer));
|
||||||
}
|
}
|
||||||
return STOP_RECURSION;
|
return STOP_RECURSION;
|
||||||
}
|
}
|
||||||
|
@ -493,10 +493,10 @@ void PaintHeightfieldColorEdit::apply(MetavoxelData& data, const WeakSharedObjec
|
||||||
}
|
}
|
||||||
|
|
||||||
PaintHeightfieldTextureEdit::PaintHeightfieldTextureEdit(const glm::vec3& position, float radius,
|
PaintHeightfieldTextureEdit::PaintHeightfieldTextureEdit(const glm::vec3& position, float radius,
|
||||||
const QUrl& url, const QColor& averageColor) :
|
const SharedObjectPointer& texture, const QColor& averageColor) :
|
||||||
position(position),
|
position(position),
|
||||||
radius(radius),
|
radius(radius),
|
||||||
url(url),
|
texture(texture),
|
||||||
averageColor(averageColor) {
|
averageColor(averageColor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,7 +531,7 @@ int PaintHeightfieldTextureEditVisitor::visit(MetavoxelInfo& info) {
|
||||||
if (!info.isLeaf) {
|
if (!info.isLeaf) {
|
||||||
return DEFAULT_ORDER;
|
return DEFAULT_ORDER;
|
||||||
}
|
}
|
||||||
HeightfieldDataPointer pointer = info.inputValues.at(1).getInlineValue<HeightfieldDataPointer>();
|
HeightfieldColorDataPointer pointer = info.inputValues.at(1).getInlineValue<HeightfieldColorDataPointer>();
|
||||||
if (!pointer) {
|
if (!pointer) {
|
||||||
return STOP_RECURSION;
|
return STOP_RECURSION;
|
||||||
}
|
}
|
||||||
|
@ -570,8 +570,8 @@ int PaintHeightfieldTextureEditVisitor::visit(MetavoxelInfo& info) {
|
||||||
lineDest += stride;
|
lineDest += stride;
|
||||||
}
|
}
|
||||||
if (changed) {
|
if (changed) {
|
||||||
HeightfieldDataPointer newPointer(new HeightfieldData(contents));
|
HeightfieldColorDataPointer newPointer(new HeightfieldColorData(contents));
|
||||||
info.outputValues[1] = AttributeValue(_outputs.at(1), encodeInline<HeightfieldDataPointer>(newPointer));
|
info.outputValues[1] = AttributeValue(_outputs.at(1), encodeInline<HeightfieldColorDataPointer>(newPointer));
|
||||||
}
|
}
|
||||||
return STOP_RECURSION;
|
return STOP_RECURSION;
|
||||||
}
|
}
|
||||||
|
|
|
@ -249,11 +249,11 @@ public:
|
||||||
|
|
||||||
STREAM glm::vec3 position;
|
STREAM glm::vec3 position;
|
||||||
STREAM float radius;
|
STREAM float radius;
|
||||||
STREAM QUrl url;
|
STREAM SharedObjectPointer texture;
|
||||||
STREAM QColor averageColor;
|
STREAM QColor averageColor;
|
||||||
|
|
||||||
PaintHeightfieldTextureEdit(const glm::vec3& position = glm::vec3(), float radius = 0.0f, const QUrl& url = QUrl(),
|
PaintHeightfieldTextureEdit(const glm::vec3& position = glm::vec3(), float radius = 0.0f,
|
||||||
const QColor& averageColor = QColor());
|
const SharedObjectPointer& texture = SharedObjectPointer(), const QColor& averageColor = QColor());
|
||||||
|
|
||||||
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
|
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -158,7 +158,7 @@ SharedObjectEditor::SharedObjectEditor(const QMetaObject* metaObject, bool nulla
|
||||||
_type->addItem("(none)");
|
_type->addItem("(none)");
|
||||||
}
|
}
|
||||||
foreach (const QMetaObject* metaObject, Bitstream::getMetaObjectSubClasses(metaObject)) {
|
foreach (const QMetaObject* metaObject, Bitstream::getMetaObjectSubClasses(metaObject)) {
|
||||||
// add add constructable subclasses
|
// add constructable subclasses
|
||||||
if (metaObject->constructorCount() > 0) {
|
if (metaObject->constructorCount() > 0) {
|
||||||
_type->addItem(metaObject->className(), QVariant::fromValue(metaObject));
|
_type->addItem(metaObject->className(), QVariant::fromValue(metaObject));
|
||||||
}
|
}
|
||||||
|
@ -226,6 +226,7 @@ void SharedObjectEditor::updateType() {
|
||||||
const QMetaObject* metaObject = _type->itemData(_type->currentIndex()).value<const QMetaObject*>();
|
const QMetaObject* metaObject = _type->itemData(_type->currentIndex()).value<const QMetaObject*>();
|
||||||
if (!metaObject) {
|
if (!metaObject) {
|
||||||
_object.reset();
|
_object.reset();
|
||||||
|
emit objectChanged(_object);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QObject* newObject = metaObject->newInstance();
|
QObject* newObject = metaObject->newInstance();
|
||||||
|
@ -259,7 +260,7 @@ void SharedObjectEditor::updateType() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_object = static_cast<SharedObject*>(newObject);
|
emit objectChanged(_object = static_cast<SharedObject*>(newObject));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharedObjectEditor::propertyChanged() {
|
void SharedObjectEditor::propertyChanged() {
|
||||||
|
@ -275,6 +276,7 @@ void SharedObjectEditor::propertyChanged() {
|
||||||
QByteArray valuePropertyName = QItemEditorFactory::defaultFactory()->valuePropertyName(property.userType());
|
QByteArray valuePropertyName = QItemEditorFactory::defaultFactory()->valuePropertyName(property.userType());
|
||||||
property.write(object, widget->property(valuePropertyName));
|
property.write(object, widget->property(valuePropertyName));
|
||||||
}
|
}
|
||||||
|
emit objectChanged(_object);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharedObjectEditor::updateProperty() {
|
void SharedObjectEditor::updateProperty() {
|
||||||
|
|
|
@ -211,7 +211,7 @@ Q_DECLARE_METATYPE(SharedObjectSet)
|
||||||
/// Allows editing shared object instances.
|
/// Allows editing shared object instances.
|
||||||
class SharedObjectEditor : public QWidget {
|
class SharedObjectEditor : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(SharedObjectPointer object READ getObject WRITE setObject USER true)
|
Q_PROPERTY(SharedObjectPointer object READ getObject WRITE setObject NOTIFY objectChanged USER true)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -222,6 +222,10 @@ public:
|
||||||
/// "Detaches" the object pointer, copying it if anyone else is holding a reference.
|
/// "Detaches" the object pointer, copying it if anyone else is holding a reference.
|
||||||
void detachObject();
|
void detachObject();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
void objectChanged(const SharedObjectPointer& object);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void setObject(const SharedObjectPointer& object);
|
void setObject(const SharedObjectPointer& object);
|
||||||
|
|
Loading…
Reference in a new issue