Push granularity option down the line in preparation for selectively

increasing resolution.
This commit is contained in:
Andrzej Kapolka 2015-01-23 13:58:51 -08:00
parent 3a1c99b5e5
commit bc0fa0ed24
7 changed files with 82 additions and 47 deletions

View file

@ -822,6 +822,12 @@ HeightfieldBrushTool::HeightfieldBrushTool(MetavoxelEditor* editor, const QStrin
_radius->setSingleStep(0.01);
_radius->setMaximum(FLT_MAX);
_radius->setValue(5.0);
_form->addRow("Granularity:", _granularity = new QDoubleSpinBox());
_granularity->setMinimum(-FLT_MAX);
_granularity->setMaximum(FLT_MAX);
_granularity->setPrefix("2^");
_granularity->setValue(8.0);
}
bool HeightfieldBrushTool::appliesTo(const AttributePointer& attribute) const {
@ -851,7 +857,7 @@ bool HeightfieldBrushTool::eventFilter(QObject* watched, QEvent* event) {
if (event->type() == QEvent::Wheel) {
float angle = static_cast<QWheelEvent*>(event)->angleDelta().y();
const float ANGLE_SCALE = 1.0f / 1000.0f;
_radius->setValue(_radius->value() * glm::pow(2.0f, angle * ANGLE_SCALE));
_radius->setValue(_radius->value() * pow(2.0f, angle * ANGLE_SCALE));
return true;
} else if (event->type() == QEvent::MouseButtonPress && _positionValid) {
@ -881,7 +887,7 @@ QVariant HeightfieldHeightBrushTool::createEdit(bool alternate) {
const int ERASE_MODE_INDEX = 2;
return QVariant::fromValue(PaintHeightfieldHeightEdit(_position, _radius->value(),
alternate ? -_height->value() : _height->value(), _mode->currentIndex() == SET_MODE_INDEX,
_mode->currentIndex() == ERASE_MODE_INDEX));
_mode->currentIndex() == ERASE_MODE_INDEX, pow(2.0f, _granularity->value())));
}
MaterialControl::MaterialControl(QWidget* widget, QFormLayout* form, bool clearable) :
@ -956,10 +962,11 @@ QVariant HeightfieldMaterialBrushTool::createEdit(bool alternate) {
sphere->setScale(_radius->value());
if (alternate) {
return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere),
SharedObjectPointer(), QColor(0, 0, 0, 0), true));
SharedObjectPointer(), QColor(0, 0, 0, 0), true, false, pow(2.0f, _granularity->value())));
} else {
return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere),
_materialControl->getMaterial(), _materialControl->getColor(), true));
_materialControl->getMaterial(), _materialControl->getColor(),
true, false, pow(2.0f, _granularity->value())));
}
}
@ -974,10 +981,11 @@ QVariant HeightfieldSculptBrushTool::createEdit(bool alternate) {
sphere->setScale(_radius->value());
if (alternate) {
return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere),
SharedObjectPointer(), QColor(0, 0, 0, 0)));
SharedObjectPointer(), QColor(0, 0, 0, 0), false, false, pow(2.0f, _granularity->value())));
} else {
return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere),
_materialControl->getMaterial(), _materialControl->getColor()));
_materialControl->getMaterial(), _materialControl->getColor(),
false, false, pow(2.0f, _granularity->value())));
}
}
@ -992,13 +1000,14 @@ HeightfieldFillBrushTool::HeightfieldFillBrushTool(MetavoxelEditor* editor) :
QVariant HeightfieldFillBrushTool::createEdit(bool alternate) {
const int FILL_MODE_INDEX = 0;
if (_mode->currentIndex() == FILL_MODE_INDEX) {
return QVariant::fromValue(FillHeightfieldHeightEdit(_position, _radius->value()));
return QVariant::fromValue(FillHeightfieldHeightEdit(_position, _radius->value(),
pow(2.0f, _granularity->value())));
}
Sphere* sphere = new Sphere();
sphere->setTranslation(_position);
sphere->setScale(_radius->value());
return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere),
SharedObjectPointer(), QColor(), false, true));
SharedObjectPointer(), QColor(), false, true, pow(2.0f, _granularity->value())));
}
HeightfieldMaterialBoxTool::HeightfieldMaterialBoxTool(MetavoxelEditor* editor) :
@ -1017,6 +1026,12 @@ HeightfieldMaterialBoxTool::HeightfieldMaterialBoxTool(MetavoxelEditor* editor)
_snapToGrid->setChecked(true);
_materialControl = new MaterialControl(this, form, true);
form->addRow("Granularity:", _granularity = new QDoubleSpinBox());
_granularity->setMinimum(-FLT_MAX);
_granularity->setMaximum(FLT_MAX);
_granularity->setPrefix("2^");
_granularity->setValue(8.0);
}
bool HeightfieldMaterialBoxTool::appliesTo(const AttributePointer& attribute) const {
@ -1039,7 +1054,7 @@ void HeightfieldMaterialBoxTool::applyValue(const glm::vec3& minimum, const glm:
cuboid->setAspectY(vector.y / vector.x);
cuboid->setAspectZ(vector.z / vector.x);
MetavoxelEditMessage message = { QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(cuboid),
_materialControl->getMaterial(), _materialControl->getColor())) };
_materialControl->getMaterial(), _materialControl->getColor(), false, false, pow(2.0f, _granularity->value()))) };
Application::getInstance()->getMetavoxels()->applyEdit(message, true);
}
@ -1056,6 +1071,12 @@ HeightfieldMaterialSpannerTool::HeightfieldMaterialSpannerTool(MetavoxelEditor*
_materialControl = new MaterialControl(this, form, true);
form->addRow("Granularity:", _granularity = new QDoubleSpinBox());
_granularity->setMinimum(-FLT_MAX);
_granularity->setMaximum(FLT_MAX);
_granularity->setPrefix("2^");
_granularity->setValue(8.0);
QPushButton* place = new QPushButton("Set");
layout()->addWidget(place);
connect(place, &QPushButton::clicked, this, &HeightfieldMaterialSpannerTool::place);
@ -1076,7 +1097,7 @@ QColor HeightfieldMaterialSpannerTool::getColor() {
void HeightfieldMaterialSpannerTool::applyEdit(const AttributePointer& attribute, const SharedObjectPointer& spanner) {
static_cast<Spanner*>(spanner.data())->setWillBeVoxelized(true);
MetavoxelEditMessage message = { QVariant::fromValue(HeightfieldMaterialSpannerEdit(spanner,
_materialControl->getMaterial(), _materialControl->getColor())) };
_materialControl->getMaterial(), _materialControl->getColor(), false, false, pow(2.0f, _granularity->value()))) };
Application::getInstance()->getMetavoxels()->applyEdit(message, true);
}

