mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 03:44:02 +02:00
Don't show grid for tools where it isn't needed, started on "fill" tool.
This commit is contained in:
parent
0dc4b26367
commit
d82f269263
6 changed files with 167 additions and 8 deletions
|
@ -129,6 +129,7 @@ MetavoxelEditor::MetavoxelEditor() :
|
|||
addTool(new HeightfieldHeightBrushTool(this));
|
||||
addTool(new HeightfieldMaterialBrushTool(this));
|
||||
addTool(new HeightfieldSculptBrushTool(this));
|
||||
addTool(new HeightfieldFillBrushTool(this));
|
||||
addTool(new HeightfieldMaterialBoxTool(this));
|
||||
addTool(new HeightfieldMaterialSpannerTool(this));
|
||||
|
||||
|
@ -330,6 +331,9 @@ void MetavoxelEditor::render() {
|
|||
MetavoxelTool* tool = getActiveTool();
|
||||
if (tool) {
|
||||
tool->render();
|
||||
if (!tool->getUsesGrid()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
glDepthMask(GL_FALSE);
|
||||
|
@ -385,10 +389,11 @@ MetavoxelTool* MetavoxelEditor::getActiveTool() const {
|
|||
|
||||
ProgramObject MetavoxelEditor::_gridProgram;
|
||||
|
||||
MetavoxelTool::MetavoxelTool(MetavoxelEditor* editor, const QString& name, bool usesValue, bool userFacing) :
|
||||
MetavoxelTool::MetavoxelTool(MetavoxelEditor* editor, const QString& name, bool usesValue, bool userFacing, bool usesGrid) :
|
||||
_editor(editor),
|
||||
_usesValue(usesValue),
|
||||
_userFacing(userFacing) {
|
||||
_userFacing(userFacing),
|
||||
_usesGrid(usesGrid) {
|
||||
|
||||
QVBoxLayout* layout = new QVBoxLayout();
|
||||
setLayout(layout);
|
||||
|
@ -669,7 +674,7 @@ void InsertSpannerTool::applyEdit(const AttributePointer& attribute, const Share
|
|||
}
|
||||
|
||||
RemoveSpannerTool::RemoveSpannerTool(MetavoxelEditor* editor) :
|
||||
MetavoxelTool(editor, "Remove Spanner", false) {
|
||||
MetavoxelTool(editor, "Remove Spanner", false, true, false) {
|
||||
}
|
||||
|
||||
bool RemoveSpannerTool::appliesTo(const AttributePointer& attribute) const {
|
||||
|
@ -696,7 +701,7 @@ bool RemoveSpannerTool::eventFilter(QObject* watched, QEvent* event) {
|
|||
}
|
||||
|
||||
ClearSpannersTool::ClearSpannersTool(MetavoxelEditor* editor) :
|
||||
MetavoxelTool(editor, "Clear Spanners", false) {
|
||||
MetavoxelTool(editor, "Clear Spanners", false, true, false) {
|
||||
|
||||
QPushButton* button = new QPushButton("Clear");
|
||||
layout()->addWidget(button);
|
||||
|
@ -717,7 +722,7 @@ void ClearSpannersTool::clear() {
|
|||
}
|
||||
|
||||
HeightfieldTool::HeightfieldTool(MetavoxelEditor* editor, const QString& name) :
|
||||
MetavoxelTool(editor, name, false) {
|
||||
MetavoxelTool(editor, name, false, true, false) {
|
||||
|
||||
QWidget* widget = new QWidget();
|
||||
widget->setLayout(_form = new QFormLayout());
|
||||
|
@ -806,7 +811,7 @@ void ImportHeightfieldTool::updateSpanner() {
|
|||
}
|
||||
|
||||
HeightfieldBrushTool::HeightfieldBrushTool(MetavoxelEditor* editor, const QString& name) :
|
||||
MetavoxelTool(editor, name, false),
|
||||
MetavoxelTool(editor, name, false, true, false),
|
||||
_positionValid(false) {
|
||||
|
||||
QWidget* widget = new QWidget();
|
||||
|
@ -968,6 +973,14 @@ QVariant HeightfieldSculptBrushTool::createEdit(bool alternate) {
|
|||
}
|
||||
}
|
||||
|
||||
HeightfieldFillBrushTool::HeightfieldFillBrushTool(MetavoxelEditor* editor) :
|
||||
HeightfieldBrushTool(editor, "Fill Brush") {
|
||||
}
|
||||
|
||||
QVariant HeightfieldFillBrushTool::createEdit(bool alternate) {
|
||||
return QVariant::fromValue(FillHeightfieldHeightEdit(_position, _radius->value()));
|
||||
}
|
||||
|
||||
HeightfieldMaterialBoxTool::HeightfieldMaterialBoxTool(MetavoxelEditor* editor) :
|
||||
BoxTool(editor, "Set Material (Box)", false) {
|
||||
|
||||
|
|
|
@ -92,12 +92,15 @@ class MetavoxelTool : public QWidget {
|
|||
|
||||
public:
|
||||
|
||||
MetavoxelTool(MetavoxelEditor* editor, const QString& name, bool usesValue = true, bool userFacing = true);
|
||||
MetavoxelTool(MetavoxelEditor* editor, const QString& name, bool usesValue = true,
|
||||
bool userFacing = true, bool usesGrid = true);
|
||||
|
||||
bool getUsesValue() const { return _usesValue; }
|
||||
|
||||
bool isUserFacing() const { return _userFacing; }
|
||||
|
||||
bool getUsesGrid() const { return _usesGrid; }
|
||||
|
||||
virtual bool appliesTo(const AttributePointer& attribute) const;
|
||||
|
||||
virtual void simulate(float deltaTime);
|
||||
|
@ -113,6 +116,7 @@ protected:
|
|||
MetavoxelEditor* _editor;
|
||||
bool _usesValue;
|
||||
bool _userFacing;
|
||||
bool _usesGrid;
|
||||
};
|
||||
|
||||
/// Base class for tools that allow dragging out a 3D box.
|
||||
|
@ -404,6 +408,19 @@ private:
|
|||
MaterialControl* _materialControl;
|
||||
};
|
||||
|
||||
/// Allows "filling" (removing dual contour stack data) parts of the heightfield.
|
||||
class HeightfieldFillBrushTool : public HeightfieldBrushTool {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
HeightfieldFillBrushTool(MetavoxelEditor* editor);
|
||||
|
||||
protected:
|
||||
|
||||
virtual QVariant createEdit(bool alternate);
|
||||
};
|
||||
|
||||
/// Allows setting heightfield materials by dragging out a box.
|
||||
class HeightfieldMaterialBoxTool : public BoxTool {
|
||||
Q_OBJECT
|
||||
|
|
|
@ -201,3 +201,21 @@ void HeightfieldMaterialSpannerEdit::apply(MetavoxelData& data, const WeakShared
|
|||
}
|
||||
}
|
||||
|
||||
FillHeightfieldHeightEdit::FillHeightfieldHeightEdit(const glm::vec3& position, float radius) :
|
||||
position(position),
|
||||
radius(radius) {
|
||||
}
|
||||
|
||||
void FillHeightfieldHeightEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
|
||||
glm::vec3 extents = glm::vec3(radius, radius, radius);
|
||||
QVector<SharedObjectPointer> results;
|
||||
data.getIntersecting(AttributeRegistry::getInstance()->getSpannersAttribute(),
|
||||
Box(position - extents, position + extents), results);
|
||||
|
||||
foreach (const SharedObjectPointer& spanner, results) {
|
||||
Spanner* newSpanner = static_cast<Spanner*>(spanner.data())->fillHeight(position, radius);
|
||||
if (newSpanner != spanner) {
|
||||
data.replace(AttributeRegistry::getInstance()->getSpannersAttribute(), spanner, newSpanner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -243,4 +243,20 @@ public:
|
|||
|
||||
DECLARE_STREAMABLE_METATYPE(HeightfieldMaterialSpannerEdit)
|
||||
|
||||
/// An edit that sets a region of a heightfield height.
|
||||
class FillHeightfieldHeightEdit : public MetavoxelEdit {
|
||||
STREAMABLE
|
||||
|
||||
public:
|
||||
|
||||
STREAM glm::vec3 position;
|
||||
STREAM float radius;
|
||||
|
||||
FillHeightfieldHeightEdit(const glm::vec3& position = glm::vec3(), float radius = 0.0f);
|
||||
|
||||
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
|
||||
};
|
||||
|
||||
DECLARE_STREAMABLE_METATYPE(FillHeightfieldHeightEdit)
|
||||
|
||||
#endif // hifi_MetavoxelMessages_h
|
||||
|
|
|
@ -115,6 +115,10 @@ Spanner* Spanner::paintHeight(const glm::vec3& position, float radius, float hei
|
|||
return this;
|
||||
}
|
||||
|
||||
Spanner* Spanner::fillHeight(const glm::vec3& position, float radius) {
|
||||
return this;
|
||||
}
|
||||
|
||||
Spanner* Spanner::setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material,
|
||||
const QColor& color, bool paint) {
|
||||
return this;
|
||||
|
@ -1926,7 +1930,8 @@ HeightfieldNode* HeightfieldNode::paintHeight(const glm::vec3& translation, cons
|
|||
maybeRenormalize(scale, normalizeScale, normalizeOffset, innerStackWidth, newHeightContents, newStackContents);
|
||||
if (!intersects) {
|
||||
return new HeightfieldNode(HeightfieldHeightPointer(new HeightfieldHeight(heightWidth, newHeightContents)),
|
||||
_color, _material, HeightfieldStackPointer(new HeightfieldStack(stackWidth, newStackContents, newStackMaterials)));
|
||||
_color, _material, HeightfieldStackPointer(newStackContents.isEmpty() ? NULL :
|
||||
new HeightfieldStack(stackWidth, newStackContents, newStackMaterials)));
|
||||
}
|
||||
|
||||
// now apply the actual change
|
||||
|
@ -1956,6 +1961,80 @@ HeightfieldNode* HeightfieldNode::paintHeight(const glm::vec3& translation, cons
|
|||
lineDest += heightWidth;
|
||||
}
|
||||
|
||||
return new HeightfieldNode(HeightfieldHeightPointer(new HeightfieldHeight(heightWidth, newHeightContents)),
|
||||
_color, _material, HeightfieldStackPointer(newStackContents.isEmpty() ? NULL :
|
||||
new HeightfieldStack(stackWidth, newStackContents, newStackMaterials)));
|
||||
}
|
||||
|
||||
HeightfieldNode* HeightfieldNode::fillHeight(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
|
||||
const glm::vec3& position, float radius) {
|
||||
if (!_height) {
|
||||
return this;
|
||||
}
|
||||
int heightWidth = _height->getWidth();
|
||||
int heightHeight = _height->getContents().size() / heightWidth;
|
||||
int innerHeightWidth = heightWidth - HeightfieldHeight::HEIGHT_EXTENSION;
|
||||
int innerHeightHeight = heightHeight - HeightfieldHeight::HEIGHT_EXTENSION;
|
||||
int highestHeightX = heightWidth - 1;
|
||||
int highestHeightZ = heightHeight - 1;
|
||||
|
||||
glm::vec3 inverseScale(innerHeightWidth / scale.x, numeric_limits<quint16>::max() / scale.y, innerHeightHeight / scale.z);
|
||||
glm::vec3 center = glm::inverse(rotation) * (position - translation) * inverseScale + glm::vec3(1.0f, 0.0f, 1.0f);
|
||||
glm::vec3 extents = radius * inverseScale;
|
||||
|
||||
if (center.x + extents.x < 0.0f || center.z + extents.z < 0.0f || center.x - extents.x > highestHeightX ||
|
||||
center.z - extents.z > highestHeightZ) {
|
||||
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]->fillHeight(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);
|
||||
if (_children[i] != newChild) {
|
||||
if (newNode == this) {
|
||||
newNode = new HeightfieldNode(*this);
|
||||
}
|
||||
newNode->setChild(i, HeightfieldNodePointer(newChild));
|
||||
}
|
||||
}
|
||||
if (newNode != this) {
|
||||
newNode->mergeChildren(true, false);
|
||||
}
|
||||
return newNode;
|
||||
}
|
||||
if (!_stack) {
|
||||
return this;
|
||||
}
|
||||
QVector<quint16> newHeightContents = _height->getContents();
|
||||
|
||||
int stackWidth = _stack->getWidth();
|
||||
QVector<StackArray> newStackContents = _stack->getContents();
|
||||
QVector<SharedObjectPointer> newStackMaterials = _stack->getMaterials();
|
||||
|
||||
glm::vec3 start = glm::clamp(glm::floor(center - extents), glm::vec3(),
|
||||
glm::vec3((float)highestHeightX, 0.0f, (float)highestHeightZ));
|
||||
glm::vec3 end = glm::clamp(glm::ceil(center + extents), glm::vec3(),
|
||||
glm::vec3((float)highestHeightX, 0.0f, (float)highestHeightZ));
|
||||
|
||||
quint16* lineDest = newHeightContents.data() + (int)start.z * heightWidth + (int)start.x;
|
||||
float squaredRadius = extents.x * extents.x;
|
||||
float multiplierZ = extents.x / extents.z;
|
||||
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) {
|
||||
|
||||
}
|
||||
}
|
||||
lineDest += heightWidth;
|
||||
}
|
||||
|
||||
return new HeightfieldNode(HeightfieldHeightPointer(new HeightfieldHeight(heightWidth, newHeightContents)),
|
||||
_color, _material, HeightfieldStackPointer(new HeightfieldStack(stackWidth, newStackContents, newStackMaterials)));
|
||||
}
|
||||
|
@ -3239,6 +3318,13 @@ Spanner* Heightfield::paintHeight(const glm::vec3& position, float radius, float
|
|||
return newHeightfield;
|
||||
}
|
||||
|
||||
Spanner* Heightfield::fillHeight(const glm::vec3& position, float radius) {
|
||||
Heightfield* newHeightfield = static_cast<Heightfield*>(clone(true));
|
||||
newHeightfield->setRoot(HeightfieldNodePointer(_root->fillHeight(getTranslation(), getRotation(),
|
||||
glm::vec3(getScale(), getScale() * _aspectY, getScale() * _aspectZ), position, radius)));
|
||||
return newHeightfield;
|
||||
}
|
||||
|
||||
Spanner* Heightfield::setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material,
|
||||
const QColor& color, bool paint) {
|
||||
// first see if we're going to exceed the range limits, normalizing if necessary
|
||||
|
|
|
@ -77,6 +77,10 @@ public:
|
|||
/// \return the modified spanner, or this if no modification was performed
|
||||
virtual Spanner* paintHeight(const glm::vec3& position, float radius, float height);
|
||||
|
||||
/// Attempts to fill the spanner's height (removing volumetric information).
|
||||
/// \return the modified spanner, or this if no modification was performed
|
||||
virtual Spanner* fillHeight(const glm::vec3& position, float radius);
|
||||
|
||||
/// Attempts to "sculpt" or "paint" with the supplied spanner.
|
||||
/// \return the modified spanner, or this if no modification was performed
|
||||
virtual Spanner* setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material,
|
||||
|
@ -691,6 +695,9 @@ public:
|
|||
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);
|
||||
|
||||
HeightfieldNode* fillHeight(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
|
||||
const glm::vec3& position, float radius);
|
||||
|
||||
void getRangeAfterEdit(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale,
|
||||
const Box& editBounds, float& minimum, float& maximum) const;
|
||||
|
||||
|
@ -795,6 +802,8 @@ public:
|
|||
|
||||
virtual Spanner* paintHeight(const glm::vec3& position, float radius, float height);
|
||||
|
||||
virtual Spanner* fillHeight(const glm::vec3& position, float radius);
|
||||
|
||||
virtual Spanner* setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material,
|
||||
const QColor& color, bool paint);
|
||||
|
||||
|
|
Loading…
Reference in a new issue