From 16cdc2614f5bca8b1498d44e40202adc1303ff91 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 30 Sep 2014 10:06:39 -0700 Subject: [PATCH] added circle overlays --- examples/editModels.js | 263 ++++++++++++++++-- interface/src/ui/overlays/Circle3DOverlay.cpp | 152 ++++++++++ interface/src/ui/overlays/Circle3DOverlay.h | 43 +++ interface/src/ui/overlays/Overlays.cpp | 7 + interface/src/ui/overlays/Sphere3DOverlay.cpp | 1 - 5 files changed, 442 insertions(+), 24 deletions(-) create mode 100644 interface/src/ui/overlays/Circle3DOverlay.cpp create mode 100644 interface/src/ui/overlays/Circle3DOverlay.h diff --git a/examples/editModels.js b/examples/editModels.js index 406dac5081..c669cf7622 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -1573,11 +1573,6 @@ var ExportMenu = function (opts) { var SelectionDisplay = function (opts) { var self = this; - var selectionBox = Overlays.addOverlay("3d", { - position: { x: 1, y: 1, z: 1 }, - scale: 1, - visible: false - }); var selectionBox = Overlays.addOverlay("cube", { position: { x:0, y: 0, z: 0}, size: 1, @@ -1587,36 +1582,258 @@ var SelectionDisplay = function (opts) { visible: false }); + var yawOverlayAngles = { x: 90, y: 0, z: 0 }; + var yawOverlayRotation = Quat.fromVec3Degrees(yawOverlayAngles); + var yawOverlayInner = Overlays.addOverlay("circle3d", { + position: { x:0, y: 0, z: 0}, + size: 1, + color: { red: 0, green: 195, blue: 255}, + alpha: 0.1, + solid: false, + visible: false, + rotation: yawOverlayRotation + }); + + var yawOverlayOuter = Overlays.addOverlay("circle3d", { + position: { x:0, y: 0, z: 0}, + size: 1, + color: { red: 0, green: 195, blue: 215}, + alpha: 0.1, + solid: false, + visible: false, + rotation: yawOverlayRotation + }); + + var yawOverlayCurrent = Overlays.addOverlay("circle3d", { + position: { x:0, y: 0, z: 0}, + size: 1, + color: { red: 255, green: 190, blue: 190}, + alpha: 1, + solid: false, + visible: false, + rotation: yawOverlayRotation + }); + + var yawHandleAngles = { x: 90, y: 90, z: 0 }; + var yawHandleRotation = Quat.fromVec3Degrees(yawHandleAngles); + var yawHandle = Overlays.addOverlay("billboard", { + url: "https://s3.amazonaws.com/uploads.hipchat.com/33953/231323/oocBjCwXpWlHpF9/rotate_arrow_black.png", + position: { x:0, y: 0, z: 0}, + solid: true, + color: { red: 0, green: 0, blue: 255 }, + alpha: 0.3, + visible: false, + size: 0.1, + scale: 0.1, + rotation: yawHandleRotation, + isFacingAvatar: false + }); + + var pitchOverlayAngles = { x: 0, y: 90, z: 0 }; + var pitchOverlayRotation = Quat.fromVec3Degrees(pitchOverlayAngles); + var pitchOverlay = Overlays.addOverlay("circle3d", { + position: { x:0, y: 0, z: 0}, + size: 1, + color: { red: 0, green: 255, blue: 0}, + alpha: 1, + solid: false, + visible: false, + rotation: pitchOverlayRotation + }); + + var pitchHandleAngles = { x: 90, y: 0, z: 90 }; + var pitchHandleRotation = Quat.fromVec3Degrees(pitchHandleAngles); + var pitchHandle = Overlays.addOverlay("billboard", { + url: "https://s3.amazonaws.com/uploads.hipchat.com/33953/231323/oocBjCwXpWlHpF9/rotate_arrow_black.png", + position: { x:0, y: 0, z: 0}, + solid: true, + color: { red: 0, green: 0, blue: 255 }, + alpha: 0.3, + visible: false, + size: 0.1, + scale: 0.1, + rotation: pitchHandleRotation, + isFacingAvatar: false + }); + + var rollOverlayAngles = { x: 0, y: 180, z: 0 }; + var rollOverlayRotation = Quat.fromVec3Degrees(rollOverlayAngles); + var rollOverlay = Overlays.addOverlay("circle3d", { + position: { x:0, y: 0, z: 0}, + size: 1, + color: { red: 255, green: 0, blue: 0}, + alpha: 1, + solid: false, + visible: false, + rotation: rollOverlayRotation + }); + + var rollHandleAngles = { x: 0, y: 0, z: 180 }; + var rollHandleRotation = Quat.fromVec3Degrees(rollHandleAngles); + var rollHandle = Overlays.addOverlay("billboard", { + url: "https://s3.amazonaws.com/uploads.hipchat.com/33953/231323/oocBjCwXpWlHpF9/rotate_arrow_black.png", + position: { x:0, y: 0, z: 0}, + solid: true, + color: { red: 0, green: 0, blue: 255 }, + alpha: 0.3, + visible: false, + size: 0.1, + scale: 0.1, + rotation: rollHandleRotation, + isFacingAvatar: false + }); + this.cleanup = function () { Overlays.deleteOverlay(selectionBox); + Overlays.deleteOverlay(yawOverlayInner); + Overlays.deleteOverlay(yawOverlayOuter); + Overlays.deleteOverlay(yawOverlayCurrent); + Overlays.deleteOverlay(pitchOverlay); + Overlays.deleteOverlay(rollOverlay); + Overlays.deleteOverlay(yawHandle); + Overlays.deleteOverlay(pitchHandle); + Overlays.deleteOverlay(rollHandle); }; this.showSelection = function (properties) { + + var diagonal = (Vec3.length(properties.dimensions) / 2) * 1.1; + var innerRadius = diagonal; + var outerRadius = diagonal * 1.15; - Overlays.editOverlay(selectionBox, - { - visible: true, - solid:false, - lineWidth: 3.0, - position: { x: properties.position.x, - y: properties.position.y, - z: properties.position.z }, + Overlays.editOverlay(selectionBox, + { + visible: true, + solid:false, + lineWidth: 2.0, + position: { x: properties.position.x, + y: properties.position.y, + z: properties.position.z }, - dimensions: properties.dimensions, - rotation: properties.rotation, + dimensions: properties.dimensions, + rotation: properties.rotation, - pulseMin: 0.1, - pulseMax: 1.0, - pulsePeriod: 4.0, - glowLevelPulse: 1.0, - alphaPulse: 0.5, - colorPulse: -0.5 + pulseMin: 0.1, + pulseMax: 1.0, + pulsePeriod: 4.0, + glowLevelPulse: 1.0, + alphaPulse: 0.5, + colorPulse: -0.5 - }); + }); + + Overlays.editOverlay(yawOverlayInner, + { + visible: true, + solid:false, + lineWidth: 5.0, + position: { x: properties.position.x, + y: properties.position.y - (properties.dimensions.y / 2), + z: properties.position.z}, + + size: innerRadius, + innerRadius: 0.9 + }); + + Overlays.editOverlay(yawOverlayOuter, + { + visible: true, + solid:false, + lineWidth: 5.0, + position: { x: properties.position.x, + y: properties.position.y - (properties.dimensions.y / 2), + z: properties.position.z}, + + size: outerRadius, + innerRadius: 0.9, + startAt: 90, + endAt: 405, + }); + + Overlays.editOverlay(yawOverlayCurrent, + { + visible: true, + solid:false, + lineWidth: 5.0, + position: { x: properties.position.x, + y: properties.position.y - (properties.dimensions.y / 2), + z: properties.position.z}, + + size: outerRadius, + startAt: 45, + endAt: 90, + innerRadius: 0.9 + }); + + Overlays.editOverlay(yawHandle, + { + visible: true, + position: { x: properties.position.x - (properties.dimensions.x / 2), + y: properties.position.y - (properties.dimensions.y / 2), + z: properties.position.z - (properties.dimensions.z / 2)}, + + //dimensions: properties.dimensions, + //rotation: properties.rotation + }); + + Overlays.editOverlay(pitchOverlay, + { + visible: false, + solid:false, + lineWidth: 5.0, + position: { x: properties.position.x + (properties.dimensions.x / 2), + y: properties.position.y, + z: properties.position.z }, + + //dimensions: properties.dimensions, + size: diagonal, + //rotation: properties.rotation + alpha: 0.5, + }); + + Overlays.editOverlay(pitchHandle, + { + visible: true, + position: { x: properties.position.x + (properties.dimensions.x / 2), + y: properties.position.y + (properties.dimensions.y / 2), + z: properties.position.z - (properties.dimensions.z / 2)}, + }); + + Overlays.editOverlay(rollOverlay, + { + visible: false, + solid:false, + lineWidth: 5.0, + position: { x: properties.position.x, + y: properties.position.y, + z: properties.position.z + (properties.dimensions.z / 2) }, + + //dimensions: properties.dimensions, + size: diagonal, + //rotation: properties.rotation + alpha: 0.5, + }); + + Overlays.editOverlay(rollHandle, + { + visible: true, + position: { x: properties.position.x - (properties.dimensions.x / 2), + y: properties.position.y + (properties.dimensions.y / 2), + z: properties.position.z + (properties.dimensions.z / 2)}, + }); + }; this.hideSelection = function () { - Overlays.editOverlay(selectionBox, { visible: false }); + Overlays.editOverlay(selectionBox, { visible: false }); + Overlays.editOverlay(yawOverlayInner, { visible: false }); + Overlays.editOverlay(yawOverlayOuter, { visible: false }); + Overlays.editOverlay(yawOverlayCurrent, { visible: false }); + Overlays.editOverlay(pitchOverlay, { visible: false }); + Overlays.editOverlay(rollOverlay, { visible: false }); + Overlays.editOverlay(yawHandle, { visible: false }); + Overlays.editOverlay(pitchHandle, { visible: false }); + Overlays.editOverlay(rollHandle, { visible: false }); }; }; diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp new file mode 100644 index 0000000000..ac3ffe4ac9 --- /dev/null +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -0,0 +1,152 @@ +// +// Circle3DOverlay.cpp +// interface/src/ui/overlays +// +// 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 +// + +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + +#include +#include + +#include "Circle3DOverlay.h" +#include "renderer/GlowEffect.h" + +Circle3DOverlay::Circle3DOverlay() : + _startAt(0.0f), + _endAt(360.0f), + _outerRadius(1.0f), + _innerRadius(0.0f) +{ +} + +Circle3DOverlay::~Circle3DOverlay() { +} + +void Circle3DOverlay::render() { + if (!_visible) { + return; // do nothing if we're not visible + } + + //const int slices = 15; + float alpha = getAlpha(); + xColor color = getColor(); + const float MAX_COLOR = 255; + glColor4f(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha); + + + glDisable(GL_LIGHTING); + + glm::vec3 position = getPosition(); + glm::vec3 center = getCenter(); + glm::vec3 dimensions = getDimensions(); + glm::quat rotation = getRotation(); + + float glowLevel = getGlowLevel(); + Glower* glower = NULL; + if (glowLevel > 0.0f) { + glower = new Glower(glowLevel); + } + + glPushMatrix(); + glTranslatef(position.x, position.y, position.z); + glm::vec3 axis = glm::axis(rotation); + glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); + glPushMatrix(); + glm::vec3 positionToCenter = center - position; + glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); + glScalef(dimensions.x, dimensions.y, dimensions.z); + + // Create the circle in the coordinates origin + float outerRadius = getOuterRadius(); + float innerRadius = getInnerRadius(); + + glLineWidth(_lineWidth); + glBegin(GL_QUAD_STRIP); + + const float PI_OVER_180 = 3.14159265358979f / 180.0f; + const float FULL_CIRCLE = 360.0f; + const float SLICES = 180.0f; // The amount of segment to create the circle + const float SLICE_ANGLE = FULL_CIRCLE / SLICES; + + float startAt = getStartAt(); + float endAt = getEndAt(); + float angle = startAt; + float angleInRadians = angle * PI_OVER_180; + glm::vec2 firstInnerPoint(cos(angleInRadians) * innerRadius, sin(angleInRadians) * innerRadius); + glm::vec2 firstOuterPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius); + + glVertex2f(firstInnerPoint.x, firstInnerPoint.y); + glVertex2f(firstOuterPoint.x, firstOuterPoint.y); + + while (angle < endAt) { + angleInRadians = angle * PI_OVER_180; + glm::vec2 thisInnerPoint(cos(angleInRadians) * innerRadius, sin(angleInRadians) * innerRadius); + glm::vec2 thisOuterPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius); + + glVertex2f(thisOuterPoint.x, thisOuterPoint.y); + glVertex2f(thisInnerPoint.x, thisInnerPoint.y); + + angle += SLICE_ANGLE; + } + + // get the last slice portion.... + angle = endAt; + angleInRadians = angle * PI_OVER_180; + glm::vec2 lastInnerPoint(cos(angleInRadians) * innerRadius, sin(angleInRadians) * innerRadius); + glm::vec2 lastOuterPoint(cos(angleInRadians) * outerRadius, sin(angleInRadians) * outerRadius); + + glVertex2f(lastOuterPoint.x, lastOuterPoint.y); + glVertex2f(lastInnerPoint.x, lastInnerPoint.y); + + glEnd(); + + glPopMatrix(); + glPopMatrix(); + + if (glower) { + delete glower; + } +} + +void Circle3DOverlay::setProperties(const QScriptValue &properties) { + Volume3DOverlay::setProperties(properties); + + QScriptValue startAt = properties.property("startAt"); + if (startAt.isValid()) { + setStartAt(startAt.toVariant().toFloat()); + } + + QScriptValue endAt = properties.property("endAt"); + if (endAt.isValid()) { + setEndAt(endAt.toVariant().toFloat()); + } + + QScriptValue outerRadius = properties.property("outerRadius"); + if (outerRadius.isValid()) { + setOuterRadius(outerRadius.toVariant().toFloat()); + } + + QScriptValue innerRadius = properties.property("innerRadius"); + if (innerRadius.isValid()) { + setInnerRadius(innerRadius.toVariant().toFloat()); + } + + qDebug() << "startAt:" << getStartAt(); + qDebug() << "endAt:" << getEndAt(); + qDebug() << "outerRadius:" << getOuterRadius(); + qDebug() << "innerRadius:" << getInnerRadius(); +} + + + + + + + + diff --git a/interface/src/ui/overlays/Circle3DOverlay.h b/interface/src/ui/overlays/Circle3DOverlay.h new file mode 100644 index 0000000000..5e30925a47 --- /dev/null +++ b/interface/src/ui/overlays/Circle3DOverlay.h @@ -0,0 +1,43 @@ +// +// Circle3DOverlay.h +// interface/src/ui/overlays +// +// 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 +// + +#ifndef hifi_Circle3DOverlay_h +#define hifi_Circle3DOverlay_h + +#include "Volume3DOverlay.h" + +class Circle3DOverlay : public Volume3DOverlay { + Q_OBJECT + +public: + Circle3DOverlay(); + ~Circle3DOverlay(); + virtual void render(); + virtual void setProperties(const QScriptValue& properties); + + float getStartAt() const { return _startAt; } + float getEndAt() const { return _endAt; } + float getOuterRadius() const { return _outerRadius; } + float getInnerRadius() const { return _innerRadius; } + + void setStartAt(float value) { _startAt = value; } + void setEndAt(float value) { _endAt = value; } + void setOuterRadius(float value) { _outerRadius = value; } + void setInnerRadius(float value) { _innerRadius = value; } + +protected: + float _startAt; + float _endAt; + float _outerRadius; + float _innerRadius; +}; + + +#endif // hifi_Circle3DOverlay_h diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 408475ea49..63af4ab282 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -11,6 +11,7 @@ #include #include "BillboardOverlay.h" +#include "Circle3DOverlay.h" #include "Cube3DOverlay.h" #include "ImageOverlay.h" #include "Line3DOverlay.h" @@ -147,6 +148,12 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope thisOverlay->setProperties(properties); created = true; is3D = true; + } else if (type == "circle3d") { + thisOverlay = new Circle3DOverlay(); + thisOverlay->init(_parent); + thisOverlay->setProperties(properties); + created = true; + is3D = true; } else if (type == "line3d") { thisOverlay = new Line3DOverlay(); thisOverlay->init(_parent); diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index 3302a74f24..226defcf77 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -40,7 +40,6 @@ void Sphere3DOverlay::render() { glm::vec3 position = getPosition(); glm::vec3 center = getCenter(); glm::vec3 dimensions = getDimensions(); - //glm::vec3 halfDimensions = dimensions / 2.0f; glm::quat rotation = getRotation(); float glowLevel = getGlowLevel();