View file

@ -326,6 +326,7 @@ protected:
QFormLayout* _form;
QDoubleSpinBox* _radius;
QDoubleSpinBox* _granularity;
glm::vec3 _position;
bool _positionValid;
@ -448,6 +449,7 @@ private:
QCheckBox* _snapToGrid;
MaterialControl* _materialControl;
QDoubleSpinBox* _granularity;
};
/// Allows setting heightfield materials by placing a spanner.
@ -470,6 +472,7 @@ private:
SharedObjectEditor* _spannerEditor;
MaterialControl* _materialControl;
QDoubleSpinBox* _granularity;
};
#endif // hifi_MetavoxelEditor_h

View file

@ -149,12 +149,13 @@ void SetDataEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects
}
PaintHeightfieldHeightEdit::PaintHeightfieldHeightEdit(const glm::vec3& position, float radius,
float height, bool set, bool erase) :
float height, bool set, bool erase, float granularity) :
position(position),
radius(radius),
height(height),
set(set),
erase(erase) {
erase(erase),
granularity(granularity) {
}
void PaintHeightfieldHeightEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
@ -166,7 +167,8 @@ void PaintHeightfieldHeightEdit::apply(MetavoxelData& data, const WeakSharedObje
Box(position - extents, position + extents), results);
foreach (const SharedObjectPointer& spanner, results) {
Spanner* newSpanner = static_cast<Spanner*>(spanner.data())->paintHeight(position, radius, height, set, erase);
Spanner* newSpanner = static_cast<Spanner*>(spanner.data())->paintHeight(position, radius,
height, set, erase, granularity);
if (newSpanner != spanner) {
data.replace(AttributeRegistry::getInstance()->getSpannersAttribute(), spanner, newSpanner);
}
@ -179,11 +181,12 @@ MaterialEdit::MaterialEdit(const SharedObjectPointer& material, const QColor& av
}
HeightfieldMaterialSpannerEdit::HeightfieldMaterialSpannerEdit(const SharedObjectPointer& spanner,
const SharedObjectPointer& material, const QColor& averageColor, bool paint, bool voxelize) :
const SharedObjectPointer& material, const QColor& averageColor, bool paint, bool voxelize, float granularity) :
MaterialEdit(material, averageColor),
spanner(spanner),
paint(paint),
voxelize(voxelize) {
voxelize(voxelize),
granularity(granularity) {
}
class SpannerProjectionFetchVisitor : public SpannerVisitor {
@ -250,16 +253,18 @@ void HeightfieldMaterialSpannerEdit::apply(MetavoxelData& data, const WeakShared
}
foreach (const SharedObjectPointer& result, results) {
Spanner* newResult = static_cast<Spanner*>(result.data())->setMaterial(spanner, material, color, paint, voxelize);
Spanner* newResult = static_cast<Spanner*>(result.data())->setMaterial(spanner, material,
color, paint, voxelize, granularity);
if (newResult != result) {
data.replace(AttributeRegistry::getInstance()->getSpannersAttribute(), result, newResult);
}
}
}
FillHeightfieldHeightEdit::FillHeightfieldHeightEdit(const glm::vec3& position, float radius) :
FillHeightfieldHeightEdit::FillHeightfieldHeightEdit(const glm::vec3& position, float radius, float granularity) :
position(position),
radius(radius) {
radius(radius),
granularity(granularity) {
}
void FillHeightfieldHeightEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
@ -269,7 +274,7 @@ void FillHeightfieldHeightEdit::apply(MetavoxelData& data, const WeakSharedObjec
Box(position - extents, position + extents), results);
foreach (const SharedObjectPointer& spanner, results) {
Spanner* newSpanner = static_cast<Spanner*>(spanner.data())->fillHeight(position, radius);
Spanner* newSpanner = static_cast<Spanner*>(spanner.data())->fillHeight(position, radius, granularity);
if (newSpanner != spanner) {
data.replace(AttributeRegistry::getInstance()->getSpannersAttribute(), spanner, newSpanner);
}

View file

@ -205,9 +205,10 @@ public:
STREAM float height;
STREAM bool set;
STREAM bool erase;
STREAM float granularity;
PaintHeightfieldHeightEdit(const glm::vec3& position = glm::vec3(), float radius = 0.0f,
float height = 0.0f, bool set = false, bool erase = false);
float height = 0.0f, bool set = false, bool erase = false, float granularity = 0.0f);
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
};
@ -237,10 +238,11 @@ public:
STREAM SharedObjectPointer spanner;
STREAM bool paint;
STREAM bool voxelize;
STREAM float granularity;
HeightfieldMaterialSpannerEdit(const SharedObjectPointer& spanner = SharedObjectPointer(),
const SharedObjectPointer& material = SharedObjectPointer(),
const QColor& averageColor = QColor(), bool paint = false, bool voxelize = false);
const QColor& averageColor = QColor(), bool paint = false, bool voxelize = false, float granularity = 0.0f);
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
};
@ -255,8 +257,9 @@ public:
STREAM glm::vec3 position;
STREAM float radius;
STREAM float granularity;
FillHeightfieldHeightEdit(const glm::vec3& position = glm::vec3(), float radius = 0.0f);
FillHeightfieldHeightEdit(const glm::vec3& position = glm::vec3(), float radius = 0.0f, float granularity = 0.0f);
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
};

