diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index bb05d054d8..6bd1ea2438 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -821,7 +821,7 @@ HeightfieldBrushTool::HeightfieldBrushTool(MetavoxelEditor* editor, const QStrin _form->addRow("Radius:", _radius = new QDoubleSpinBox()); _radius->setSingleStep(0.01); _radius->setMaximum(FLT_MAX); - _radius->setValue(1.0); + _radius->setValue(5.0); } bool HeightfieldBrushTool::appliesTo(const AttributePointer& attribute) const { @@ -975,10 +975,21 @@ QVariant HeightfieldSculptBrushTool::createEdit(bool alternate) { HeightfieldFillBrushTool::HeightfieldFillBrushTool(MetavoxelEditor* editor) : HeightfieldBrushTool(editor, "Fill Brush") { + + _form->addRow("Mode:", _mode = new QComboBox()); + _mode->addItem("Fill"); + _mode->addItem("Voxelize"); } QVariant HeightfieldFillBrushTool::createEdit(bool alternate) { - return QVariant::fromValue(FillHeightfieldHeightEdit(_position, _radius->value())); + if (_mode->currentIndex() == 0) { + return QVariant::fromValue(FillHeightfieldHeightEdit(_position, _radius->value())); + } + Sphere* sphere = new Sphere(); + sphere->setTranslation(_position); + sphere->setScale(_radius->value()); + return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere), + SharedObjectPointer(), QColor(), false, true)); } HeightfieldMaterialBoxTool::HeightfieldMaterialBoxTool(MetavoxelEditor* editor) : diff --git a/interface/src/ui/MetavoxelEditor.h b/interface/src/ui/MetavoxelEditor.h index 922cb298c4..5ddf582f52 100644 --- a/interface/src/ui/MetavoxelEditor.h +++ b/interface/src/ui/MetavoxelEditor.h @@ -419,6 +419,10 @@ public: protected: virtual QVariant createEdit(bool alternate); + +private: + + QComboBox* _mode; }; /// Allows setting heightfield materials by dragging out a box. diff --git a/libraries/metavoxels/src/MetavoxelMessages.cpp b/libraries/metavoxels/src/MetavoxelMessages.cpp index a5bcd5fc40..f95efeb359 100644 --- a/libraries/metavoxels/src/MetavoxelMessages.cpp +++ b/libraries/metavoxels/src/MetavoxelMessages.cpp @@ -176,10 +176,11 @@ MaterialEdit::MaterialEdit(const SharedObjectPointer& material, const QColor& av } HeightfieldMaterialSpannerEdit::HeightfieldMaterialSpannerEdit(const SharedObjectPointer& spanner, - const SharedObjectPointer& material, const QColor& averageColor, bool paint) : + const SharedObjectPointer& material, const QColor& averageColor, bool paint, bool voxelize) : MaterialEdit(material, averageColor), spanner(spanner), - paint(paint) { + paint(paint), + voxelize(voxelize) { } class SpannerProjectionFetchVisitor : public SpannerVisitor { @@ -246,7 +247,7 @@ void HeightfieldMaterialSpannerEdit::apply(MetavoxelData& data, const WeakShared } foreach (const SharedObjectPointer& result, results) { - Spanner* newResult = static_cast(result.data())->setMaterial(spanner, material, color, paint); + Spanner* newResult = static_cast(result.data())->setMaterial(spanner, material, color, paint, voxelize); if (newResult != result) { data.replace(AttributeRegistry::getInstance()->getSpannersAttribute(), result, newResult); } diff --git a/libraries/metavoxels/src/MetavoxelMessages.h b/libraries/metavoxels/src/MetavoxelMessages.h index 0605fb4dd2..4e478e5109 100644 --- a/libraries/metavoxels/src/MetavoxelMessages.h +++ b/libraries/metavoxels/src/MetavoxelMessages.h @@ -233,17 +233,18 @@ public: STREAM SharedObjectPointer spanner; STREAM bool paint; + STREAM bool voxelize; HeightfieldMaterialSpannerEdit(const SharedObjectPointer& spanner = SharedObjectPointer(), const SharedObjectPointer& material = SharedObjectPointer(), - const QColor& averageColor = QColor(), bool paint = false); + const QColor& averageColor = QColor(), bool paint = false, bool voxelize = false); virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const; }; DECLARE_STREAMABLE_METATYPE(HeightfieldMaterialSpannerEdit) -/// An edit that sets a region of a heightfield height. +/// An edit that fills a region of a heightfield height. class FillHeightfieldHeightEdit : public MetavoxelEdit { STREAMABLE @@ -251,7 +252,7 @@ public: STREAM glm::vec3 position; STREAM float radius; - + FillHeightfieldHeightEdit(const glm::vec3& position = glm::vec3(), float radius = 0.0f); virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const; diff --git a/libraries/metavoxels/src/Spanner.cpp b/libraries/metavoxels/src/Spanner.cpp index 1937dd5934..f9e650f4ca 100644 --- a/libraries/metavoxels/src/Spanner.cpp +++ b/libraries/metavoxels/src/Spanner.cpp @@ -120,7 +120,7 @@ Spanner* Spanner::fillHeight(const glm::vec3& position, float radius) { } Spanner* Spanner::setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material, - const QColor& color, bool paint) { + const QColor& color, bool paint, bool voxelize) { return this; } @@ -2129,7 +2129,7 @@ static inline bool isSet(const QVector& stackContents, int stackWidt } HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale, - Spanner* spanner, const SharedObjectPointer& material, const QColor& color, bool paint, + Spanner* spanner, const SharedObjectPointer& material, const QColor& color, bool paint, bool voxelize, float normalizeScale, float normalizeOffset) { if (!_height) { return this; @@ -2150,8 +2150,8 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons 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, paint, normalizeScale, normalizeOffset); + i & Y_MAXIMUM_FLAG ? nextScale.z : 0.0f), rotation, nextScale, spanner, + material, color, paint, voxelize, normalizeScale, normalizeOffset); if (_children[i] != newChild) { if (newNode == this) { newNode = new HeightfieldNode(*this); @@ -2399,7 +2399,8 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons float oldVoxelHeight = *oldHeightLineDest * voxelScale; float oldNextVoxelHeightX = oldHeightLineDest[1] * voxelScale; float oldNextVoxelHeightZ = oldHeightLineDest[heightWidth] * voxelScale; - for (int y = newTop; y >= newBottom; y--, entryDest--, pos -= worldStepY) { + // skip the actual set if voxelizing + for (int y = voxelize ? newBottom - 1 : newTop; y >= newBottom; y--, entryDest--, pos -= worldStepY) { int oldCurrentAlpha = stackDest->getEntryAlpha(y, oldVoxelHeight); if (spanner->contains(pos)) { if (hasOwnColors && !erase) { @@ -3376,7 +3377,7 @@ Spanner* Heightfield::fillHeight(const glm::vec3& position, float radius) { } Spanner* Heightfield::setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material, - const QColor& color, bool paint) { + const QColor& color, bool paint, bool voxelize) { // first see if we're going to exceed the range limits, normalizing if necessary Spanner* spannerData = static_cast(spanner.data()); float normalizeScale = 1.0f, normalizeOffset = 0.0f; @@ -3391,7 +3392,7 @@ Spanner* Heightfield::setMaterial(const SharedObjectPointer& spanner, const Shar } newHeightfield->setRoot(HeightfieldNodePointer(_root->setMaterial(newHeightfield->getTranslation(), getRotation(), glm::vec3(getScale(), getScale() * newHeightfield->getAspectY(), getScale() * _aspectZ), spannerData, - material, color, paint, normalizeScale, normalizeOffset))); + material, color, paint, voxelize, normalizeScale, normalizeOffset))); return newHeightfield; } diff --git a/libraries/metavoxels/src/Spanner.h b/libraries/metavoxels/src/Spanner.h index 6a445ad84e..48daf380fd 100644 --- a/libraries/metavoxels/src/Spanner.h +++ b/libraries/metavoxels/src/Spanner.h @@ -77,14 +77,14 @@ public: /// \return the modified spanner, or this if no modification was performed virtual Spanner* paintHeight(const glm::vec3& position, float radius, float height); - /// Attempts to fill the spanner's height (removing volumetric information). + /// Attempts to fill the spanner's height (adding removing volumetric information). /// \return the modified spanner, or this if no modification was performed virtual Spanner* fillHeight(const glm::vec3& position, float radius); - /// Attempts to "sculpt" or "paint" with the supplied spanner. + /// Attempts to "sculpt" or "paint," etc., with the supplied spanner. /// \return the modified spanner, or this if no modification was performed virtual Spanner* setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material, - const QColor& color, bool paint); + const QColor& color, bool paint, bool voxelize); /// Checks whether this spanner has its own colors. virtual bool hasOwnColors() const; @@ -700,9 +700,9 @@ public: void getRangeAfterEdit(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale, const Box& editBounds, float& minimum, float& maximum) const; - + HeightfieldNode* setMaterial(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale, - Spanner* spanner, const SharedObjectPointer& material, const QColor& color, bool paint, + Spanner* spanner, const SharedObjectPointer& material, const QColor& color, bool paint, bool voxelize, float normalizeScale, float normalizeOffset); void read(HeightfieldStreamState& state); @@ -805,7 +805,7 @@ public: virtual Spanner* fillHeight(const glm::vec3& position, float radius); virtual Spanner* setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material, - const QColor& color, bool paint); + const QColor& color, bool paint, bool voxelize); virtual bool hasOwnColors() const; virtual bool hasOwnMaterials() const;