mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-04 10:13:12 +02:00
Set/erase brushes.
This commit is contained in:
parent
52641bd20f
commit
a9f7533477
6 changed files with 48 additions and 19 deletions
|
@ -869,11 +869,16 @@ HeightfieldHeightBrushTool::HeightfieldHeightBrushTool(MetavoxelEditor* editor)
|
|||
_height->setMinimum(-FLT_MAX);
|
||||
_height->setMaximum(FLT_MAX);
|
||||
_height->setValue(1.0);
|
||||
|
||||
_form->addRow("Mode:", _mode = new QComboBox());
|
||||
_mode->addItem("Raise/Lower");
|
||||
_mode->addItem("Set");
|
||||
_mode->addItem("Erase");
|
||||
}
|
||||
|
||||
QVariant HeightfieldHeightBrushTool::createEdit(bool alternate) {
|
||||
return QVariant::fromValue(PaintHeightfieldHeightEdit(_position, _radius->value(),
|
||||
alternate ? -_height->value() : _height->value()));
|
||||
alternate ? -_height->value() : _height->value(), _mode->currentIndex() == 1, _mode->currentIndex() == 2));
|
||||
}
|
||||
|
||||
MaterialControl::MaterialControl(QWidget* widget, QFormLayout* form, bool clearable) :
|
||||
|
|
|
@ -346,6 +346,7 @@ protected:
|
|||
private:
|
||||
|
||||
QDoubleSpinBox* _height;
|
||||
QComboBox* _mode;
|
||||
};
|
||||
|
||||
/// Contains widgets for editing materials.
|
||||
|
|
|
@ -148,10 +148,13 @@ void SetDataEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects
|
|||
data.set(minimum, this->data, blend);
|
||||
}
|
||||
|
||||
PaintHeightfieldHeightEdit::PaintHeightfieldHeightEdit(const glm::vec3& position, float radius, float height) :
|
||||
PaintHeightfieldHeightEdit::PaintHeightfieldHeightEdit(const glm::vec3& position, float radius,
|
||||
float height, bool set, bool erase) :
|
||||
position(position),
|
||||
radius(radius),
|
||||
height(height) {
|
||||
height(height),
|
||||
set(set),
|
||||
erase(erase) {
|
||||
}
|
||||
|
||||
void PaintHeightfieldHeightEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
|
||||
|
@ -163,7 +166,7 @@ void PaintHeightfieldHeightEdit::apply(MetavoxelData& data, const WeakSharedObje
|
|||
Box(position - extents, position + extents), results);
|
||||
|
||||
foreach (const SharedObjectPointer& spanner, results) {
|
||||
Spanner* newSpanner = static_cast<Spanner*>(spanner.data())->paintHeight(position, radius, height);
|
||||
Spanner* newSpanner = static_cast<Spanner*>(spanner.data())->paintHeight(position, radius, height, set, erase);
|
||||
if (newSpanner != spanner) {
|
||||
data.replace(AttributeRegistry::getInstance()->getSpannersAttribute(), spanner, newSpanner);
|
||||
}
|
||||
|
|
|
@ -203,8 +203,11 @@ public:
|
|||
STREAM glm::vec3 position;
|
||||
STREAM float radius;
|
||||
STREAM float height;
|
||||
STREAM bool set;
|
||||
STREAM bool erase;
|
||||
|
||||
PaintHeightfieldHeightEdit(const glm::vec3& position = glm::vec3(), float radius = 0.0f, float height = 0.0f);
|
||||
PaintHeightfieldHeightEdit(const glm::vec3& position = glm::vec3(), float radius = 0.0f,
|
||||
float height = 0.0f, bool set = false, bool erase = false);
|
||||
|
||||
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
|
||||
};
|
||||
|
|
|
@ -111,7 +111,7 @@ bool Spanner::findRayIntersection(const glm::vec3& origin, const glm::vec3& dire
|
|||
return _bounds.findRayIntersection(origin, direction, distance);
|
||||
}
|
||||
|
||||
Spanner* Spanner::paintHeight(const glm::vec3& position, float radius, float height) {
|
||||
Spanner* Spanner::paintHeight(const glm::vec3& position, float radius, float height, bool set, bool erase) {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -1825,7 +1825,8 @@ void HeightfieldNode::getRangeAfterHeightPaint(const glm::vec3& translation, con
|
|||
}
|
||||
|
||||
HeightfieldNode* HeightfieldNode::paintHeight(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
|
||||
const glm::vec3& position, float radius, float height, float normalizeScale, float normalizeOffset) {
|
||||
const glm::vec3& position, float radius, float height, bool set, bool erase,
|
||||
float normalizeScale, float normalizeOffset) {
|
||||
if (!_height) {
|
||||
return this;
|
||||
}
|
||||
|
@ -1852,7 +1853,7 @@ HeightfieldNode* HeightfieldNode::paintHeight(const glm::vec3& translation, cons
|
|||
HeightfieldNode* newChild = _children[i]->paintHeight(translation +
|
||||
rotation * glm::vec3(i & X_MAXIMUM_FLAG ? nextScale.x : 0.0f, 0.0f,
|
||||
i & Y_MAXIMUM_FLAG ? nextScale.z : 0.0f), rotation,
|
||||
nextScale, position, radius, height, normalizeScale, normalizeOffset);
|
||||
nextScale, position, radius, height, set, erase, normalizeScale, normalizeOffset);
|
||||
if (_children[i] != newChild) {
|
||||
if (newNode == this) {
|
||||
newNode = new HeightfieldNode(*this);
|
||||
|
@ -1896,16 +1897,22 @@ HeightfieldNode* HeightfieldNode::paintHeight(const glm::vec3& translation, cons
|
|||
float squaredRadiusReciprocal = 1.0f / squaredRadius;
|
||||
float multiplierZ = extents.x / extents.z;
|
||||
float relativeHeight = height * numeric_limits<quint16>::max() / scale.y;
|
||||
quint16 heightValue = erase ? 0 : relativeHeight;
|
||||
for (float z = start.z; z <= end.z; z += 1.0f) {
|
||||
quint16* dest = lineDest;
|
||||
for (float x = start.x; x <= end.x; x += 1.0f, dest++) {
|
||||
float dx = x - center.x, dz = (z - center.z) * multiplierZ;
|
||||
float distanceSquared = dx * dx + dz * dz;
|
||||
if (distanceSquared <= squaredRadius) {
|
||||
// height falls off towards edges
|
||||
int value = *dest;
|
||||
if (value != 0) {
|
||||
*dest = value + relativeHeight * (squaredRadius - distanceSquared) * squaredRadiusReciprocal;
|
||||
if (erase || set) {
|
||||
*dest = heightValue;
|
||||
|
||||
} else {
|
||||
// height falls off towards edges
|
||||
int value = *dest;
|
||||
if (value != 0) {
|
||||
*dest = value + relativeHeight * (squaredRadius - distanceSquared) * squaredRadiusReciprocal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3352,18 +3359,25 @@ bool Heightfield::findRayIntersection(const glm::vec3& origin, const glm::vec3&
|
|||
getScale() * _aspectZ), origin, direction, distance);
|
||||
}
|
||||
|
||||
Spanner* Heightfield::paintHeight(const glm::vec3& position, float radius, float height) {
|
||||
Spanner* Heightfield::paintHeight(const glm::vec3& position, float radius, float height, bool set, bool erase) {
|
||||
// first see if we're going to exceed the range limits
|
||||
float minimumValue = 1.0f, maximumValue = numeric_limits<quint16>::max();
|
||||
_root->getRangeAfterHeightPaint(getTranslation(), getRotation(), glm::vec3(getScale(), getScale() * _aspectY,
|
||||
getScale() * _aspectZ), position, radius, height, minimumValue, maximumValue);
|
||||
if (set) {
|
||||
float heightValue = height * numeric_limits<quint16>::max() / (getScale() * _aspectY);
|
||||
minimumValue = qMin(minimumValue, heightValue);
|
||||
maximumValue = qMax(maximumValue, heightValue);
|
||||
|
||||
} else if (!erase) {
|
||||
_root->getRangeAfterHeightPaint(getTranslation(), getRotation(), glm::vec3(getScale(), getScale() * _aspectY,
|
||||
getScale() * _aspectZ), position, radius, height, minimumValue, maximumValue);
|
||||
}
|
||||
|
||||
// normalize if necessary
|
||||
float normalizeScale, normalizeOffset;
|
||||
Heightfield* newHeightfield = prepareEdit(minimumValue, maximumValue, normalizeScale, normalizeOffset);
|
||||
newHeightfield->setRoot(HeightfieldNodePointer(_root->paintHeight(newHeightfield->getTranslation(), getRotation(),
|
||||
glm::vec3(getScale(), getScale() * newHeightfield->getAspectY(), getScale() * _aspectZ), position, radius, height,
|
||||
normalizeScale, normalizeOffset)));
|
||||
set, erase, normalizeScale, normalizeOffset)));
|
||||
return newHeightfield;
|
||||
}
|
||||
|
||||
|
|
|
@ -74,8 +74,10 @@ public:
|
|||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
|
||||
|
||||
/// Attempts to modify the spanner's height.
|
||||
/// \param set whether to set the height as opposed to raising/lowering it
|
||||
/// \param erase whether to erase height values
|
||||
/// \return the modified spanner, or this if no modification was performed
|
||||
virtual Spanner* paintHeight(const glm::vec3& position, float radius, float height);
|
||||
virtual Spanner* paintHeight(const glm::vec3& position, float radius, float height, bool set, bool erase);
|
||||
|
||||
/// Attempts to fill the spanner's height (adding removing volumetric information).
|
||||
/// \return the modified spanner, or this if no modification was performed
|
||||
|
@ -693,7 +695,8 @@ public:
|
|||
const glm::vec3& position, float radius, float height, float& minimum, float& maximum) const;
|
||||
|
||||
HeightfieldNode* paintHeight(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
|
||||
const glm::vec3& position, float radius, float height, float normalizeScale, float normalizeOffset);
|
||||
const glm::vec3& position, float radius, float height, bool set, bool erase,
|
||||
float normalizeScale, float normalizeOffset);
|
||||
|
||||
HeightfieldNode* fillHeight(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
|
||||
const glm::vec3& position, float radius);
|
||||
|
@ -800,7 +803,7 @@ public:
|
|||
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
|
||||
|
||||
virtual Spanner* paintHeight(const glm::vec3& position, float radius, float height);
|
||||
virtual Spanner* paintHeight(const glm::vec3& position, float radius, float height, bool set, bool erase);
|
||||
|
||||
virtual Spanner* fillHeight(const glm::vec3& position, float radius);
|
||||
|
||||
|
|
Loading…
Reference in a new issue