View file

@ -111,16 +111,16 @@ bool Spanner::findRayIntersection(const glm::vec3& origin, const glm::vec3& dire
return _bounds.findRayIntersection(origin, direction, distance);
}
Spanner* Spanner::paintHeight(const glm::vec3& position, float radius, float height, bool set, bool erase) {
Spanner* Spanner::paintHeight(const glm::vec3& position, float radius, float height, bool set, bool erase, float granularity) {
return this;
}
Spanner* Spanner::fillHeight(const glm::vec3& position, float radius) {
Spanner* Spanner::fillHeight(const glm::vec3& position, float radius, float granularity) {
return this;
}
Spanner* Spanner::setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material,
const QColor& color, bool paint, bool voxelize) {
const QColor& color, bool paint, bool voxelize, float granularity) {
return this;
}
@ -1786,7 +1786,7 @@ void HeightfieldNode::getRangeAfterHeightPaint(const glm::vec3& translation, con
HeightfieldNode* HeightfieldNode::paintHeight(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
const glm::vec3& position, float radius, float height, bool set, bool erase,
float normalizeScale, float normalizeOffset) {
float normalizeScale, float normalizeOffset, float granularity) {
if (!_height) {
return this;
}
@ -1813,7 +1813,7 @@ HeightfieldNode* HeightfieldNode::paintHeight(const glm::vec3& translation, cons
HeightfieldNode* newChild = _children[i]->paintHeight(translation +
rotation * glm::vec3(i & X_MAXIMUM_FLAG ? nextScale.x : 0.0f, 0.0f,
i & Y_MAXIMUM_FLAG ? nextScale.z : 0.0f), rotation,
nextScale, position, radius, height, set, erase, normalizeScale, normalizeOffset);
nextScale, position, radius, height, set, erase, normalizeScale, normalizeOffset, granularity);
if (_children[i] != newChild) {
if (newNode == this) {
newNode = new HeightfieldNode(*this);
@ -1885,7 +1885,7 @@ HeightfieldNode* HeightfieldNode::paintHeight(const glm::vec3& translation, cons
}
HeightfieldNode* HeightfieldNode::fillHeight(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
const glm::vec3& position, float radius) {
const glm::vec3& position, float radius, float granularity) {
if (!_height) {
return this;
}
@ -1911,7 +1911,7 @@ HeightfieldNode* HeightfieldNode::fillHeight(const glm::vec3& translation, const
HeightfieldNode* newChild = _children[i]->fillHeight(translation +
rotation * glm::vec3(i & X_MAXIMUM_FLAG ? nextScale.x : 0.0f, 0.0f,
i & Y_MAXIMUM_FLAG ? nextScale.z : 0.0f), rotation,
nextScale, position, radius);
nextScale, position, radius, granularity);
if (_children[i] != newChild) {
if (newNode == this) {
newNode = new HeightfieldNode(*this);
@ -2088,7 +2088,7 @@ void HeightfieldNode::getRangeAfterEdit(const glm::vec3& translation, const glm:
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, bool voxelize,
float normalizeScale, float normalizeOffset) {
float normalizeScale, float normalizeOffset, float granularity) {
if (!_height) {
return this;
}
@ -2109,7 +2109,7 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
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, voxelize, normalizeScale, normalizeOffset);
material, color, paint, voxelize, normalizeScale, normalizeOffset, granularity);
if (_children[i] != newChild) {
if (newNode == this) {
newNode = new HeightfieldNode(*this);
@ -3310,7 +3310,8 @@ bool Heightfield::findRayIntersection(const glm::vec3& origin, const glm::vec3&
getScale() * _aspectZ), origin, direction, distance);
}
Spanner* Heightfield::paintHeight(const glm::vec3& position, float radius, float height, bool set, bool erase) {
Spanner* Heightfield::paintHeight(const glm::vec3& position, float radius, float height,
bool set, bool erase, float granularity) {
// first see if we're going to exceed the range limits
float minimumValue = 1.0f, maximumValue = numeric_limits<quint16>::max();
if (set) {
@ -3328,19 +3329,19 @@ Spanner* Heightfield::paintHeight(const glm::vec3& position, float radius, float
Heightfield* newHeightfield = prepareEdit(minimumValue, maximumValue, normalizeScale, normalizeOffset);
newHeightfield->setRoot(HeightfieldNodePointer(_root->paintHeight(newHeightfield->getTranslation(), getRotation(),
glm::vec3(getScale(), getScale() * newHeightfield->getAspectY(), getScale() * _aspectZ), position, radius, height,
set, erase, normalizeScale, normalizeOffset)));
set, erase, normalizeScale, normalizeOffset, granularity)));
return newHeightfield;
}
Spanner* Heightfield::fillHeight(const glm::vec3& position, float radius) {
Spanner* Heightfield::fillHeight(const glm::vec3& position, float radius, float granularity) {
Heightfield* newHeightfield = static_cast<Heightfield*>(clone(true));
newHeightfield->setRoot(HeightfieldNodePointer(_root->fillHeight(getTranslation(), getRotation(),
glm::vec3(getScale(), getScale() * _aspectY, getScale() * _aspectZ), position, radius)));
glm::vec3(getScale(), getScale() * _aspectY, getScale() * _aspectZ), position, radius, granularity)));
return newHeightfield;
}
Spanner* Heightfield::setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material,
const QColor& color, bool paint, bool voxelize) {
const QColor& color, bool paint, bool voxelize, float granularity) {
// first see if we're going to exceed the range limits, normalizing if necessary
Spanner* spannerData = static_cast<Spanner*>(spanner.data());
float normalizeScale = 1.0f, normalizeOffset = 0.0f;
@ -3355,7 +3356,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, voxelize, normalizeScale, normalizeOffset)));
material, color, paint, voxelize, normalizeScale, normalizeOffset, granularity)));
return newHeightfield;
}

