mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 12:12:32 +02:00
Merge pull request #4161 from ey6es/master
Partial implementation of "granularity" setting for metavoxel tools.
This commit is contained in:
commit
f2f054f689
7 changed files with 310 additions and 48 deletions
|
@ -822,6 +822,12 @@ HeightfieldBrushTool::HeightfieldBrushTool(MetavoxelEditor* editor, const QStrin
|
||||||
_radius->setSingleStep(0.01);
|
_radius->setSingleStep(0.01);
|
||||||
_radius->setMaximum(FLT_MAX);
|
_radius->setMaximum(FLT_MAX);
|
||||||
_radius->setValue(5.0);
|
_radius->setValue(5.0);
|
||||||
|
|
||||||
|
_form->addRow("Granularity:", _granularity = new QDoubleSpinBox());
|
||||||
|
_granularity->setMinimum(-FLT_MAX);
|
||||||
|
_granularity->setMaximum(FLT_MAX);
|
||||||
|
_granularity->setPrefix("2^");
|
||||||
|
_granularity->setValue(8.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HeightfieldBrushTool::appliesTo(const AttributePointer& attribute) const {
|
bool HeightfieldBrushTool::appliesTo(const AttributePointer& attribute) const {
|
||||||
|
@ -851,7 +857,7 @@ bool HeightfieldBrushTool::eventFilter(QObject* watched, QEvent* event) {
|
||||||
if (event->type() == QEvent::Wheel) {
|
if (event->type() == QEvent::Wheel) {
|
||||||
float angle = static_cast<QWheelEvent*>(event)->angleDelta().y();
|
float angle = static_cast<QWheelEvent*>(event)->angleDelta().y();
|
||||||
const float ANGLE_SCALE = 1.0f / 1000.0f;
|
const float ANGLE_SCALE = 1.0f / 1000.0f;
|
||||||
_radius->setValue(_radius->value() * glm::pow(2.0f, angle * ANGLE_SCALE));
|
_radius->setValue(_radius->value() * pow(2.0f, angle * ANGLE_SCALE));
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
} else if (event->type() == QEvent::MouseButtonPress && _positionValid) {
|
} else if (event->type() == QEvent::MouseButtonPress && _positionValid) {
|
||||||
|
@ -881,7 +887,7 @@ QVariant HeightfieldHeightBrushTool::createEdit(bool alternate) {
|
||||||
const int ERASE_MODE_INDEX = 2;
|
const int ERASE_MODE_INDEX = 2;
|
||||||
return QVariant::fromValue(PaintHeightfieldHeightEdit(_position, _radius->value(),
|
return QVariant::fromValue(PaintHeightfieldHeightEdit(_position, _radius->value(),
|
||||||
alternate ? -_height->value() : _height->value(), _mode->currentIndex() == SET_MODE_INDEX,
|
alternate ? -_height->value() : _height->value(), _mode->currentIndex() == SET_MODE_INDEX,
|
||||||
_mode->currentIndex() == ERASE_MODE_INDEX));
|
_mode->currentIndex() == ERASE_MODE_INDEX, pow(2.0f, _granularity->value())));
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialControl::MaterialControl(QWidget* widget, QFormLayout* form, bool clearable) :
|
MaterialControl::MaterialControl(QWidget* widget, QFormLayout* form, bool clearable) :
|
||||||
|
@ -956,10 +962,11 @@ QVariant HeightfieldMaterialBrushTool::createEdit(bool alternate) {
|
||||||
sphere->setScale(_radius->value());
|
sphere->setScale(_radius->value());
|
||||||
if (alternate) {
|
if (alternate) {
|
||||||
return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere),
|
return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere),
|
||||||
SharedObjectPointer(), QColor(0, 0, 0, 0), true));
|
SharedObjectPointer(), QColor(0, 0, 0, 0), true, false, pow(2.0f, _granularity->value())));
|
||||||
} else {
|
} else {
|
||||||
return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere),
|
return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere),
|
||||||
_materialControl->getMaterial(), _materialControl->getColor(), true));
|
_materialControl->getMaterial(), _materialControl->getColor(),
|
||||||
|
true, false, pow(2.0f, _granularity->value())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -974,10 +981,11 @@ QVariant HeightfieldSculptBrushTool::createEdit(bool alternate) {
|
||||||
sphere->setScale(_radius->value());
|
sphere->setScale(_radius->value());
|
||||||
if (alternate) {
|
if (alternate) {
|
||||||
return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere),
|
return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere),
|
||||||
SharedObjectPointer(), QColor(0, 0, 0, 0)));
|
SharedObjectPointer(), QColor(0, 0, 0, 0), false, false, pow(2.0f, _granularity->value())));
|
||||||
} else {
|
} else {
|
||||||
return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere),
|
return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere),
|
||||||
_materialControl->getMaterial(), _materialControl->getColor()));
|
_materialControl->getMaterial(), _materialControl->getColor(),
|
||||||
|
false, false, pow(2.0f, _granularity->value())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -992,13 +1000,14 @@ HeightfieldFillBrushTool::HeightfieldFillBrushTool(MetavoxelEditor* editor) :
|
||||||
QVariant HeightfieldFillBrushTool::createEdit(bool alternate) {
|
QVariant HeightfieldFillBrushTool::createEdit(bool alternate) {
|
||||||
const int FILL_MODE_INDEX = 0;
|
const int FILL_MODE_INDEX = 0;
|
||||||
if (_mode->currentIndex() == FILL_MODE_INDEX) {
|
if (_mode->currentIndex() == FILL_MODE_INDEX) {
|
||||||
return QVariant::fromValue(FillHeightfieldHeightEdit(_position, _radius->value()));
|
return QVariant::fromValue(FillHeightfieldHeightEdit(_position, _radius->value(),
|
||||||
|
pow(2.0f, _granularity->value())));
|
||||||
}
|
}
|
||||||
Sphere* sphere = new Sphere();
|
Sphere* sphere = new Sphere();
|
||||||
sphere->setTranslation(_position);
|
sphere->setTranslation(_position);
|
||||||
sphere->setScale(_radius->value());
|
sphere->setScale(_radius->value());
|
||||||
return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere),
|
return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere),
|
||||||
SharedObjectPointer(), QColor(), false, true));
|
SharedObjectPointer(), QColor(), false, true, pow(2.0f, _granularity->value())));
|
||||||
}
|
}
|
||||||
|
|
||||||
HeightfieldMaterialBoxTool::HeightfieldMaterialBoxTool(MetavoxelEditor* editor) :
|
HeightfieldMaterialBoxTool::HeightfieldMaterialBoxTool(MetavoxelEditor* editor) :
|
||||||
|
@ -1017,6 +1026,12 @@ HeightfieldMaterialBoxTool::HeightfieldMaterialBoxTool(MetavoxelEditor* editor)
|
||||||
_snapToGrid->setChecked(true);
|
_snapToGrid->setChecked(true);
|
||||||
|
|
||||||
_materialControl = new MaterialControl(this, form, true);
|
_materialControl = new MaterialControl(this, form, true);
|
||||||
|
|
||||||
|
form->addRow("Granularity:", _granularity = new QDoubleSpinBox());
|
||||||
|
_granularity->setMinimum(-FLT_MAX);
|
||||||
|
_granularity->setMaximum(FLT_MAX);
|
||||||
|
_granularity->setPrefix("2^");
|
||||||
|
_granularity->setValue(8.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HeightfieldMaterialBoxTool::appliesTo(const AttributePointer& attribute) const {
|
bool HeightfieldMaterialBoxTool::appliesTo(const AttributePointer& attribute) const {
|
||||||
|
@ -1039,7 +1054,7 @@ void HeightfieldMaterialBoxTool::applyValue(const glm::vec3& minimum, const glm:
|
||||||
cuboid->setAspectY(vector.y / vector.x);
|
cuboid->setAspectY(vector.y / vector.x);
|
||||||
cuboid->setAspectZ(vector.z / vector.x);
|
cuboid->setAspectZ(vector.z / vector.x);
|
||||||
MetavoxelEditMessage message = { QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(cuboid),
|
MetavoxelEditMessage message = { QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(cuboid),
|
||||||
_materialControl->getMaterial(), _materialControl->getColor())) };
|
_materialControl->getMaterial(), _materialControl->getColor(), false, false, pow(2.0f, _granularity->value()))) };
|
||||||
Application::getInstance()->getMetavoxels()->applyEdit(message, true);
|
Application::getInstance()->getMetavoxels()->applyEdit(message, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1056,6 +1071,12 @@ HeightfieldMaterialSpannerTool::HeightfieldMaterialSpannerTool(MetavoxelEditor*
|
||||||
|
|
||||||
_materialControl = new MaterialControl(this, form, true);
|
_materialControl = new MaterialControl(this, form, true);
|
||||||
|
|
||||||
|
form->addRow("Granularity:", _granularity = new QDoubleSpinBox());
|
||||||
|
_granularity->setMinimum(-FLT_MAX);
|
||||||
|
_granularity->setMaximum(FLT_MAX);
|
||||||
|
_granularity->setPrefix("2^");
|
||||||
|
_granularity->setValue(8.0);
|
||||||
|
|
||||||
QPushButton* place = new QPushButton("Set");
|
QPushButton* place = new QPushButton("Set");
|
||||||
layout()->addWidget(place);
|
layout()->addWidget(place);
|
||||||
connect(place, &QPushButton::clicked, this, &HeightfieldMaterialSpannerTool::place);
|
connect(place, &QPushButton::clicked, this, &HeightfieldMaterialSpannerTool::place);
|
||||||
|
@ -1076,7 +1097,7 @@ QColor HeightfieldMaterialSpannerTool::getColor() {
|
||||||
void HeightfieldMaterialSpannerTool::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(HeightfieldMaterialSpannerEdit(spanner,
|
MetavoxelEditMessage message = { QVariant::fromValue(HeightfieldMaterialSpannerEdit(spanner,
|
||||||
_materialControl->getMaterial(), _materialControl->getColor())) };
|
_materialControl->getMaterial(), _materialControl->getColor(), false, false, pow(2.0f, _granularity->value()))) };
|
||||||
Application::getInstance()->getMetavoxels()->applyEdit(message, true);
|
Application::getInstance()->getMetavoxels()->applyEdit(message, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -326,6 +326,7 @@ protected:
|
||||||
|
|
||||||
QFormLayout* _form;
|
QFormLayout* _form;
|
||||||
QDoubleSpinBox* _radius;
|
QDoubleSpinBox* _radius;
|
||||||
|
QDoubleSpinBox* _granularity;
|
||||||
|
|
||||||
glm::vec3 _position;
|
glm::vec3 _position;
|
||||||
bool _positionValid;
|
bool _positionValid;
|
||||||
|
@ -448,6 +449,7 @@ private:
|
||||||
|
|
||||||
QCheckBox* _snapToGrid;
|
QCheckBox* _snapToGrid;
|
||||||
MaterialControl* _materialControl;
|
MaterialControl* _materialControl;
|
||||||
|
QDoubleSpinBox* _granularity;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Allows setting heightfield materials by placing a spanner.
|
/// Allows setting heightfield materials by placing a spanner.
|
||||||
|
@ -470,6 +472,7 @@ private:
|
||||||
|
|
||||||
SharedObjectEditor* _spannerEditor;
|
SharedObjectEditor* _spannerEditor;
|
||||||
MaterialControl* _materialControl;
|
MaterialControl* _materialControl;
|
||||||
|
QDoubleSpinBox* _granularity;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_MetavoxelEditor_h
|
#endif // hifi_MetavoxelEditor_h
|
||||||
|
|
|
@ -149,12 +149,13 @@ void SetDataEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects
|
||||||
}
|
}
|
||||||
|
|
||||||
PaintHeightfieldHeightEdit::PaintHeightfieldHeightEdit(const glm::vec3& position, float radius,
|
PaintHeightfieldHeightEdit::PaintHeightfieldHeightEdit(const glm::vec3& position, float radius,
|
||||||
float height, bool set, bool erase) :
|
float height, bool set, bool erase, float granularity) :
|
||||||
position(position),
|
position(position),
|
||||||
radius(radius),
|
radius(radius),
|
||||||
height(height),
|
height(height),
|
||||||
set(set),
|
set(set),
|
||||||
erase(erase) {
|
erase(erase),
|
||||||
|
granularity(granularity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PaintHeightfieldHeightEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
|
void PaintHeightfieldHeightEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
|
||||||
|
@ -166,7 +167,8 @@ void PaintHeightfieldHeightEdit::apply(MetavoxelData& data, const WeakSharedObje
|
||||||
Box(position - extents, position + extents), results);
|
Box(position - extents, position + extents), results);
|
||||||
|
|
||||||
foreach (const SharedObjectPointer& spanner, results) {
|
foreach (const SharedObjectPointer& spanner, results) {
|
||||||
Spanner* newSpanner = static_cast<Spanner*>(spanner.data())->paintHeight(position, radius, height, set, erase);
|
Spanner* newSpanner = static_cast<Spanner*>(spanner.data())->paintHeight(position, radius,
|
||||||
|
height, set, erase, granularity);
|
||||||
if (newSpanner != spanner) {
|
if (newSpanner != spanner) {
|
||||||
data.replace(AttributeRegistry::getInstance()->getSpannersAttribute(), spanner, newSpanner);
|
data.replace(AttributeRegistry::getInstance()->getSpannersAttribute(), spanner, newSpanner);
|
||||||
}
|
}
|
||||||
|
@ -179,11 +181,12 @@ MaterialEdit::MaterialEdit(const SharedObjectPointer& material, const QColor& av
|
||||||
}
|
}
|
||||||
|
|
||||||
HeightfieldMaterialSpannerEdit::HeightfieldMaterialSpannerEdit(const SharedObjectPointer& spanner,
|
HeightfieldMaterialSpannerEdit::HeightfieldMaterialSpannerEdit(const SharedObjectPointer& spanner,
|
||||||
const SharedObjectPointer& material, const QColor& averageColor, bool paint, bool voxelize) :
|
const SharedObjectPointer& material, const QColor& averageColor, bool paint, bool voxelize, float granularity) :
|
||||||
MaterialEdit(material, averageColor),
|
MaterialEdit(material, averageColor),
|
||||||
spanner(spanner),
|
spanner(spanner),
|
||||||
paint(paint),
|
paint(paint),
|
||||||
voxelize(voxelize) {
|
voxelize(voxelize),
|
||||||
|
granularity(granularity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
class SpannerProjectionFetchVisitor : public SpannerVisitor {
|
class SpannerProjectionFetchVisitor : public SpannerVisitor {
|
||||||
|
@ -250,16 +253,18 @@ void HeightfieldMaterialSpannerEdit::apply(MetavoxelData& data, const WeakShared
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (const SharedObjectPointer& result, results) {
|
foreach (const SharedObjectPointer& result, results) {
|
||||||
Spanner* newResult = static_cast<Spanner*>(result.data())->setMaterial(spanner, material, color, paint, voxelize);
|
Spanner* newResult = static_cast<Spanner*>(result.data())->setMaterial(spanner, material,
|
||||||
|
color, paint, voxelize, granularity);
|
||||||
if (newResult != result) {
|
if (newResult != result) {
|
||||||
data.replace(AttributeRegistry::getInstance()->getSpannersAttribute(), result, newResult);
|
data.replace(AttributeRegistry::getInstance()->getSpannersAttribute(), result, newResult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FillHeightfieldHeightEdit::FillHeightfieldHeightEdit(const glm::vec3& position, float radius) :
|
FillHeightfieldHeightEdit::FillHeightfieldHeightEdit(const glm::vec3& position, float radius, float granularity) :
|
||||||
position(position),
|
position(position),
|
||||||
radius(radius) {
|
radius(radius),
|
||||||
|
granularity(granularity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FillHeightfieldHeightEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
|
void FillHeightfieldHeightEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
|
||||||
|
@ -269,7 +274,7 @@ void FillHeightfieldHeightEdit::apply(MetavoxelData& data, const WeakSharedObjec
|
||||||
Box(position - extents, position + extents), results);
|
Box(position - extents, position + extents), results);
|
||||||
|
|
||||||
foreach (const SharedObjectPointer& spanner, results) {
|
foreach (const SharedObjectPointer& spanner, results) {
|
||||||
Spanner* newSpanner = static_cast<Spanner*>(spanner.data())->fillHeight(position, radius);
|
Spanner* newSpanner = static_cast<Spanner*>(spanner.data())->fillHeight(position, radius, granularity);
|
||||||
if (newSpanner != spanner) {
|
if (newSpanner != spanner) {
|
||||||
data.replace(AttributeRegistry::getInstance()->getSpannersAttribute(), spanner, newSpanner);
|
data.replace(AttributeRegistry::getInstance()->getSpannersAttribute(), spanner, newSpanner);
|
||||||
}
|
}
|
||||||
|
|
|
@ -205,9 +205,10 @@ public:
|
||||||
STREAM float height;
|
STREAM float height;
|
||||||
STREAM bool set;
|
STREAM bool set;
|
||||||
STREAM bool erase;
|
STREAM bool erase;
|
||||||
|
STREAM float granularity;
|
||||||
|
|
||||||
PaintHeightfieldHeightEdit(const glm::vec3& position = glm::vec3(), float radius = 0.0f,
|
PaintHeightfieldHeightEdit(const glm::vec3& position = glm::vec3(), float radius = 0.0f,
|
||||||
float height = 0.0f, bool set = false, bool erase = false);
|
float height = 0.0f, bool set = false, bool erase = false, float granularity = 0.0f);
|
||||||
|
|
||||||
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
|
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
|
||||||
};
|
};
|
||||||
|
@ -237,10 +238,11 @@ public:
|
||||||
STREAM SharedObjectPointer spanner;
|
STREAM SharedObjectPointer spanner;
|
||||||
STREAM bool paint;
|
STREAM bool paint;
|
||||||
STREAM bool voxelize;
|
STREAM bool voxelize;
|
||||||
|
STREAM float granularity;
|
||||||
|
|
||||||
HeightfieldMaterialSpannerEdit(const SharedObjectPointer& spanner = SharedObjectPointer(),
|
HeightfieldMaterialSpannerEdit(const SharedObjectPointer& spanner = SharedObjectPointer(),
|
||||||
const SharedObjectPointer& material = SharedObjectPointer(),
|
const SharedObjectPointer& material = SharedObjectPointer(),
|
||||||
const QColor& averageColor = QColor(), bool paint = false, bool voxelize = false);
|
const QColor& averageColor = QColor(), bool paint = false, bool voxelize = false, float granularity = 0.0f);
|
||||||
|
|
||||||
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
|
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
|
||||||
};
|
};
|
||||||
|
@ -255,8 +257,9 @@ public:
|
||||||
|
|
||||||
STREAM glm::vec3 position;
|
STREAM glm::vec3 position;
|
||||||
STREAM float radius;
|
STREAM float radius;
|
||||||
|
STREAM float granularity;
|
||||||
|
|
||||||
FillHeightfieldHeightEdit(const glm::vec3& position = glm::vec3(), float radius = 0.0f);
|
FillHeightfieldHeightEdit(const glm::vec3& position = glm::vec3(), float radius = 0.0f, float granularity = 0.0f);
|
||||||
|
|
||||||
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
|
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -111,16 +111,16 @@ bool Spanner::findRayIntersection(const glm::vec3& origin, const glm::vec3& dire
|
||||||
return _bounds.findRayIntersection(origin, direction, distance);
|
return _bounds.findRayIntersection(origin, direction, distance);
|
||||||
}
|
}
|
||||||
|
|
||||||
Spanner* Spanner::paintHeight(const glm::vec3& position, float radius, float height, bool set, bool erase) {
|
Spanner* Spanner::paintHeight(const glm::vec3& position, float radius, float height, bool set, bool erase, float granularity) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Spanner* Spanner::fillHeight(const glm::vec3& position, float radius) {
|
Spanner* Spanner::fillHeight(const glm::vec3& position, float radius, float granularity) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Spanner* Spanner::setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material,
|
Spanner* Spanner::setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material,
|
||||||
const QColor& color, bool paint, bool voxelize) {
|
const QColor& color, bool paint, bool voxelize, float granularity) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1786,7 +1786,7 @@ void HeightfieldNode::getRangeAfterHeightPaint(const glm::vec3& translation, con
|
||||||
|
|
||||||
HeightfieldNode* HeightfieldNode::paintHeight(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
|
HeightfieldNode* HeightfieldNode::paintHeight(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
|
||||||
const glm::vec3& position, float radius, float height, bool set, bool erase,
|
const glm::vec3& position, float radius, float height, bool set, bool erase,
|
||||||
float normalizeScale, float normalizeOffset) {
|
float normalizeScale, float normalizeOffset, float granularity) {
|
||||||
if (!_height) {
|
if (!_height) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -1813,7 +1813,7 @@ HeightfieldNode* HeightfieldNode::paintHeight(const glm::vec3& translation, cons
|
||||||
HeightfieldNode* newChild = _children[i]->paintHeight(translation +
|
HeightfieldNode* newChild = _children[i]->paintHeight(translation +
|
||||||
rotation * glm::vec3(i & X_MAXIMUM_FLAG ? nextScale.x : 0.0f, 0.0f,
|
rotation * glm::vec3(i & X_MAXIMUM_FLAG ? nextScale.x : 0.0f, 0.0f,
|
||||||
i & Y_MAXIMUM_FLAG ? nextScale.z : 0.0f), rotation,
|
i & Y_MAXIMUM_FLAG ? nextScale.z : 0.0f), rotation,
|
||||||
nextScale, position, radius, height, set, erase, normalizeScale, normalizeOffset);
|
nextScale, position, radius, height, set, erase, normalizeScale, normalizeOffset, granularity);
|
||||||
if (_children[i] != newChild) {
|
if (_children[i] != newChild) {
|
||||||
if (newNode == this) {
|
if (newNode == this) {
|
||||||
newNode = new HeightfieldNode(*this);
|
newNode = new HeightfieldNode(*this);
|
||||||
|
@ -1846,6 +1846,13 @@ HeightfieldNode* HeightfieldNode::paintHeight(const glm::vec3& translation, cons
|
||||||
new HeightfieldStack(stackWidth, newStackContents, newStackMaterials)));
|
new HeightfieldStack(stackWidth, newStackContents, newStackMaterials)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if the granularity is insufficient, we must subdivide
|
||||||
|
if (scale.x / innerHeightWidth > granularity || scale.z / innerHeightHeight > granularity) {
|
||||||
|
HeightfieldNodePointer newNode(subdivide(newHeightContents, newStackContents));
|
||||||
|
return newNode->paintHeight(translation, rotation, scale, position, radius, height, set,
|
||||||
|
erase, 1.0f, 0.0f, granularity);
|
||||||
|
}
|
||||||
|
|
||||||
// now apply the actual change
|
// now apply the actual change
|
||||||
glm::vec3 start = glm::clamp(glm::floor(center - extents), glm::vec3(),
|
glm::vec3 start = glm::clamp(glm::floor(center - extents), glm::vec3(),
|
||||||
glm::vec3((float)highestHeightX, 0.0f, (float)highestHeightZ));
|
glm::vec3((float)highestHeightX, 0.0f, (float)highestHeightZ));
|
||||||
|
@ -1885,7 +1892,7 @@ HeightfieldNode* HeightfieldNode::paintHeight(const glm::vec3& translation, cons
|
||||||
}
|
}
|
||||||
|
|
||||||
HeightfieldNode* HeightfieldNode::fillHeight(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
|
HeightfieldNode* HeightfieldNode::fillHeight(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
|
||||||
const glm::vec3& position, float radius) {
|
const glm::vec3& position, float radius, float granularity) {
|
||||||
if (!_height) {
|
if (!_height) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -1911,7 +1918,7 @@ HeightfieldNode* HeightfieldNode::fillHeight(const glm::vec3& translation, const
|
||||||
HeightfieldNode* newChild = _children[i]->fillHeight(translation +
|
HeightfieldNode* newChild = _children[i]->fillHeight(translation +
|
||||||
rotation * glm::vec3(i & X_MAXIMUM_FLAG ? nextScale.x : 0.0f, 0.0f,
|
rotation * glm::vec3(i & X_MAXIMUM_FLAG ? nextScale.x : 0.0f, 0.0f,
|
||||||
i & Y_MAXIMUM_FLAG ? nextScale.z : 0.0f), rotation,
|
i & Y_MAXIMUM_FLAG ? nextScale.z : 0.0f), rotation,
|
||||||
nextScale, position, radius);
|
nextScale, position, radius, granularity);
|
||||||
if (_children[i] != newChild) {
|
if (_children[i] != newChild) {
|
||||||
if (newNode == this) {
|
if (newNode == this) {
|
||||||
newNode = new HeightfieldNode(*this);
|
newNode = new HeightfieldNode(*this);
|
||||||
|
@ -1927,9 +1934,15 @@ HeightfieldNode* HeightfieldNode::fillHeight(const glm::vec3& translation, const
|
||||||
if (!_stack) {
|
if (!_stack) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
QVector<quint16> newHeightContents = _height->getContents();
|
|
||||||
|
|
||||||
|
// if the granularity is insufficient, we must subdivide
|
||||||
|
QVector<quint16> newHeightContents = _height->getContents();
|
||||||
QVector<StackArray> newStackContents = _stack->getContents();
|
QVector<StackArray> newStackContents = _stack->getContents();
|
||||||
|
if (scale.x / innerHeightWidth > granularity || scale.z / innerHeightHeight > granularity) {
|
||||||
|
HeightfieldNodePointer newNode(subdivide(newHeightContents, newStackContents));
|
||||||
|
return newNode->fillHeight(translation, rotation, scale, position, radius, granularity);
|
||||||
|
}
|
||||||
|
|
||||||
int stackWidth = _stack->getWidth();
|
int stackWidth = _stack->getWidth();
|
||||||
int stackHeight = newStackContents.size() / stackWidth;
|
int stackHeight = newStackContents.size() / stackWidth;
|
||||||
QVector<SharedObjectPointer> newStackMaterials = _stack->getMaterials();
|
QVector<SharedObjectPointer> newStackMaterials = _stack->getMaterials();
|
||||||
|
@ -2088,7 +2101,7 @@ void HeightfieldNode::getRangeAfterEdit(const glm::vec3& translation, const glm:
|
||||||
|
|
||||||
HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
|
HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
|
||||||
Spanner* spanner, const SharedObjectPointer& material, const QColor& color, bool paint, bool voxelize,
|
Spanner* spanner, const SharedObjectPointer& material, const QColor& color, bool paint, bool voxelize,
|
||||||
float normalizeScale, float normalizeOffset) {
|
float normalizeScale, float normalizeOffset, float granularity) {
|
||||||
if (!_height) {
|
if (!_height) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -2109,7 +2122,7 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
|
||||||
HeightfieldNode* newChild = _children[i]->setMaterial(translation +
|
HeightfieldNode* newChild = _children[i]->setMaterial(translation +
|
||||||
rotation * glm::vec3(i & X_MAXIMUM_FLAG ? nextScale.x : 0.0f, 0.0f,
|
rotation * glm::vec3(i & X_MAXIMUM_FLAG ? nextScale.x : 0.0f, 0.0f,
|
||||||
i & Y_MAXIMUM_FLAG ? nextScale.z : 0.0f), rotation, nextScale, spanner,
|
i & Y_MAXIMUM_FLAG ? nextScale.z : 0.0f), rotation, nextScale, spanner,
|
||||||
material, color, paint, voxelize, normalizeScale, normalizeOffset);
|
material, color, paint, voxelize, normalizeScale, normalizeOffset, granularity);
|
||||||
if (_children[i] != newChild) {
|
if (_children[i] != newChild) {
|
||||||
if (newNode == this) {
|
if (newNode == this) {
|
||||||
newNode = new HeightfieldNode(*this);
|
newNode = new HeightfieldNode(*this);
|
||||||
|
@ -2149,6 +2162,14 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
|
||||||
return new HeightfieldNode(HeightfieldHeightPointer(new HeightfieldHeight(heightWidth, newHeightContents)),
|
return new HeightfieldNode(HeightfieldHeightPointer(new HeightfieldHeight(heightWidth, newHeightContents)),
|
||||||
_color, _material, HeightfieldStackPointer(new HeightfieldStack(stackWidth, newStackContents, newStackMaterials)));
|
_color, _material, HeightfieldStackPointer(new HeightfieldStack(stackWidth, newStackContents, newStackMaterials)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if the granularity is insufficient, we must subdivide
|
||||||
|
if (scale.x / innerHeightWidth > granularity || scale.z / innerHeightHeight > granularity) {
|
||||||
|
HeightfieldNodePointer newNode(subdivide(newHeightContents, newStackContents));
|
||||||
|
return newNode->setMaterial(translation, rotation, scale, spanner, material, color,
|
||||||
|
paint, voxelize, 1.0f, 0.0f, granularity);
|
||||||
|
}
|
||||||
|
|
||||||
QVector<quint16> oldHeightContents = newHeightContents;
|
QVector<quint16> oldHeightContents = newHeightContents;
|
||||||
QVector<StackArray> oldStackContents = newStackContents;
|
QVector<StackArray> oldStackContents = newStackContents;
|
||||||
|
|
||||||
|
@ -3210,6 +3231,210 @@ bool HeightfieldNode::findHeightfieldRayIntersection(const glm::vec3& origin, co
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline float mixHeights(float firstHeight, float secondHeight, float t) {
|
||||||
|
return (firstHeight == 0.0f) ? secondHeight : (secondHeight == 0.0f ? firstHeight :
|
||||||
|
glm::mix(firstHeight, secondHeight, t));
|
||||||
|
}
|
||||||
|
|
||||||
|
HeightfieldNode* HeightfieldNode::subdivide(const QVector<quint16>& heightContents,
|
||||||
|
const QVector<StackArray>& stackContents) const {
|
||||||
|
HeightfieldNode* newNode = new HeightfieldNode(*this);
|
||||||
|
int heightWidth = _height->getWidth();
|
||||||
|
int heightHeight = heightContents.size() / heightWidth;
|
||||||
|
newNode->setHeight(HeightfieldHeightPointer(new HeightfieldHeight(heightWidth, heightContents)));
|
||||||
|
int stackWidth = 0, stackHeight = 0;
|
||||||
|
QVector<SharedObjectPointer> stackMaterials;
|
||||||
|
if (_stack) {
|
||||||
|
stackWidth = _stack->getWidth();
|
||||||
|
stackHeight = stackContents.size() / stackWidth;
|
||||||
|
stackMaterials = _stack->getMaterials();
|
||||||
|
newNode->setStack(HeightfieldStackPointer(new HeightfieldStack(stackWidth, stackContents, stackMaterials)));
|
||||||
|
}
|
||||||
|
int colorWidth = 0, colorHeight = 0;
|
||||||
|
if (_color) {
|
||||||
|
colorWidth = _color->getWidth();
|
||||||
|
colorHeight = _color->getContents().size() / (colorWidth * DataBlock::COLOR_BYTES);
|
||||||
|
}
|
||||||
|
int materialWidth = 0, materialHeight = 0;
|
||||||
|
QVector<SharedObjectPointer> materialMaterials;
|
||||||
|
if (_material) {
|
||||||
|
materialWidth = _material->getWidth();
|
||||||
|
materialHeight = _material->getContents().size() / materialWidth;
|
||||||
|
materialMaterials = _material->getMaterials();
|
||||||
|
}
|
||||||
|
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||||
|
QVector<quint16> childHeightContents(heightWidth * heightHeight);
|
||||||
|
QByteArray childColorContents(colorWidth * colorHeight * DataBlock::COLOR_BYTES, 0xFF);
|
||||||
|
QByteArray childMaterialContents(materialWidth * materialHeight, 0);
|
||||||
|
QVector<StackArray> childStackContents(stackWidth * stackHeight);
|
||||||
|
|
||||||
|
quint16* heightDest = childHeightContents.data();
|
||||||
|
const quint16* heightSrc = heightContents.constData() + (i & Y_MAXIMUM_FLAG ? (heightHeight / 2) * heightWidth : 0) +
|
||||||
|
(i & X_MAXIMUM_FLAG ? heightWidth / 2 : 0);
|
||||||
|
for (int z = 0; z < heightHeight; z++) {
|
||||||
|
float srcZ = z * 0.5f + 0.5f;
|
||||||
|
float fractZ = glm::fract(srcZ);
|
||||||
|
const quint16* heightSrcZ = heightSrc + (int)srcZ * heightWidth;
|
||||||
|
for (int x = 0; x < heightWidth; x++) {
|
||||||
|
float srcX = x * 0.5f + 0.5f;
|
||||||
|
float fractX = glm::fract(srcX);
|
||||||
|
const quint16* heightSrcX = heightSrcZ + (int)srcX;
|
||||||
|
if (fractZ == 0.0f) {
|
||||||
|
if (fractX == 0.0f) {
|
||||||
|
*heightDest++ = heightSrcX[0];
|
||||||
|
} else {
|
||||||
|
*heightDest++ = mixHeights(heightSrcX[0], heightSrcX[1], fractX);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (fractX == 0.0f) {
|
||||||
|
*heightDest++ = mixHeights(heightSrcX[0], heightSrcX[heightWidth], fractZ);
|
||||||
|
} else {
|
||||||
|
*heightDest++ = mixHeights(mixHeights(heightSrcX[0], heightSrcX[1], fractX),
|
||||||
|
mixHeights(heightSrcX[heightWidth], heightSrcX[heightWidth + 1], fractX), fractZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (colorWidth != 0) {
|
||||||
|
char* colorDest = childColorContents.data();
|
||||||
|
const uchar* colorSrc = (const uchar*)_color->getContents().constData() +
|
||||||
|
((i & Y_MAXIMUM_FLAG ? (colorHeight / 2) * colorWidth : 0) +
|
||||||
|
(i & X_MAXIMUM_FLAG ? colorWidth / 2 : 0)) * DataBlock::COLOR_BYTES;
|
||||||
|
for (int z = 0; z < colorHeight; z++) {
|
||||||
|
float srcZ = z * 0.5f;
|
||||||
|
float fractZ = glm::fract(srcZ);
|
||||||
|
const uchar* colorSrcZ = colorSrc + (int)srcZ * colorWidth * DataBlock::COLOR_BYTES;
|
||||||
|
for (int x = 0; x < colorWidth; x++) {
|
||||||
|
float srcX = x * 0.5f;
|
||||||
|
float fractX = glm::fract(srcX);
|
||||||
|
const uchar* colorSrcX = colorSrcZ + (int)srcX * DataBlock::COLOR_BYTES;
|
||||||
|
const uchar* nextColorSrcX = colorSrcX + colorWidth * DataBlock::COLOR_BYTES;
|
||||||
|
if (fractZ == 0.0f) {
|
||||||
|
if (fractX == 0.0f) {
|
||||||
|
*colorDest++ = colorSrcX[0];
|
||||||
|
*colorDest++ = colorSrcX[1];
|
||||||
|
*colorDest++ = colorSrcX[2];
|
||||||
|
} else {
|
||||||
|
*colorDest++ = glm::mix(colorSrcX[0], colorSrcX[3], fractX);
|
||||||
|
*colorDest++ = glm::mix(colorSrcX[1], colorSrcX[4], fractX);
|
||||||
|
*colorDest++ = glm::mix(colorSrcX[2], colorSrcX[5], fractX);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (fractX == 0.0f) {
|
||||||
|
*colorDest++ = glm::mix(colorSrcX[0], nextColorSrcX[0], fractZ);
|
||||||
|
*colorDest++ = glm::mix(colorSrcX[1], nextColorSrcX[1], fractZ);
|
||||||
|
*colorDest++ = glm::mix(colorSrcX[2], nextColorSrcX[2], fractZ);
|
||||||
|
} else {
|
||||||
|
*colorDest++ = glm::mix(glm::mix(colorSrcX[0], colorSrcX[3], fractX),
|
||||||
|
glm::mix(nextColorSrcX[0], nextColorSrcX[3], fractX), fractZ);
|
||||||
|
*colorDest++ = glm::mix(glm::mix(colorSrcX[1], colorSrcX[4], fractX),
|
||||||
|
glm::mix(nextColorSrcX[1], nextColorSrcX[4], fractX), fractZ);
|
||||||
|
*colorDest++ = glm::mix(glm::mix(colorSrcX[2], colorSrcX[5], fractX),
|
||||||
|
glm::mix(nextColorSrcX[2], nextColorSrcX[5], fractX), fractZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (materialWidth != 0) {
|
||||||
|
char* materialDest = childMaterialContents.data();
|
||||||
|
const char* materialSrc = _material->getContents().constData() +
|
||||||
|
(i & Y_MAXIMUM_FLAG ? (materialHeight / 2) * materialWidth : 0) +
|
||||||
|
(i & X_MAXIMUM_FLAG ? materialWidth / 2 : 0);
|
||||||
|
for (int z = 0; z < materialHeight; z++) {
|
||||||
|
float srcZ = z * 0.5f;
|
||||||
|
const char* materialSrcZ = materialSrc + (int)srcZ * materialWidth;
|
||||||
|
for (int x = 0; x < materialWidth; x++) {
|
||||||
|
float srcX = x * 0.5f;
|
||||||
|
const char* materialSrcX = materialSrcZ + (int)srcX;
|
||||||
|
*materialDest++ = *materialSrcX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackWidth != 0) {
|
||||||
|
StackArray* stackDest = childStackContents.data();
|
||||||
|
const StackArray* stackSrc = _stack->getContents().constData() +
|
||||||
|
(i & Y_MAXIMUM_FLAG ? (stackHeight / 2) * stackWidth : 0) +
|
||||||
|
(i & X_MAXIMUM_FLAG ? stackWidth / 2 : 0);
|
||||||
|
for (int z = 0; z < stackHeight; z++) {
|
||||||
|
float srcZ = z * 0.5f;
|
||||||
|
float fractZ = glm::fract(srcZ);
|
||||||
|
const StackArray* stackSrcZ = stackSrc + (int)srcZ * stackWidth;
|
||||||
|
for (int x = 0; x < stackWidth; x++) {
|
||||||
|
float srcX = x * 0.5f;
|
||||||
|
float fractX = glm::fract(srcX);
|
||||||
|
const StackArray* stackSrcX = stackSrcZ + (int)srcX;
|
||||||
|
if (stackSrcX->isEmpty()) {
|
||||||
|
stackDest++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int minimumY = stackSrcX->getPosition() * 2;
|
||||||
|
int maximumY = (stackSrcX->getPosition() + stackSrcX->getEntryCount() - 1) * 2;
|
||||||
|
*stackDest = StackArray(maximumY - minimumY + 1);
|
||||||
|
stackDest->setPosition(minimumY);
|
||||||
|
for (int y = minimumY; y <= maximumY; y++) {
|
||||||
|
float srcY = y * 0.5f;
|
||||||
|
float fractY = glm::fract(srcY);
|
||||||
|
const StackArray::Entry& srcEntry = stackSrcX->getEntry((int)srcY);
|
||||||
|
StackArray::Entry& destEntry = stackDest->getEntry(y);
|
||||||
|
destEntry.color = srcEntry.color;
|
||||||
|
destEntry.material = srcEntry.material;
|
||||||
|
if (srcEntry.hermiteX != 0) {
|
||||||
|
glm::vec3 normal;
|
||||||
|
float distance = srcEntry.getHermiteX(normal);
|
||||||
|
if (distance < fractX) {
|
||||||
|
const StackArray::Entry& nextSrcEntryX = stackSrcX[1].getEntry((int)srcY);
|
||||||
|
destEntry.color = nextSrcEntryX.color;
|
||||||
|
destEntry.material = nextSrcEntryX.material;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
destEntry.setHermiteX(normal, (distance - fractX) / 0.5f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (srcEntry.hermiteY != 0) {
|
||||||
|
glm::vec3 normal;
|
||||||
|
float distance = srcEntry.getHermiteY(normal);
|
||||||
|
if (distance < fractY) {
|
||||||
|
const StackArray::Entry& nextSrcEntryY = stackSrcX->getEntry((int)srcY + 1);
|
||||||
|
destEntry.color = nextSrcEntryY.color;
|
||||||
|
destEntry.material = nextSrcEntryY.material;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
destEntry.setHermiteY(normal, (distance - fractY) / 0.5f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (srcEntry.hermiteZ != 0) {
|
||||||
|
glm::vec3 normal;
|
||||||
|
float distance = srcEntry.getHermiteZ(normal);
|
||||||
|
if (distance < fractZ) {
|
||||||
|
const StackArray::Entry& nextSrcEntryZ = stackSrcX[stackWidth].getEntry((int)srcY);
|
||||||
|
destEntry.color = nextSrcEntryZ.color;
|
||||||
|
destEntry.material = nextSrcEntryZ.material;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
destEntry.setHermiteZ(normal, (distance - fractZ) / 0.5f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stackDest++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newNode->setChild(i, HeightfieldNodePointer(new HeightfieldNode(
|
||||||
|
HeightfieldHeightPointer(new HeightfieldHeight(heightWidth, childHeightContents)),
|
||||||
|
HeightfieldColorPointer(colorWidth == 0 ? NULL : new HeightfieldColor(colorWidth, childColorContents)),
|
||||||
|
HeightfieldMaterialPointer(materialWidth == 0 ? NULL :
|
||||||
|
new HeightfieldMaterial(materialWidth, childMaterialContents, materialMaterials)),
|
||||||
|
HeightfieldStackPointer(stackWidth == 0 ? NULL :
|
||||||
|
new HeightfieldStack(stackWidth, childStackContents, stackMaterials)))));
|
||||||
|
}
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
AbstractHeightfieldNodeRenderer::~AbstractHeightfieldNodeRenderer() {
|
AbstractHeightfieldNodeRenderer::~AbstractHeightfieldNodeRenderer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3310,7 +3535,8 @@ bool Heightfield::findRayIntersection(const glm::vec3& origin, const glm::vec3&
|
||||||
getScale() * _aspectZ), origin, direction, distance);
|
getScale() * _aspectZ), origin, direction, distance);
|
||||||
}
|
}
|
||||||
|
|
||||||
Spanner* Heightfield::paintHeight(const glm::vec3& position, float radius, float height, bool set, bool erase) {
|
Spanner* Heightfield::paintHeight(const glm::vec3& position, float radius, float height,
|
||||||
|
bool set, bool erase, float granularity) {
|
||||||
// first see if we're going to exceed the range limits
|
// first see if we're going to exceed the range limits
|
||||||
float minimumValue = 1.0f, maximumValue = numeric_limits<quint16>::max();
|
float minimumValue = 1.0f, maximumValue = numeric_limits<quint16>::max();
|
||||||
if (set) {
|
if (set) {
|
||||||
|
@ -3328,19 +3554,19 @@ Spanner* Heightfield::paintHeight(const glm::vec3& position, float radius, float
|
||||||
Heightfield* newHeightfield = prepareEdit(minimumValue, maximumValue, normalizeScale, normalizeOffset);
|
Heightfield* newHeightfield = prepareEdit(minimumValue, maximumValue, normalizeScale, normalizeOffset);
|
||||||
newHeightfield->setRoot(HeightfieldNodePointer(_root->paintHeight(newHeightfield->getTranslation(), getRotation(),
|
newHeightfield->setRoot(HeightfieldNodePointer(_root->paintHeight(newHeightfield->getTranslation(), getRotation(),
|
||||||
glm::vec3(getScale(), getScale() * newHeightfield->getAspectY(), getScale() * _aspectZ), position, radius, height,
|
glm::vec3(getScale(), getScale() * newHeightfield->getAspectY(), getScale() * _aspectZ), position, radius, height,
|
||||||
set, erase, normalizeScale, normalizeOffset)));
|
set, erase, normalizeScale, normalizeOffset, granularity)));
|
||||||
return newHeightfield;
|
return newHeightfield;
|
||||||
}
|
}
|
||||||
|
|
||||||
Spanner* Heightfield::fillHeight(const glm::vec3& position, float radius) {
|
Spanner* Heightfield::fillHeight(const glm::vec3& position, float radius, float granularity) {
|
||||||
Heightfield* newHeightfield = static_cast<Heightfield*>(clone(true));
|
Heightfield* newHeightfield = static_cast<Heightfield*>(clone(true));
|
||||||
newHeightfield->setRoot(HeightfieldNodePointer(_root->fillHeight(getTranslation(), getRotation(),
|
newHeightfield->setRoot(HeightfieldNodePointer(_root->fillHeight(getTranslation(), getRotation(),
|
||||||
glm::vec3(getScale(), getScale() * _aspectY, getScale() * _aspectZ), position, radius)));
|
glm::vec3(getScale(), getScale() * _aspectY, getScale() * _aspectZ), position, radius, granularity)));
|
||||||
return newHeightfield;
|
return newHeightfield;
|
||||||
}
|
}
|
||||||
|
|
||||||
Spanner* Heightfield::setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material,
|
Spanner* Heightfield::setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material,
|
||||||
const QColor& color, bool paint, bool voxelize) {
|
const QColor& color, bool paint, bool voxelize, float granularity) {
|
||||||
// first see if we're going to exceed the range limits, normalizing if necessary
|
// first see if we're going to exceed the range limits, normalizing if necessary
|
||||||
Spanner* spannerData = static_cast<Spanner*>(spanner.data());
|
Spanner* spannerData = static_cast<Spanner*>(spanner.data());
|
||||||
float normalizeScale = 1.0f, normalizeOffset = 0.0f;
|
float normalizeScale = 1.0f, normalizeOffset = 0.0f;
|
||||||
|
@ -3355,7 +3581,7 @@ Spanner* Heightfield::setMaterial(const SharedObjectPointer& spanner, const Shar
|
||||||
}
|
}
|
||||||
newHeightfield->setRoot(HeightfieldNodePointer(_root->setMaterial(newHeightfield->getTranslation(), getRotation(),
|
newHeightfield->setRoot(HeightfieldNodePointer(_root->setMaterial(newHeightfield->getTranslation(), getRotation(),
|
||||||
glm::vec3(getScale(), getScale() * newHeightfield->getAspectY(), getScale() * _aspectZ), spannerData,
|
glm::vec3(getScale(), getScale() * newHeightfield->getAspectY(), getScale() * _aspectZ), spannerData,
|
||||||
material, color, paint, voxelize, normalizeScale, normalizeOffset)));
|
material, color, paint, voxelize, normalizeScale, normalizeOffset, granularity)));
|
||||||
return newHeightfield;
|
return newHeightfield;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,16 +77,17 @@ public:
|
||||||
/// \param set whether to set the height as opposed to raising/lowering it
|
/// \param set whether to set the height as opposed to raising/lowering it
|
||||||
/// \param erase whether to erase height values
|
/// \param erase whether to erase height values
|
||||||
/// \return the modified spanner, or this if no modification was performed
|
/// \return the modified spanner, or this if no modification was performed
|
||||||
virtual Spanner* paintHeight(const glm::vec3& position, float radius, float height, bool set, bool erase);
|
virtual Spanner* paintHeight(const glm::vec3& position, float radius, float height,
|
||||||
|
bool set, bool erase, float granularity);
|
||||||
|
|
||||||
/// Attempts to fill the spanner's height (adding removing volumetric information).
|
/// Attempts to fill the spanner's height (adding removing volumetric information).
|
||||||
/// \return the modified spanner, or this if no modification was performed
|
/// \return the modified spanner, or this if no modification was performed
|
||||||
virtual Spanner* fillHeight(const glm::vec3& position, float radius);
|
virtual Spanner* fillHeight(const glm::vec3& position, float radius, float granularity);
|
||||||
|
|
||||||
/// Attempts to "sculpt" or "paint," etc., with the supplied spanner.
|
/// Attempts to "sculpt" or "paint," etc., 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* setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material,
|
virtual Spanner* setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material,
|
||||||
const QColor& color, bool paint, bool voxelize);
|
const QColor& color, bool paint, bool voxelize, float granularity);
|
||||||
|
|
||||||
/// Checks whether this spanner has its own colors.
|
/// Checks whether this spanner has its own colors.
|
||||||
virtual bool hasOwnColors() const;
|
virtual bool hasOwnColors() const;
|
||||||
|
@ -696,17 +697,17 @@ public:
|
||||||
|
|
||||||
HeightfieldNode* paintHeight(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
|
HeightfieldNode* paintHeight(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
|
||||||
const glm::vec3& position, float radius, float height, bool set, bool erase,
|
const glm::vec3& position, float radius, float height, bool set, bool erase,
|
||||||
float normalizeScale, float normalizeOffset);
|
float normalizeScale, float normalizeOffset, float granularity);
|
||||||
|
|
||||||
HeightfieldNode* fillHeight(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
|
HeightfieldNode* fillHeight(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
|
||||||
const glm::vec3& position, float radius);
|
const glm::vec3& position, float radius, float granularity);
|
||||||
|
|
||||||
void getRangeAfterEdit(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
|
void getRangeAfterEdit(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
|
||||||
const Box& editBounds, float& minimum, float& maximum) const;
|
const Box& editBounds, float& minimum, float& maximum) const;
|
||||||
|
|
||||||
HeightfieldNode* setMaterial(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
|
HeightfieldNode* setMaterial(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
|
||||||
Spanner* spanner, const SharedObjectPointer& material, const QColor& color, bool paint, bool voxelize,
|
Spanner* spanner, const SharedObjectPointer& material, const QColor& color, bool paint, bool voxelize,
|
||||||
float normalizeScale, float normalizeOffset);
|
float normalizeScale, float normalizeOffset, float granularity);
|
||||||
|
|
||||||
void read(HeightfieldStreamState& state);
|
void read(HeightfieldStreamState& state);
|
||||||
void write(HeightfieldStreamState& state) const;
|
void write(HeightfieldStreamState& state) const;
|
||||||
|
@ -736,6 +737,8 @@ private:
|
||||||
bool findHeightfieldRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
bool findHeightfieldRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
float boundsDistance, float& distance) const;
|
float boundsDistance, float& distance) const;
|
||||||
|
|
||||||
|
HeightfieldNode* subdivide(const QVector<quint16>& heightContents, const QVector<StackArray>& stackContents) const;
|
||||||
|
|
||||||
HeightfieldHeightPointer _height;
|
HeightfieldHeightPointer _height;
|
||||||
HeightfieldColorPointer _color;
|
HeightfieldColorPointer _color;
|
||||||
HeightfieldMaterialPointer _material;
|
HeightfieldMaterialPointer _material;
|
||||||
|
@ -803,12 +806,13 @@ public:
|
||||||
|
|
||||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
|
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
|
||||||
|
|
||||||
virtual Spanner* paintHeight(const glm::vec3& position, float radius, float height, bool set, bool erase);
|
virtual Spanner* paintHeight(const glm::vec3& position, float radius, float height,
|
||||||
|
bool set, bool erase, float granularity);
|
||||||
|
|
||||||
virtual Spanner* fillHeight(const glm::vec3& position, float radius);
|
virtual Spanner* fillHeight(const glm::vec3& position, float radius, float granularity);
|
||||||
|
|
||||||
virtual Spanner* setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material,
|
virtual Spanner* setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material,
|
||||||
const QColor& color, bool paint, bool voxelize);
|
const QColor& color, bool paint, bool voxelize, float granularity);
|
||||||
|
|
||||||
virtual bool hasOwnColors() const;
|
virtual bool hasOwnColors() const;
|
||||||
virtual bool hasOwnMaterials() const;
|
virtual bool hasOwnMaterials() const;
|
||||||
|
|
|
@ -78,7 +78,7 @@ PacketVersion versionForPacketType(PacketType type) {
|
||||||
case PacketTypeAudioStreamStats:
|
case PacketTypeAudioStreamStats:
|
||||||
return 1;
|
return 1;
|
||||||
case PacketTypeMetavoxelData:
|
case PacketTypeMetavoxelData:
|
||||||
return 12;
|
return 13;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue