mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 19:04:32 +02:00
More progress towards stacks.
This commit is contained in:
parent
5e01695899
commit
dfcb22bd7a
9 changed files with 123 additions and 370 deletions
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue