From 62e6493456711da6c71f999c0154b0caa3f9c6c6 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 6 Aug 2014 17:09:22 -0700 Subject: [PATCH 01/11] Started on heightfield brush tool, added simple query for heightfield height (accessible from scripts). --- interface/src/ui/MetavoxelEditor.cpp | 44 +++++++++++ interface/src/ui/MetavoxelEditor.h | 31 +++++++- .../metavoxels/src/MetavoxelClientManager.cpp | 73 +++++++++++++++++++ .../metavoxels/src/MetavoxelClientManager.h | 2 + 4 files changed, 149 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index 096798e77e..32ffedf0c8 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -118,6 +118,7 @@ MetavoxelEditor::MetavoxelEditor() : addTool(new SetSpannerTool(this)); addTool(new ImportHeightfieldTool(this)); addTool(new EraseHeightfieldTool(this)); + addTool(new HeightBrushTool(this)); updateAttributes(); @@ -1080,3 +1081,46 @@ void EraseHeightfieldTool::apply() { message.edit = QVariant::fromValue(edit); Application::getInstance()->getMetavoxels()->applyEdit(message, true); } + +HeightfieldBrushTool::HeightfieldBrushTool(MetavoxelEditor* editor, const QString& name) : + MetavoxelTool(editor, name, 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(1.0); +} + +void HeightfieldBrushTool::render() { + // find the intersection with the heightfield + glm::vec3 origin = Application::getInstance()->getMouseRayOrigin(); + glm::vec3 direction = Application::getInstance()->getMouseRayDirection(); + + float distance = -origin.y / direction.y; + glm::vec3 point = origin + distance * direction; + + point.y = Application::getInstance()->getMetavoxels()->getHeight(point); + + glPushMatrix(); + glTranslatef(point.x, point.y, point.z); + + glColor4f(1.0f, 0.0f, 0.0f, 1.0f); + + glutSolidSphere(0.1f, 8, 8); + + glPopMatrix(); +} + +HeightBrushTool::HeightBrushTool(MetavoxelEditor* editor) : + HeightfieldBrushTool(editor, "Height Brush") { + + _form->addRow("Height:", _height = new QDoubleSpinBox()); + _height->setMinimum(-FLT_MAX); + _height->setMaximum(FLT_MAX); + _height->setValue(1.0); +} + diff --git a/interface/src/ui/MetavoxelEditor.h b/interface/src/ui/MetavoxelEditor.h index cc30896c49..50b477a2bf 100644 --- a/interface/src/ui/MetavoxelEditor.h +++ b/interface/src/ui/MetavoxelEditor.h @@ -282,7 +282,7 @@ private: HeightfieldPreview _preview; }; -// Allows clearing heighfield blocks. +/// Allows clearing heighfield blocks. class EraseHeightfieldTool : public HeightfieldTool { Q_OBJECT @@ -302,4 +302,33 @@ private: QSpinBox* _length; }; +/// Base class for tools that allow painting on heightfields. +class HeightfieldBrushTool : public MetavoxelTool { + Q_OBJECT + +public: + + HeightfieldBrushTool(MetavoxelEditor* editor, const QString& name); + + virtual void render(); + +protected: + + QFormLayout* _form; + QDoubleSpinBox* _radius; +}; + +/// Allows raising or lowering parts of the heightfield. +class HeightBrushTool : public HeightfieldBrushTool { + Q_OBJECT + +public: + + HeightBrushTool(MetavoxelEditor* editor); + +private: + + QDoubleSpinBox* _height; +}; + #endif // hifi_MetavoxelEditor_h diff --git a/libraries/metavoxels/src/MetavoxelClientManager.cpp b/libraries/metavoxels/src/MetavoxelClientManager.cpp index a2d3410314..d86ad86df4 100644 --- a/libraries/metavoxels/src/MetavoxelClientManager.cpp +++ b/libraries/metavoxels/src/MetavoxelClientManager.cpp @@ -78,6 +78,79 @@ void MetavoxelClientManager::applyEdit(const MetavoxelEditMessage& edit, bool re QMetaObject::invokeMethod(_updater, "applyEdit", Q_ARG(const MetavoxelEditMessage&, edit), Q_ARG(bool, reliable)); } +class HeightVisitor : public MetavoxelVisitor { +public: + + float height; + + HeightVisitor(const MetavoxelLOD& lod, const glm::vec3& location); + + virtual int visit(MetavoxelInfo& info); + +private: + + glm::vec3 _location; +}; + +HeightVisitor::HeightVisitor(const MetavoxelLOD& lod, const glm::vec3& location) : + MetavoxelVisitor(QVector() << AttributeRegistry::getInstance()->getHeightfieldAttribute(), + QVector(), lod), + height(-FLT_MAX), + _location(location) { +} + +static const int REVERSE_ORDER = MetavoxelVisitor::encodeOrder(7, 6, 5, 4, 3, 2, 1, 0); +static const float EIGHT_BIT_MAXIMUM_RECIPROCAL = 1.0f / 255.0f; + +int HeightVisitor::visit(MetavoxelInfo& info) { + glm::vec3 relative = _location - info.minimum; + if (relative.x < 0.0f || relative.z < 0.0f || relative.x > info.size || relative.z > info.size || + height >= info.minimum.y + info.size) { + return STOP_RECURSION; + } + if (!info.isLeaf) { + return REVERSE_ORDER; + } + HeightfieldDataPointer pointer = info.inputValues.at(0).getInlineValue(); + if (!pointer) { + return STOP_RECURSION; + } + const QByteArray& contents = pointer->getContents(); + const uchar* src = (const uchar*)contents.constData(); + int size = glm::sqrt((float)contents.size()); + int highest = size - 1; + relative *= highest / info.size; + glm::vec3 floors = glm::floor(relative); + glm::vec3 ceils = glm::ceil(relative); + glm::vec3 fracts = glm::fract(relative); + int floorX = qMin(qMax((int)floors.x, 0), highest); + int floorZ = qMin(qMax((int)floors.z, 0), highest); + int ceilX = qMin(qMax((int)ceils.x, 0), highest); + int ceilZ = qMin(qMax((int)ceils.z, 0), highest); + float upperLeft = src[floorZ * size + floorX]; + float lowerRight = src[ceilZ * size + ceilX]; + float interpolatedHeight; + if (fracts.x > fracts.z) { + float upperRight = src[floorZ * size + ceilX]; + interpolatedHeight = glm::mix(glm::mix(upperLeft, upperRight, fracts.x), lowerRight, fracts.z); + + } else { + float lowerLeft = src[ceilZ * size + floorX]; + interpolatedHeight = glm::mix(upperLeft, glm::mix(lowerLeft, lowerRight, fracts.x), fracts.z); + } + if (interpolatedHeight == 0.0f) { + return STOP_RECURSION; + } + height = qMax(height, info.minimum.y + interpolatedHeight * info.size * EIGHT_BIT_MAXIMUM_RECIPROCAL); + return SHORT_CIRCUIT; +} + +float MetavoxelClientManager::getHeight(const glm::vec3& location) { + HeightVisitor visitor(getLOD(), location); + guide(visitor); + return visitor.height; +} + MetavoxelLOD MetavoxelClientManager::getLOD() { return MetavoxelLOD(); } diff --git a/libraries/metavoxels/src/MetavoxelClientManager.h b/libraries/metavoxels/src/MetavoxelClientManager.h index 333b709b9e..22c71bd63b 100644 --- a/libraries/metavoxels/src/MetavoxelClientManager.h +++ b/libraries/metavoxels/src/MetavoxelClientManager.h @@ -43,6 +43,8 @@ public: Q_INVOKABLE void applyEdit(const MetavoxelEditMessage& edit, bool reliable = false); + Q_INVOKABLE float getHeight(const glm::vec3& location); + /// Returns the current LOD. This must be thread-safe, as it will be called from the updater thread. virtual MetavoxelLOD getLOD(); From acb973d245475d00f29970ee23685563bc0f7019 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 6 Aug 2014 19:41:25 -0700 Subject: [PATCH 02/11] Working on ray intersection testing. --- interface/src/ui/MetavoxelEditor.cpp | 2 +- .../metavoxels/src/MetavoxelClientManager.cpp | 91 +++++++++++++++++-- .../metavoxels/src/MetavoxelClientManager.h | 4 +- 3 files changed, 88 insertions(+), 9 deletions(-) diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index 32ffedf0c8..a2bb1770b2 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -1103,7 +1103,7 @@ void HeightfieldBrushTool::render() { float distance = -origin.y / direction.y; glm::vec3 point = origin + distance * direction; - point.y = Application::getInstance()->getMetavoxels()->getHeight(point); + point.y = Application::getInstance()->getMetavoxels()->getHeightfieldHeight(point); glPushMatrix(); glTranslatef(point.x, point.y, point.z); diff --git a/libraries/metavoxels/src/MetavoxelClientManager.cpp b/libraries/metavoxels/src/MetavoxelClientManager.cpp index d86ad86df4..51eb4c653c 100644 --- a/libraries/metavoxels/src/MetavoxelClientManager.cpp +++ b/libraries/metavoxels/src/MetavoxelClientManager.cpp @@ -61,6 +61,84 @@ SharedObjectPointer MetavoxelClientManager::findFirstRaySpannerIntersection(cons return closestSpanner; } +class RayHeightfieldIntersectionVisitor : public RayIntersectionVisitor { +public: + + RayHeightfieldIntersectionVisitor(const glm::vec3& origin, const glm::vec3& direction, const MetavoxelLOD& lod); + + virtual int visit(MetavoxelInfo& info, float distance); +}; + +RayHeightfieldIntersectionVisitor::RayHeightfieldIntersectionVisitor(const glm::vec3& origin, + const glm::vec3& direction, const MetavoxelLOD& lod) : + RayIntersectionVisitor(origin, direction, QVector() << + AttributeRegistry::getInstance()->getHeightfieldAttribute(), QVector(), lod) { +} + +static const float EIGHT_BIT_MAXIMUM_RECIPROCAL = 1.0f / 255.0f; + +int RayHeightfieldIntersectionVisitor::visit(MetavoxelInfo& info, float distance) { + if (!info.isLeaf) { + return _order; + } + HeightfieldDataPointer pointer = info.inputValues.at(0).getInlineValue(); + if (!pointer) { + return STOP_RECURSION; + } + const QByteArray& contents = pointer->getContents(); + const uchar* src = (const uchar*)contents.constData(); + int size = glm::sqrt((float)contents.size()); + int highest = size - 1; + float heightScale = highest / EIGHT_BIT_MAXIMUM_RECIPROCAL; + + // find the initial location + glm::vec3 location = (_origin + distance * _direction - info.minimum) * (float)highest / info.size; + + glm::vec3 floors = glm::floor(location); + glm::vec3 ceils = glm::ceil(location); + int floorX = qMin(qMax((int)floors.x, 0), highest); + int floorZ = qMin(qMax((int)floors.z, 0), highest); + int ceilX = qMin(qMax((int)ceils.x, 0), highest); + int ceilZ = qMin(qMax((int)ceils.z, 0), highest); + float upperLeft = src[floorZ * size + floorX] * heightScale; + float upperRight = src[floorZ * size + ceilX] * heightScale; + float lowerLeft = src[ceilZ * size + floorX] * heightScale; + float lowerRight = src[ceilZ * size + ceilX] * heightScale; + + glm::vec3 relativeLocation = location - glm::vec3(floors.x, upperLeft, floors.z); + + glm::vec3 lowerNormal(lowerLeft - lowerRight, 1.0f, upperLeft - lowerLeft); + float lowerProduct = glm::dot(lowerNormal, _direction); + if (lowerProduct < EPSILON) { + float distance = -glm::dot(lowerNormal, relativeLocation) / lowerProduct; + glm::vec3 intersection = relativeLocation + distance * _direction; + if (intersection.x >= 0.0f && intersection.x <= 1.0f && intersection.z >= 0.0f && intersection.z <= 1.0f && + intersection.z >= intersection.x) { + return SHORT_CIRCUIT; + } + } + + glm::vec3 upperNormal(upperLeft - upperRight, 1.0f, upperRight - lowerRight); + float upperProduct = glm::dot(upperNormal, _direction); + if (upperProduct < EPSILON) { + float distance = -glm::dot(upperNormal, relativeLocation) / upperProduct; + glm::vec3 intersection = relativeLocation + distance * _direction; + if (intersection.x >= 0.0f && intersection.x <= 1.0f && intersection.z >= 0.0f && intersection.z <= 1.0f && + intersection.x >= intersection.z) { + return SHORT_CIRCUIT; + } + } + + return STOP_RECURSION; +} + +bool MetavoxelClientManager::findFirstRayHeightfieldIntersection(const glm::vec3& origin, + const glm::vec3& direction, float& distance) { + RayHeightfieldIntersectionVisitor visitor(origin, direction, getLOD()); + guide(visitor); + return false; +} + void MetavoxelClientManager::setSphere(const glm::vec3& center, float radius, const QColor& color) { Sphere* sphere = new Sphere(); sphere->setTranslation(center); @@ -78,12 +156,12 @@ void MetavoxelClientManager::applyEdit(const MetavoxelEditMessage& edit, bool re QMetaObject::invokeMethod(_updater, "applyEdit", Q_ARG(const MetavoxelEditMessage&, edit), Q_ARG(bool, reliable)); } -class HeightVisitor : public MetavoxelVisitor { +class HeightfieldHeightVisitor : public MetavoxelVisitor { public: float height; - HeightVisitor(const MetavoxelLOD& lod, const glm::vec3& location); + HeightfieldHeightVisitor(const MetavoxelLOD& lod, const glm::vec3& location); virtual int visit(MetavoxelInfo& info); @@ -92,7 +170,7 @@ private: glm::vec3 _location; }; -HeightVisitor::HeightVisitor(const MetavoxelLOD& lod, const glm::vec3& location) : +HeightfieldHeightVisitor::HeightfieldHeightVisitor(const MetavoxelLOD& lod, const glm::vec3& location) : MetavoxelVisitor(QVector() << AttributeRegistry::getInstance()->getHeightfieldAttribute(), QVector(), lod), height(-FLT_MAX), @@ -100,9 +178,8 @@ HeightVisitor::HeightVisitor(const MetavoxelLOD& lod, const glm::vec3& location) } static const int REVERSE_ORDER = MetavoxelVisitor::encodeOrder(7, 6, 5, 4, 3, 2, 1, 0); -static const float EIGHT_BIT_MAXIMUM_RECIPROCAL = 1.0f / 255.0f; -int HeightVisitor::visit(MetavoxelInfo& info) { +int HeightfieldHeightVisitor::visit(MetavoxelInfo& info) { glm::vec3 relative = _location - info.minimum; if (relative.x < 0.0f || relative.z < 0.0f || relative.x > info.size || relative.z > info.size || height >= info.minimum.y + info.size) { @@ -145,8 +222,8 @@ int HeightVisitor::visit(MetavoxelInfo& info) { return SHORT_CIRCUIT; } -float MetavoxelClientManager::getHeight(const glm::vec3& location) { - HeightVisitor visitor(getLOD(), location); +float MetavoxelClientManager::getHeightfieldHeight(const glm::vec3& location) { + HeightfieldHeightVisitor visitor(getLOD(), location); guide(visitor); return visitor.height; } diff --git a/libraries/metavoxels/src/MetavoxelClientManager.h b/libraries/metavoxels/src/MetavoxelClientManager.h index 22c71bd63b..8fc9bcd38d 100644 --- a/libraries/metavoxels/src/MetavoxelClientManager.h +++ b/libraries/metavoxels/src/MetavoxelClientManager.h @@ -37,13 +37,15 @@ public: SharedObjectPointer findFirstRaySpannerIntersection(const glm::vec3& origin, const glm::vec3& direction, const AttributePointer& attribute, float& distance); + bool findFirstRayHeightfieldIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance); + Q_INVOKABLE void setSphere(const glm::vec3& center, float radius, const QColor& color = QColor(Qt::gray)); Q_INVOKABLE void setSpanner(const SharedObjectPointer& object, bool reliable = false); Q_INVOKABLE void applyEdit(const MetavoxelEditMessage& edit, bool reliable = false); - Q_INVOKABLE float getHeight(const glm::vec3& location); + Q_INVOKABLE float getHeightfieldHeight(const glm::vec3& location); /// Returns the current LOD. This must be thread-safe, as it will be called from the updater thread. virtual MetavoxelLOD getLOD(); From 8de2dd9485373a5f5e2cdcde0cbab2756f2b2fed Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 7 Aug 2014 14:38:47 -0700 Subject: [PATCH 03/11] Working on ray intersection testing. --- interface/src/ui/MetavoxelEditor.cpp | 8 +- .../metavoxels/src/MetavoxelClientManager.cpp | 170 ++++++++++++++---- 2 files changed, 140 insertions(+), 38 deletions(-) diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index a2bb1770b2..a5186567bd 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -1100,11 +1100,13 @@ void HeightfieldBrushTool::render() { glm::vec3 origin = Application::getInstance()->getMouseRayOrigin(); glm::vec3 direction = Application::getInstance()->getMouseRayDirection(); - float distance = -origin.y / direction.y; + float distance; + if (!Application::getInstance()->getMetavoxels()->findFirstRayHeightfieldIntersection(origin, direction, distance)) { + return; + } + qDebug() << distance; glm::vec3 point = origin + distance * direction; - point.y = Application::getInstance()->getMetavoxels()->getHeightfieldHeight(point); - glPushMatrix(); glTranslatef(point.x, point.y, point.z); diff --git a/libraries/metavoxels/src/MetavoxelClientManager.cpp b/libraries/metavoxels/src/MetavoxelClientManager.cpp index 51eb4c653c..a9eff58f33 100644 --- a/libraries/metavoxels/src/MetavoxelClientManager.cpp +++ b/libraries/metavoxels/src/MetavoxelClientManager.cpp @@ -64,6 +64,8 @@ SharedObjectPointer MetavoxelClientManager::findFirstRaySpannerIntersection(cons class RayHeightfieldIntersectionVisitor : public RayIntersectionVisitor { public: + float intersectionDistance; + RayHeightfieldIntersectionVisitor(const glm::vec3& origin, const glm::vec3& direction, const MetavoxelLOD& lod); virtual int visit(MetavoxelInfo& info, float distance); @@ -72,7 +74,8 @@ public: RayHeightfieldIntersectionVisitor::RayHeightfieldIntersectionVisitor(const glm::vec3& origin, const glm::vec3& direction, const MetavoxelLOD& lod) : RayIntersectionVisitor(origin, direction, QVector() << - AttributeRegistry::getInstance()->getHeightfieldAttribute(), QVector(), lod) { + AttributeRegistry::getInstance()->getHeightfieldAttribute(), QVector(), lod), + intersectionDistance(FLT_MAX) { } static const float EIGHT_BIT_MAXIMUM_RECIPROCAL = 1.0f / 255.0f; @@ -91,42 +94,129 @@ int RayHeightfieldIntersectionVisitor::visit(MetavoxelInfo& info, float distance int highest = size - 1; float heightScale = highest / EIGHT_BIT_MAXIMUM_RECIPROCAL; - // find the initial location - glm::vec3 location = (_origin + distance * _direction - info.minimum) * (float)highest / info.size; - - glm::vec3 floors = glm::floor(location); - glm::vec3 ceils = glm::ceil(location); - int floorX = qMin(qMax((int)floors.x, 0), highest); - int floorZ = qMin(qMax((int)floors.z, 0), highest); - int ceilX = qMin(qMax((int)ceils.x, 0), highest); - int ceilZ = qMin(qMax((int)ceils.z, 0), highest); - float upperLeft = src[floorZ * size + floorX] * heightScale; - float upperRight = src[floorZ * size + ceilX] * heightScale; - float lowerLeft = src[ceilZ * size + floorX] * heightScale; - float lowerRight = src[ceilZ * size + ceilX] * heightScale; - - glm::vec3 relativeLocation = location - glm::vec3(floors.x, upperLeft, floors.z); - - glm::vec3 lowerNormal(lowerLeft - lowerRight, 1.0f, upperLeft - lowerLeft); - float lowerProduct = glm::dot(lowerNormal, _direction); - if (lowerProduct < EPSILON) { - float distance = -glm::dot(lowerNormal, relativeLocation) / lowerProduct; - glm::vec3 intersection = relativeLocation + distance * _direction; - if (intersection.x >= 0.0f && intersection.x <= 1.0f && intersection.z >= 0.0f && intersection.z <= 1.0f && - intersection.z >= intersection.x) { - return SHORT_CIRCUIT; + // find the initial location in heightfield coordinates + glm::vec3 entry = (_origin + distance * _direction - info.minimum) * (float)highest / info.size; + glm::vec3 floors = glm::floor(entry); + glm::vec3 ceils = glm::ceil(entry); + if (floors.x == ceils.x) { + if (_direction.x > 0.0f) { + ceils.x += 1.0f; + } else { + floors.x -= 1.0f; + } + } + if (floors.z == ceils.z) { + if (_direction.z > 0.0f) { + ceils.z += 1.0f; + } else { + floors.z -= 1.0f; } } - glm::vec3 upperNormal(upperLeft - upperRight, 1.0f, upperRight - lowerRight); - float upperProduct = glm::dot(upperNormal, _direction); - if (upperProduct < EPSILON) { - float distance = -glm::dot(upperNormal, relativeLocation) / upperProduct; - glm::vec3 intersection = relativeLocation + distance * _direction; - if (intersection.x >= 0.0f && intersection.x <= 1.0f && intersection.z >= 0.0f && intersection.z <= 1.0f && - intersection.x >= intersection.z) { - return SHORT_CIRCUIT; + bool withinBounds = true; + float accumulatedDistance = 0.0f; + while (withinBounds) { + // find the heights at the corners of the current cell + int floorX = qMin(qMax((int)floors.x, 0), highest); + int floorZ = qMin(qMax((int)floors.z, 0), highest); + int ceilX = qMin(qMax((int)ceils.x, 0), highest); + int ceilZ = qMin(qMax((int)ceils.z, 0), highest); + float upperLeft = src[floorZ * size + floorX] * heightScale; + float upperRight = src[floorZ * size + ceilX] * heightScale; + float lowerLeft = src[ceilZ * size + floorX] * heightScale; + float lowerRight = src[ceilZ * size + ceilX] * heightScale; + + // find the distance to the next x coordinate + float xDistance = FLT_MAX; + if (_direction.x > 0.0f) { + xDistance = (ceils.x - entry.x) / _direction.x; + } else if (_direction.x < 0.0f) { + xDistance = (floors.x - entry.x) / _direction.x; } + + // and the distance to the next z coordinate + float zDistance = FLT_MAX; + if (_direction.z > 0.0f) { + zDistance = (ceils.z - entry.z) / _direction.z; + } else if (_direction.z < 0.0f) { + zDistance = (floors.z - entry.z) / _direction.z; + } + + // the exit distance is the lower of those two + float exitDistance = qMin(xDistance, zDistance); + glm::vec3 exit, nextFloors = floors, nextCeils = ceils; + if (exitDistance == FLT_MAX) { + if (_direction.y > 0.0f) { + return SHORT_CIRCUIT; // line points upwards; no collisions possible + } + withinBounds = false; // line points downwards; check this cell only + + } else { + // find the exit point and the next cell, and determine whether it's still within the bounds + exit = entry + exitDistance * _direction; + withinBounds = (exit.y >= 0.0f && exit.y <= highest); + if (exitDistance == xDistance) { + if (_direction.x > 0.0f) { + nextFloors.x += 1.0f; + withinBounds &= (nextCeils.x += 1.0f) <= highest; + } else { + withinBounds &= (nextFloors.x -= 1.0f) >= 0.0f; + nextCeils.x -= 1.0f; + } + } + if (exitDistance == zDistance) { + if (_direction.z > 0.0f) { + nextFloors.z += 1.0f; + withinBounds &= (nextCeils.z += 1.0f) <= highest; + } else { + withinBounds &= (nextFloors.z -= 1.0f) >= 0.0f; + nextCeils.z -= 1.0f; + } + } + // check the vertical range of the ray against the ranges of the cell heights + if (qMin(entry.y, exit.y) > qMax(qMax(upperLeft, upperRight), qMax(lowerLeft, lowerRight)) || + qMax(entry.y, exit.y) < qMin(qMin(upperLeft, upperRight), qMin(lowerLeft, lowerRight))) { + entry = exit; + floors = nextFloors; + ceils = nextCeils; + accumulatedDistance += exitDistance; + continue; + } + } + // having passed the bounds check, we must check against the planes + glm::vec3 relativeEntry = entry - glm::vec3(floors.x, upperLeft, floors.z); + + // first check the triangle including the Z+ segment + glm::vec3 lowerNormal(lowerLeft - lowerRight, 1.0f, upperLeft - lowerLeft); + float lowerProduct = glm::dot(lowerNormal, _direction); + if (lowerProduct < 0.0f) { + float planeDistance = -glm::dot(lowerNormal, relativeEntry) / lowerProduct; + glm::vec3 intersection = relativeEntry + planeDistance * _direction; + if (intersection.x >= 0.0f && intersection.x <= 1.0f && intersection.z >= 0.0f && intersection.z <= 1.0f && + intersection.z >= intersection.x) { + intersectionDistance = distance + (accumulatedDistance + planeDistance) * (info.size / highest); + return SHORT_CIRCUIT; + } + } + + // then the one with the X+ segment + glm::vec3 upperNormal(upperLeft - upperRight, 1.0f, upperRight - lowerRight); + float upperProduct = glm::dot(upperNormal, _direction); + if (upperProduct < 0.0f) { + float planeDistance = -glm::dot(upperNormal, relativeEntry) / upperProduct; + glm::vec3 intersection = relativeEntry + planeDistance * _direction; + if (intersection.x >= 0.0f && intersection.x <= 1.0f && intersection.z >= 0.0f && intersection.z <= 1.0f && + intersection.x >= intersection.z) { + intersectionDistance = distance + (accumulatedDistance + planeDistance) * (info.size / highest); + return SHORT_CIRCUIT; + } + } + + // no joy; continue on our way + entry = exit; + floors = nextFloors; + ceils = nextCeils; + accumulatedDistance += exitDistance; } return STOP_RECURSION; @@ -136,7 +226,11 @@ bool MetavoxelClientManager::findFirstRayHeightfieldIntersection(const glm::vec3 const glm::vec3& direction, float& distance) { RayHeightfieldIntersectionVisitor visitor(origin, direction, getLOD()); guide(visitor); - return false; + if (visitor.intersectionDistance == FLT_MAX) { + return false; + } + distance = visitor.intersectionDistance; + return true; } void MetavoxelClientManager::setSphere(const glm::vec3& center, float radius, const QColor& color) { @@ -197,6 +291,8 @@ int HeightfieldHeightVisitor::visit(MetavoxelInfo& info) { int size = glm::sqrt((float)contents.size()); int highest = size - 1; relative *= highest / info.size; + + // find the bounds of the cell containing the point and the shared vertex heights glm::vec3 floors = glm::floor(relative); glm::vec3 ceils = glm::ceil(relative); glm::vec3 fracts = glm::fract(relative); @@ -207,6 +303,8 @@ int HeightfieldHeightVisitor::visit(MetavoxelInfo& info) { float upperLeft = src[floorZ * size + floorX]; float lowerRight = src[ceilZ * size + ceilX]; float interpolatedHeight; + + // the final vertex (and thus which triangle we check) depends on which half we're on if (fracts.x > fracts.z) { float upperRight = src[floorZ * size + ceilX]; interpolatedHeight = glm::mix(glm::mix(upperLeft, upperRight, fracts.x), lowerRight, fracts.z); @@ -216,8 +314,10 @@ int HeightfieldHeightVisitor::visit(MetavoxelInfo& info) { interpolatedHeight = glm::mix(upperLeft, glm::mix(lowerLeft, lowerRight, fracts.x), fracts.z); } if (interpolatedHeight == 0.0f) { - return STOP_RECURSION; + return STOP_RECURSION; // ignore zero values } + + // convert the interpolated height into world space height = qMax(height, info.minimum.y + interpolatedHeight * info.size * EIGHT_BIT_MAXIMUM_RECIPROCAL); return SHORT_CIRCUIT; } From 4e1886dfcbbcfc28d06a190f83c7a03c962f27eb Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 7 Aug 2014 15:04:55 -0700 Subject: [PATCH 04/11] Divided when I should have multiplied. --- interface/src/ui/MetavoxelEditor.cpp | 3 +-- libraries/metavoxels/src/MetavoxelClientManager.cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index a5186567bd..01b5ad0718 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -1104,7 +1104,6 @@ void HeightfieldBrushTool::render() { if (!Application::getInstance()->getMetavoxels()->findFirstRayHeightfieldIntersection(origin, direction, distance)) { return; } - qDebug() << distance; glm::vec3 point = origin + distance * direction; glPushMatrix(); @@ -1112,7 +1111,7 @@ void HeightfieldBrushTool::render() { glColor4f(1.0f, 0.0f, 0.0f, 1.0f); - glutSolidSphere(0.1f, 8, 8); + glutSolidSphere(1.0f, 8, 8); glPopMatrix(); } diff --git a/libraries/metavoxels/src/MetavoxelClientManager.cpp b/libraries/metavoxels/src/MetavoxelClientManager.cpp index a9eff58f33..0ffdefd134 100644 --- a/libraries/metavoxels/src/MetavoxelClientManager.cpp +++ b/libraries/metavoxels/src/MetavoxelClientManager.cpp @@ -92,7 +92,7 @@ int RayHeightfieldIntersectionVisitor::visit(MetavoxelInfo& info, float distance const uchar* src = (const uchar*)contents.constData(); int size = glm::sqrt((float)contents.size()); int highest = size - 1; - float heightScale = highest / EIGHT_BIT_MAXIMUM_RECIPROCAL; + float heightScale = highest * EIGHT_BIT_MAXIMUM_RECIPROCAL; // find the initial location in heightfield coordinates glm::vec3 entry = (_origin + distance * _direction - info.minimum) * (float)highest / info.size; From 0fc34a47aacdfcec1480dd8c91fc9d30e20adcb8 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 7 Aug 2014 18:19:58 -0700 Subject: [PATCH 05/11] Show heightfield cursor. --- .../shaders/metavoxel_heightfield_cursor.frag | 20 +++ .../shaders/metavoxel_heightfield_cursor.vert | 31 ++++ interface/src/MetavoxelSystem.cpp | 140 +++++++++++++++++- interface/src/MetavoxelSystem.h | 19 ++- interface/src/ui/MetavoxelEditor.cpp | 10 +- .../metavoxels/src/MetavoxelClientManager.cpp | 6 +- 6 files changed, 204 insertions(+), 22 deletions(-) create mode 100644 interface/resources/shaders/metavoxel_heightfield_cursor.frag create mode 100644 interface/resources/shaders/metavoxel_heightfield_cursor.vert diff --git a/interface/resources/shaders/metavoxel_heightfield_cursor.frag b/interface/resources/shaders/metavoxel_heightfield_cursor.frag new file mode 100644 index 0000000000..20efc51e08 --- /dev/null +++ b/interface/resources/shaders/metavoxel_heightfield_cursor.frag @@ -0,0 +1,20 @@ +#version 120 + +// +// metavoxel_heightfield_cursor.frag +// fragment shader +// +// Created by Andrzej Kapolka on 8/7/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// the cursor texture +uniform sampler2D cursorMap; + +void main(void) { + // just multiply the color by the cursor texture + gl_FragColor = gl_Color * texture2D(cursorMap, gl_TexCoord[0].st); +} diff --git a/interface/resources/shaders/metavoxel_heightfield_cursor.vert b/interface/resources/shaders/metavoxel_heightfield_cursor.vert new file mode 100644 index 0000000000..20502fbdce --- /dev/null +++ b/interface/resources/shaders/metavoxel_heightfield_cursor.vert @@ -0,0 +1,31 @@ +#version 120 + +// +// metavoxel_heighfield_cursor.vert +// vertex shader +// +// Created by Andrzej Kapolka on 8/7/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// the height texture +uniform sampler2D heightMap; + +// the distance between height points in texture space +uniform float heightScale; + +void main(void) { + // compute the view space coordinates + float height = texture2D(heightMap, gl_MultiTexCoord0.st).r; + vec4 viewPosition = gl_ModelViewMatrix * (gl_Vertex + vec4(0.0, height, 0.0, 0.0)); + gl_Position = gl_ProjectionMatrix * viewPosition; + + // generate the texture coordinates from the view position + gl_TexCoord[0] = vec4(dot(viewPosition, gl_EyePlaneS[4]), dot(viewPosition, gl_EyePlaneT[4]), 0.0, 1.0); + + // the zero height should be invisible + gl_FrontColor = vec4(1.0, 1.0, 1.0, 1.0 - step(height, 0.0)); +} diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index f66d71070a..85a1f5a1fc 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -31,6 +31,10 @@ REGISTER_META_OBJECT(StaticModelRenderer) static int bufferPointVectorMetaTypeId = qRegisterMetaType(); +MetavoxelSystem::MetavoxelSystem() : + _cursorTexture(QOpenGLTexture::Target2D) { +} + void MetavoxelSystem::init() { MetavoxelClientManager::init(); DefaultMetavoxelRendererImplementation::init(); @@ -118,6 +122,105 @@ void MetavoxelSystem::render() { guideToAugmented(renderVisitor); } +class HeightfieldCursorRenderVisitor : public MetavoxelVisitor { +public: + + HeightfieldCursorRenderVisitor(const MetavoxelLOD& lod, const Box& bounds); + + virtual int visit(MetavoxelInfo& info); + +private: + + Box _bounds; +}; + +HeightfieldCursorRenderVisitor::HeightfieldCursorRenderVisitor(const MetavoxelLOD& lod, const Box& bounds) : + MetavoxelVisitor(QVector() << + Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), QVector(), lod), + _bounds(bounds) { +} + +int HeightfieldCursorRenderVisitor::visit(MetavoxelInfo& info) { + if (!info.getBounds().intersects(_bounds)) { + return STOP_RECURSION; + } + if (!info.isLeaf) { + return DEFAULT_ORDER; + } + BufferDataPointer buffer = info.inputValues.at(0).getInlineValue(); + if (buffer) { + buffer->render(true); + } + return STOP_RECURSION; +} + +void MetavoxelSystem::renderHeightfieldCursor(const glm::vec3& position, float radius) { + // create the cursor texture lazily + if (!_cursorTexture.isCreated()) { + const int CURSOR_TEXTURE_SIZE = 512; + QImage cursorImage(CURSOR_TEXTURE_SIZE, CURSOR_TEXTURE_SIZE, QImage::Format_ARGB32_Premultiplied); + cursorImage.fill(0x0); + { + QPainter painter(&cursorImage); + const int ELLIPSE_EDGE = 10; + const int OUTER_WIDTH = 10; + QPen outerPen; + outerPen.setWidth(OUTER_WIDTH); + painter.setPen(outerPen); + const int HALF_TEXTURE_SIZE = CURSOR_TEXTURE_SIZE / 2; + painter.drawEllipse(QPoint(HALF_TEXTURE_SIZE, HALF_TEXTURE_SIZE), HALF_TEXTURE_SIZE - ELLIPSE_EDGE, + HALF_TEXTURE_SIZE - ELLIPSE_EDGE); + QPen innerPen(Qt::white); + const int INNER_WIDTH = 6; + innerPen.setWidth(INNER_WIDTH); + painter.setPen(innerPen); + painter.drawEllipse(QPoint(HALF_TEXTURE_SIZE, HALF_TEXTURE_SIZE), HALF_TEXTURE_SIZE - ELLIPSE_EDGE, + HALF_TEXTURE_SIZE - ELLIPSE_EDGE); + } + _cursorTexture.setData(cursorImage, QOpenGLTexture::DontGenerateMipMaps); + _cursorTexture.setWrapMode(QOpenGLTexture::ClampToEdge); + _cursorTexture.setMinificationFilter(QOpenGLTexture::Linear); + } + + glDepthFunc(GL_LEQUAL); + glEnable(GL_CULL_FACE); + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.0f, -1.0f); + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + DefaultMetavoxelRendererImplementation::getHeightfieldCursorProgram().bind(); + + glActiveTexture(GL_TEXTURE4); + float scale = 1.0f / radius; + glm::vec4 sCoefficients(scale, 0.0f, 0.0f, 0.5f - scale * position.x); + glm::vec4 tCoefficients(0.0f, 0.0f, scale, 0.5f - scale * position.z); + glTexGenfv(GL_S, GL_EYE_PLANE, (const GLfloat*)&sCoefficients); + glTexGenfv(GL_T, GL_EYE_PLANE, (const GLfloat*)&tCoefficients); + + _cursorTexture.bind(1); + glActiveTexture(GL_TEXTURE0); + + glm::vec3 extents(radius, radius, radius); + HeightfieldCursorRenderVisitor visitor(getLOD(), Box(position - extents, position + extents)); + guideToAugmented(visitor); + + _cursorTexture.release(1); + glActiveTexture(GL_TEXTURE0); + + DefaultMetavoxelRendererImplementation::getHeightfieldCursorProgram().release(); + + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + + glDisable(GL_POLYGON_OFFSET_FILL); + glDisable(GL_CULL_FACE); + glDepthFunc(GL_LESS); +} + void MetavoxelSystem::deleteTextures(int heightID, int colorID) { glDeleteTextures(1, (GLuint*)&heightID); glDeleteTextures(1, (GLuint*)&colorID); @@ -239,7 +342,7 @@ PointBuffer::PointBuffer(const BufferPointVector& points) : _points(points) { } -void PointBuffer::render() { +void PointBuffer::render(bool cursor) { // initialize buffer, etc. on first render if (!_buffer.isCreated()) { _buffer.setUsagePattern(QOpenGLBuffer::StaticDraw); @@ -294,7 +397,7 @@ public: glm::vec3 vertex; }; -void HeightfieldBuffer::render() { +void HeightfieldBuffer::render(bool cursor) { // initialize textures, etc. on first render if (_heightTextureID == 0) { glGenTextures(1, &_heightTextureID); @@ -385,17 +488,24 @@ void HeightfieldBuffer::render() { glBindTexture(GL_TEXTURE_2D, _heightTextureID); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, _colorTextureID); + int heightScaleLocation; + if (cursor) { + heightScaleLocation = DefaultMetavoxelRendererImplementation::getCursorHeightScaleLocation(); + } else { + heightScaleLocation = DefaultMetavoxelRendererImplementation::getHeightScaleLocation(); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, _colorTextureID); + } - DefaultMetavoxelRendererImplementation::getHeightfieldProgram().setUniformValue( - DefaultMetavoxelRendererImplementation::getHeightScaleLocation(), 1.0f / _heightSize); + DefaultMetavoxelRendererImplementation::getHeightfieldProgram().setUniformValue(heightScaleLocation, 1.0f / _heightSize); glDrawRangeElements(GL_QUADS, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0); - glBindTexture(GL_TEXTURE_2D, 0); + if (!cursor) { + glBindTexture(GL_TEXTURE_2D, 0); + glActiveTexture(GL_TEXTURE0); + } - glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); glPopMatrix(); @@ -475,6 +585,18 @@ void DefaultMetavoxelRendererImplementation::init() { _heightfieldProgram.setUniformValue("diffuseMap", 1); _heightScaleLocation = _heightfieldProgram.uniformLocation("heightScale"); _heightfieldProgram.release(); + + _heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + + "shaders/metavoxel_heightfield_cursor.vert"); + _heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + + "shaders/metavoxel_heightfield_cursor.frag"); + _heightfieldCursorProgram.link(); + + _heightfieldCursorProgram.bind(); + _heightfieldCursorProgram.setUniformValue("heightMap", 0); + _heightfieldCursorProgram.setUniformValue("cursorMap", 1); + _cursorHeightScaleLocation = _heightfieldCursorProgram.uniformLocation("heightScale"); + _heightfieldCursorProgram.release(); } } @@ -771,6 +893,8 @@ ProgramObject DefaultMetavoxelRendererImplementation::_pointProgram; int DefaultMetavoxelRendererImplementation::_pointScaleLocation; ProgramObject DefaultMetavoxelRendererImplementation::_heightfieldProgram; int DefaultMetavoxelRendererImplementation::_heightScaleLocation; +ProgramObject DefaultMetavoxelRendererImplementation::_heightfieldCursorProgram; +int DefaultMetavoxelRendererImplementation::_cursorHeightScaleLocation; static void enableClipPlane(GLenum plane, float x, float y, float z, float w) { GLdouble coefficients[] = { x, y, z, w }; diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h index e7ee0d2c18..a2d3128cb7 100644 --- a/interface/src/MetavoxelSystem.h +++ b/interface/src/MetavoxelSystem.h @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -31,6 +32,8 @@ class MetavoxelSystem : public MetavoxelClientManager { public: + MetavoxelSystem(); + virtual void init(); virtual MetavoxelLOD getLOD(); @@ -43,6 +46,8 @@ public: void simulate(float deltaTime); void render(); + void renderHeightfieldCursor(const glm::vec3& position, float radius); + Q_INVOKABLE void deleteTextures(int heightID, int colorID); protected: @@ -59,6 +64,8 @@ private: MetavoxelLOD _lod; QReadWriteLock _lodLock; Frustum _frustum; + + QOpenGLTexture _cursorTexture; }; /// Describes contents of a point in a point buffer. @@ -105,7 +112,7 @@ public: virtual ~BufferData(); - virtual void render() = 0; + virtual void render(bool cursor = false) = 0; }; typedef QExplicitlySharedDataPointer BufferDataPointer; @@ -116,7 +123,7 @@ public: PointBuffer(const BufferPointVector& points); - virtual void render(); + virtual void render(bool cursor = false); private: @@ -140,7 +147,7 @@ public: const QByteArray& getHeight() const { return _height; } const QByteArray& getColor() const { return _color; } - virtual void render(); + virtual void render(bool cursor = false); private: @@ -193,6 +200,9 @@ public: static ProgramObject& getHeightfieldProgram() { return _heightfieldProgram; } static int getHeightScaleLocation() { return _heightScaleLocation; } + static ProgramObject& getHeightfieldCursorProgram() { return _heightfieldCursorProgram; } + static int getCursorHeightScaleLocation() { return _cursorHeightScaleLocation; } + Q_INVOKABLE DefaultMetavoxelRendererImplementation(); virtual void augment(MetavoxelData& data, const MetavoxelData& previous, MetavoxelInfo& info, const MetavoxelLOD& lod); @@ -206,6 +216,9 @@ private: static ProgramObject _heightfieldProgram; static int _heightScaleLocation; + + static ProgramObject _heightfieldCursorProgram; + static int _cursorHeightScaleLocation; }; /// Base class for spanner renderers; provides clipping. diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index 01b5ad0718..28a4d6da27 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -1105,15 +1105,7 @@ void HeightfieldBrushTool::render() { return; } glm::vec3 point = origin + distance * direction; - - glPushMatrix(); - glTranslatef(point.x, point.y, point.z); - - glColor4f(1.0f, 0.0f, 0.0f, 1.0f); - - glutSolidSphere(1.0f, 8, 8); - - glPopMatrix(); + Application::getInstance()->getMetavoxels()->renderHeightfieldCursor(point, _radius->value()); } HeightBrushTool::HeightBrushTool(MetavoxelEditor* editor) : diff --git a/libraries/metavoxels/src/MetavoxelClientManager.cpp b/libraries/metavoxels/src/MetavoxelClientManager.cpp index 0ffdefd134..70b574d2a2 100644 --- a/libraries/metavoxels/src/MetavoxelClientManager.cpp +++ b/libraries/metavoxels/src/MetavoxelClientManager.cpp @@ -194,7 +194,8 @@ int RayHeightfieldIntersectionVisitor::visit(MetavoxelInfo& info, float distance glm::vec3 intersection = relativeEntry + planeDistance * _direction; if (intersection.x >= 0.0f && intersection.x <= 1.0f && intersection.z >= 0.0f && intersection.z <= 1.0f && intersection.z >= intersection.x) { - intersectionDistance = distance + (accumulatedDistance + planeDistance) * (info.size / highest); + intersectionDistance = qMin(intersectionDistance, distance + + (accumulatedDistance + planeDistance) * (info.size / highest)); return SHORT_CIRCUIT; } } @@ -207,7 +208,8 @@ int RayHeightfieldIntersectionVisitor::visit(MetavoxelInfo& info, float distance glm::vec3 intersection = relativeEntry + planeDistance * _direction; if (intersection.x >= 0.0f && intersection.x <= 1.0f && intersection.z >= 0.0f && intersection.z <= 1.0f && intersection.x >= intersection.z) { - intersectionDistance = distance + (accumulatedDistance + planeDistance) * (info.size / highest); + intersectionDistance = qMin(intersectionDistance, distance + + (accumulatedDistance + planeDistance) * (info.size / highest)); return SHORT_CIRCUIT; } } From 6930174a9ecc9b4adf0846d13c38cfe2160deb47 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 7 Aug 2014 18:30:33 -0700 Subject: [PATCH 06/11] Hide the cursor when the mouse pointer is hidden. --- interface/src/ui/MetavoxelEditor.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index 28a4d6da27..48fa2ed070 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -1096,6 +1096,10 @@ HeightfieldBrushTool::HeightfieldBrushTool(MetavoxelEditor* editor, const QStrin } void HeightfieldBrushTool::render() { + if (Application::getInstance()->isMouseHidden()) { + return; + } + // find the intersection with the heightfield glm::vec3 origin = Application::getInstance()->getMouseRayOrigin(); glm::vec3 direction = Application::getInstance()->getMouseRayDirection(); From b7b1b018eedc7e79b21d7d9b27bedbf907ec28b4 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 8 Aug 2014 11:24:57 -0700 Subject: [PATCH 07/11] No need to use a texture for the cursor; we can just use a fragment shader. --- .../shaders/metavoxel_heightfield_cursor.frag | 20 ++++++++-- interface/src/MetavoxelSystem.cpp | 40 +------------------ interface/src/MetavoxelSystem.h | 5 --- 3 files changed, 18 insertions(+), 47 deletions(-) diff --git a/interface/resources/shaders/metavoxel_heightfield_cursor.frag b/interface/resources/shaders/metavoxel_heightfield_cursor.frag index 20efc51e08..0bb5e21e7d 100644 --- a/interface/resources/shaders/metavoxel_heightfield_cursor.frag +++ b/interface/resources/shaders/metavoxel_heightfield_cursor.frag @@ -11,10 +11,22 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -// the cursor texture -uniform sampler2D cursorMap; +// the inner radius of the outline, squared +const float SQUARED_OUTLINE_INNER_RADIUS = 0.81; + +// the outer radius of the outline, squared +const float SQUARED_OUTLINE_OUTER_RADIUS = 1.0; + +// the inner radius of the inset, squared +const float SQUARED_INSET_INNER_RADIUS = 0.855625; + +// the outer radius of the inset, squared +const float SQUARED_INSET_OUTER_RADIUS = 0.950625; void main(void) { - // just multiply the color by the cursor texture - gl_FragColor = gl_Color * texture2D(cursorMap, gl_TexCoord[0].st); + // use the distance to compute the ring color, then multiply it by the varying color + float squaredDistance = dot(gl_TexCoord[0].st, gl_TexCoord[0].st); + float alpha = step(SQUARED_OUTLINE_INNER_RADIUS, squaredDistance) * step(squaredDistance, SQUARED_OUTLINE_OUTER_RADIUS); + float white = step(SQUARED_INSET_INNER_RADIUS, squaredDistance) * step(squaredDistance, SQUARED_INSET_OUTER_RADIUS); + gl_FragColor = gl_Color * vec4(white, white, white, alpha); } diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 85a1f5a1fc..f62a85025b 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -31,10 +31,6 @@ REGISTER_META_OBJECT(StaticModelRenderer) static int bufferPointVectorMetaTypeId = qRegisterMetaType(); -MetavoxelSystem::MetavoxelSystem() : - _cursorTexture(QOpenGLTexture::Target2D) { -} - void MetavoxelSystem::init() { MetavoxelClientManager::init(); DefaultMetavoxelRendererImplementation::init(); @@ -155,33 +151,6 @@ int HeightfieldCursorRenderVisitor::visit(MetavoxelInfo& info) { } void MetavoxelSystem::renderHeightfieldCursor(const glm::vec3& position, float radius) { - // create the cursor texture lazily - if (!_cursorTexture.isCreated()) { - const int CURSOR_TEXTURE_SIZE = 512; - QImage cursorImage(CURSOR_TEXTURE_SIZE, CURSOR_TEXTURE_SIZE, QImage::Format_ARGB32_Premultiplied); - cursorImage.fill(0x0); - { - QPainter painter(&cursorImage); - const int ELLIPSE_EDGE = 10; - const int OUTER_WIDTH = 10; - QPen outerPen; - outerPen.setWidth(OUTER_WIDTH); - painter.setPen(outerPen); - const int HALF_TEXTURE_SIZE = CURSOR_TEXTURE_SIZE / 2; - painter.drawEllipse(QPoint(HALF_TEXTURE_SIZE, HALF_TEXTURE_SIZE), HALF_TEXTURE_SIZE - ELLIPSE_EDGE, - HALF_TEXTURE_SIZE - ELLIPSE_EDGE); - QPen innerPen(Qt::white); - const int INNER_WIDTH = 6; - innerPen.setWidth(INNER_WIDTH); - painter.setPen(innerPen); - painter.drawEllipse(QPoint(HALF_TEXTURE_SIZE, HALF_TEXTURE_SIZE), HALF_TEXTURE_SIZE - ELLIPSE_EDGE, - HALF_TEXTURE_SIZE - ELLIPSE_EDGE); - } - _cursorTexture.setData(cursorImage, QOpenGLTexture::DontGenerateMipMaps); - _cursorTexture.setWrapMode(QOpenGLTexture::ClampToEdge); - _cursorTexture.setMinificationFilter(QOpenGLTexture::Linear); - } - glDepthFunc(GL_LEQUAL); glEnable(GL_CULL_FACE); glEnable(GL_POLYGON_OFFSET_FILL); @@ -196,21 +165,16 @@ void MetavoxelSystem::renderHeightfieldCursor(const glm::vec3& position, float r glActiveTexture(GL_TEXTURE4); float scale = 1.0f / radius; - glm::vec4 sCoefficients(scale, 0.0f, 0.0f, 0.5f - scale * position.x); - glm::vec4 tCoefficients(0.0f, 0.0f, scale, 0.5f - scale * position.z); + glm::vec4 sCoefficients(scale, 0.0f, 0.0f, -scale * position.x); + glm::vec4 tCoefficients(0.0f, 0.0f, scale, -scale * position.z); glTexGenfv(GL_S, GL_EYE_PLANE, (const GLfloat*)&sCoefficients); glTexGenfv(GL_T, GL_EYE_PLANE, (const GLfloat*)&tCoefficients); - - _cursorTexture.bind(1); glActiveTexture(GL_TEXTURE0); glm::vec3 extents(radius, radius, radius); HeightfieldCursorRenderVisitor visitor(getLOD(), Box(position - extents, position + extents)); guideToAugmented(visitor); - _cursorTexture.release(1); - glActiveTexture(GL_TEXTURE0); - DefaultMetavoxelRendererImplementation::getHeightfieldCursorProgram().release(); glDisableClientState(GL_TEXTURE_COORD_ARRAY); diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h index a2d3128cb7..7b681ff3a9 100644 --- a/interface/src/MetavoxelSystem.h +++ b/interface/src/MetavoxelSystem.h @@ -14,7 +14,6 @@ #include #include -#include #include #include @@ -32,8 +31,6 @@ class MetavoxelSystem : public MetavoxelClientManager { public: - MetavoxelSystem(); - virtual void init(); virtual MetavoxelLOD getLOD(); @@ -64,8 +61,6 @@ private: MetavoxelLOD _lod; QReadWriteLock _lodLock; Frustum _frustum; - - QOpenGLTexture _cursorTexture; }; /// Describes contents of a point in a point buffer. From e24ff0130f03c0255c7647a081fa828a767e3268 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 8 Aug 2014 14:10:44 -0700 Subject: [PATCH 08/11] Basic color/height painting. --- interface/src/ui/MetavoxelEditor.cpp | 37 +++- interface/src/ui/MetavoxelEditor.h | 32 +++- .../metavoxels/src/MetavoxelMessages.cpp | 163 ++++++++++++++++++ libraries/metavoxels/src/MetavoxelMessages.h | 34 ++++ libraries/metavoxels/src/MetavoxelUtil.h | 2 + 5 files changed, 262 insertions(+), 6 deletions(-) diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index 48fa2ed070..bac8c56bc5 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -118,7 +118,8 @@ MetavoxelEditor::MetavoxelEditor() : addTool(new SetSpannerTool(this)); addTool(new ImportHeightfieldTool(this)); addTool(new EraseHeightfieldTool(this)); - addTool(new HeightBrushTool(this)); + addTool(new HeightfieldHeightBrushTool(this)); + addTool(new HeightfieldColorBrushTool(this)); updateAttributes(); @@ -1108,11 +1109,26 @@ void HeightfieldBrushTool::render() { if (!Application::getInstance()->getMetavoxels()->findFirstRayHeightfieldIntersection(origin, direction, distance)) { return; } - glm::vec3 point = origin + distance * direction; - Application::getInstance()->getMetavoxels()->renderHeightfieldCursor(point, _radius->value()); + Application::getInstance()->getMetavoxels()->renderHeightfieldCursor( + _position = origin + distance * direction, _radius->value()); } -HeightBrushTool::HeightBrushTool(MetavoxelEditor* editor) : +bool HeightfieldBrushTool::eventFilter(QObject* watched, QEvent* event) { + if (event->type() == QEvent::Wheel) { + float angle = static_cast(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) { + MetavoxelEditMessage message = { createEdit(static_cast(event)->button() == Qt::RightButton) }; + Application::getInstance()->getMetavoxels()->applyEdit(message, true); + return true; + } + return false; +} + +HeightfieldHeightBrushTool::HeightfieldHeightBrushTool(MetavoxelEditor* editor) : HeightfieldBrushTool(editor, "Height Brush") { _form->addRow("Height:", _height = new QDoubleSpinBox()); @@ -1121,3 +1137,16 @@ HeightBrushTool::HeightBrushTool(MetavoxelEditor* editor) : _height->setValue(1.0); } +QVariant HeightfieldHeightBrushTool::createEdit(bool alternate) { + return QVariant::fromValue(PaintHeightfieldHeightEdit(_position, _radius->value(), _height->value())); +} + +HeightfieldColorBrushTool::HeightfieldColorBrushTool(MetavoxelEditor* editor) : + HeightfieldBrushTool(editor, "Color Brush") { + + _form->addRow("Color:", _color = new QColorEditor(this)); +} + +QVariant HeightfieldColorBrushTool::createEdit(bool alternate) { + return QVariant::fromValue(PaintHeightfieldColorEdit(_position, _radius->value(), _color->getColor())); +} diff --git a/interface/src/ui/MetavoxelEditor.h b/interface/src/ui/MetavoxelEditor.h index 50b477a2bf..87d95a6927 100644 --- a/interface/src/ui/MetavoxelEditor.h +++ b/interface/src/ui/MetavoxelEditor.h @@ -18,6 +18,7 @@ #include "MetavoxelSystem.h" #include "renderer/ProgramObject.h" +class QColorEditor; class QComboBox; class QDoubleSpinBox; class QGroupBox; @@ -312,23 +313,50 @@ public: virtual void render(); + virtual bool eventFilter(QObject* watched, QEvent* event); + protected: + virtual QVariant createEdit(bool alternate) = 0; + QFormLayout* _form; QDoubleSpinBox* _radius; + + glm::vec3 _position; }; /// Allows raising or lowering parts of the heightfield. -class HeightBrushTool : public HeightfieldBrushTool { +class HeightfieldHeightBrushTool : public HeightfieldBrushTool { Q_OBJECT public: - HeightBrushTool(MetavoxelEditor* editor); + HeightfieldHeightBrushTool(MetavoxelEditor* editor); + +protected: + + virtual QVariant createEdit(bool alternate); private: QDoubleSpinBox* _height; }; +/// Allows coloring parts of the heightfield. +class HeightfieldColorBrushTool : public HeightfieldBrushTool { + Q_OBJECT + +public: + + HeightfieldColorBrushTool(MetavoxelEditor* editor); + +protected: + + virtual QVariant createEdit(bool alternate); + +private: + + QColorEditor* _color; +}; + #endif // hifi_MetavoxelEditor_h diff --git a/libraries/metavoxels/src/MetavoxelMessages.cpp b/libraries/metavoxels/src/MetavoxelMessages.cpp index dba9bc9c5c..dfd647fdb5 100644 --- a/libraries/metavoxels/src/MetavoxelMessages.cpp +++ b/libraries/metavoxels/src/MetavoxelMessages.cpp @@ -318,3 +318,166 @@ SetDataEdit::SetDataEdit(const glm::vec3& minimum, const MetavoxelData& data, bo void SetDataEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const { data.set(minimum, this->data, blend); } + +PaintHeightfieldHeightEdit::PaintHeightfieldHeightEdit(const glm::vec3& position, float radius, float height) : + position(position), + radius(radius), + height(height) { +} + +class PaintHeightfieldHeightEditVisitor : public MetavoxelVisitor { +public: + + PaintHeightfieldHeightEditVisitor(const PaintHeightfieldHeightEdit& edit); + + virtual int visit(MetavoxelInfo& info); + +private: + + PaintHeightfieldHeightEdit _edit; + Box _bounds; +}; + +PaintHeightfieldHeightEditVisitor::PaintHeightfieldHeightEditVisitor(const PaintHeightfieldHeightEdit& edit) : + MetavoxelVisitor(QVector() << AttributeRegistry::getInstance()->getHeightfieldAttribute(), + QVector() << AttributeRegistry::getInstance()->getHeightfieldAttribute()), + _edit(edit) { + + glm::vec3 extents(_edit.radius, _edit.radius, _edit.radius); + _bounds = Box(_edit.position - extents, _edit.position + extents); +} + +int PaintHeightfieldHeightEditVisitor::visit(MetavoxelInfo& info) { + if (!info.getBounds().intersects(_bounds)) { + return STOP_RECURSION; + } + if (!info.isLeaf) { + return DEFAULT_ORDER; + } + HeightfieldDataPointer pointer = info.inputValues.at(0).getInlineValue(); + if (!pointer) { + return STOP_RECURSION; + } + QByteArray contents(pointer->getContents()); + int size = glm::sqrt((float)contents.size()); + int highest = size - 1; + float heightScale = highest / info.size; + + glm::vec3 center = (_edit.position - info.minimum) * heightScale; + float scaledRadius = _edit.radius * heightScale; + glm::vec3 extents(scaledRadius, scaledRadius, scaledRadius); + + glm::vec3 start = glm::floor(center - extents); + glm::vec3 end = glm::ceil(center + extents); + + float z = qMax(start.z, 0.0f); + float startX = qMax(start.x, 0.0f), endX = qMin(end.x, (float)highest); + uchar* lineDest = (uchar*)contents.data() + (int)z * size + (int)startX; + float squaredRadius = scaledRadius * scaledRadius; + float squaredRadiusReciprocal = 1.0f / squaredRadius; + const int EIGHT_BIT_MAXIMUM = 255; + float scaledHeight = _edit.height * EIGHT_BIT_MAXIMUM / info.size; + for (float endZ = qMin(end.z, (float)highest); z <= endZ; z += 1.0f) { + uchar* dest = lineDest; + for (float x = startX; x <= endX; x += 1.0f, dest++) { + float dx = x - center.x, dz = z - center.z; + float distanceSquared = dx * dx + dz * dz; + if (distanceSquared <= squaredRadius) { + int value = *dest + scaledHeight * (squaredRadius - distanceSquared) * squaredRadiusReciprocal; + *dest = qMin(qMax(value, 0), EIGHT_BIT_MAXIMUM); + } + } + lineDest += size; + } + + HeightfieldDataPointer newPointer(new HeightfieldData(contents)); + info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(newPointer)); + return STOP_RECURSION; +} + +void PaintHeightfieldHeightEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const { + PaintHeightfieldHeightEditVisitor visitor(*this); + data.guide(visitor); +} + +PaintHeightfieldColorEdit::PaintHeightfieldColorEdit(const glm::vec3& position, float radius, const QColor& color) : + position(position), + radius(radius), + color(color) { +} + +class PaintHeightfieldColorEditVisitor : public MetavoxelVisitor { +public: + + PaintHeightfieldColorEditVisitor(const PaintHeightfieldColorEdit& edit); + + virtual int visit(MetavoxelInfo& info); + +private: + + PaintHeightfieldColorEdit _edit; + Box _bounds; +}; + +PaintHeightfieldColorEditVisitor::PaintHeightfieldColorEditVisitor(const PaintHeightfieldColorEdit& edit) : + MetavoxelVisitor(QVector() << AttributeRegistry::getInstance()->getHeightfieldColorAttribute(), + QVector() << AttributeRegistry::getInstance()->getHeightfieldColorAttribute()), + _edit(edit) { + + glm::vec3 extents(_edit.radius, _edit.radius, _edit.radius); + _bounds = Box(_edit.position - extents, _edit.position + extents); +} + +int PaintHeightfieldColorEditVisitor::visit(MetavoxelInfo& info) { + if (!info.getBounds().intersects(_bounds)) { + return STOP_RECURSION; + } + if (!info.isLeaf) { + return DEFAULT_ORDER; + } + HeightfieldDataPointer pointer = info.inputValues.at(0).getInlineValue(); + if (!pointer) { + return STOP_RECURSION; + } + QByteArray contents(pointer->getContents()); + const int BYTES_PER_PIXEL = 3; + int size = glm::sqrt((float)contents.size() / BYTES_PER_PIXEL); + int highest = size - 1; + float heightScale = highest / info.size; + + glm::vec3 center = (_edit.position - info.minimum) * heightScale; + float scaledRadius = _edit.radius * heightScale; + glm::vec3 extents(scaledRadius, scaledRadius, scaledRadius); + + glm::vec3 start = glm::floor(center - extents); + glm::vec3 end = glm::ceil(center + extents); + + float z = qMax(start.z, 0.0f); + float startX = qMax(start.x, 0.0f), endX = qMin(end.x, (float)highest); + int stride = size * BYTES_PER_PIXEL; + char* lineDest = contents.data() + (int)z * stride + (int)startX * BYTES_PER_PIXEL; + float squaredRadius = scaledRadius * scaledRadius; + char red = _edit.color.red(), green = _edit.color.green(), blue = _edit.color.blue(); + for (float endZ = qMin(end.z, (float)highest); z <= endZ; z += 1.0f) { + char* dest = lineDest; + for (float x = startX; x <= endX; x += 1.0f, dest += BYTES_PER_PIXEL) { + float dx = x - center.x, dz = z - center.z; + if (dx * dx + dz * dz <= squaredRadius) { + dest[0] = red; + dest[1] = green; + dest[2] = blue; + } + } + lineDest += stride; + } + + HeightfieldDataPointer newPointer(new HeightfieldData(contents)); + info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(newPointer)); + return STOP_RECURSION; +} + +void PaintHeightfieldColorEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const { + PaintHeightfieldColorEditVisitor visitor(*this); + data.guide(visitor); +} + diff --git a/libraries/metavoxels/src/MetavoxelMessages.h b/libraries/metavoxels/src/MetavoxelMessages.h index 91d73c08a9..2fc8cbf030 100644 --- a/libraries/metavoxels/src/MetavoxelMessages.h +++ b/libraries/metavoxels/src/MetavoxelMessages.h @@ -207,4 +207,38 @@ public: DECLARE_STREAMABLE_METATYPE(SetDataEdit) +/// An edit that sets a region of a heightfield height. +class PaintHeightfieldHeightEdit : public MetavoxelEdit { + STREAMABLE + +public: + + STREAM glm::vec3 position; + STREAM float radius; + STREAM float height; + + PaintHeightfieldHeightEdit(const glm::vec3& position = glm::vec3(), float radius = 0.0f, float height = 0.0f); + + virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const; +}; + +DECLARE_STREAMABLE_METATYPE(PaintHeightfieldHeightEdit) + +/// An edit that sets a region of a heightfield color. +class PaintHeightfieldColorEdit : public MetavoxelEdit { + STREAMABLE + +public: + + STREAM glm::vec3 position; + STREAM float radius; + STREAM QColor color; + + PaintHeightfieldColorEdit(const glm::vec3& position = glm::vec3(), float radius = 0.0f, const QColor& color = QColor()); + + virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const; +}; + +DECLARE_STREAMABLE_METATYPE(PaintHeightfieldColorEdit) + #endif // hifi_MetavoxelMessages_h diff --git a/libraries/metavoxels/src/MetavoxelUtil.h b/libraries/metavoxels/src/MetavoxelUtil.h index a2b0586708..339c07a21e 100644 --- a/libraries/metavoxels/src/MetavoxelUtil.h +++ b/libraries/metavoxels/src/MetavoxelUtil.h @@ -138,6 +138,8 @@ public: QColorEditor(QWidget* parent); + const QColor& getColor() const { return _color; } + signals: void colorChanged(const QColor& color); From 768410ca0b1c8b5f8a6322a31990b0ef81c0e38a Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 8 Aug 2014 14:14:35 -0700 Subject: [PATCH 09/11] A couple comments, let right mouse button decrease height. --- interface/src/ui/MetavoxelEditor.cpp | 3 ++- libraries/metavoxels/src/MetavoxelMessages.cpp | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index bac8c56bc5..b6f5eb11b3 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -1138,7 +1138,8 @@ HeightfieldHeightBrushTool::HeightfieldHeightBrushTool(MetavoxelEditor* editor) } QVariant HeightfieldHeightBrushTool::createEdit(bool alternate) { - return QVariant::fromValue(PaintHeightfieldHeightEdit(_position, _radius->value(), _height->value())); + return QVariant::fromValue(PaintHeightfieldHeightEdit(_position, _radius->value(), + alternate ? (-_height->value() : _height->value()))); } HeightfieldColorBrushTool::HeightfieldColorBrushTool(MetavoxelEditor* editor) : diff --git a/libraries/metavoxels/src/MetavoxelMessages.cpp b/libraries/metavoxels/src/MetavoxelMessages.cpp index dfd647fdb5..926d839991 100644 --- a/libraries/metavoxels/src/MetavoxelMessages.cpp +++ b/libraries/metavoxels/src/MetavoxelMessages.cpp @@ -370,6 +370,7 @@ int PaintHeightfieldHeightEditVisitor::visit(MetavoxelInfo& info) { glm::vec3 start = glm::floor(center - extents); glm::vec3 end = glm::ceil(center + extents); + // raise/lower all points within the radius float z = qMax(start.z, 0.0f); float startX = qMax(start.x, 0.0f), endX = qMin(end.x, (float)highest); uchar* lineDest = (uchar*)contents.data() + (int)z * size + (int)startX; @@ -383,6 +384,7 @@ int PaintHeightfieldHeightEditVisitor::visit(MetavoxelInfo& info) { float dx = x - center.x, dz = z - center.z; float distanceSquared = dx * dx + dz * dz; if (distanceSquared <= squaredRadius) { + // height falls off towards edges int value = *dest + scaledHeight * (squaredRadius - distanceSquared) * squaredRadiusReciprocal; *dest = qMin(qMax(value, 0), EIGHT_BIT_MAXIMUM); } @@ -452,6 +454,7 @@ int PaintHeightfieldColorEditVisitor::visit(MetavoxelInfo& info) { glm::vec3 start = glm::floor(center - extents); glm::vec3 end = glm::ceil(center + extents); + // paint all points within the radius float z = qMax(start.z, 0.0f); float startX = qMax(start.x, 0.0f), endX = qMin(end.x, (float)highest); int stride = size * BYTES_PER_PIXEL; From 468a3d4d67d7c888db3e6926ff5169d95ac3e42c Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 8 Aug 2014 14:18:32 -0700 Subject: [PATCH 10/11] Bump up the packet version. --- interface/src/ui/MetavoxelEditor.cpp | 2 +- libraries/networking/src/PacketHeaders.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index b6f5eb11b3..d35ed93f1b 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -1139,7 +1139,7 @@ HeightfieldHeightBrushTool::HeightfieldHeightBrushTool(MetavoxelEditor* editor) QVariant HeightfieldHeightBrushTool::createEdit(bool alternate) { return QVariant::fromValue(PaintHeightfieldHeightEdit(_position, _radius->value(), - alternate ? (-_height->value() : _height->value()))); + alternate ? -_height->value() : _height->value())); } HeightfieldColorBrushTool::HeightfieldColorBrushTool(MetavoxelEditor* editor) : diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index f17715ddfe..1b48a2e333 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -80,6 +80,8 @@ PacketVersion versionForPacketType(PacketType type) { return 1; case PacketTypeAudioStreamStats: return 1; + case PacketTypeMetavoxelData: + return 1; default: return 0; } From 18256a657e812405da4b91f566eb0ffc6893abd3 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 8 Aug 2014 14:25:02 -0700 Subject: [PATCH 11/11] Removed unused uniform. --- interface/src/MetavoxelSystem.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index f62a85025b..597542778a 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -558,7 +558,6 @@ void DefaultMetavoxelRendererImplementation::init() { _heightfieldCursorProgram.bind(); _heightfieldCursorProgram.setUniformValue("heightMap", 0); - _heightfieldCursorProgram.setUniformValue("cursorMap", 1); _cursorHeightScaleLocation = _heightfieldCursorProgram.uniformLocation("heightScale"); _heightfieldCursorProgram.release(); }