More progress towards stacks.

This commit is contained in:
Andrzej Kapolka 2014-12-12 15:12:03 -08:00
parent 5e01695899
commit dfcb22bd7a
9 changed files with 123 additions and 370 deletions

View file

@ -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);
}

View file

@ -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); }

View file

@ -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*>(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<QWheelEvent*>(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<QMouseEvent*>(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()));
}
}

View file

@ -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

View file

@ -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);
}

View file

@ -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<AttributePointer>() << 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<Spanner*>(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<SharedObjectPointer> results;
data.getIntersecting(AttributeRegistry::getInstance()->getSpannersAttribute(), expandedBounds, results);
data.getIntersecting(AttributeRegistry::getInstance()->getSpannersAttribute(),
static_cast<Spanner*>(spanner.data())->getBounds(), results);
// clear/voxelize as appropriate
SharedObjectPointer heightfield;
foreach (const SharedObjectPointer& result, results) {
Spanner* newSpanner = static_cast<Spanner*>(result.data())->clearAndFetchHeight(bounds, heightfield);
if (newSpanner != result) {
data.replace(AttributeRegistry::getInstance()->getSpannersAttribute(), result, newSpanner);
Spanner* newResult = static_cast<Spanner*>(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<Spanner*>(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<AttributePointer>() << AttributeRegistry::getInstance()->getVoxelColorAttribute() <<
AttributeRegistry::getInstance()->getVoxelMaterialAttribute(), QVector<AttributePointer>() <<
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<VoxelColorDataPointer>();
VoxelMaterialDataPointer materialPointer = info.inputValues.at(1).getInlineValue<VoxelMaterialDataPointer>();
if (!(colorPointer && materialPointer && colorPointer->getSize() == materialPointer->getSize())) {
return STOP_RECURSION;
}
QVector<QRgb> colorContents = colorPointer->getContents();
QByteArray materialContents = materialPointer->getContents();
QVector<SharedObjectPointer> 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<VoxelColorDataPointer>(newColorPointer));
clearUnusedMaterials(materials, materialContents);
VoxelMaterialDataPointer newMaterialPointer(new VoxelMaterialData(materialContents, size, materials));
info.outputValues[1] = AttributeValue(_inputs.at(1), encodeInline<VoxelMaterialDataPointer>(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);
}

View file

@ -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

View file

@ -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*>(spanner.data()), material, color);
if (_root == newRoot) {
return this;
}

View file

@ -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;