Working on voxel edits.

This commit is contained in:
Andrzej Kapolka 2014-08-26 17:15:02 -07:00
parent c6486b7f23
commit 9c0888afff
6 changed files with 466 additions and 50 deletions

View file

@ -66,13 +66,16 @@ MetavoxelEditor::MetavoxelEditor() :
attributeLayout->addLayout(attributeButtonLayout);
QPushButton* newAttribute = new QPushButton("New...");
attributeButtonLayout->addWidget(newAttribute);
attributeButtonLayout->addWidget(newAttribute, 1);
connect(newAttribute, SIGNAL(clicked()), SLOT(createNewAttribute()));
attributeButtonLayout->addWidget(_deleteAttribute = new QPushButton("Delete"));
attributeButtonLayout->addWidget(_deleteAttribute = new QPushButton("Delete"), 1);
_deleteAttribute->setEnabled(false);
connect(_deleteAttribute, SIGNAL(clicked()), SLOT(deleteSelectedAttribute()));
attributeButtonLayout->addWidget(_showAll = new QCheckBox("Show All"));
connect(_showAll, SIGNAL(clicked()), SLOT(updateAttributes()));
QFormLayout* formLayout = new QFormLayout();
topLayout->addLayout(formLayout);
@ -116,11 +119,13 @@ MetavoxelEditor::MetavoxelEditor() :
addTool(new RemoveSpannerTool(this));
addTool(new ClearSpannersTool(this));
addTool(new SetSpannerTool(this));
addTool(new ImportHeightfieldTool(this));
addTool(new EraseHeightfieldTool(this));
addTool(new HeightfieldHeightBrushTool(this));
addTool(new HeightfieldColorBrushTool(this));
addTool(new HeightfieldMaterialBrushTool(this));
addTool(new ImportHeightfieldTool(this));
addTool(new EraseHeightfieldTool(this));
addTool(new VoxelColorBoxTool(this));
addTool(new VoxelMaterialBoxTool(this));
updateAttributes();
@ -200,7 +205,7 @@ void MetavoxelEditor::selectedAttributeChanged() {
AttributePointer attribute = AttributeRegistry::getInstance()->getAttribute(selected);
foreach (MetavoxelTool* tool, _tools) {
if (tool->appliesTo(attribute)) {
if (tool->appliesTo(attribute) && (tool->isUserFacing() || _showAll->isChecked())) {
_toolBox->addItem(tool->objectName(), QVariant::fromValue(tool));
}
}
@ -271,6 +276,35 @@ void MetavoxelEditor::alignGridPosition() {
_gridPosition->setValue(step * floor(_gridPosition->value() / step));
}
void MetavoxelEditor::updateAttributes(const QString& select) {
// remember the selection in order to preserve it
QString selected = select.isNull() ? getSelectedAttribute() : select;
_attributes->clear();
// sort the names for consistent ordering
QList<QString> names;
if (_showAll->isChecked()) {
names = AttributeRegistry::getInstance()->getAttributes().keys();
} else {
foreach (const AttributePointer& attribute, AttributeRegistry::getInstance()->getAttributes()) {
if (attribute->isUserFacing()) {
names.append(attribute->getName());
}
}
}
qSort(names);
foreach (const QString& name, names) {
QListWidgetItem* item = new QListWidgetItem(name);
_attributes->addItem(item);
if (name == selected || selected.isNull()) {
item->setSelected(true);
selected = name;
}
}
}
void MetavoxelEditor::updateTool() {
MetavoxelTool* active = getActiveTool();
foreach (MetavoxelTool* tool, _tools) {
@ -335,25 +369,6 @@ void MetavoxelEditor::addTool(MetavoxelTool* tool) {
layout()->addWidget(tool);
}
void MetavoxelEditor::updateAttributes(const QString& select) {
// remember the selection in order to preserve it
QString selected = select.isNull() ? getSelectedAttribute() : select;
_attributes->clear();
// sort the names for consistent ordering
QList<QString> names = AttributeRegistry::getInstance()->getAttributes().keys();
qSort(names);
foreach (const QString& name, names) {
QListWidgetItem* item = new QListWidgetItem(name);
_attributes->addItem(item);
if (name == selected || selected.isNull()) {
item->setSelected(true);
selected = name;
}
}
}
MetavoxelTool* MetavoxelEditor::getActiveTool() const {
int index = _toolBox->currentIndex();
return (index == -1) ? NULL : static_cast<MetavoxelTool*>(_toolBox->itemData(index).value<QObject*>());
@ -361,9 +376,10 @@ MetavoxelTool* MetavoxelEditor::getActiveTool() const {
ProgramObject MetavoxelEditor::_gridProgram;
MetavoxelTool::MetavoxelTool(MetavoxelEditor* editor, const QString& name, bool usesValue) :
MetavoxelTool::MetavoxelTool(MetavoxelEditor* editor, const QString& name, bool usesValue, bool userFacing) :
_editor(editor),
_usesValue(usesValue) {
_usesValue(usesValue),
_userFacing(userFacing) {
QVBoxLayout* layout = new QVBoxLayout();
setLayout(layout);
@ -385,13 +401,13 @@ void MetavoxelTool::render() {
// nothing by default
}
BoxSetTool::BoxSetTool(MetavoxelEditor* editor) :
MetavoxelTool(editor, "Set Value (Box)") {
BoxTool::BoxTool(MetavoxelEditor* editor, const QString& name, bool usesValue, bool userFacing) :
MetavoxelTool(editor, name, usesValue, userFacing) {
resetState();
}
void BoxSetTool::render() {
void BoxTool::render() {
if (Application::getInstance()->isMouseHidden()) {
resetState();
return;
@ -457,7 +473,7 @@ void BoxSetTool::render() {
glTranslatef(0.5f, 0.5f, 0.5f);
if (_state != HOVERING_STATE) {
const float BOX_ALPHA = 0.25f;
QColor color = _editor->getValue().value<QColor>();
QColor color = getColor();
if (color.isValid()) {
glColor4f(color.redF(), color.greenF(), color.blueF(), BOX_ALPHA);
} else {
@ -476,7 +492,7 @@ void BoxSetTool::render() {
glPopMatrix();
}
bool BoxSetTool::eventFilter(QObject* watched, QEvent* event) {
bool BoxTool::eventFilter(QObject* watched, QEvent* event) {
switch (_state) {
case HOVERING_STATE:
if (event->type() == QEvent::MouseButtonPress && _startPosition != INVALID_VECTOR) {
@ -515,12 +531,20 @@ bool BoxSetTool::eventFilter(QObject* watched, QEvent* event) {
return false;
}
void BoxSetTool::resetState() {
void BoxTool::resetState() {
_state = HOVERING_STATE;
_startPosition = INVALID_VECTOR;
_height = 0.0f;
}
BoxSetTool::BoxSetTool(MetavoxelEditor* editor) :
BoxTool(editor, "Set Value (Box)", true, false) {
}
QColor BoxSetTool::getColor() {
return _editor->getValue().value<QColor>();
}
void BoxSetTool::applyValue(const glm::vec3& minimum, const glm::vec3& maximum) {
AttributePointer attribute = AttributeRegistry::getInstance()->getAttribute(_editor->getSelectedAttribute());
if (!attribute) {
@ -533,7 +557,7 @@ void BoxSetTool::applyValue(const glm::vec3& minimum, const glm::vec3& maximum)
}
GlobalSetTool::GlobalSetTool(MetavoxelEditor* editor) :
MetavoxelTool(editor, "Set Value (Global)") {
MetavoxelTool(editor, "Set Value (Global)", true, false) {
QPushButton* button = new QPushButton("Apply");
layout()->addWidget(button);
@ -1199,3 +1223,61 @@ void HeightfieldMaterialBrushTool::updateTexture() {
MaterialObject* material = static_cast<MaterialObject*>(_materialEditor->getObject().data());
_texture = Application::getInstance()->getTextureCache()->getTexture(material->getDiffuse(), SPLAT_TEXTURE);
}
VoxelColorBoxTool::VoxelColorBoxTool(MetavoxelEditor* editor) :
BoxTool(editor, "Set Voxel Color (Box)", false) {
QWidget* widget = new QWidget();
QFormLayout* form = new QFormLayout();
widget->setLayout(form);
layout()->addWidget(widget);
form->addRow("Color:", _color = new QColorEditor(this));
}
bool VoxelColorBoxTool::appliesTo(const AttributePointer& attribute) const {
return attribute->inherits("VoxelColorAttribute");
}
QColor VoxelColorBoxTool::getColor() {
return _color->getColor();
}
void VoxelColorBoxTool::applyValue(const glm::vec3& minimum, const glm::vec3& maximum) {
MetavoxelEditMessage message = { QVariant::fromValue(VoxelColorBoxEdit(Box(minimum, maximum),
_editor->getGridSpacing(), _color->getColor())) };
Application::getInstance()->getMetavoxels()->applyEdit(message, true);
}
VoxelMaterialBoxTool::VoxelMaterialBoxTool(MetavoxelEditor* editor) :
BoxTool(editor, "Set Voxel Material (Box)", false) {
QWidget* widget = new QWidget();
QFormLayout* form = new QFormLayout();
widget->setLayout(form);
layout()->addWidget(widget);
form->addRow(_materialEditor = new SharedObjectEditor(&MaterialObject::staticMetaObject, false));
connect(_materialEditor, &SharedObjectEditor::objectChanged, this, &VoxelMaterialBoxTool::updateTexture);
}
bool VoxelMaterialBoxTool::appliesTo(const AttributePointer& attribute) const {
return attribute->inherits("VoxelColorAttribute");
}
QColor VoxelMaterialBoxTool::getColor() {
return _texture ? _texture->getAverageColor() : QColor();
}
void VoxelMaterialBoxTool::applyValue(const glm::vec3& minimum, const glm::vec3& maximum) {
SharedObjectPointer material = _materialEditor->getObject();
_materialEditor->detachObject();
MetavoxelEditMessage message = { QVariant::fromValue(VoxelMaterialBoxEdit(Box(minimum, maximum),
_editor->getGridSpacing(), material, _texture ? _texture->getAverageColor() : QColor())) };
Application::getInstance()->getMetavoxels()->applyEdit(message, true);
}
void VoxelMaterialBoxTool::updateTexture() {
MaterialObject* material = static_cast<MaterialObject*>(_materialEditor->getObject().data());
_texture = Application::getInstance()->getTextureCache()->getTexture(material->getDiffuse(), SPLAT_TEXTURE);
}

View file

@ -57,6 +57,7 @@ private slots:
void deleteSelectedAttribute();
void centerGridPosition();
void alignGridPosition();
void updateAttributes(const QString& select = QString());
void updateTool();
void simulate(float deltaTime);
@ -65,11 +66,11 @@ private slots:
private:
void addTool(MetavoxelTool* tool);
void updateAttributes(const QString& select = QString());
MetavoxelTool* getActiveTool() const;
QListWidget* _attributes;
QPushButton* _deleteAttribute;
QCheckBox* _showAll;
QComboBox* _gridPlane;
QDoubleSpinBox* _gridSpacing;
@ -90,10 +91,12 @@ class MetavoxelTool : public QWidget {
public:
MetavoxelTool(MetavoxelEditor* editor, const QString& name, bool usesValue = true);
MetavoxelTool(MetavoxelEditor* editor, const QString& name, bool usesValue = true, bool userFacing = true);
bool getUsesValue() const { return _usesValue; }
bool isUserFacing() const { return _userFacing; }
virtual bool appliesTo(const AttributePointer& attribute) const;
virtual void simulate(float deltaTime);
@ -105,24 +108,30 @@ protected:
MetavoxelEditor* _editor;
bool _usesValue;
bool _userFacing;
};
/// Allows setting the value of a region by dragging out a box.
class BoxSetTool : public MetavoxelTool {
/// Base class for tools that allow dragging out a 3D box.
class BoxTool : public MetavoxelTool {
Q_OBJECT
public:
BoxSetTool(MetavoxelEditor* editor);
BoxTool(MetavoxelEditor* editor, const QString& name, bool usesValue = true, bool userFacing = true);
virtual void render();
virtual bool eventFilter(QObject* watched, QEvent* event);
protected:
virtual QColor getColor() = 0;
virtual void applyValue(const glm::vec3& minimum, const glm::vec3& maximum) = 0;
private:
void resetState();
void applyValue(const glm::vec3& minimum, const glm::vec3& maximum);
enum State { HOVERING_STATE, DRAGGING_STATE, RAISING_STATE };
@ -134,6 +143,21 @@ private:
float _height; ///< the selection height
};
/// Allows setting the value of a region by dragging out a box.
class BoxSetTool : public BoxTool {
Q_OBJECT
public:
BoxSetTool(MetavoxelEditor* editor);
protected:
virtual QColor getColor();
virtual void applyValue(const glm::vec3& minimum, const glm::vec3& maximum);
};
/// Allows setting the value across the entire space.
class GlobalSetTool : public MetavoxelTool {
Q_OBJECT
@ -384,4 +408,51 @@ private:
QSharedPointer<NetworkTexture> _texture;
};
/// Allows setting voxel colors by dragging out a box.
class VoxelColorBoxTool : public BoxTool {
Q_OBJECT
public:
VoxelColorBoxTool(MetavoxelEditor* editor);
virtual bool appliesTo(const AttributePointer& attribute) const;
protected:
virtual QColor getColor();
virtual void applyValue(const glm::vec3& minimum, const glm::vec3& maximum);
private:
QColorEditor* _color;
};
/// Allows setting voxel materials by dragging out a box.
class VoxelMaterialBoxTool : public BoxTool {
Q_OBJECT
public:
VoxelMaterialBoxTool(MetavoxelEditor* editor);
virtual bool appliesTo(const AttributePointer& attribute) const;
protected:
virtual QColor getColor();
virtual void applyValue(const glm::vec3& minimum, const glm::vec3& maximum);
private slots:
void updateTexture();
private:
SharedObjectEditor* _materialEditor;
QSharedPointer<NetworkTexture> _texture;
};
#endif // hifi_MetavoxelEditor_h

View file

@ -30,6 +30,8 @@ REGISTER_META_OBJECT(HeightfieldMaterialAttribute)
REGISTER_META_OBJECT(SharedObjectAttribute)
REGISTER_META_OBJECT(SharedObjectSetAttribute)
REGISTER_META_OBJECT(SpannerSetAttribute)
REGISTER_META_OBJECT(VoxelColorAttribute)
REGISTER_META_OBJECT(VoxelMaterialAttribute)
static int attributePointerMetaTypeId = qRegisterMetaType<AttributePointer>();
static int ownedAttributeValueMetaTypeId = qRegisterMetaType<OwnedAttributeValue>();
@ -53,6 +55,7 @@ AttributeRegistry::AttributeRegistry() :
_heightfieldAttribute(registerAttribute(new HeightfieldAttribute("heightfield"))),
_heightfieldColorAttribute(registerAttribute(new HeightfieldColorAttribute("heightfieldColor"))),
_heightfieldMaterialAttribute(registerAttribute(new HeightfieldMaterialAttribute("heightfieldMaterial"))),
_voxelColorAttribute(registerAttribute(new VoxelColorAttribute("voxelColor"))),
_voxelMaterialAttribute(registerAttribute(new VoxelMaterialAttribute("voxelMaterial"))) {
// our baseline LOD threshold is for voxels; spanners and heightfields are a different story
@ -61,10 +64,13 @@ AttributeRegistry::AttributeRegistry() :
const float HEIGHTFIELD_LOD_THRESHOLD_MULTIPLIER = 32.0f;
_heightfieldAttribute->setLODThresholdMultiplier(HEIGHTFIELD_LOD_THRESHOLD_MULTIPLIER);
_heightfieldAttribute->setUserFacing(true);
_heightfieldColorAttribute->setLODThresholdMultiplier(HEIGHTFIELD_LOD_THRESHOLD_MULTIPLIER);
_heightfieldMaterialAttribute->setLODThresholdMultiplier(HEIGHTFIELD_LOD_THRESHOLD_MULTIPLIER);
const float VOXEL_LOD_THRESHOLD_MULTIPLIER = 32.0f;
_voxelColorAttribute->setLODThresholdMultiplier(VOXEL_LOD_THRESHOLD_MULTIPLIER);
_voxelColorAttribute->setUserFacing(true);
_voxelMaterialAttribute->setLODThresholdMultiplier(VOXEL_LOD_THRESHOLD_MULTIPLIER);
}
@ -205,7 +211,8 @@ OwnedAttributeValue& OwnedAttributeValue::operator=(const OwnedAttributeValue& o
}
Attribute::Attribute(const QString& name) :
_lodThresholdMultiplier(1.0f) {
_lodThresholdMultiplier(1.0f),
_userFacing(false) {
setObjectName(name);
}
@ -1390,8 +1397,41 @@ bool HeightfieldMaterialAttribute::merge(void*& parent, void* children[], bool p
return maxSize == 0;
}
VoxelColorData::VoxelColorData(const QVector<QRgb>& contents) :
_contents(contents) {
const int VOXEL_COLOR_HEADER_SIZE = sizeof(qint32) * 6;
static QByteArray encodeVoxelColor(int offsetX, int offsetY, int offsetZ,
int sizeX, int sizeY, int sizeZ, const QVector<QRgb>& contents) {
QByteArray inflated(VOXEL_COLOR_HEADER_SIZE, 0);
qint32* header = (qint32*)inflated.data();
*header++ = offsetX;
*header++ = offsetY;
*header++ = offsetZ;
*header++ = sizeX;
*header++ = sizeY;
*header++ = sizeZ;
inflated.append((const char*)contents.constData(), contents.size() * sizeof(QRgb));
return qCompress(inflated);
}
static QVector<QRgb> decodeVoxelColor(const QByteArray& encoded, int& offsetX, int& offsetY, int& offsetZ,
int& sizeX, int& sizeY, int& sizeZ) {
QByteArray inflated = qUncompress(encoded);
const qint32* header = (const qint32*)inflated.constData();
offsetX = *header++;
offsetY = *header++;
offsetZ = *header++;
sizeX = *header++;
sizeY = *header++;
sizeZ = *header++;
int payloadSize = inflated.size() - VOXEL_COLOR_HEADER_SIZE;
QVector<QRgb> contents(payloadSize / sizeof(QRgb));
memcpy(contents.data(), inflated.constData() + VOXEL_COLOR_HEADER_SIZE, payloadSize);
return contents;
}
VoxelColorData::VoxelColorData(const QVector<QRgb>& contents, int size) :
_contents(contents),
_size(size) {
}
VoxelColorData::VoxelColorData(Bitstream& in, int bytes) {
@ -1407,32 +1447,170 @@ VoxelColorData::VoxelColorData(Bitstream& in, int bytes, const VoxelColorDataPoi
reference->setEncodedDelta(in.readAligned(bytes));
reference->setDeltaData(DataBlockPointer(this));
_contents = reference->getContents();
_size = reference->getSize();
int offsetX, offsetY, offsetZ, sizeX, sizeY, sizeZ;
QVector<QRgb> delta = decodeVoxelColor(reference->getEncodedDelta(), offsetX, offsetY, offsetZ, sizeX, sizeY, sizeZ);
if (delta.isEmpty()) {
return;
}
if (offsetX == 0) {
_contents = delta;
_size = sizeX;
return;
}
int minX = offsetX - 1;
int minY = offsetY - 1;
int minZ = offsetZ - 1;
const QRgb* src = delta.constData();
int size2 = _size * _size;
QRgb* planeDest = _contents.data() + minZ * size2 + minY * _size + minX;
int length = sizeX * sizeof(QRgb);
for (int z = 0; z < sizeZ; z++, planeDest += size2) {
QRgb* dest = planeDest;
for (int y = 0; y < sizeY; y++, src += sizeX, dest += _size) {
memcpy(dest, src, length);
}
}
}
void VoxelColorData::write(Bitstream& out) {
QMutexLocker locker(&_encodedMutex);
if (_encoded.isEmpty()) {
_encoded = encodeVoxelColor(0, 0, 0, _size, _size, _size, _contents);
}
out << _encoded.size();
out.writeAligned(_encoded);
}
void VoxelColorData::writeDelta(Bitstream& out, const VoxelColorDataPointer& reference) {
if (!reference || reference->getContents().size() != _contents.size()) {
if (!reference || reference->getSize() != _size) {
write(out);
return;
}
QMutexLocker locker(&reference->getEncodedDeltaMutex());
if (reference->getEncodedDelta().isEmpty() || reference->getDeltaData() != this) {
int minX = _size, minY = _size, minZ = _size;
int maxX = -1, maxY = -1, maxZ = -1;
const QRgb* src = _contents.constData();
const QRgb* ref = reference->getContents().constData();
for (int z = 0; z < _size; z++) {
bool differenceZ = false;
for (int y = 0; y < _size; y++) {
bool differenceY = false;
for (int x = 0; x < _size; x++) {
if (*src++ != *ref++) {
minX = qMin(minX, x);
maxX = qMax(maxX, x);
differenceY = differenceZ = true;
}
}
if (differenceY) {
minY = qMin(minY, y);
maxY = qMax(maxY, y);
}
}
if (differenceZ) {
minZ = qMin(minZ, z);
maxZ = qMax(maxZ, z);
}
}
QVector<QRgb> delta;
int sizeX = 0, sizeY = 0, sizeZ = 0;
if (maxX >= minX) {
sizeX = maxX - minX + 1;
sizeY = maxY - minY + 1;
sizeZ = maxZ - minZ + 1;
delta = QVector<QRgb>(sizeX * sizeY * sizeZ, 0);
QRgb* dest = delta.data();
int size2 = _size * _size;
const QRgb* planeSrc = _contents.constData() + minZ * size2 + minY * _size + minX;
int length = sizeX * sizeof(QRgb);
for (int z = 0; z < sizeZ; z++, planeSrc += size2) {
src = planeSrc;
for (int y = 0; y < sizeY; y++, src += _size, dest += sizeX) {
memcpy(dest, src, length);
}
}
}
reference->setEncodedDelta(encodeVoxelColor(minX + 1, minY + 1, minZ + 1, sizeX, sizeY, sizeZ, delta));
reference->setDeltaData(DataBlockPointer(this));
}
out << reference->getEncodedDelta().size();
out.writeAligned(reference->getEncodedDelta());
}
void VoxelColorData::read(Bitstream& in, int bytes) {
int offsetX, offsetY, offsetZ, sizeX, sizeY, sizeZ;
_contents = decodeVoxelColor(_encoded = in.readAligned(bytes), offsetX, offsetY, offsetZ, sizeX, sizeY, sizeZ);
_size = sizeX;
}
VoxelColorAttribute::VoxelColorAttribute(const QString& name) :
InlineAttribute<VoxelColorDataPointer>(name) {
}
void VoxelColorAttribute::read(Bitstream& in, void*& value, bool isLeaf) const {
if (!isLeaf) {
return;
}
int size;
in >> size;
if (size == 0) {
*(VoxelColorDataPointer*)&value = VoxelColorDataPointer();
} else {
*(VoxelColorDataPointer*)&value = VoxelColorDataPointer(new VoxelColorData(in, size));
}
}
void VoxelColorAttribute::write(Bitstream& out, void* value, bool isLeaf) const {
if (!isLeaf) {
return;
}
VoxelColorDataPointer data = decodeInline<VoxelColorDataPointer>(value);
if (data) {
data->write(out);
} else {
out << 0;
}
}
void VoxelColorAttribute::readDelta(Bitstream& in, void*& value, void* reference, bool isLeaf) const {
if (!isLeaf) {
return;
}
int size;
in >> size;
if (size == 0) {
*(VoxelColorDataPointer*)&value = VoxelColorDataPointer();
} else {
*(VoxelColorDataPointer*)&value = VoxelColorDataPointer(new VoxelColorData(
in, size, decodeInline<VoxelColorDataPointer>(reference)));
}
}
void VoxelColorAttribute::writeDelta(Bitstream& out, void* value, void* reference, bool isLeaf) const {
if (!isLeaf) {
return;
}
VoxelColorDataPointer data = decodeInline<VoxelColorDataPointer>(value);
if (data) {
data->writeDelta(out, decodeInline<VoxelColorDataPointer>(reference));
} else {
out << 0;
}
}
bool VoxelColorAttribute::merge(void*& parent, void* children[], bool postRead) const {
int maxSize = 0;
for (int i = 0; i < MERGE_COUNT; i++) {
VoxelColorDataPointer pointer = decodeInline<VoxelColorDataPointer>(children[i]);
if (pointer) {
maxSize = qMax(maxSize, pointer->getSize());
}
}
*(VoxelColorDataPointer*)&parent = VoxelColorDataPointer();
return maxSize == 0;
}
const int VOXEL_MATERIAL_HEADER_SIZE = sizeof(qint32) * 6;
@ -1461,7 +1639,7 @@ static QByteArray decodeVoxelMaterial(const QByteArray& encoded, int& offsetX, i
sizeX = *header++;
sizeY = *header++;
sizeZ = *header++;
return inflated.mid(HEIGHTFIELD_MATERIAL_HEADER_SIZE);
return inflated.mid(VOXEL_MATERIAL_HEADER_SIZE);
}
VoxelMaterialData::VoxelMaterialData(const QByteArray& contents, int size, const QVector<SharedObjectPointer>& materials) :
@ -1644,7 +1822,7 @@ bool VoxelMaterialAttribute::merge(void*& parent, void* children[], bool postRea
for (int i = 0; i < MERGE_COUNT; i++) {
VoxelMaterialDataPointer pointer = decodeInline<VoxelMaterialDataPointer>(children[i]);
if (pointer) {
maxSize = qMax(maxSize, pointer->getContents().size());
maxSize = qMax(maxSize, pointer->getSize());
}
}
*(VoxelMaterialDataPointer*)&parent = VoxelMaterialDataPointer();

View file

@ -111,6 +111,9 @@ public:
/// Returns a reference to the standard HeightfieldMaterialDataPointer "heightfieldMaterial" attribute.
const AttributePointer& getHeightfieldMaterialAttribute() const { return _heightfieldMaterialAttribute; }
/// Returns a reference to the standard VoxelColorDataPointer "voxelColor" attribute.
const AttributePointer& getVoxelColorAttribute() const { return _voxelColorAttribute; }
/// Returns a reference to the standard VoxelMaterialDataPointer "voxelMaterial" attribute.
const AttributePointer& getVoxelMaterialAttribute() const { return _voxelMaterialAttribute; }
@ -132,6 +135,7 @@ private:
AttributePointer _heightfieldAttribute;
AttributePointer _heightfieldColorAttribute;
AttributePointer _heightfieldMaterialAttribute;
AttributePointer _voxelColorAttribute;
AttributePointer _voxelMaterialAttribute;
};
@ -212,6 +216,7 @@ Q_DECLARE_METATYPE(OwnedAttributeValue)
class Attribute : public SharedObject {
Q_OBJECT
Q_PROPERTY(float lodThresholdMultiplier MEMBER _lodThresholdMultiplier)
Q_PROPERTY(bool userFacing MEMBER _userFacing)
public:
@ -225,6 +230,9 @@ public:
float getLODThresholdMultiplier() const { return _lodThresholdMultiplier; }
void setLODThresholdMultiplier(float multiplier) { _lodThresholdMultiplier = multiplier; }
bool isUserFacing() const { return _userFacing; }
void setUserFacing(bool userFacing) { _userFacing = userFacing; }
void* create() const { return create(getDefaultValue()); }
virtual void* create(void* copy) const = 0;
virtual void destroy(void* value) const = 0;
@ -289,6 +297,7 @@ public:
private:
float _lodThresholdMultiplier;
bool _userFacing;
};
/// A simple attribute class that stores its values inline.
@ -637,12 +646,14 @@ typedef QExplicitlySharedDataPointer<VoxelColorData> VoxelColorDataPointer;
class VoxelColorData : public DataBlock {
public:
VoxelColorData(const QVector<QRgb>& contents);
VoxelColorData(const QVector<QRgb>& contents, int size);
VoxelColorData(Bitstream& in, int bytes);
VoxelColorData(Bitstream& in, int bytes, const VoxelColorDataPointer& reference);
const QVector<QRgb>& getContents() const { return _contents; }
int getSize() const { return _size; }
void write(Bitstream& out);
void writeDelta(Bitstream& out, const VoxelColorDataPointer& reference);
@ -651,6 +662,24 @@ private:
void read(Bitstream& in, int bytes);
QVector<QRgb> _contents;
int _size;
};
/// An attribute that stores voxel colors.
class VoxelColorAttribute : public InlineAttribute<VoxelColorDataPointer> {
Q_OBJECT
public:
Q_INVOKABLE VoxelColorAttribute(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 void readDelta(Bitstream& in, void*& value, void* reference, bool isLeaf) const;
virtual void writeDelta(Bitstream& out, void* value, void* reference, bool isLeaf) const;
virtual bool merge(void*& parent, void* children[], bool postRead = false) const;
};
typedef QExplicitlySharedDataPointer<VoxelMaterialData> VoxelMaterialDataPointer;

View file

@ -642,3 +642,23 @@ void PaintHeightfieldMaterialEdit::apply(MetavoxelData& data, const WeakSharedOb
PaintHeightfieldMaterialEditVisitor visitor(*this);
data.guide(visitor);
}
VoxelColorBoxEdit::VoxelColorBoxEdit(const Box& region, float granularity, const QColor& color) :
region(region),
granularity(granularity),
color(color) {
}
void VoxelColorBoxEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
}
VoxelMaterialBoxEdit::VoxelMaterialBoxEdit(const Box& region, float granularity,
const SharedObjectPointer& material, const QColor& averageColor) :
region(region),
granularity(granularity),
material(material),
averageColor(averageColor) {
}
void VoxelMaterialBoxEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
}

View file

@ -260,4 +260,40 @@ public:
DECLARE_STREAMABLE_METATYPE(PaintHeightfieldMaterialEdit)
/// An edit that sets the color of voxels within a box to a value.
class VoxelColorBoxEdit : public MetavoxelEdit {
STREAMABLE
public:
STREAM Box region;
STREAM float granularity;
STREAM QColor color;
VoxelColorBoxEdit(const Box& region = Box(), float granularity = 0.0f, const QColor& color = QColor());
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
};
DECLARE_STREAMABLE_METATYPE(VoxelColorBoxEdit)
/// An edit that sets the materials of voxels within a box to a value.
class VoxelMaterialBoxEdit : public MetavoxelEdit {
STREAMABLE
public:
STREAM Box region;
STREAM float granularity;
STREAM SharedObjectPointer material;
STREAM QColor averageColor;
VoxelMaterialBoxEdit(const Box& region = Box(), float granularity = 0.0f,
const SharedObjectPointer& material = SharedObjectPointer(), const QColor& averageColor = QColor());
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
};
DECLARE_STREAMABLE_METATYPE(VoxelMaterialBoxEdit)
#endif // hifi_MetavoxelMessages_h