From dfcb22bd7ac06c5f68767232771dea9ee1b59c5c Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 12 Dec 2014 15:12:03 -0800 Subject: [PATCH] More progress towards stacks. --- interface/src/MetavoxelSystem.cpp | 18 +- interface/src/MetavoxelSystem.h | 8 +- interface/src/ui/MetavoxelEditor.cpp | 146 +++++----------- interface/src/ui/MetavoxelEditor.h | 88 +++------- .../metavoxels/src/AttributeRegistry.cpp | 1 - .../metavoxels/src/MetavoxelMessages.cpp | 158 ++---------------- libraries/metavoxels/src/MetavoxelMessages.h | 25 +-- libraries/metavoxels/src/Spanner.cpp | 41 ++++- libraries/metavoxels/src/Spanner.h | 8 +- 9 files changed, 123 insertions(+), 370 deletions(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 08a85df090..c3734b6349 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -559,23 +559,13 @@ void MetavoxelSystem::paintHeightfieldMaterial(const glm::vec3& position, float applyMaterialEdit(edit, true); } -void MetavoxelSystem::paintVoxelColor(const glm::vec3& position, float radius, const QColor& color) { - MetavoxelEditMessage edit = { QVariant::fromValue(PaintVoxelMaterialEdit(position, radius, SharedObjectPointer(), color)) }; +void MetavoxelSystem::setHeightfieldColor(const SharedObjectPointer& spanner, const QColor& color) { + MetavoxelEditMessage edit = { QVariant::fromValue(HeightfieldMaterialSpannerEdit(spanner, SharedObjectPointer(), color)) }; applyEdit(edit, true); } -void MetavoxelSystem::paintVoxelMaterial(const glm::vec3& position, float radius, const SharedObjectPointer& material) { - MetavoxelEditMessage edit = { QVariant::fromValue(PaintVoxelMaterialEdit(position, radius, material)) }; - applyMaterialEdit(edit, true); -} - -void MetavoxelSystem::setVoxelColor(const SharedObjectPointer& spanner, const QColor& color) { - MetavoxelEditMessage edit = { QVariant::fromValue(VoxelMaterialSpannerEdit(spanner, SharedObjectPointer(), color)) }; - applyEdit(edit, true); -} - -void MetavoxelSystem::setVoxelMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material) { - MetavoxelEditMessage edit = { QVariant::fromValue(VoxelMaterialSpannerEdit(spanner, material)) }; +void MetavoxelSystem::setHeightfieldMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material) { + MetavoxelEditMessage edit = { QVariant::fromValue(HeightfieldMaterialSpannerEdit(spanner, material)) }; applyMaterialEdit(edit, true); } diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h index e04bb6a772..78d5bd39ef 100644 --- a/interface/src/MetavoxelSystem.h +++ b/interface/src/MetavoxelSystem.h @@ -76,13 +76,9 @@ public: Q_INVOKABLE void paintHeightfieldMaterial(const glm::vec3& position, float radius, const SharedObjectPointer& material); - Q_INVOKABLE void paintVoxelColor(const glm::vec3& position, float radius, const QColor& color); - - Q_INVOKABLE void paintVoxelMaterial(const glm::vec3& position, float radius, const SharedObjectPointer& material); + Q_INVOKABLE void setHeightfieldColor(const SharedObjectPointer& spanner, const QColor& color); - Q_INVOKABLE void setVoxelColor(const SharedObjectPointer& spanner, const QColor& color); - - Q_INVOKABLE void setVoxelMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material); + Q_INVOKABLE void setHeightfieldMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material); void addHeightfieldBaseBatch(const HeightfieldBaseLayerBatch& batch) { _heightfieldBaseBatches.append(batch); } void addHeightfieldSplatBatch(const HeightfieldSplatBatch& batch) { _heightfieldSplatBatches.append(batch); } diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index 97c4c08b41..21d8d8abaf 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -122,13 +122,12 @@ MetavoxelEditor::MetavoxelEditor() : addTool(new InsertSpannerTool(this)); addTool(new RemoveSpannerTool(this)); addTool(new ClearSpannersTool(this)); + addTool(new ImportHeightfieldTool(this)); addTool(new HeightfieldHeightBrushTool(this)); addTool(new HeightfieldMaterialBrushTool(this)); - addTool(new ImportHeightfieldTool(this)); - addTool(new VoxelMaterialBoxTool(this)); - addTool(new VoxelMaterialSpannerTool(this)); - addTool(new VoxelMaterialBrushTool(this)); - addTool(new VoxelSculptBrushTool(this)); + addTool(new HeightfieldSculptBrushTool(this)); + addTool(new HeightfieldMaterialBoxTool(this)); + addTool(new HeightfieldMaterialSpannerTool(this)); updateAttributes(); @@ -944,8 +943,26 @@ QVariant HeightfieldMaterialBrushTool::createEdit(bool alternate) { } } -VoxelMaterialBoxTool::VoxelMaterialBoxTool(MetavoxelEditor* editor) : - BoxTool(editor, "Set Voxel Material (Box)", false) { +HeightfieldSculptBrushTool::HeightfieldSculptBrushTool(MetavoxelEditor* editor) : + HeightfieldBrushTool(editor, "Sculpt Brush"), + _materialControl(new MaterialControl(this, _form, true)) { +} + +QVariant HeightfieldSculptBrushTool::createEdit(bool alternate) { + Sphere* sphere = new Sphere(); + sphere->setTranslation(_position); + sphere->setScale(_radius->value()); + if (alternate) { + return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere), + SharedObjectPointer(), QColor(0, 0, 0, 0))); + } else { + return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere), + _materialControl->getMaterial(), _materialControl->getColor())); + } +} + +HeightfieldMaterialBoxTool::HeightfieldMaterialBoxTool(MetavoxelEditor* editor) : + BoxTool(editor, "Set Material (Box)", false) { QWidget* widget = new QWidget(); QFormLayout* form = new QFormLayout(); @@ -962,32 +979,32 @@ VoxelMaterialBoxTool::VoxelMaterialBoxTool(MetavoxelEditor* editor) : _materialControl = new MaterialControl(this, form, true); } -bool VoxelMaterialBoxTool::appliesTo(const AttributePointer& attribute) const { - return attribute->inherits("VoxelColorAttribute"); +bool HeightfieldMaterialBoxTool::appliesTo(const AttributePointer& attribute) const { + return attribute->inherits("SpannerSetAttribute"); } -bool VoxelMaterialBoxTool::shouldSnapToGrid() { +bool HeightfieldMaterialBoxTool::shouldSnapToGrid() { return _snapToGrid->isChecked(); } -QColor VoxelMaterialBoxTool::getColor() { +QColor HeightfieldMaterialBoxTool::getColor() { return _materialControl->getColor(); } -void VoxelMaterialBoxTool::applyValue(const glm::vec3& minimum, const glm::vec3& maximum) { +void HeightfieldMaterialBoxTool::applyValue(const glm::vec3& minimum, const glm::vec3& maximum) { Cuboid* cuboid = new Cuboid(); cuboid->setTranslation((maximum + minimum) * 0.5f); glm::vec3 vector = (maximum - minimum) * 0.5f; cuboid->setScale(vector.x); cuboid->setAspectY(vector.y / vector.x); cuboid->setAspectZ(vector.z / vector.x); - MetavoxelEditMessage message = { QVariant::fromValue(VoxelMaterialSpannerEdit(SharedObjectPointer(cuboid), + MetavoxelEditMessage message = { QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(cuboid), _materialControl->getMaterial(), _materialControl->getColor())) }; Application::getInstance()->getMetavoxels()->applyEdit(message, true); } -VoxelMaterialSpannerTool::VoxelMaterialSpannerTool(MetavoxelEditor* editor) : - PlaceSpannerTool(editor, "Set Voxel Material (Spanner)", QString(), false) { +HeightfieldMaterialSpannerTool::HeightfieldMaterialSpannerTool(MetavoxelEditor* editor) : + PlaceSpannerTool(editor, "Set Material (Spanner)", QString(), false) { QWidget* widget = new QWidget(); QFormLayout* form = new QFormLayout(); @@ -1001,110 +1018,25 @@ VoxelMaterialSpannerTool::VoxelMaterialSpannerTool(MetavoxelEditor* editor) : QPushButton* place = new QPushButton("Set"); layout()->addWidget(place); - connect(place, &QPushButton::clicked, this, &VoxelMaterialSpannerTool::place); + connect(place, &QPushButton::clicked, this, &HeightfieldMaterialSpannerTool::place); } -bool VoxelMaterialSpannerTool::appliesTo(const AttributePointer& attribute) const { - return attribute->inherits("VoxelColorAttribute"); +bool HeightfieldMaterialSpannerTool::appliesTo(const AttributePointer& attribute) const { + return attribute->inherits("SpannerSetAttribute"); } -SharedObjectPointer VoxelMaterialSpannerTool::getSpanner() { +SharedObjectPointer HeightfieldMaterialSpannerTool::getSpanner() { return _spannerEditor->getObject(); } -QColor VoxelMaterialSpannerTool::getColor() { +QColor HeightfieldMaterialSpannerTool::getColor() { return _materialControl->getColor(); } -void VoxelMaterialSpannerTool::applyEdit(const AttributePointer& attribute, const SharedObjectPointer& spanner) { +void HeightfieldMaterialSpannerTool::applyEdit(const AttributePointer& attribute, const SharedObjectPointer& spanner) { static_cast(spanner.data())->setWillBeVoxelized(true); - MetavoxelEditMessage message = { QVariant::fromValue(VoxelMaterialSpannerEdit(spanner, + MetavoxelEditMessage message = { QVariant::fromValue(HeightfieldMaterialSpannerEdit(spanner, _materialControl->getMaterial(), _materialControl->getColor())) }; Application::getInstance()->getMetavoxels()->applyEdit(message, true); } -VoxelBrushTool::VoxelBrushTool(MetavoxelEditor* editor, const QString& name) : - MetavoxelTool(editor, name, false, true), - _positionValid(false) { - - QWidget* widget = new QWidget(); - widget->setLayout(_form = new QFormLayout()); - layout()->addWidget(widget); - - _form->addRow("Radius:", _radius = new QDoubleSpinBox()); - _radius->setSingleStep(0.01); - _radius->setMaximum(FLT_MAX); - _radius->setValue(0.25); -} - -bool VoxelBrushTool::appliesTo(const AttributePointer& attribute) const { - return attribute->inherits("VoxelColorAttribute"); -} - -void VoxelBrushTool::render() { - if (Application::getInstance()->isMouseHidden()) { - return; - } - - // find the intersection with the voxels - glm::vec3 origin = Application::getInstance()->getMouseRayOrigin(); - glm::vec3 direction = Application::getInstance()->getMouseRayDirection(); - - float heightfieldDistance = FLT_MAX, voxelDistance = FLT_MAX; - if (!(Application::getInstance()->getMetavoxels()->findFirstRayHeightfieldIntersection( - origin, direction, heightfieldDistance) | - Application::getInstance()->getMetavoxels()->findFirstRayVoxelIntersection(origin, direction, voxelDistance))) { - _positionValid = false; - return; - } - _positionValid = true; - Application::getInstance()->getMetavoxels()->renderVoxelCursor( - _position = origin + qMin(heightfieldDistance, voxelDistance) * direction, _radius->value()); -} - -bool VoxelBrushTool::eventFilter(QObject* watched, QEvent* event) { - if (event->type() == QEvent::Wheel) { - float angle = static_cast(event)->angleDelta().y(); - const float ANGLE_SCALE = 1.0f / 1000.0f; - _radius->setValue(_radius->value() * glm::pow(2.0f, angle * ANGLE_SCALE)); - return true; - - } else if (event->type() == QEvent::MouseButtonPress && _positionValid) { - MetavoxelEditMessage message = { createEdit(static_cast(event)->button() == Qt::RightButton) }; - Application::getInstance()->getMetavoxels()->applyEdit(message, true); - return true; - } - return false; -} - -VoxelMaterialBrushTool::VoxelMaterialBrushTool(MetavoxelEditor* editor) : - VoxelBrushTool(editor, "Material Brush"), - _materialControl(new MaterialControl(this, _form)) { -} - -QVariant VoxelMaterialBrushTool::createEdit(bool alternate) { - if (alternate) { - return QVariant::fromValue(PaintVoxelMaterialEdit(_position, _radius->value(), SharedObjectPointer(), QColor())); - } else { - return QVariant::fromValue(PaintVoxelMaterialEdit(_position, _radius->value(), - _materialControl->getMaterial(), _materialControl->getColor())); - } -} - -VoxelSculptBrushTool::VoxelSculptBrushTool(MetavoxelEditor* editor) : - VoxelBrushTool(editor, "Sculpt Brush"), - _materialControl(new MaterialControl(this, _form, true)) { -} - -QVariant VoxelSculptBrushTool::createEdit(bool alternate) { - Sphere* sphere = new Sphere(); - sphere->setTranslation(_position); - sphere->setScale(_radius->value()); - if (alternate) { - return QVariant::fromValue(VoxelMaterialSpannerEdit(SharedObjectPointer(sphere), - SharedObjectPointer(), QColor(0, 0, 0, 0))); - } else { - return QVariant::fromValue(VoxelMaterialSpannerEdit(SharedObjectPointer(sphere), - _materialControl->getMaterial(), _materialControl->getColor())); - } -} diff --git a/interface/src/ui/MetavoxelEditor.h b/interface/src/ui/MetavoxelEditor.h index c154d7bc59..4389a97512 100644 --- a/interface/src/ui/MetavoxelEditor.h +++ b/interface/src/ui/MetavoxelEditor.h @@ -386,13 +386,30 @@ private: MaterialControl* _materialControl; }; -/// Allows setting voxel materials by dragging out a box. -class VoxelMaterialBoxTool : public BoxTool { +/// Allows sculpting parts of the heightfield. +class HeightfieldSculptBrushTool : public HeightfieldBrushTool { Q_OBJECT public: - VoxelMaterialBoxTool(MetavoxelEditor* editor); + HeightfieldSculptBrushTool(MetavoxelEditor* editor); + +protected: + + virtual QVariant createEdit(bool alternate); + +private: + + MaterialControl* _materialControl; +}; + +/// Allows setting heightfield materials by dragging out a box. +class HeightfieldMaterialBoxTool : public BoxTool { + Q_OBJECT + +public: + + HeightfieldMaterialBoxTool(MetavoxelEditor* editor); virtual bool appliesTo(const AttributePointer& attribute) const; @@ -410,13 +427,13 @@ private: MaterialControl* _materialControl; }; -/// Allows setting voxel materials by placing a spanner. -class VoxelMaterialSpannerTool : public PlaceSpannerTool { +/// Allows setting heightfield materials by placing a spanner. +class HeightfieldMaterialSpannerTool : public PlaceSpannerTool { Q_OBJECT public: - VoxelMaterialSpannerTool(MetavoxelEditor* editor); + HeightfieldMaterialSpannerTool(MetavoxelEditor* editor); virtual bool appliesTo(const AttributePointer& attribute) const; @@ -432,63 +449,4 @@ private: MaterialControl* _materialControl; }; -/// Base class for voxel brush tools. -class VoxelBrushTool : public MetavoxelTool { - Q_OBJECT - -public: - - VoxelBrushTool(MetavoxelEditor* editor, const QString& name); - - virtual bool appliesTo(const AttributePointer& attribute) const; - - virtual void render(); - - virtual bool eventFilter(QObject* watched, QEvent* event); - -protected: - - virtual QVariant createEdit(bool alternate) = 0; - - QFormLayout* _form; - QDoubleSpinBox* _radius; - - glm::vec3 _position; - bool _positionValid; -}; - -/// Allows texturing parts of the voxel field. -class VoxelMaterialBrushTool : public VoxelBrushTool { - Q_OBJECT - -public: - - VoxelMaterialBrushTool(MetavoxelEditor* editor); - -protected: - - virtual QVariant createEdit(bool alternate); - -private: - - MaterialControl* _materialControl; -}; - -/// Allows sculpting parts of the voxel field. -class VoxelSculptBrushTool : public VoxelBrushTool { - Q_OBJECT - -public: - - VoxelSculptBrushTool(MetavoxelEditor* editor); - -protected: - - virtual QVariant createEdit(bool alternate); - -private: - - MaterialControl* _materialControl; -}; - #endif // hifi_MetavoxelEditor_h diff --git a/libraries/metavoxels/src/AttributeRegistry.cpp b/libraries/metavoxels/src/AttributeRegistry.cpp index afdc0c923f..b10d162b34 100644 --- a/libraries/metavoxels/src/AttributeRegistry.cpp +++ b/libraries/metavoxels/src/AttributeRegistry.cpp @@ -53,7 +53,6 @@ AttributeRegistry::AttributeRegistry() : const float VOXEL_LOD_THRESHOLD_MULTIPLIER = 16.0f; _voxelColorAttribute->setLODThresholdMultiplier(VOXEL_LOD_THRESHOLD_MULTIPLIER); - _voxelColorAttribute->setUserFacing(true); _voxelMaterialAttribute->setLODThresholdMultiplier(VOXEL_LOD_THRESHOLD_MULTIPLIER); _voxelHermiteAttribute->setLODThresholdMultiplier(VOXEL_LOD_THRESHOLD_MULTIPLIER); } diff --git a/libraries/metavoxels/src/MetavoxelMessages.cpp b/libraries/metavoxels/src/MetavoxelMessages.cpp index 1225752df7..ab0fe34552 100644 --- a/libraries/metavoxels/src/MetavoxelMessages.cpp +++ b/libraries/metavoxels/src/MetavoxelMessages.cpp @@ -199,16 +199,16 @@ const int VOXEL_BLOCK_SAMPLES = VOXEL_BLOCK_SIZE + 1; const int VOXEL_BLOCK_AREA = VOXEL_BLOCK_SAMPLES * VOXEL_BLOCK_SAMPLES; const int VOXEL_BLOCK_VOLUME = VOXEL_BLOCK_AREA * VOXEL_BLOCK_SAMPLES; -VoxelMaterialSpannerEdit::VoxelMaterialSpannerEdit(const SharedObjectPointer& spanner, +HeightfieldMaterialSpannerEdit::HeightfieldMaterialSpannerEdit(const SharedObjectPointer& spanner, const SharedObjectPointer& material, const QColor& averageColor) : MaterialEdit(material, averageColor), spanner(spanner) { } -class VoxelMaterialSpannerEditVisitor : public MetavoxelVisitor { +class HeightfieldMaterialSpannerEditVisitor : public MetavoxelVisitor { public: - VoxelMaterialSpannerEditVisitor(Spanner* spanner, const SharedObjectPointer& material, const QColor& color); + HeightfieldMaterialSpannerEditVisitor(Spanner* spanner, const SharedObjectPointer& material, const QColor& color); virtual int visit(MetavoxelInfo& info); @@ -220,7 +220,7 @@ private: float _blockSize; }; -VoxelMaterialSpannerEditVisitor::VoxelMaterialSpannerEditVisitor(Spanner* spanner, +HeightfieldMaterialSpannerEditVisitor::HeightfieldMaterialSpannerEditVisitor(Spanner* spanner, const SharedObjectPointer& material, const QColor& color) : MetavoxelVisitor(QVector() << AttributeRegistry::getInstance()->getVoxelColorAttribute() << AttributeRegistry::getInstance()->getVoxelHermiteAttribute() << @@ -234,7 +234,7 @@ VoxelMaterialSpannerEditVisitor::VoxelMaterialSpannerEditVisitor(Spanner* spanne _blockSize(spanner->getVoxelizationGranularity() * VOXEL_BLOCK_SIZE) { } -int VoxelMaterialSpannerEditVisitor::visit(MetavoxelInfo& info) { +int HeightfieldMaterialSpannerEditVisitor::visit(MetavoxelInfo& info) { Box bounds = info.getBounds(); if (!bounds.intersects(_spanner->getBounds())) { return STOP_RECURSION; @@ -492,154 +492,20 @@ int VoxelMaterialSpannerEditVisitor::visit(MetavoxelInfo& info) { return STOP_RECURSION; } -void VoxelMaterialSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const { - // expand to fit the entire edit - Spanner* spanner = static_cast(this->spanner.data()); - while (!data.getBounds().contains(spanner->getBounds())) { - data.expand(); - } - // make sure it's either 100% transparent or 100% opaque +void HeightfieldMaterialSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const { + // make sure the color is either 100% transparent or 100% opaque QColor color = averageColor; color.setAlphaF(color.alphaF() > 0.5f ? 1.0f : 0.0f); - // find the bounds of all voxel nodes intersected - float nodeSize = VOXEL_BLOCK_SIZE * glm::pow(2.0f, glm::floor( - glm::log(spanner->getVoxelizationGranularity()) / glm::log(2.0f))); - Box bounds(glm::floor(spanner->getBounds().minimum / nodeSize) * nodeSize, - glm::ceil(spanner->getBounds().maximum / nodeSize) * nodeSize); - - // expand to include edges - Box expandedBounds = bounds; - float increment = nodeSize / VOXEL_BLOCK_SIZE; - expandedBounds.maximum.x += increment; - expandedBounds.maximum.z += increment; - - // get all intersecting spanners QVector results; - data.getIntersecting(AttributeRegistry::getInstance()->getSpannersAttribute(), expandedBounds, results); + data.getIntersecting(AttributeRegistry::getInstance()->getSpannersAttribute(), + static_cast(spanner.data())->getBounds(), results); - // clear/voxelize as appropriate - SharedObjectPointer heightfield; foreach (const SharedObjectPointer& result, results) { - Spanner* newSpanner = static_cast(result.data())->clearAndFetchHeight(bounds, heightfield); - if (newSpanner != result) { - data.replace(AttributeRegistry::getInstance()->getSpannersAttribute(), result, newSpanner); + Spanner* newResult = static_cast(result.data())->setMaterial(spanner, material, color); + if (newResult != result) { + data.replace(AttributeRegistry::getInstance()->getSpannersAttribute(), result, newResult); } } - - // voxelize the fetched heightfield, if any - if (heightfield) { - VoxelMaterialSpannerEditVisitor visitor(static_cast(heightfield.data()), material, color); - data.guide(visitor); - } - - VoxelMaterialSpannerEditVisitor visitor(spanner, material, color); - data.guide(visitor); } -PaintVoxelMaterialEdit::PaintVoxelMaterialEdit(const glm::vec3& position, float radius, - const SharedObjectPointer& material, const QColor& averageColor) : - MaterialEdit(material, averageColor), - position(position), - radius(radius) { -} - -class PaintVoxelMaterialEditVisitor : public MetavoxelVisitor { -public: - - PaintVoxelMaterialEditVisitor(const glm::vec3& position, float radius, - const SharedObjectPointer& material, const QColor& color); - - virtual int visit(MetavoxelInfo& info); - -private: - - glm::vec3 _position; - float _radius; - SharedObjectPointer _material; - QColor _color; - Box _bounds; -}; - -PaintVoxelMaterialEditVisitor::PaintVoxelMaterialEditVisitor(const glm::vec3& position, float radius, - const SharedObjectPointer& material, const QColor& color) : - MetavoxelVisitor(QVector() << AttributeRegistry::getInstance()->getVoxelColorAttribute() << - AttributeRegistry::getInstance()->getVoxelMaterialAttribute(), QVector() << - AttributeRegistry::getInstance()->getVoxelColorAttribute() << - AttributeRegistry::getInstance()->getVoxelMaterialAttribute()), - _position(position), - _radius(radius), - _material(material), - _color(color) { - - glm::vec3 extents(_radius, _radius, _radius); - _bounds = Box(_position - extents, _position + extents); -} - -int PaintVoxelMaterialEditVisitor::visit(MetavoxelInfo& info) { - if (!info.getBounds().intersects(_bounds)) { - return STOP_RECURSION; - } - if (!info.isLeaf) { - return DEFAULT_ORDER; - } - VoxelColorDataPointer colorPointer = info.inputValues.at(0).getInlineValue(); - VoxelMaterialDataPointer materialPointer = info.inputValues.at(1).getInlineValue(); - if (!(colorPointer && materialPointer && colorPointer->getSize() == materialPointer->getSize())) { - return STOP_RECURSION; - } - QVector colorContents = colorPointer->getContents(); - QByteArray materialContents = materialPointer->getContents(); - QVector materials = materialPointer->getMaterials(); - - Box overlap = info.getBounds().getIntersection(_bounds); - int size = colorPointer->getSize(); - int area = size * size; - float scale = (size - 1.0f) / info.size; - overlap.minimum = (overlap.minimum - info.minimum) * scale; - overlap.maximum = (overlap.maximum - info.minimum) * scale; - int minX = glm::ceil(overlap.minimum.x); - int minY = glm::ceil(overlap.minimum.y); - int minZ = glm::ceil(overlap.minimum.z); - int sizeX = (int)overlap.maximum.x - minX + 1; - int sizeY = (int)overlap.maximum.y - minY + 1; - int sizeZ = (int)overlap.maximum.z - minZ + 1; - - QRgb rgb = _color.rgba(); - float step = 1.0f / scale; - glm::vec3 position(0.0f, 0.0f, info.minimum.z + minZ * step); - uchar materialIndex = getMaterialIndex(_material, materials, materialContents); - QRgb* colorData = colorContents.data(); - uchar* materialData = (uchar*)materialContents.data(); - for (int destZ = minZ * area + minY * size + minX, endZ = destZ + sizeZ * area; destZ != endZ; - destZ += area, position.z += step) { - position.y = info.minimum.y + minY * step; - for (int destY = destZ, endY = destY + sizeY * size; destY != endY; destY += size, position.y += step) { - position.x = info.minimum.x + minX * step; - for (int destX = destY, endX = destX + sizeX; destX != endX; destX++, position.x += step) { - QRgb& color = colorData[destX]; - if (qAlpha(color) != 0 && glm::distance(position, _position) <= _radius) { - color = rgb; - materialData[destX] = materialIndex; - } - } - } - } - VoxelColorDataPointer newColorPointer(new VoxelColorData(colorContents, size)); - info.outputValues[0] = AttributeValue(info.inputValues.at(0).getAttribute(), - encodeInline(newColorPointer)); - - clearUnusedMaterials(materials, materialContents); - VoxelMaterialDataPointer newMaterialPointer(new VoxelMaterialData(materialContents, size, materials)); - info.outputValues[1] = AttributeValue(_inputs.at(1), encodeInline(newMaterialPointer)); - - return STOP_RECURSION; -} - -void PaintVoxelMaterialEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const { - // make sure it's 100% opaque - QColor color = averageColor; - color.setAlphaF(1.0f); - PaintVoxelMaterialEditVisitor visitor(position, radius, material, color); - data.guide(visitor); -} diff --git a/libraries/metavoxels/src/MetavoxelMessages.h b/libraries/metavoxels/src/MetavoxelMessages.h index 10477e0486..00c4353603 100644 --- a/libraries/metavoxels/src/MetavoxelMessages.h +++ b/libraries/metavoxels/src/MetavoxelMessages.h @@ -242,37 +242,20 @@ public: DECLARE_STREAMABLE_METATYPE(PaintHeightfieldMaterialEdit) -/// An edit that sets the materials of voxels within a spanner to a value. -class VoxelMaterialSpannerEdit : STREAM public MaterialEdit { +/// An edit that sets the materials of a heightfield within a spanner to a value. +class HeightfieldMaterialSpannerEdit : STREAM public MaterialEdit { STREAMABLE public: STREAM SharedObjectPointer spanner; - VoxelMaterialSpannerEdit(const SharedObjectPointer& spanner = SharedObjectPointer(), + HeightfieldMaterialSpannerEdit(const SharedObjectPointer& spanner = SharedObjectPointer(), const SharedObjectPointer& material = SharedObjectPointer(), const QColor& averageColor = QColor()); virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const; }; -DECLARE_STREAMABLE_METATYPE(VoxelMaterialSpannerEdit) - -/// An edit that sets a region of a voxel material. -class PaintVoxelMaterialEdit : STREAM public MaterialEdit { - STREAMABLE - -public: - - STREAM glm::vec3 position; - STREAM float radius; - - PaintVoxelMaterialEdit(const glm::vec3& position = glm::vec3(), float radius = 0.0f, - const SharedObjectPointer& material = SharedObjectPointer(), const QColor& averageColor = QColor()); - - virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const; -}; - -DECLARE_STREAMABLE_METATYPE(PaintVoxelMaterialEdit) +DECLARE_STREAMABLE_METATYPE(HeightfieldMaterialSpannerEdit) #endif // hifi_MetavoxelMessages_h diff --git a/libraries/metavoxels/src/Spanner.cpp b/libraries/metavoxels/src/Spanner.cpp index a976f56ae5..d743155a1e 100644 --- a/libraries/metavoxels/src/Spanner.cpp +++ b/libraries/metavoxels/src/Spanner.cpp @@ -123,7 +123,7 @@ Spanner* Spanner::clearAndFetchHeight(const Box& bounds, SharedObjectPointer& he return this; } -Spanner* Spanner::sculptMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material, +Spanner* Spanner::setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material, const QColor& color) { return this; } @@ -2244,8 +2244,36 @@ HeightfieldNode* HeightfieldNode::clearAndFetchHeight(const glm::vec3& translati return newNode; } -HeightfieldNode* HeightfieldNode::sculptMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material, - const QColor& color) { +HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale, + Spanner* spanner, const SharedObjectPointer& material, const QColor& color) { + Box bounds = glm::translate(translation) * glm::mat4_cast(rotation) * Box(glm::vec3(), scale); + if (!bounds.intersects(spanner->getBounds())) { + return this; + } + if (!isLeaf()) { + HeightfieldNode* newNode = this; + for (int i = 0; i < CHILD_COUNT; i++) { + glm::vec3 nextScale = scale * glm::vec3(0.5f, 1.0f, 0.5f); + HeightfieldNode* newChild = _children[i]->setMaterial(translation + + rotation * glm::vec3(i & X_MAXIMUM_FLAG ? nextScale.x : 0.0f, 0.0f, + i & Y_MAXIMUM_FLAG ? nextScale.z : 0.0f), rotation, + nextScale, spanner, material, color); + if (_children[i] != newChild) { + if (newNode == this) { + newNode = new HeightfieldNode(*this); + } + newNode->setChild(i, HeightfieldNodePointer(newChild)); + } + } + if (newNode != this) { + newNode->mergeChildren(); + } + return newNode; + } + if (!_height) { + return this; + } + return this; } @@ -2353,7 +2381,7 @@ void HeightfieldNode::writeDelta(const HeightfieldNodePointer& reference, Height state.base.stream.writeDelta(_height, reference->getHeight()); state.base.stream.writeDelta(_color, reference->getColor()); state.base.stream.writeDelta(_material, reference->getMaterial()); - state.base.stream.writeDelta(_material, reference->getStack()); + state.base.stream.writeDelta(_stack, reference->getStack()); } else { HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; @@ -2853,9 +2881,10 @@ Spanner* Heightfield::clearAndFetchHeight(const Box& bounds, SharedObjectPointer return newHeightfield; } -Spanner* Heightfield::sculptMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material, +Spanner* Heightfield::setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material, const QColor& color) { - HeightfieldNode* newRoot = _root->sculptMaterial(spanner, material, color); + HeightfieldNode* newRoot = _root->setMaterial(getTranslation(), getRotation(), glm::vec3(getScale(), + getScale() * _aspectY, getScale() * _aspectZ), static_cast(spanner.data()), material, color); if (_root == newRoot) { return this; } diff --git a/libraries/metavoxels/src/Spanner.h b/libraries/metavoxels/src/Spanner.h index 083dff3c5f..b7998d59c0 100644 --- a/libraries/metavoxels/src/Spanner.h +++ b/libraries/metavoxels/src/Spanner.h @@ -88,7 +88,7 @@ public: /// Attempts to "sculpt" with the supplied spanner. /// \return the modified spanner, or this if no modification was performed - virtual Spanner* sculptMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material, + virtual Spanner* setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material, const QColor& color); /// Checks whether this spanner has its own colors. @@ -583,8 +583,8 @@ public: HeightfieldNode* clearAndFetchHeight(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale, const Box& bounds, SharedObjectPointer& heightfield); - HeightfieldNode* sculptMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material, - const QColor& color); + HeightfieldNode* setMaterial(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale, + Spanner* spanner, const SharedObjectPointer& material, const QColor& color); void read(HeightfieldStreamState& state); void write(HeightfieldStreamState& state) const; @@ -679,7 +679,7 @@ public: virtual Spanner* clearAndFetchHeight(const Box& bounds, SharedObjectPointer& heightfield); - virtual Spanner* sculptMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material, + virtual Spanner* setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material, const QColor& color); virtual bool hasOwnColors() const;