mirror of
https://github.com/overte-org/overte.git
synced 2025-07-10 18:58:37 +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);
|
applyMaterialEdit(edit, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetavoxelSystem::paintVoxelColor(const glm::vec3& position, float radius, const QColor& color) {
|
void MetavoxelSystem::setHeightfieldColor(const SharedObjectPointer& spanner, const QColor& color) {
|
||||||
MetavoxelEditMessage edit = { QVariant::fromValue(PaintVoxelMaterialEdit(position, radius, SharedObjectPointer(), color)) };
|
MetavoxelEditMessage edit = { QVariant::fromValue(HeightfieldMaterialSpannerEdit(spanner, SharedObjectPointer(), color)) };
|
||||||
applyEdit(edit, true);
|
applyEdit(edit, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetavoxelSystem::paintVoxelMaterial(const glm::vec3& position, float radius, const SharedObjectPointer& material) {
|
void MetavoxelSystem::setHeightfieldMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material) {
|
||||||
MetavoxelEditMessage edit = { QVariant::fromValue(PaintVoxelMaterialEdit(position, radius, material)) };
|
MetavoxelEditMessage edit = { QVariant::fromValue(HeightfieldMaterialSpannerEdit(spanner, 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)) };
|
|
||||||
applyMaterialEdit(edit, true);
|
applyMaterialEdit(edit, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,13 +76,9 @@ public:
|
||||||
|
|
||||||
Q_INVOKABLE void paintHeightfieldMaterial(const glm::vec3& position, float radius, const SharedObjectPointer& material);
|
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 setHeightfieldColor(const SharedObjectPointer& spanner, const QColor& color);
|
||||||
|
|
||||||
Q_INVOKABLE void paintVoxelMaterial(const glm::vec3& position, float radius, const SharedObjectPointer& material);
|
|
||||||
|
|
||||||
Q_INVOKABLE void setVoxelColor(const SharedObjectPointer& spanner, const QColor& color);
|
Q_INVOKABLE void setHeightfieldMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material);
|
||||||
|
|
||||||
Q_INVOKABLE void setVoxelMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material);
|
|
||||||
|
|
||||||
void addHeightfieldBaseBatch(const HeightfieldBaseLayerBatch& batch) { _heightfieldBaseBatches.append(batch); }
|
void addHeightfieldBaseBatch(const HeightfieldBaseLayerBatch& batch) { _heightfieldBaseBatches.append(batch); }
|
||||||
void addHeightfieldSplatBatch(const HeightfieldSplatBatch& batch) { _heightfieldSplatBatches.append(batch); }
|
void addHeightfieldSplatBatch(const HeightfieldSplatBatch& batch) { _heightfieldSplatBatches.append(batch); }
|
||||||
|
|
|
@ -122,13 +122,12 @@ MetavoxelEditor::MetavoxelEditor() :
|
||||||
addTool(new InsertSpannerTool(this));
|
addTool(new InsertSpannerTool(this));
|
||||||
addTool(new RemoveSpannerTool(this));
|
addTool(new RemoveSpannerTool(this));
|
||||||
addTool(new ClearSpannersTool(this));
|
addTool(new ClearSpannersTool(this));
|
||||||
|
addTool(new ImportHeightfieldTool(this));
|
||||||
addTool(new HeightfieldHeightBrushTool(this));
|
addTool(new HeightfieldHeightBrushTool(this));
|
||||||
addTool(new HeightfieldMaterialBrushTool(this));
|
addTool(new HeightfieldMaterialBrushTool(this));
|
||||||
addTool(new ImportHeightfieldTool(this));
|
addTool(new HeightfieldSculptBrushTool(this));
|
||||||
addTool(new VoxelMaterialBoxTool(this));
|
addTool(new HeightfieldMaterialBoxTool(this));
|
||||||
addTool(new VoxelMaterialSpannerTool(this));
|
addTool(new HeightfieldMaterialSpannerTool(this));
|
||||||
addTool(new VoxelMaterialBrushTool(this));
|
|
||||||
addTool(new VoxelSculptBrushTool(this));
|
|
||||||
|
|
||||||
updateAttributes();
|
updateAttributes();
|
||||||
|
|
||||||
|
@ -944,8 +943,26 @@ QVariant HeightfieldMaterialBrushTool::createEdit(bool alternate) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VoxelMaterialBoxTool::VoxelMaterialBoxTool(MetavoxelEditor* editor) :
|
HeightfieldSculptBrushTool::HeightfieldSculptBrushTool(MetavoxelEditor* editor) :
|
||||||
BoxTool(editor, "Set Voxel Material (Box)", false) {
|
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();
|
QWidget* widget = new QWidget();
|
||||||
QFormLayout* form = new QFormLayout();
|
QFormLayout* form = new QFormLayout();
|
||||||
|
@ -962,32 +979,32 @@ VoxelMaterialBoxTool::VoxelMaterialBoxTool(MetavoxelEditor* editor) :
|
||||||
_materialControl = new MaterialControl(this, form, true);
|
_materialControl = new MaterialControl(this, form, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VoxelMaterialBoxTool::appliesTo(const AttributePointer& attribute) const {
|
bool HeightfieldMaterialBoxTool::appliesTo(const AttributePointer& attribute) const {
|
||||||
return attribute->inherits("VoxelColorAttribute");
|
return attribute->inherits("SpannerSetAttribute");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VoxelMaterialBoxTool::shouldSnapToGrid() {
|
bool HeightfieldMaterialBoxTool::shouldSnapToGrid() {
|
||||||
return _snapToGrid->isChecked();
|
return _snapToGrid->isChecked();
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor VoxelMaterialBoxTool::getColor() {
|
QColor HeightfieldMaterialBoxTool::getColor() {
|
||||||
return _materialControl->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* cuboid = new Cuboid();
|
||||||
cuboid->setTranslation((maximum + minimum) * 0.5f);
|
cuboid->setTranslation((maximum + minimum) * 0.5f);
|
||||||
glm::vec3 vector = (maximum - minimum) * 0.5f;
|
glm::vec3 vector = (maximum - minimum) * 0.5f;
|
||||||
cuboid->setScale(vector.x);
|
cuboid->setScale(vector.x);
|
||||||
cuboid->setAspectY(vector.y / vector.x);
|
cuboid->setAspectY(vector.y / vector.x);
|
||||||
cuboid->setAspectZ(vector.z / 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())) };
|
_materialControl->getMaterial(), _materialControl->getColor())) };
|
||||||
Application::getInstance()->getMetavoxels()->applyEdit(message, true);
|
Application::getInstance()->getMetavoxels()->applyEdit(message, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
VoxelMaterialSpannerTool::VoxelMaterialSpannerTool(MetavoxelEditor* editor) :
|
HeightfieldMaterialSpannerTool::HeightfieldMaterialSpannerTool(MetavoxelEditor* editor) :
|
||||||
PlaceSpannerTool(editor, "Set Voxel Material (Spanner)", QString(), false) {
|
PlaceSpannerTool(editor, "Set Material (Spanner)", QString(), false) {
|
||||||
|
|
||||||
QWidget* widget = new QWidget();
|
QWidget* widget = new QWidget();
|
||||||
QFormLayout* form = new QFormLayout();
|
QFormLayout* form = new QFormLayout();
|
||||||
|
@ -1001,110 +1018,25 @@ VoxelMaterialSpannerTool::VoxelMaterialSpannerTool(MetavoxelEditor* editor) :
|
||||||
|
|
||||||
QPushButton* place = new QPushButton("Set");
|
QPushButton* place = new QPushButton("Set");
|
||||||
layout()->addWidget(place);
|
layout()->addWidget(place);
|
||||||
connect(place, &QPushButton::clicked, this, &VoxelMaterialSpannerTool::place);
|
connect(place, &QPushButton::clicked, this, &HeightfieldMaterialSpannerTool::place);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VoxelMaterialSpannerTool::appliesTo(const AttributePointer& attribute) const {
|
bool HeightfieldMaterialSpannerTool::appliesTo(const AttributePointer& attribute) const {
|
||||||
return attribute->inherits("VoxelColorAttribute");
|
return attribute->inherits("SpannerSetAttribute");
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedObjectPointer VoxelMaterialSpannerTool::getSpanner() {
|
SharedObjectPointer HeightfieldMaterialSpannerTool::getSpanner() {
|
||||||
return _spannerEditor->getObject();
|
return _spannerEditor->getObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor VoxelMaterialSpannerTool::getColor() {
|
QColor HeightfieldMaterialSpannerTool::getColor() {
|
||||||
return _materialControl->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);
|
static_cast<Spanner*>(spanner.data())->setWillBeVoxelized(true);
|
||||||
MetavoxelEditMessage message = { QVariant::fromValue(VoxelMaterialSpannerEdit(spanner,
|
MetavoxelEditMessage message = { QVariant::fromValue(HeightfieldMaterialSpannerEdit(spanner,
|
||||||
_materialControl->getMaterial(), _materialControl->getColor())) };
|
_materialControl->getMaterial(), _materialControl->getColor())) };
|
||||||
Application::getInstance()->getMetavoxels()->applyEdit(message, true);
|
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;
|
MaterialControl* _materialControl;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Allows setting voxel materials by dragging out a box.
|
/// Allows sculpting parts of the heightfield.
|
||||||
class VoxelMaterialBoxTool : public BoxTool {
|
class HeightfieldSculptBrushTool : public HeightfieldBrushTool {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
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;
|
virtual bool appliesTo(const AttributePointer& attribute) const;
|
||||||
|
|
||||||
|
@ -410,13 +427,13 @@ private:
|
||||||
MaterialControl* _materialControl;
|
MaterialControl* _materialControl;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Allows setting voxel materials by placing a spanner.
|
/// Allows setting heightfield materials by placing a spanner.
|
||||||
class VoxelMaterialSpannerTool : public PlaceSpannerTool {
|
class HeightfieldMaterialSpannerTool : public PlaceSpannerTool {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
VoxelMaterialSpannerTool(MetavoxelEditor* editor);
|
HeightfieldMaterialSpannerTool(MetavoxelEditor* editor);
|
||||||
|
|
||||||
virtual bool appliesTo(const AttributePointer& attribute) const;
|
virtual bool appliesTo(const AttributePointer& attribute) const;
|
||||||
|
|
||||||
|
@ -432,63 +449,4 @@ private:
|
||||||
MaterialControl* _materialControl;
|
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
|
#endif // hifi_MetavoxelEditor_h
|
||||||
|
|
|
@ -53,7 +53,6 @@ AttributeRegistry::AttributeRegistry() :
|
||||||
|
|
||||||
const float VOXEL_LOD_THRESHOLD_MULTIPLIER = 16.0f;
|
const float VOXEL_LOD_THRESHOLD_MULTIPLIER = 16.0f;
|
||||||
_voxelColorAttribute->setLODThresholdMultiplier(VOXEL_LOD_THRESHOLD_MULTIPLIER);
|
_voxelColorAttribute->setLODThresholdMultiplier(VOXEL_LOD_THRESHOLD_MULTIPLIER);
|
||||||
_voxelColorAttribute->setUserFacing(true);
|
|
||||||
_voxelMaterialAttribute->setLODThresholdMultiplier(VOXEL_LOD_THRESHOLD_MULTIPLIER);
|
_voxelMaterialAttribute->setLODThresholdMultiplier(VOXEL_LOD_THRESHOLD_MULTIPLIER);
|
||||||
_voxelHermiteAttribute->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_AREA = VOXEL_BLOCK_SAMPLES * VOXEL_BLOCK_SAMPLES;
|
||||||
const int VOXEL_BLOCK_VOLUME = VOXEL_BLOCK_AREA * 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) :
|
const SharedObjectPointer& material, const QColor& averageColor) :
|
||||||
MaterialEdit(material, averageColor),
|
MaterialEdit(material, averageColor),
|
||||||
spanner(spanner) {
|
spanner(spanner) {
|
||||||
}
|
}
|
||||||
|
|
||||||
class VoxelMaterialSpannerEditVisitor : public MetavoxelVisitor {
|
class HeightfieldMaterialSpannerEditVisitor : public MetavoxelVisitor {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
VoxelMaterialSpannerEditVisitor(Spanner* spanner, const SharedObjectPointer& material, const QColor& color);
|
HeightfieldMaterialSpannerEditVisitor(Spanner* spanner, const SharedObjectPointer& material, const QColor& color);
|
||||||
|
|
||||||
virtual int visit(MetavoxelInfo& info);
|
virtual int visit(MetavoxelInfo& info);
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@ private:
|
||||||
float _blockSize;
|
float _blockSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
VoxelMaterialSpannerEditVisitor::VoxelMaterialSpannerEditVisitor(Spanner* spanner,
|
HeightfieldMaterialSpannerEditVisitor::HeightfieldMaterialSpannerEditVisitor(Spanner* spanner,
|
||||||
const SharedObjectPointer& material, const QColor& color) :
|
const SharedObjectPointer& material, const QColor& color) :
|
||||||
MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getVoxelColorAttribute() <<
|
MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getVoxelColorAttribute() <<
|
||||||
AttributeRegistry::getInstance()->getVoxelHermiteAttribute() <<
|
AttributeRegistry::getInstance()->getVoxelHermiteAttribute() <<
|
||||||
|
@ -234,7 +234,7 @@ VoxelMaterialSpannerEditVisitor::VoxelMaterialSpannerEditVisitor(Spanner* spanne
|
||||||
_blockSize(spanner->getVoxelizationGranularity() * VOXEL_BLOCK_SIZE) {
|
_blockSize(spanner->getVoxelizationGranularity() * VOXEL_BLOCK_SIZE) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int VoxelMaterialSpannerEditVisitor::visit(MetavoxelInfo& info) {
|
int HeightfieldMaterialSpannerEditVisitor::visit(MetavoxelInfo& info) {
|
||||||
Box bounds = info.getBounds();
|
Box bounds = info.getBounds();
|
||||||
if (!bounds.intersects(_spanner->getBounds())) {
|
if (!bounds.intersects(_spanner->getBounds())) {
|
||||||
return STOP_RECURSION;
|
return STOP_RECURSION;
|
||||||
|
@ -492,154 +492,20 @@ int VoxelMaterialSpannerEditVisitor::visit(MetavoxelInfo& info) {
|
||||||
return STOP_RECURSION;
|
return STOP_RECURSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelMaterialSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
|
void HeightfieldMaterialSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
|
||||||
// expand to fit the entire edit
|
// make sure the color is either 100% transparent or 100% opaque
|
||||||
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
|
|
||||||
QColor color = averageColor;
|
QColor color = averageColor;
|
||||||
color.setAlphaF(color.alphaF() > 0.5f ? 1.0f : 0.0f);
|
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;
|
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) {
|
foreach (const SharedObjectPointer& result, results) {
|
||||||
Spanner* newSpanner = static_cast<Spanner*>(result.data())->clearAndFetchHeight(bounds, heightfield);
|
Spanner* newResult = static_cast<Spanner*>(result.data())->setMaterial(spanner, material, color);
|
||||||
if (newSpanner != result) {
|
if (newResult != result) {
|
||||||
data.replace(AttributeRegistry::getInstance()->getSpannersAttribute(), result, newSpanner);
|
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)
|
DECLARE_STREAMABLE_METATYPE(PaintHeightfieldMaterialEdit)
|
||||||
|
|
||||||
/// An edit that sets the materials of voxels within a spanner to a value.
|
/// An edit that sets the materials of a heightfield within a spanner to a value.
|
||||||
class VoxelMaterialSpannerEdit : STREAM public MaterialEdit {
|
class HeightfieldMaterialSpannerEdit : STREAM public MaterialEdit {
|
||||||
STREAMABLE
|
STREAMABLE
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
STREAM SharedObjectPointer spanner;
|
STREAM SharedObjectPointer spanner;
|
||||||
|
|
||||||
VoxelMaterialSpannerEdit(const SharedObjectPointer& spanner = SharedObjectPointer(),
|
HeightfieldMaterialSpannerEdit(const SharedObjectPointer& spanner = SharedObjectPointer(),
|
||||||
const SharedObjectPointer& material = SharedObjectPointer(), const QColor& averageColor = QColor());
|
const SharedObjectPointer& material = SharedObjectPointer(), const QColor& averageColor = QColor());
|
||||||
|
|
||||||
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
|
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
DECLARE_STREAMABLE_METATYPE(VoxelMaterialSpannerEdit)
|
DECLARE_STREAMABLE_METATYPE(HeightfieldMaterialSpannerEdit)
|
||||||
|
|
||||||
/// 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)
|
|
||||||
|
|
||||||
#endif // hifi_MetavoxelMessages_h
|
#endif // hifi_MetavoxelMessages_h
|
||||||
|
|
|
@ -123,7 +123,7 @@ Spanner* Spanner::clearAndFetchHeight(const Box& bounds, SharedObjectPointer& he
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Spanner* Spanner::sculptMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material,
|
Spanner* Spanner::setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material,
|
||||||
const QColor& color) {
|
const QColor& color) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -2244,8 +2244,36 @@ HeightfieldNode* HeightfieldNode::clearAndFetchHeight(const glm::vec3& translati
|
||||||
return newNode;
|
return newNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
HeightfieldNode* HeightfieldNode::sculptMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material,
|
HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
|
||||||
const QColor& color) {
|
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;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2353,7 +2381,7 @@ void HeightfieldNode::writeDelta(const HeightfieldNodePointer& reference, Height
|
||||||
state.base.stream.writeDelta(_height, reference->getHeight());
|
state.base.stream.writeDelta(_height, reference->getHeight());
|
||||||
state.base.stream.writeDelta(_color, reference->getColor());
|
state.base.stream.writeDelta(_color, reference->getColor());
|
||||||
state.base.stream.writeDelta(_material, reference->getMaterial());
|
state.base.stream.writeDelta(_material, reference->getMaterial());
|
||||||
state.base.stream.writeDelta(_material, reference->getStack());
|
state.base.stream.writeDelta(_stack, reference->getStack());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f };
|
HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f };
|
||||||
|
@ -2853,9 +2881,10 @@ Spanner* Heightfield::clearAndFetchHeight(const Box& bounds, SharedObjectPointer
|
||||||
return newHeightfield;
|
return newHeightfield;
|
||||||
}
|
}
|
||||||
|
|
||||||
Spanner* Heightfield::sculptMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material,
|
Spanner* Heightfield::setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material,
|
||||||
const QColor& color) {
|
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) {
|
if (_root == newRoot) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,7 @@ public:
|
||||||
|
|
||||||
/// Attempts to "sculpt" with the supplied spanner.
|
/// Attempts to "sculpt" with the supplied spanner.
|
||||||
/// \return the modified spanner, or this if no modification was performed
|
/// \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);
|
const QColor& color);
|
||||||
|
|
||||||
/// Checks whether this spanner has its own colors.
|
/// 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,
|
HeightfieldNode* clearAndFetchHeight(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
|
||||||
const Box& bounds, SharedObjectPointer& heightfield);
|
const Box& bounds, SharedObjectPointer& heightfield);
|
||||||
|
|
||||||
HeightfieldNode* sculptMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material,
|
HeightfieldNode* setMaterial(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
|
||||||
const QColor& color);
|
Spanner* spanner, const SharedObjectPointer& material, const QColor& color);
|
||||||
|
|
||||||
void read(HeightfieldStreamState& state);
|
void read(HeightfieldStreamState& state);
|
||||||
void write(HeightfieldStreamState& state) const;
|
void write(HeightfieldStreamState& state) const;
|
||||||
|
@ -679,7 +679,7 @@ public:
|
||||||
|
|
||||||
virtual Spanner* clearAndFetchHeight(const Box& bounds, SharedObjectPointer& heightfield);
|
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);
|
const QColor& color);
|
||||||
|
|
||||||
virtual bool hasOwnColors() const;
|
virtual bool hasOwnColors() const;
|
||||||
|
|
Loading…
Reference in a new issue