View file

@ -77,16 +77,17 @@ public:
/// \param set whether to set the height as opposed to raising/lowering it
/// \param erase whether to erase height values
/// \return the modified spanner, or this if no modification was performed
virtual Spanner* paintHeight(const glm::vec3& position, float radius, float height, bool set, bool erase);
virtual Spanner* paintHeight(const glm::vec3& position, float radius, float height,
bool set, bool erase, float granularity);
/// 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);
virtual Spanner* fillHeight(const glm::vec3& position, float radius, float granularity);
/// 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, bool voxelize);
const QColor& color, bool paint, bool voxelize, float granularity);
/// Checks whether this spanner has its own colors.
virtual bool hasOwnColors() const;
@ -696,17 +697,17 @@ public:
HeightfieldNode* paintHeight(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
const glm::vec3& position, float radius, float height, bool set, bool erase,
float normalizeScale, float normalizeOffset);
float normalizeScale, float normalizeOffset, float granularity);
HeightfieldNode* fillHeight(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
const glm::vec3& position, float radius);
const glm::vec3& position, float radius, float granularity);
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, bool voxelize,
float normalizeScale, float normalizeOffset);
float normalizeScale, float normalizeOffset, float granularity);
void read(HeightfieldStreamState& state);
void write(HeightfieldStreamState& state) const;
@ -803,12 +804,13 @@ public:
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
virtual Spanner* paintHeight(const glm::vec3& position, float radius, float height, bool set, bool erase);
virtual Spanner* paintHeight(const glm::vec3& position, float radius, float height,
bool set, bool erase, float granularity);
virtual Spanner* fillHeight(const glm::vec3& position, float radius);
virtual Spanner* fillHeight(const glm::vec3& position, float radius, float granularity);
virtual Spanner* setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material,
const QColor& color, bool paint, bool voxelize);
const QColor& color, bool paint, bool voxelize, float granularity);
virtual bool hasOwnColors() const;
virtual bool hasOwnMaterials() const;

View file

@ -78,7 +78,7 @@ PacketVersion versionForPacketType(PacketType type) {
case PacketTypeAudioStreamStats:
return 1;
case PacketTypeMetavoxelData:
return 12;
return 13;
default:
return 0;
}