From b6a626c92893753a628746aa3bce034f27e279cb Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Wed, 2 Jul 2014 17:18:12 -0700 Subject: [PATCH 01/33] Removed comment --- interface/src/ui/ApplicationOverlay.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 44a83e164a..c423a967f2 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -335,7 +335,6 @@ void ApplicationOverlay::displayOverlayTexture3DTV(Camera& whichCamera, float as glColor4f(1.0f, 1.0f, 1.0f, _alpha); //Render - // fov -= RADIANS_PER_DEGREE * 2.5f; //reduce by 5 degrees so it fits in the view const GLfloat distance = 1.0f; const GLfloat halfQuadHeight = distance * tan(fov); From bf2959675fd537ffcbfee9acfa19985baf9395a5 Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Thu, 3 Jul 2014 16:09:54 -0700 Subject: [PATCH 02/33] First pass at laser oculus UI pointer --- examples/editModels.js | 3 +- examples/flockingBirds.js | 6 +- interface/src/Application.cpp | 5 + interface/src/devices/OculusManager.cpp | 28 +++++ interface/src/devices/OculusManager.h | 5 + interface/src/ui/ApplicationOverlay.cpp | 158 +++++++++++++++++------- 6 files changed, 153 insertions(+), 52 deletions(-) diff --git a/examples/editModels.js b/examples/editModels.js index 64c203534c..9e1581e205 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -31,8 +31,7 @@ var toolWidth = 50; var LASER_WIDTH = 4; var LASER_COLOR = { red: 255, green: 0, blue: 0 }; -var LASER_LENGTH_FACTOR = 500 -; +var LASER_LENGTH_FACTOR = 500; var MIN_ANGULAR_SIZE = 2; var MAX_ANGULAR_SIZE = 45; diff --git a/examples/flockingBirds.js b/examples/flockingBirds.js index 3fa8681abe..0eb348b7b9 100644 --- a/examples/flockingBirds.js +++ b/examples/flockingBirds.js @@ -31,7 +31,7 @@ var count=0; // iterations var enableFlyTowardPoints = true; // some birds have a point they want to fly to var enabledClustedFlyTowardPoints = true; // the flyToward points will be generally near each other -var flyToFrames = 10; // number of frames the bird would like to attempt to fly to it's flyTo point +var flyToFrames = 100; // number of frames the bird would like to attempt to fly to it's flyTo point var PROBABILITY_OF_FLY_TOWARD_CHANGE = 0.01; // chance the bird will decide to change its flyTo point var PROBABILITY_EACH_BIRD_WILL_FLY_TOWARD = 0.2; // chance the bird will decide to flyTo, otherwise it follows var flyingToCount = 0; // count of birds currently flying to someplace @@ -56,11 +56,11 @@ var PROBABILITY_TO_LEAD = 0.1; // probability a bird will choose to lead var birds = new Array(); // array of bird state data -var flockStartPosition = { x: 100, y: 10, z: 100}; +var flockStartPosition = MyAvatar.position; var flockStartVelocity = { x: 0, y: 0, z: 0}; var flockStartThrust = { x: 0, y: 0, z: 0}; // slightly upward against gravity var INITIAL_XY_VELOCITY_SCALE = 2; -var birdRadius = 0.0625; +var birdRadius = 0.0925; var baseBirdColor = { red: 0, green: 255, blue: 255 }; var glidingColor = { red: 255, green: 0, blue: 0 }; var thrustUpwardColor = { red: 0, green: 255, blue: 0 }; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7cfadc1ff2..c0f952d604 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2778,6 +2778,11 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { bool mirrorMode = (whichCamera.getInterpolatedMode() == CAMERA_MODE_MIRROR); { PerformanceTimer perfTimer("paintGL/displaySide/renderAvatars"); + + if (1 || OculusManager::isConnected()) { + OculusManager::renderLaserPointer(); + } + _avatarManager.renderAvatars(mirrorMode ? Avatar::MIRROR_RENDER_MODE : Avatar::NORMAL_RENDER_MODE, selfAvatarOnly); } diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index e156e148ab..71073d2647 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -455,3 +455,31 @@ QSize OculusManager::getRenderTargetSize() { #endif } +void OculusManager::renderLaserPointer() { +#ifdef HAVE_LIBOVR + const float PALM_TIP_ROD_RADIUS = 0.009f; + + MyAvatar* myAvatar = Application::getInstance()->getAvatar(); + + //If the Oculus is enabled, we will draw a blue cursor ray + + // Draw the palm ball and disk + for (size_t i = 0; i < myAvatar->getHand()->getNumPalms(); ++i) { + PalmData& palm = myAvatar->getHand()->getPalms()[i]; + if (palm.isActive()) { + glColor4f(0, 1, 1, 1); + glm::vec3 tip = getLaserPointerTipPosition(&palm); + glm::vec3 root = palm.getPosition(); + Avatar::renderJointConnectingCone(root, tip, PALM_TIP_ROD_RADIUS, PALM_TIP_ROD_RADIUS); + } + } +#endif +} + +glm::vec3 OculusManager::getLaserPointerTipPosition(const PalmData* palm) { +#ifdef HAVE_LIBOVR + const float PALM_TIP_ROD_LENGTH_MULT = 2.0f; + return (palm->getTipPosition() - palm->getPosition()) * PALM_TIP_ROD_LENGTH_MULT; +#endif + return glm::vec3(0.0f); +} \ No newline at end of file diff --git a/interface/src/devices/OculusManager.h b/interface/src/devices/OculusManager.h index 7798875c2c..73ce6ef2d3 100644 --- a/interface/src/devices/OculusManager.h +++ b/interface/src/devices/OculusManager.h @@ -23,6 +23,7 @@ const float DEFAULT_OCULUS_UI_ANGULAR_SIZE = 72.0f; class Camera; +class PalmData; /// Handles interaction with the Oculus Rift. class OculusManager { @@ -41,6 +42,10 @@ public: /// param \roll[out] roll in radians static void getEulerAngles(float& yaw, float& pitch, float& roll); static QSize getRenderTargetSize(); + + /// Renders a laser pointer for UI picking + static void renderLaserPointer(); + static glm::vec3 getLaserPointerTipPosition(const PalmData* palm); private: #ifdef HAVE_LIBOVR diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index c423a967f2..f63a302cde 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -277,7 +277,7 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { glColor4f(1.0f, 1.0f, 1.0f, _alpha); renderTexturedHemisphere(); - + renderControllerPointersOculus(); glPopMatrix(); @@ -560,7 +560,26 @@ void ApplicationOverlay::renderControllerPointers() { } } +bool findSphereIntersection(const glm::vec3 &start, const glm::vec3 &end, const glm::vec3 &spos, const float r, glm::vec3 &result) { + double a = pow(end.x - start.x, 2) + pow(end.y - start.y, 2) + pow(end.z - start.z, 2); + double b = 2.0f * ((end.x - start.x) * (start.x - spos.x) + (end.y - start.x) * (start.y - spos.y) + (end.z - start.z) * (start.z - spos.z)); + double c = pow(start.x - spos.x, 2) + pow(start.y - spos.y, 2) + pow(start.z - spos.z, 2) - r*r; + + double delta = b * b - 4.0 * a * c; + printf("Intersection Delta %lf\n", delta); + + if (delta == 0) { + float d = -b / (2.0 * a); + result = start + d * (end - start); + } else { + return false; + } +} + void ApplicationOverlay::renderControllerPointersOculus() { + + const bool useLaser = true; + Application* application = Application::getInstance(); QGLWidget* glWidget = application->getGLWidget(); @@ -573,54 +592,99 @@ void ApplicationOverlay::renderControllerPointersOculus() { glDisable(GL_DEPTH_TEST); for (int i = 0; i < NUMBER_OF_MAGNIFIERS; i++) { + if (i > 0 && useLaser) { + MyAvatar* myAvatar = application->getAvatar(); + PalmData& palm = myAvatar->getHand()->getPalms()[i]; + if (palm.isActive()) { + + glm::vec3 tip = OculusManager::getLaserPointerTipPosition(&palm); + glm::vec3 result; - //Dont render the reticle if its inactive - if (!_reticleActive[i]) { - continue; + if (findSphereIntersection(myAvatar->getHead()->calculateAverageEyePosition(), + tip, glm::vec3(0, 0, 0), 1, result)){ + printf("Intersection Found: "); + printVector(result); + } + + + //float lX = sin((newULeft - 0.5f) * _textureFov); + //float rX = sin((newURight - 0.5f) * _textureFov); + //float bY = sin((newVBottom - 0.5f) * _textureFov); + //float tY = sin((newVTop - 0.5f) * _textureFov); + + //float dist; + ////Bottom Left + //dist = sqrt(lX * lX + bY * bY); + //float blZ = sqrt(1.0f - dist * dist); + ////Top Left + //dist = sqrt(lX * lX + tY * tY); + //float tlZ = sqrt(1.0f - dist * dist); + ////Bottom Right + //dist = sqrt(rX * rX + bY * bY); + //float brZ = sqrt(1.0f - dist * dist); + ////Top Right + //dist = sqrt(rX * rX + tY * tY); + //float trZ = sqrt(1.0f - dist * dist); + + //glBegin(GL_QUADS); + + //glColor4f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], _alpha); + + //glTexCoord2f(0.0f, 0.0f); glVertex3f(lX, tY, -tlZ); + //glTexCoord2f(1.0f, 0.0f); glVertex3f(rX, tY, -trZ); + //glTexCoord2f(1.0f, 1.0f); glVertex3f(rX, bY, -brZ); + //glTexCoord2f(0.0f, 1.0f); glVertex3f(lX, bY, -blZ); + + //glEnd(); + } + } else { + //Dont render the reticle if its inactive + if (!_reticleActive[i]) { + continue; + } + + float mouseX = (float)_mouseX[i]; + float mouseY = (float)_mouseY[i]; + mouseX -= reticleSize / 2; + mouseY += reticleSize / 2; + + //Get new UV coordinates from our magnification window + float newULeft = mouseX / widgetWidth; + float newURight = (mouseX + reticleSize) / widgetWidth; + float newVBottom = 1.0 - mouseY / widgetHeight; + float newVTop = 1.0 - (mouseY - reticleSize) / widgetHeight; + + // Project our position onto the hemisphere using the UV coordinates + float lX = sin((newULeft - 0.5f) * _textureFov); + float rX = sin((newURight - 0.5f) * _textureFov); + float bY = sin((newVBottom - 0.5f) * _textureFov); + float tY = sin((newVTop - 0.5f) * _textureFov); + + float dist; + //Bottom Left + dist = sqrt(lX * lX + bY * bY); + float blZ = sqrt(1.0f - dist * dist); + //Top Left + dist = sqrt(lX * lX + tY * tY); + float tlZ = sqrt(1.0f - dist * dist); + //Bottom Right + dist = sqrt(rX * rX + bY * bY); + float brZ = sqrt(1.0f - dist * dist); + //Top Right + dist = sqrt(rX * rX + tY * tY); + float trZ = sqrt(1.0f - dist * dist); + + glBegin(GL_QUADS); + + glColor4f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], _alpha); + + glTexCoord2f(0.0f, 0.0f); glVertex3f(lX, tY, -tlZ); + glTexCoord2f(1.0f, 0.0f); glVertex3f(rX, tY, -trZ); + glTexCoord2f(1.0f, 1.0f); glVertex3f(rX, bY, -brZ); + glTexCoord2f(0.0f, 1.0f); glVertex3f(lX, bY, -blZ); + + glEnd(); } - - float mouseX = (float)_mouseX[i]; - float mouseY = (float)_mouseY[i]; - mouseX -= reticleSize / 2; - mouseY += reticleSize / 2; - - //Get new UV coordinates from our magnification window - float newULeft = mouseX / widgetWidth; - float newURight = (mouseX + reticleSize) / widgetWidth; - float newVBottom = 1.0 - mouseY / widgetHeight; - float newVTop = 1.0 - (mouseY - reticleSize) / widgetHeight; - - // Project our position onto the hemisphere using the UV coordinates - float lX = sin((newULeft - 0.5f) * _textureFov); - float rX = sin((newURight - 0.5f) * _textureFov); - float bY = sin((newVBottom - 0.5f) * _textureFov); - float tY = sin((newVTop - 0.5f) * _textureFov); - - float dist; - //Bottom Left - dist = sqrt(lX * lX + bY * bY); - float blZ = sqrt(1.0f - dist * dist); - //Top Left - dist = sqrt(lX * lX + tY * tY); - float tlZ = sqrt(1.0f - dist * dist); - //Bottom Right - dist = sqrt(rX * rX + bY * bY); - float brZ = sqrt(1.0f - dist * dist); - //Top Right - dist = sqrt(rX * rX + tY * tY); - float trZ = sqrt(1.0f - dist * dist); - - glBegin(GL_QUADS); - - glColor4f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], _alpha); - - glTexCoord2f(0.0f, 0.0f); glVertex3f(lX, tY, -tlZ); - glTexCoord2f(1.0f, 0.0f); glVertex3f(rX, tY, -trZ); - glTexCoord2f(1.0f, 1.0f); glVertex3f(rX, bY, -brZ); - glTexCoord2f(0.0f, 1.0f); glVertex3f(lX, bY, -blZ); - - glEnd(); - } glEnable(GL_DEPTH_TEST); } From cc63f706a745dbc1c2c57aa9d405752526ec6b6f Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Tue, 8 Jul 2014 11:43:24 -0700 Subject: [PATCH 03/33] Functional sixense "laser" oculus selection mode. --- interface/src/devices/OculusManager.cpp | 14 +- interface/src/devices/SixenseManager.cpp | 28 ++- interface/src/ui/ApplicationOverlay.cpp | 238 ++++++++++++++++++----- interface/src/ui/ApplicationOverlay.h | 1 + 4 files changed, 215 insertions(+), 66 deletions(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index befe48e42d..976bd5ba8e 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -443,7 +443,15 @@ void OculusManager::getEulerAngles(float& yaw, float& pitch, float& roll) { ovrPosef pose = ss.Predicted.Pose; Quatf orientation = Quatf(pose.Orientation); orientation.GetEulerAngles(&yaw, &pitch, &roll); + } else { + yaw = 0.0f; + pitch = 0.0f; + roll = 0.0f; } +#else + yaw = 0.0f; + pitch = 0.0f; + roll = 0.0f; #endif } @@ -461,7 +469,7 @@ QSize OculusManager::getRenderTargetSize() { void OculusManager::renderLaserPointer() { #ifdef HAVE_LIBOVR - const float PALM_TIP_ROD_RADIUS = 0.009f; + const float PALM_TIP_ROD_RADIUS = 0.002f; MyAvatar* myAvatar = Application::getInstance()->getAvatar(); @@ -482,8 +490,8 @@ void OculusManager::renderLaserPointer() { glm::vec3 OculusManager::getLaserPointerTipPosition(const PalmData* palm) { #ifdef HAVE_LIBOVR - const float PALM_TIP_ROD_LENGTH_MULT = 2.0f; - return (palm->getTipPosition() - palm->getPosition()) * PALM_TIP_ROD_LENGTH_MULT; + const float PALM_TIP_ROD_LENGTH_MULT = 11.0f; + return palm->getPosition() + (palm->getTipPosition() - palm->getPosition()) * PALM_TIP_ROD_LENGTH_MULT; #endif return glm::vec3(0.0f); } diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index c50fc887d6..ecf7fea5cb 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -13,6 +13,7 @@ #include "Application.h" #include "SixenseManager.h" +#include "devices/OculusManager.h" #include "UserActivityLogger.h" #ifdef HAVE_SIXENSE @@ -358,9 +359,7 @@ void SixenseManager::emulateMouse(PalmData* palm, int index) { MyAvatar* avatar = application->getAvatar(); QGLWidget* widget = application->getGLWidget(); QPoint pos; - // Get directon relative to avatar orientation - glm::vec3 direction = glm::inverse(avatar->getOrientation()) * palm->getFingerDirection(); - + Qt::MouseButton bumperButton; Qt::MouseButton triggerButton; @@ -372,15 +371,24 @@ void SixenseManager::emulateMouse(PalmData* palm, int index) { triggerButton = Qt::LeftButton; } - // Get the angles, scaled between (-0.5,0.5) - float xAngle = (atan2(direction.z, direction.x) + M_PI_2); - float yAngle = 0.5f - ((atan2(direction.z, direction.y) + M_PI_2)); + if (OculusManager::isConnected()) { + pos = application->getApplicationOverlay().getOculusPalmClickLocation(palm); + printf("CLICK: %d %d\n", pos.x(), pos.y()); + } else { + // Get directon relative to avatar orientation + glm::vec3 direction = glm::inverse(avatar->getOrientation()) * palm->getFingerDirection(); - // Get the pixel range over which the xAngle and yAngle are scaled - float cursorRange = widget->width() * getCursorPixelRangeMult(); + // Get the angles, scaled between (-0.5,0.5) + float xAngle = (atan2(direction.z, direction.x) + M_PI_2); + float yAngle = 0.5f - ((atan2(direction.z, direction.y) + M_PI_2)); - pos.setX(widget->width() / 2.0f + cursorRange * xAngle); - pos.setY(widget->height() / 2.0f + cursorRange * yAngle); + // Get the pixel range over which the xAngle and yAngle are scaled + float cursorRange = widget->width() * getCursorPixelRangeMult(); + + pos.setX(widget->width() / 2.0f + cursorRange * xAngle); + pos.setY(widget->height() / 2.0f + cursorRange * yAngle); + + } //If we are off screen then we should stop processing, and if a trigger or bumper is pressed, //we should unpress them. diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 42c4f36470..64aafbb49c 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -205,6 +205,103 @@ void ApplicationOverlay::getClickLocation(int &x, int &y) const { } } + +//Checks if the given ray intersects the sphere at the origin. result will store a multiplier that should +//be multiplied by dir and added to origin to get the location of the collision +bool raySphereIntersect(const glm::vec3 &dir, const glm::vec3 &origin, float r, float* result) +{ + //Source: http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection + + //Compute A, B and C coefficients + float a = glm::dot(dir, dir); + float b = 2 * glm::dot(dir, origin); + float c = glm::dot(origin, origin) - (r * r); + + //Find discriminant + float disc = b * b - 4 * a * c; + + // if discriminant is negative there are no real roots, so return + // false as ray misses sphere + if (disc < 0) { + return false; + } + + // compute q as described above + float distSqrt = sqrtf(disc); + float q; + if (b < 0) { + q = (-b - distSqrt) / 2.0; + } else { + q = (-b + distSqrt) / 2.0; + } + + // compute t0 and t1 + float t0 = q / a; + float t1 = c / q; + + // make sure t0 is smaller than t1 + if (t0 > t1) { + // if t0 is bigger than t1 swap them around + float temp = t0; + t0 = t1; + t1 = temp; + } + + // if t1 is less than zero, the object is in the ray's negative direction + // and consequently the ray misses the sphere + if (t1 < 0) { + return false; + } + + // if t0 is less than zero, the intersection point is at t1 + if (t0 < 0) { + *result = t1; + return true; + } else { // else the intersection point is at t0 + *result = t0; + return true; + } +} + + +QPoint ApplicationOverlay::getOculusPalmClickLocation(PalmData *palm) const { + + Application* application = Application::getInstance(); + QGLWidget* glWidget = application->getGLWidget(); + MyAvatar* myAvatar = application->getAvatar(); + + const int widgetWidth = glWidget->width(); + const int widgetHeight = glWidget->height(); + + + glm::vec3 tip = OculusManager::getLaserPointerTipPosition(palm); + glm::vec3 eyePos = myAvatar->getHead()->calculateAverageEyePosition(); + glm::quat orientation = glm::inverse(myAvatar->getOrientation()); + glm::vec3 dir = orientation * glm::normalize(eyePos - tip); //direction of ray goes towards camera + glm::vec3 tipPos = orientation * (tip - eyePos); + + QPoint rv; + + float t; + + //Find intersection of crosshair ray + if (raySphereIntersect(dir, tipPos, 1, &t)){ + glm::vec3 collisionPos = tipPos + dir * t; + + float u = asin(collisionPos.x) / (_textureFov)+0.5f; + float v = 1.0 - (asin(collisionPos.y) / (_textureFov)+0.5f); + + rv.setX(u * glWidget->width()); + rv.setY(v * glWidget->height()); + + } else { + //if they did not click on the overlay, just set the coords to INT_MAX + rv.setX(INT_MAX); + rv.setY(INT_MAX); + } + return rv; +} + // Draws the FBO texture for Oculus rift. void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { @@ -221,11 +318,14 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { glEnable(GL_BLEND); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); - glBindTexture(GL_TEXTURE_2D, getFramebufferObject()->texture()); glEnable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glEnable(GL_TEXTURE_2D); + renderControllerPointersOculus(); + + glBindTexture(GL_TEXTURE_2D, getFramebufferObject()->texture()); + glMatrixMode(GL_MODELVIEW); glPushMatrix(); @@ -277,8 +377,6 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { renderTexturedHemisphere(); - renderControllerPointersOculus(); - glPopMatrix(); glDepthMask(GL_TRUE); @@ -559,22 +657,6 @@ void ApplicationOverlay::renderControllerPointers() { } } -bool findSphereIntersection(const glm::vec3 &start, const glm::vec3 &end, const glm::vec3 &spos, const float r, glm::vec3 &result) { - double a = pow(end.x - start.x, 2) + pow(end.y - start.y, 2) + pow(end.z - start.z, 2); - double b = 2.0f * ((end.x - start.x) * (start.x - spos.x) + (end.y - start.x) * (start.y - spos.y) + (end.z - start.z) * (start.z - spos.z)); - double c = pow(start.x - spos.x, 2) + pow(start.y - spos.y, 2) + pow(start.z - spos.z, 2) - r*r; - - double delta = b * b - 4.0 * a * c; - printf("Intersection Delta %lf\n", delta); - - if (delta == 0) { - float d = -b / (2.0 * a); - result = start + d * (end - start); - } else { - return false; - } -} - void ApplicationOverlay::renderControllerPointersOculus() { const bool useLaser = true; @@ -589,54 +671,104 @@ void ApplicationOverlay::renderControllerPointersOculus() { glBindTexture(GL_TEXTURE_2D, _crosshairTexture); glDisable(GL_DEPTH_TEST); - - for (int i = 0; i < NUMBER_OF_MAGNIFIERS; i++) { - if (i > 0 && useLaser) { - MyAvatar* myAvatar = application->getAvatar(); + glMatrixMode(GL_MODELVIEW); + MyAvatar* myAvatar = application->getAvatar(); + + //Determine how much we need to iterate + const int ITERATIONS = max(myAvatar->getHand()->getNumPalms(), 3); + + for (int i = 0; i < ITERATIONS; i++) { + if (useLaser && i < myAvatar->getHand()->getNumPalms()) { + PalmData& palm = myAvatar->getHand()->getPalms()[i]; if (palm.isActive()) { - glm::vec3 tip = OculusManager::getLaserPointerTipPosition(&palm); glm::vec3 result; + glm::vec3 eyePos = myAvatar->getHead()->calculateAverageEyePosition(); + glm::quat orientation = glm::inverse(myAvatar->getOrientation()); + glm::vec3 dir = orientation * glm::normalize(eyePos - tip); //direction of ray goes towards camera + glm::vec3 tipPos = (tip - eyePos); + + float t; + float length = glm::length(eyePos - tip); + float size = 0.045f * length; - if (findSphereIntersection(myAvatar->getHead()->calculateAverageEyePosition(), - tip, glm::vec3(0, 0, 0), 1, result)){ - printf("Intersection Found: "); - printVector(result); + glm::vec3 up = glm::vec3(0.0, 1.0, 0.0) * size; + glm::vec3 right = glm::vec3(1.0, 0.0, 0.0) * size; + + glm::vec3 cursorVerts[4]; + cursorVerts[0] = -right + up; + cursorVerts[1] = right + up; + cursorVerts[2] = right - up; + cursorVerts[3] = -right - up; + + glPushMatrix(); + // glLoadIdentity(); + + // objToCamProj is the vector in world coordinates from the + // local origin to the camera projected in the XZ plane + glm::vec3 cursorToCameraXZ(-tipPos.x, 0, -tipPos.z); + cursorToCameraXZ = glm::normalize(cursorToCameraXZ); + + // This is the original lookAt vector for the object + // in world coordinates + glm::vec3 direction(0, 0, 1); + glTranslatef(tip.x, tip.y, tip.z); + + // easy fix to determine wether the angle is negative or positive + // for positive angles upAux will be a vector pointing in the + // positive y direction, otherwise upAux will point downwards + // effectively reversing the rotation. + glm::vec3 upAux = glm::cross(direction, cursorToCameraXZ); + + // compute the angle + float angleCosine = glm::dot(direction, cursorToCameraXZ); + + // perform the rotation. The if statement is used for stability reasons + // if the lookAt and objToCamProj vectors are too close together then + // |angleCosine| could be bigger than 1 due to lack of precision + if ((angleCosine < 0.999999) && (angleCosine > -0.999999)) { + glRotatef(acos(angleCosine) * DEGREES_PER_RADIAN, upAux[0], upAux[1], upAux[2]); } + // so far it is just like the cylindrical billboard. The code for the + // second rotation comes now + // The second part tilts the object so that it faces the camera - //float lX = sin((newULeft - 0.5f) * _textureFov); - //float rX = sin((newURight - 0.5f) * _textureFov); - //float bY = sin((newVBottom - 0.5f) * _textureFov); - //float tY = sin((newVTop - 0.5f) * _textureFov); + // objToCam is the vector in world coordinates from + // the local origin to the camera + glm::vec3 cursorToCamera = glm::normalize(-tipPos); - //float dist; - ////Bottom Left - //dist = sqrt(lX * lX + bY * bY); - //float blZ = sqrt(1.0f - dist * dist); - ////Top Left - //dist = sqrt(lX * lX + tY * tY); - //float tlZ = sqrt(1.0f - dist * dist); - ////Bottom Right - //dist = sqrt(rX * rX + bY * bY); - //float brZ = sqrt(1.0f - dist * dist); - ////Top Right - //dist = sqrt(rX * rX + tY * tY); - //float trZ = sqrt(1.0f - dist * dist); + // Compute the angle between objToCamProj and objToCam, + //i.e. compute the required angle for the lookup vector - //glBegin(GL_QUADS); + angleCosine = glm::dot(cursorToCameraXZ, cursorToCamera); - //glColor4f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], _alpha); + // Tilt the object. The test is done to prevent instability + // when objToCam and objToCamProj have a very small + // angle between them - //glTexCoord2f(0.0f, 0.0f); glVertex3f(lX, tY, -tlZ); - //glTexCoord2f(1.0f, 0.0f); glVertex3f(rX, tY, -trZ); - //glTexCoord2f(1.0f, 1.0f); glVertex3f(rX, bY, -brZ); - //glTexCoord2f(0.0f, 1.0f); glVertex3f(lX, bY, -blZ); + if ((angleCosine < 0.99990) && (angleCosine > -0.9999)) + if (cursorToCamera.y < 0) { + glRotatef(acos(angleCosine) * DEGREES_PER_RADIAN, 1, 0, 0); + } else { + glRotatef(acos(angleCosine) * DEGREES_PER_RADIAN, -1, 0, 0); + } - //glEnd(); + glBegin(GL_QUADS); + + glColor4f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], _alpha); + + glTexCoord2f(0.0f, 0.0f); glVertex3f(cursorVerts[0].x, cursorVerts[0].y, cursorVerts[0].z); + glTexCoord2f(1.0f, 0.0f); glVertex3f(cursorVerts[1].x, cursorVerts[1].y, cursorVerts[1].z); + glTexCoord2f(1.0f, 1.0f); glVertex3f(cursorVerts[2].x, cursorVerts[2].y, cursorVerts[2].z); + glTexCoord2f(0.0f, 1.0f); glVertex3f(cursorVerts[3].x, cursorVerts[3].y, cursorVerts[3].z); + + glEnd(); + + glPopMatrix(); } - } else { + } else if (i < NUMBER_OF_MAGNIFIERS) { //Dont render the reticle if its inactive if (!_reticleActive[i]) { continue; diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index 7c1f87d575..ebac5f3cfc 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -32,6 +32,7 @@ public: void displayOverlayTexture3DTV(Camera& whichCamera, float aspectRatio, float fov); void computeOculusPickRay(float x, float y, glm::vec3& direction) const; void getClickLocation(int &x, int &y) const; + QPoint getOculusPalmClickLocation(PalmData *palm) const; // Getters QOpenGLFramebufferObject* getFramebufferObject(); From 0ce7b178b081d76816623b901cb3fa0d00e1efdc Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Tue, 8 Jul 2014 12:47:41 -0700 Subject: [PATCH 04/33] Made Oculus UI framebuffer resize when window resizes --- interface/src/ui/ApplicationOverlay.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 64aafbb49c..dfa6b63fa5 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -95,6 +95,8 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) { glMatrixMode(GL_PROJECTION); glPushMatrix(); + printf("%d %d\n", glWidget->width(), glWidget->height()); + glLoadIdentity(); gluOrtho2D(0, glWidget->width(), glWidget->height(), 0); glDisable(GL_DEPTH_TEST); @@ -205,7 +207,6 @@ void ApplicationOverlay::getClickLocation(int &x, int &y) const { } } - //Checks if the given ray intersects the sphere at the origin. result will store a multiplier that should //be multiplied by dir and added to origin to get the location of the collision bool raySphereIntersect(const glm::vec3 &dir, const glm::vec3 &origin, float r, float* result) @@ -1194,8 +1195,12 @@ void ApplicationOverlay::renderTexturedHemisphere() { } QOpenGLFramebufferObject* ApplicationOverlay::getFramebufferObject() { - if (!_framebufferObject) { - _framebufferObject = new QOpenGLFramebufferObject(Application::getInstance()->getGLWidget()->size()); + QSize size = Application::getInstance()->getGLWidget()->size(); + if (!_framebufferObject || _framebufferObject->size() != size) { + if (_framebufferObject){ + delete _framebufferObject; + } + _framebufferObject = new QOpenGLFramebufferObject(size); glBindTexture(GL_TEXTURE_2D, _framebufferObject->texture()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); From 87ad87e10fb1666bca84d4b1e6ddb1dbef8c0819 Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Tue, 8 Jul 2014 16:25:21 -0700 Subject: [PATCH 05/33] Actual stereoscopic 3D UI. Looks better now. --- interface/src/ui/ApplicationOverlay.cpp | 85 ++++++++++++++----------- 1 file changed, 49 insertions(+), 36 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index dfa6b63fa5..b768c522ad 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -313,8 +313,7 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { Application* application = Application::getInstance(); MyAvatar* myAvatar = application->getAvatar(); - const glm::vec3& viewMatrixTranslation = application->getViewMatrixTranslation(); - + glActiveTexture(GL_TEXTURE0); glEnable(GL_BLEND); @@ -323,34 +322,25 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { glDisable(GL_LIGHTING); glEnable(GL_TEXTURE_2D); - renderControllerPointersOculus(); - glBindTexture(GL_TEXTURE_2D, getFramebufferObject()->texture()); glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - // Transform to world space - glm::quat rotation = whichCamera.getRotation(); - glm::vec3 axis2 = glm::axis(rotation); - glRotatef(-glm::degrees(glm::angle(rotation)), axis2.x, axis2.y, axis2.z); - glTranslatef(viewMatrixTranslation.x, viewMatrixTranslation.y, viewMatrixTranslation.z); - - // Translate to the front of the camera - glm::vec3 pos = whichCamera.getPosition(); - glm::quat rot = myAvatar->getOrientation(); - glm::vec3 axis = glm::axis(rot); - - glTranslatef(pos.x, pos.y, pos.z); - glRotatef(glm::degrees(glm::angle(rot)), axis.x, axis.y, axis.z); - glDepthMask(GL_TRUE); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.01f); //Update and draw the magnifiers + + glPushMatrix(); + const glm::quat& orientation = myAvatar->getOrientation(); + const glm::vec3& position = myAvatar->getHead()->calculateAverageEyePosition(); + + glm::mat4 rotation = glm::toMat4(orientation); + + glTranslatef(position.x, position.y, position.z); + glMultMatrixf(&rotation[0][0]); for (int i = 0; i < NUMBER_OF_MAGNIFIERS; i++) { if (_magActive[i]) { @@ -370,6 +360,7 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { renderMagnifier(_magX[i], _magY[i], _magSizeMult[i], i != MOUSE); } } + glPopMatrix(); glDepthMask(GL_FALSE); glDisable(GL_ALPHA_TEST); @@ -378,7 +369,7 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { renderTexturedHemisphere(); - glPopMatrix(); + renderControllerPointersOculus(); glDepthMask(GL_TRUE); glBindTexture(GL_TEXTURE_2D, 0); @@ -504,7 +495,6 @@ void ApplicationOverlay::renderPointers() { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, _crosshairTexture); - if (OculusManager::isConnected() && application->getLastMouseMoveType() == QEvent::MouseMove) { //If we are in oculus, render reticle later _reticleActive[MOUSE] = true; @@ -513,7 +503,6 @@ void ApplicationOverlay::renderPointers() { _mouseY[MOUSE] = application->getMouseY(); _magX[MOUSE] = _mouseX[MOUSE]; _magY[MOUSE] = _mouseY[MOUSE]; - _reticleActive[LEFT_CONTROLLER] = false; _reticleActive[RIGHT_CONTROLLER] = false; @@ -664,6 +653,7 @@ void ApplicationOverlay::renderControllerPointersOculus() { Application* application = Application::getInstance(); QGLWidget* glWidget = application->getGLWidget(); + glm::vec3 cursorVerts[4]; const int widgetWidth = glWidget->width(); const int widgetHeight = glWidget->height(); @@ -678,14 +668,14 @@ void ApplicationOverlay::renderControllerPointersOculus() { //Determine how much we need to iterate const int ITERATIONS = max(myAvatar->getHand()->getNumPalms(), 3); + glm::vec3 eyePos = myAvatar->getHead()->calculateAverageEyePosition(); + for (int i = 0; i < ITERATIONS; i++) { if (useLaser && i < myAvatar->getHand()->getNumPalms()) { PalmData& palm = myAvatar->getHand()->getPalms()[i]; if (palm.isActive()) { glm::vec3 tip = OculusManager::getLaserPointerTipPosition(&palm); - glm::vec3 result; - glm::vec3 eyePos = myAvatar->getHead()->calculateAverageEyePosition(); glm::quat orientation = glm::inverse(myAvatar->getOrientation()); glm::vec3 dir = orientation * glm::normalize(eyePos - tip); //direction of ray goes towards camera glm::vec3 tipPos = (tip - eyePos); @@ -697,7 +687,6 @@ void ApplicationOverlay::renderControllerPointersOculus() { glm::vec3 up = glm::vec3(0.0, 1.0, 0.0) * size; glm::vec3 right = glm::vec3(1.0, 0.0, 0.0) * size; - glm::vec3 cursorVerts[4]; cursorVerts[0] = -right + up; cursorVerts[1] = right + up; cursorVerts[2] = right - up; @@ -749,12 +738,13 @@ void ApplicationOverlay::renderControllerPointersOculus() { // when objToCam and objToCamProj have a very small // angle between them - if ((angleCosine < 0.99990) && (angleCosine > -0.9999)) - if (cursorToCamera.y < 0) { - glRotatef(acos(angleCosine) * DEGREES_PER_RADIAN, 1, 0, 0); - } else { - glRotatef(acos(angleCosine) * DEGREES_PER_RADIAN, -1, 0, 0); - } + // if ((angleCosine < 0.9999) && (angleCosine > -0.99999)) { + if (cursorToCamera.y < 0) { + glRotatef(acos(angleCosine) * DEGREES_PER_RADIAN, 1, 0, 0); + } else { + glRotatef(acos(angleCosine) * DEGREES_PER_RADIAN, -1, 0, 0); + } + // } glBegin(GL_QUADS); @@ -780,6 +770,8 @@ void ApplicationOverlay::renderControllerPointersOculus() { mouseX -= reticleSize / 2; mouseY += reticleSize / 2; + printf("MOUSEPOS: %f %f\n", mouseX, mouseY); + //Get new UV coordinates from our magnification window float newULeft = mouseX / widgetWidth; float newURight = (mouseX + reticleSize) / widgetWidth; @@ -810,10 +802,17 @@ void ApplicationOverlay::renderControllerPointersOculus() { glColor4f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], _alpha); - glTexCoord2f(0.0f, 0.0f); glVertex3f(lX, tY, -tlZ); - glTexCoord2f(1.0f, 0.0f); glVertex3f(rX, tY, -trZ); - glTexCoord2f(1.0f, 1.0f); glVertex3f(rX, bY, -brZ); - glTexCoord2f(0.0f, 1.0f); glVertex3f(lX, bY, -blZ); + + const glm::quat& orientation = myAvatar->getOrientation(); + cursorVerts[0] = orientation * glm::vec3(lX, tY, -tlZ) + eyePos; + cursorVerts[1] = orientation * glm::vec3(rX, tY, -trZ) + eyePos; + cursorVerts[2] = orientation * glm::vec3(rX, bY, -brZ) + eyePos; + cursorVerts[3] = orientation * glm::vec3(lX, bY, -blZ) + eyePos; + + glTexCoord2f(0.0f, 0.0f); glVertex3f(cursorVerts[0].x, cursorVerts[0].y, cursorVerts[0].z); + glTexCoord2f(1.0f, 0.0f); glVertex3f(cursorVerts[1].x, cursorVerts[1].y, cursorVerts[1].z); + glTexCoord2f(1.0f, 1.0f); glVertex3f(cursorVerts[2].x, cursorVerts[2].y, cursorVerts[2].z); + glTexCoord2f(0.0f, 1.0f); glVertex3f(cursorVerts[3].x, cursorVerts[3].y, cursorVerts[3].z); glEnd(); } @@ -1183,9 +1182,23 @@ void ApplicationOverlay::renderTexturedHemisphere() { glVertexPointer(3, GL_FLOAT, sizeof(TextureVertex), (void*)0); glTexCoordPointer(2, GL_FLOAT, sizeof(TextureVertex), (void*)12); + + glPushMatrix(); + Application* application = Application::getInstance(); + MyAvatar* myAvatar = application->getAvatar(); + const glm::quat& orientation = myAvatar->getOrientation(); + const glm::vec3& position = myAvatar->getHead()->calculateAverageEyePosition(); + + glm::mat4 rotation = glm::toMat4(orientation); + + glTranslatef(position.x, position.y, position.z); + glMultMatrixf(&rotation[0][0]); + glDrawRangeElements(GL_TRIANGLES, 0, vertices - 1, indices, GL_UNSIGNED_SHORT, 0); + glPopMatrix(); + glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); From f8fdd2d11f3411a4f7a521cfcb88b4bfd154fde7 Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Tue, 8 Jul 2014 17:15:11 -0700 Subject: [PATCH 06/33] Minor adjustments --- interface/src/devices/OculusManager.cpp | 2 +- interface/src/ui/ApplicationOverlay.cpp | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 976bd5ba8e..804ebd1873 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -490,7 +490,7 @@ void OculusManager::renderLaserPointer() { glm::vec3 OculusManager::getLaserPointerTipPosition(const PalmData* palm) { #ifdef HAVE_LIBOVR - const float PALM_TIP_ROD_LENGTH_MULT = 11.0f; + const float PALM_TIP_ROD_LENGTH_MULT = 4.0f; return palm->getPosition() + (palm->getTipPosition() - palm->getPosition()) * PALM_TIP_ROD_LENGTH_MULT; #endif return glm::vec3(0.0f); diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index b768c522ad..bc30ab6b54 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -274,7 +274,6 @@ QPoint ApplicationOverlay::getOculusPalmClickLocation(PalmData *palm) const { const int widgetWidth = glWidget->width(); const int widgetHeight = glWidget->height(); - glm::vec3 tip = OculusManager::getLaserPointerTipPosition(palm); glm::vec3 eyePos = myAvatar->getHead()->calculateAverageEyePosition(); glm::quat orientation = glm::inverse(myAvatar->getOrientation()); @@ -285,9 +284,11 @@ QPoint ApplicationOverlay::getOculusPalmClickLocation(PalmData *palm) const { float t; - //Find intersection of crosshair ray - if (raySphereIntersect(dir, tipPos, 1, &t)){ - glm::vec3 collisionPos = tipPos + dir * t; + //We back the ray up by dir to ensure that it will not start inside the UI. + glm::vec3 adjustedPos = tipPos - dir; + //Find intersection of crosshair ray. + if (raySphereIntersect(dir, adjustedPos, 1, &t)){ + glm::vec3 collisionPos = adjustedPos + dir * t; float u = asin(collisionPos.x) / (_textureFov)+0.5f; float v = 1.0 - (asin(collisionPos.y) / (_textureFov)+0.5f); @@ -682,7 +683,7 @@ void ApplicationOverlay::renderControllerPointersOculus() { float t; float length = glm::length(eyePos - tip); - float size = 0.045f * length; + float size = 0.03f * length; glm::vec3 up = glm::vec3(0.0, 1.0, 0.0) * size; glm::vec3 right = glm::vec3(1.0, 0.0, 0.0) * size; From d044af140001d6eec01e56b352d301fb2a8770ef Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Wed, 9 Jul 2014 11:12:02 -0700 Subject: [PATCH 07/33] Made it so you can only select in a 180 degree radius with oculus --- interface/src/devices/SixenseManager.cpp | 3 +-- interface/src/ui/ApplicationOverlay.cpp | 14 ++++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index ecf7fea5cb..33d485ea84 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -373,7 +373,6 @@ void SixenseManager::emulateMouse(PalmData* palm, int index) { if (OculusManager::isConnected()) { pos = application->getApplicationOverlay().getOculusPalmClickLocation(palm); - printf("CLICK: %d %d\n", pos.x(), pos.y()); } else { // Get directon relative to avatar orientation glm::vec3 direction = glm::inverse(avatar->getOrientation()) * palm->getFingerDirection(); @@ -392,7 +391,7 @@ void SixenseManager::emulateMouse(PalmData* palm, int index) { //If we are off screen then we should stop processing, and if a trigger or bumper is pressed, //we should unpress them. - if (pos.x() < 0 || pos.x() > widget->width() || pos.y() < 0 || pos.y() > widget->height()) { + if (pos.x() == INT_MAX) { if (_bumperPressed[index]) { QMouseEvent mouseEvent(QEvent::MouseButtonRelease, pos, bumperButton, bumperButton, 0); diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index bc30ab6b54..87ee46ca2b 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -290,12 +290,18 @@ QPoint ApplicationOverlay::getOculusPalmClickLocation(PalmData *palm) const { if (raySphereIntersect(dir, adjustedPos, 1, &t)){ glm::vec3 collisionPos = adjustedPos + dir * t; - float u = asin(collisionPos.x) / (_textureFov)+0.5f; - float v = 1.0 - (asin(collisionPos.y) / (_textureFov)+0.5f); + //If we hit the back hemisphere, mark it as not a collision + if (collisionPos.z > 0) { + rv.setX(INT_MAX); + rv.setY(INT_MAX); + } else { - rv.setX(u * glWidget->width()); - rv.setY(v * glWidget->height()); + float u = asin(collisionPos.x) / (_textureFov)+0.5f; + float v = 1.0 - (asin(collisionPos.y) / (_textureFov)+0.5f); + rv.setX(u * glWidget->width()); + rv.setY(v * glWidget->height()); + } } else { //if they did not click on the overlay, just set the coords to INT_MAX rv.setX(INT_MAX); From e64f34a257d44056e46e85ac368747e3fde4871f Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Wed, 9 Jul 2014 12:03:32 -0700 Subject: [PATCH 08/33] Separated mouse and controller pointers --- interface/src/ui/ApplicationOverlay.cpp | 125 ++++++++++++------------ interface/src/ui/ApplicationOverlay.h | 2 +- 2 files changed, 63 insertions(+), 64 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 87ee46ca2b..b9b10f697e 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -376,7 +376,7 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { renderTexturedHemisphere(); - renderControllerPointersOculus(); + renderPointersOculus(); glDepthMask(GL_TRUE); glBindTexture(GL_TEXTURE_2D, 0); @@ -654,7 +654,7 @@ void ApplicationOverlay::renderControllerPointers() { } } -void ApplicationOverlay::renderControllerPointersOculus() { +void ApplicationOverlay::renderPointersOculus() { const bool useLaser = true; @@ -672,12 +672,10 @@ void ApplicationOverlay::renderControllerPointersOculus() { glMatrixMode(GL_MODELVIEW); MyAvatar* myAvatar = application->getAvatar(); - //Determine how much we need to iterate - const int ITERATIONS = max(myAvatar->getHand()->getNumPalms(), 3); - glm::vec3 eyePos = myAvatar->getHead()->calculateAverageEyePosition(); - for (int i = 0; i < ITERATIONS; i++) { + //Controller Pointers + for (int i = 0; i < myAvatar->getHand()->getNumPalms(); i++) { if (useLaser && i < myAvatar->getHand()->getNumPalms()) { PalmData& palm = myAvatar->getHand()->getPalms()[i]; @@ -766,64 +764,65 @@ void ApplicationOverlay::renderControllerPointersOculus() { glPopMatrix(); } - } else if (i < NUMBER_OF_MAGNIFIERS) { - //Dont render the reticle if its inactive - if (!_reticleActive[i]) { - continue; - } - - float mouseX = (float)_mouseX[i]; - float mouseY = (float)_mouseY[i]; - mouseX -= reticleSize / 2; - mouseY += reticleSize / 2; - - printf("MOUSEPOS: %f %f\n", mouseX, mouseY); - - //Get new UV coordinates from our magnification window - float newULeft = mouseX / widgetWidth; - float newURight = (mouseX + reticleSize) / widgetWidth; - float newVBottom = 1.0 - mouseY / widgetHeight; - float newVTop = 1.0 - (mouseY - reticleSize) / widgetHeight; - - // Project our position onto the hemisphere using the UV coordinates - float lX = sin((newULeft - 0.5f) * _textureFov); - float rX = sin((newURight - 0.5f) * _textureFov); - float bY = sin((newVBottom - 0.5f) * _textureFov); - float tY = sin((newVTop - 0.5f) * _textureFov); - - float dist; - //Bottom Left - dist = sqrt(lX * lX + bY * bY); - float blZ = sqrt(1.0f - dist * dist); - //Top Left - dist = sqrt(lX * lX + tY * tY); - float tlZ = sqrt(1.0f - dist * dist); - //Bottom Right - dist = sqrt(rX * rX + bY * bY); - float brZ = sqrt(1.0f - dist * dist); - //Top Right - dist = sqrt(rX * rX + tY * tY); - float trZ = sqrt(1.0f - dist * dist); - - glBegin(GL_QUADS); - - glColor4f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], _alpha); - - - const glm::quat& orientation = myAvatar->getOrientation(); - cursorVerts[0] = orientation * glm::vec3(lX, tY, -tlZ) + eyePos; - cursorVerts[1] = orientation * glm::vec3(rX, tY, -trZ) + eyePos; - cursorVerts[2] = orientation * glm::vec3(rX, bY, -brZ) + eyePos; - cursorVerts[3] = orientation * glm::vec3(lX, bY, -blZ) + eyePos; - - glTexCoord2f(0.0f, 0.0f); glVertex3f(cursorVerts[0].x, cursorVerts[0].y, cursorVerts[0].z); - glTexCoord2f(1.0f, 0.0f); glVertex3f(cursorVerts[1].x, cursorVerts[1].y, cursorVerts[1].z); - glTexCoord2f(1.0f, 1.0f); glVertex3f(cursorVerts[2].x, cursorVerts[2].y, cursorVerts[2].z); - glTexCoord2f(0.0f, 1.0f); glVertex3f(cursorVerts[3].x, cursorVerts[3].y, cursorVerts[3].z); - - glEnd(); - } + } } + + //Mouse Pointer + if (_reticleActive[MOUSE]) { + + float mouseX = (float)_mouseX[MOUSE]; + float mouseY = (float)_mouseY[MOUSE]; + mouseX -= reticleSize / 2; + mouseY += reticleSize / 2; + + printf("MOUSEPOS: %f %f\n", mouseX, mouseY); + + //Get new UV coordinates from our magnification window + float newULeft = mouseX / widgetWidth; + float newURight = (mouseX + reticleSize) / widgetWidth; + float newVBottom = 1.0 - mouseY / widgetHeight; + float newVTop = 1.0 - (mouseY - reticleSize) / widgetHeight; + + // Project our position onto the hemisphere using the UV coordinates + float lX = sin((newULeft - 0.5f) * _textureFov); + float rX = sin((newURight - 0.5f) * _textureFov); + float bY = sin((newVBottom - 0.5f) * _textureFov); + float tY = sin((newVTop - 0.5f) * _textureFov); + + float dist; + //Bottom Left + dist = sqrt(lX * lX + bY * bY); + float blZ = sqrt(1.0f - dist * dist); + //Top Left + dist = sqrt(lX * lX + tY * tY); + float tlZ = sqrt(1.0f - dist * dist); + //Bottom Right + dist = sqrt(rX * rX + bY * bY); + float brZ = sqrt(1.0f - dist * dist); + //Top Right + dist = sqrt(rX * rX + tY * tY); + float trZ = sqrt(1.0f - dist * dist); + + glBegin(GL_QUADS); + + glColor4f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], _alpha); + + + const glm::quat& orientation = myAvatar->getOrientation(); + cursorVerts[0] = orientation * glm::vec3(lX, tY, -tlZ) + eyePos; + cursorVerts[1] = orientation * glm::vec3(rX, tY, -trZ) + eyePos; + cursorVerts[2] = orientation * glm::vec3(rX, bY, -brZ) + eyePos; + cursorVerts[3] = orientation * glm::vec3(lX, bY, -blZ) + eyePos; + + glTexCoord2f(0.0f, 0.0f); glVertex3f(cursorVerts[0].x, cursorVerts[0].y, cursorVerts[0].z); + glTexCoord2f(1.0f, 0.0f); glVertex3f(cursorVerts[1].x, cursorVerts[1].y, cursorVerts[1].z); + glTexCoord2f(1.0f, 1.0f); glVertex3f(cursorVerts[2].x, cursorVerts[2].y, cursorVerts[2].z); + glTexCoord2f(0.0f, 1.0f); glVertex3f(cursorVerts[3].x, cursorVerts[3].y, cursorVerts[3].z); + + glEnd(); + } + + glEnable(GL_DEPTH_TEST); } diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index ebac5f3cfc..117dd02f3b 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -49,7 +49,7 @@ private: void renderPointers(); void renderControllerPointers(); - void renderControllerPointersOculus(); + void renderPointersOculus(); void renderMagnifier(int mouseX, int mouseY, float sizeMult, bool showBorder) const; void renderAudioMeter(); void renderStatsAndLogs(); From a2225da13d53dfba7ce9436f3896fc26438ed796 Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Wed, 9 Jul 2014 12:11:06 -0700 Subject: [PATCH 09/33] Code cleanup --- interface/src/ui/ApplicationOverlay.cpp | 135 ++++++++++-------------- 1 file changed, 53 insertions(+), 82 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index b9b10f697e..15dc18e74e 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -95,8 +95,6 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) { glMatrixMode(GL_PROJECTION); glPushMatrix(); - printf("%d %d\n", glWidget->width(), glWidget->height()); - glLoadIdentity(); gluOrtho2D(0, glWidget->width(), glWidget->height(), 0); glDisable(GL_DEPTH_TEST); @@ -656,8 +654,6 @@ void ApplicationOverlay::renderControllerPointers() { void ApplicationOverlay::renderPointersOculus() { - const bool useLaser = true; - Application* application = Application::getInstance(); QGLWidget* glWidget = application->getGLWidget(); glm::vec3 cursorVerts[4]; @@ -676,94 +672,72 @@ void ApplicationOverlay::renderPointersOculus() { //Controller Pointers for (int i = 0; i < myAvatar->getHand()->getNumPalms(); i++) { - if (useLaser && i < myAvatar->getHand()->getNumPalms()) { - - PalmData& palm = myAvatar->getHand()->getPalms()[i]; - if (palm.isActive()) { - glm::vec3 tip = OculusManager::getLaserPointerTipPosition(&palm); - glm::quat orientation = glm::inverse(myAvatar->getOrientation()); - glm::vec3 dir = orientation * glm::normalize(eyePos - tip); //direction of ray goes towards camera - glm::vec3 tipPos = (tip - eyePos); + + PalmData& palm = myAvatar->getHand()->getPalms()[i]; + if (palm.isActive()) { + glm::vec3 tip = OculusManager::getLaserPointerTipPosition(&palm); + glm::quat orientation = glm::inverse(myAvatar->getOrientation()); + glm::vec3 dir = orientation * glm::normalize(eyePos - tip); //direction of ray goes towards camera + glm::vec3 tipPos = (tip - eyePos); - float t; - float length = glm::length(eyePos - tip); - float size = 0.03f * length; + float length = glm::length(eyePos - tip); + float size = 0.03f * length; - glm::vec3 up = glm::vec3(0.0, 1.0, 0.0) * size; - glm::vec3 right = glm::vec3(1.0, 0.0, 0.0) * size; + glm::vec3 up = glm::vec3(0.0, 1.0, 0.0) * size; + glm::vec3 right = glm::vec3(1.0, 0.0, 0.0) * size; - cursorVerts[0] = -right + up; - cursorVerts[1] = right + up; - cursorVerts[2] = right - up; - cursorVerts[3] = -right - up; + cursorVerts[0] = -right + up; + cursorVerts[1] = right + up; + cursorVerts[2] = right - up; + cursorVerts[3] = -right - up; - glPushMatrix(); - // glLoadIdentity(); + glPushMatrix(); - // objToCamProj is the vector in world coordinates from the - // local origin to the camera projected in the XZ plane - glm::vec3 cursorToCameraXZ(-tipPos.x, 0, -tipPos.z); - cursorToCameraXZ = glm::normalize(cursorToCameraXZ); + // objToCamProj is the vector in world coordinates from the + // local origin to the camera projected in the XZ plane + glm::vec3 cursorToCameraXZ(-tipPos.x, 0, -tipPos.z); + cursorToCameraXZ = glm::normalize(cursorToCameraXZ); - // This is the original lookAt vector for the object - // in world coordinates - glm::vec3 direction(0, 0, 1); - glTranslatef(tip.x, tip.y, tip.z); + //Translate the cursor to the tip of the oculus ray + glTranslatef(tip.x, tip.y, tip.z); - // easy fix to determine wether the angle is negative or positive - // for positive angles upAux will be a vector pointing in the - // positive y direction, otherwise upAux will point downwards - // effectively reversing the rotation. - glm::vec3 upAux = glm::cross(direction, cursorToCameraXZ); + glm::vec3 direction(0, 0, 1); + // easy fix to determine wether the angle is negative or positive + // for positive angles upAux will be a vector pointing in the + // positive y direction, otherwise upAux will point downwards + // effectively reversing the rotation. + glm::vec3 upAux = glm::cross(direction, cursorToCameraXZ); - // compute the angle - float angleCosine = glm::dot(direction, cursorToCameraXZ); + // compute the angle + float angleCosine = glm::dot(direction, cursorToCameraXZ); - // perform the rotation. The if statement is used for stability reasons - // if the lookAt and objToCamProj vectors are too close together then - // |angleCosine| could be bigger than 1 due to lack of precision - if ((angleCosine < 0.999999) && (angleCosine > -0.999999)) { - glRotatef(acos(angleCosine) * DEGREES_PER_RADIAN, upAux[0], upAux[1], upAux[2]); - } + //Rotate in XZ direction + glRotatef(acos(angleCosine) * DEGREES_PER_RADIAN, upAux[0], upAux[1], upAux[2]); - // so far it is just like the cylindrical billboard. The code for the - // second rotation comes now - // The second part tilts the object so that it faces the camera + glm::vec3 cursorToCamera = glm::normalize(-tipPos); - // objToCam is the vector in world coordinates from - // the local origin to the camera - glm::vec3 cursorToCamera = glm::normalize(-tipPos); + // Compute the angle between cursorToCameraXZ and cursorToCamera, + angleCosine = glm::dot(cursorToCameraXZ, cursorToCamera); - // Compute the angle between objToCamProj and objToCam, - //i.e. compute the required angle for the lookup vector - - angleCosine = glm::dot(cursorToCameraXZ, cursorToCamera); - - // Tilt the object. The test is done to prevent instability - // when objToCam and objToCamProj have a very small - // angle between them - - // if ((angleCosine < 0.9999) && (angleCosine > -0.99999)) { - if (cursorToCamera.y < 0) { - glRotatef(acos(angleCosine) * DEGREES_PER_RADIAN, 1, 0, 0); - } else { - glRotatef(acos(angleCosine) * DEGREES_PER_RADIAN, -1, 0, 0); - } - // } - - glBegin(GL_QUADS); - - glColor4f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], _alpha); - - glTexCoord2f(0.0f, 0.0f); glVertex3f(cursorVerts[0].x, cursorVerts[0].y, cursorVerts[0].z); - glTexCoord2f(1.0f, 0.0f); glVertex3f(cursorVerts[1].x, cursorVerts[1].y, cursorVerts[1].z); - glTexCoord2f(1.0f, 1.0f); glVertex3f(cursorVerts[2].x, cursorVerts[2].y, cursorVerts[2].z); - glTexCoord2f(0.0f, 1.0f); glVertex3f(cursorVerts[3].x, cursorVerts[3].y, cursorVerts[3].z); - - glEnd(); - - glPopMatrix(); + //Rotate in Y direction + if (cursorToCamera.y < 0) { + glRotatef(acos(angleCosine) * DEGREES_PER_RADIAN, 1, 0, 0); + } else { + glRotatef(acos(angleCosine) * DEGREES_PER_RADIAN, -1, 0, 0); } + + glBegin(GL_QUADS); + + glColor4f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], _alpha); + + glTexCoord2f(0.0f, 0.0f); glVertex3f(cursorVerts[0].x, cursorVerts[0].y, cursorVerts[0].z); + glTexCoord2f(1.0f, 0.0f); glVertex3f(cursorVerts[1].x, cursorVerts[1].y, cursorVerts[1].z); + glTexCoord2f(1.0f, 1.0f); glVertex3f(cursorVerts[2].x, cursorVerts[2].y, cursorVerts[2].z); + glTexCoord2f(0.0f, 1.0f); glVertex3f(cursorVerts[3].x, cursorVerts[3].y, cursorVerts[3].z); + + glEnd(); + + glPopMatrix(); } } @@ -775,8 +749,6 @@ void ApplicationOverlay::renderPointersOculus() { mouseX -= reticleSize / 2; mouseY += reticleSize / 2; - printf("MOUSEPOS: %f %f\n", mouseX, mouseY); - //Get new UV coordinates from our magnification window float newULeft = mouseX / widgetWidth; float newURight = (mouseX + reticleSize) / widgetWidth; @@ -807,7 +779,6 @@ void ApplicationOverlay::renderPointersOculus() { glColor4f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], _alpha); - const glm::quat& orientation = myAvatar->getOrientation(); cursorVerts[0] = orientation * glm::vec3(lX, tY, -tlZ) + eyePos; cursorVerts[1] = orientation * glm::vec3(rX, tY, -trZ) + eyePos; From 090f1fd8521389912d0cca030f5ce25b7cb895de Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Wed, 9 Jul 2014 16:09:06 -0700 Subject: [PATCH 10/33] Fixed bug with 3rd person UI ray picking --- interface/src/ui/ApplicationOverlay.cpp | 18 +++++++++++------- interface/src/ui/ApplicationOverlay.h | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 15dc18e74e..0d05de76c5 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -165,7 +165,8 @@ void ApplicationOverlay::displayOverlayTexture() { } void ApplicationOverlay::computeOculusPickRay(float x, float y, glm::vec3& direction) const { - glm::quat rot = Application::getInstance()->getAvatar()->getOrientation(); + MyAvatar* myAvatar = Application::getInstance()->getAvatar(); + glm::quat rot = myAvatar->getOrientation(); //invert y direction y = 1.0 - y; @@ -177,8 +178,11 @@ void ApplicationOverlay::computeOculusPickRay(float x, float y, glm::vec3& direc float dist = sqrt(x * x + y * y); float z = -sqrt(1.0f - dist * dist); + glm::vec3 relativePosition = myAvatar->getHead()->calculateAverageEyePosition() + + glm::normalize(rot * glm::vec3(x, y, z)); + //Rotate the UI pick ray by the avatar orientation - direction = glm::normalize(rot * glm::vec3(x, y, z)); + direction = glm::normalize(relativePosition - Application::getInstance()->getCamera()->getPosition()); } // Calculates the click location on the screen by taking into account any @@ -275,7 +279,7 @@ QPoint ApplicationOverlay::getOculusPalmClickLocation(PalmData *palm) const { glm::vec3 tip = OculusManager::getLaserPointerTipPosition(palm); glm::vec3 eyePos = myAvatar->getHead()->calculateAverageEyePosition(); glm::quat orientation = glm::inverse(myAvatar->getOrientation()); - glm::vec3 dir = orientation * glm::normalize(eyePos - tip); //direction of ray goes towards camera + glm::vec3 dir = orientation * glm::normalize(application->getCamera()->getPosition() - tip); //direction of ray goes towards camera glm::vec3 tipPos = orientation * (tip - eyePos); QPoint rv; @@ -299,6 +303,8 @@ QPoint ApplicationOverlay::getOculusPalmClickLocation(PalmData *palm) const { rv.setX(u * glWidget->width()); rv.setY(v * glWidget->height()); + + printf("%d %d\n", rv.x(), rv.y()); } } else { //if they did not click on the overlay, just set the coords to INT_MAX @@ -374,7 +380,7 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { renderTexturedHemisphere(); - renderPointersOculus(); + renderPointersOculus(whichCamera.getPosition()); glDepthMask(GL_TRUE); glBindTexture(GL_TEXTURE_2D, 0); @@ -652,7 +658,7 @@ void ApplicationOverlay::renderControllerPointers() { } } -void ApplicationOverlay::renderPointersOculus() { +void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) { Application* application = Application::getInstance(); QGLWidget* glWidget = application->getGLWidget(); @@ -668,8 +674,6 @@ void ApplicationOverlay::renderPointersOculus() { glMatrixMode(GL_MODELVIEW); MyAvatar* myAvatar = application->getAvatar(); - glm::vec3 eyePos = myAvatar->getHead()->calculateAverageEyePosition(); - //Controller Pointers for (int i = 0; i < myAvatar->getHand()->getNumPalms(); i++) { diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index 117dd02f3b..726d0a3769 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -49,7 +49,7 @@ private: void renderPointers(); void renderControllerPointers(); - void renderPointersOculus(); + void renderPointersOculus(const glm::vec3& eyePos); void renderMagnifier(int mouseX, int mouseY, float sizeMult, bool showBorder) const; void renderAudioMeter(); void renderStatsAndLogs(); From 8147f2cd91b5471e5565406bab94c2664ffbb5b0 Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Wed, 9 Jul 2014 16:30:00 -0700 Subject: [PATCH 11/33] Fixed some magnification window bugs --- interface/src/ui/ApplicationOverlay.cpp | 44 ++++++++++++------------- interface/src/ui/ApplicationOverlay.h | 2 +- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 0d05de76c5..c064bb040a 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -191,7 +191,7 @@ void ApplicationOverlay::getClickLocation(int &x, int &y) const { int dx; int dy; const float xRange = MAGNIFY_WIDTH * MAGNIFY_MULT / 2.0f; - const float yRange = MAGNIFY_WIDTH * MAGNIFY_MULT / 2.0f; + const float yRange = MAGNIFY_HEIGHT * MAGNIFY_MULT / 2.0f; //Loop through all magnification windows for (int i = 0; i < NUMBER_OF_MAGNIFIERS; i++) { @@ -267,7 +267,7 @@ bool raySphereIntersect(const glm::vec3 &dir, const glm::vec3 &origin, float r, } -QPoint ApplicationOverlay::getOculusPalmClickLocation(PalmData *palm) const { +QPoint ApplicationOverlay::getOculusPalmClickLocation(const PalmData *palm) const { Application* application = Application::getInstance(); QGLWidget* glWidget = application->getGLWidget(); @@ -303,8 +303,6 @@ QPoint ApplicationOverlay::getOculusPalmClickLocation(PalmData *palm) const { rv.setX(u * glWidget->width()); rv.setY(v * glWidget->height()); - - printf("%d %d\n", rv.x(), rv.y()); } } else { //if they did not click on the overlay, just set the coords to INT_MAX @@ -600,13 +598,32 @@ void ApplicationOverlay::renderControllerPointers() { } else { bumperPressed[index] = false; } + + //if we have the oculus, we should make the cursor smaller since it will be + //magnified + if (OculusManager::isConnected()) { + QPoint point = getOculusPalmClickLocation(palmData); + + _mouseX[index] = point.x(); + _mouseY[index] = point.y(); + + //When button 2 is pressed we drag the mag window + if (isPressed[index]) { + _magActive[index] = true; + _magX[index] = point.x(); + _magY[index] = point.y(); + } + + // If oculus is enabled, we draw the crosshairs later + continue; + } // Get directon relative to avatar orientation glm::vec3 direction = glm::inverse(myAvatar->getOrientation()) * palmData->getFingerDirection(); // Get the angles, scaled between (-0.5,0.5) - float xAngle = (atan2(direction.z, direction.x) + M_PI_2) ; + float xAngle = (atan2(direction.z, direction.x) + M_PI_2); float yAngle = 0.5f - ((atan2(direction.z, direction.y) + M_PI_2)); // Get the pixel range over which the xAngle and yAngle are scaled @@ -621,24 +638,7 @@ void ApplicationOverlay::renderControllerPointers() { continue; } _reticleActive[index] = true; - - //if we have the oculus, we should make the cursor smaller since it will be - //magnified - if (OculusManager::isConnected()) { - - _mouseX[index] = mouseX; - _mouseY[index] = mouseY; - //When button 2 is pressed we drag the mag window - if (isPressed[index]) { - _magActive[index] = true; - _magX[index] = mouseX; - _magY[index] = mouseY; - } - - // If oculus is enabled, we draw the crosshairs later - continue; - } const float reticleSize = 40.0f; diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index 726d0a3769..fc282c2903 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -32,7 +32,7 @@ public: void displayOverlayTexture3DTV(Camera& whichCamera, float aspectRatio, float fov); void computeOculusPickRay(float x, float y, glm::vec3& direction) const; void getClickLocation(int &x, int &y) const; - QPoint getOculusPalmClickLocation(PalmData *palm) const; + QPoint getOculusPalmClickLocation(const PalmData *palm) const; // Getters QOpenGLFramebufferObject* getFramebufferObject(); From 56ff74dd56334b9300fba948c239843a6098b263 Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Wed, 9 Jul 2014 16:39:05 -0700 Subject: [PATCH 12/33] Removed ApplicationOverlay::resize() --- interface/src/Application.cpp | 1 - interface/src/ui/ApplicationOverlay.cpp | 14 +++----------- interface/src/ui/ApplicationOverlay.h | 5 +---- 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 42184bbdda..06ba3e442e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -723,7 +723,6 @@ void Application::resizeGL(int width, int height) { resetCamerasOnResizeGL(_myCamera, width, height); glViewport(0, 0, width, height); // shouldn't this account for the menu??? - _applicationOverlay.resize(); updateProjectionMatrix(); glLoadIdentity(); diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index caf103c00c..9ec87483dc 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -1189,20 +1189,12 @@ void ApplicationOverlay::renderTexturedHemisphere() { } -void ApplicationOverlay::resize() { - if (_framebufferObject != NULL) { - delete _framebufferObject; - _framebufferObject = NULL; - } - // _framebufferObject is recreated at the correct size the next time it is accessed via getFramebufferObject(). -} - QOpenGLFramebufferObject* ApplicationOverlay::getFramebufferObject() { QSize size = Application::getInstance()->getGLWidget()->size(); if (!_framebufferObject || _framebufferObject->size() != size) { - if (_framebufferObject){ - delete _framebufferObject; - } + + delete _framebufferObject; + _framebufferObject = new QOpenGLFramebufferObject(size); glBindTexture(GL_TEXTURE_2D, _framebufferObject->texture()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index a956858051..a64e26ed67 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -32,11 +32,8 @@ public: void displayOverlayTexture3DTV(Camera& whichCamera, float aspectRatio, float fov); void computeOculusPickRay(float x, float y, glm::vec3& direction) const; void getClickLocation(int &x, int &y) const; -<<<<<<< HEAD QPoint getOculusPalmClickLocation(const PalmData *palm) const; -======= - void resize(); ->>>>>>> af6704a83cec1d69b3dc3e1145238919fcb82933 + // Getters QOpenGLFramebufferObject* getFramebufferObject(); From 004db004a6318d3762ffe8d394529ab65e0eb304 Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Wed, 9 Jul 2014 17:03:09 -0700 Subject: [PATCH 13/33] Dynamically resize lasers so they always end on UI --- interface/src/devices/OculusManager.cpp | 12 ++++++++++-- interface/src/ui/ApplicationOverlay.cpp | 18 ++++++++++++++++++ interface/src/ui/ApplicationOverlay.h | 1 + 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 2e6d4cb9a2..b3c478e5e9 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -490,8 +490,16 @@ void OculusManager::renderLaserPointer() { glm::vec3 OculusManager::getLaserPointerTipPosition(const PalmData* palm) { #ifdef HAVE_LIBOVR - const float PALM_TIP_ROD_LENGTH_MULT = 4.0f; - return palm->getPosition() + (palm->getTipPosition() - palm->getPosition()) * PALM_TIP_ROD_LENGTH_MULT; + const ApplicationOverlay& applicationOverlay = Application::getInstance()->getApplicationOverlay(); + const float PALM_TIP_ROD_LENGTH_MULT = 40.0f; + + glm::vec3 direction = glm::normalize(palm->getTipPosition() - palm->getPosition()); + glm::vec3 result; + if (applicationOverlay.calculateRayUICollisionPoint(palm->getPosition(), direction, result)) { + return result; + } + + return palm->getPosition(); #endif return glm::vec3(0.0f); } diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 9ec87483dc..6d8af6641f 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -311,6 +311,24 @@ QPoint ApplicationOverlay::getOculusPalmClickLocation(const PalmData *palm) cons return rv; } +bool ApplicationOverlay::calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const { + Application* application = Application::getInstance(); + MyAvatar* myAvatar = application->getAvatar(); + + glm::quat orientation = myAvatar->getOrientation(); + + glm::vec3 relativePosition = orientation * (position - myAvatar->getHead()->calculateAverageEyePosition()); + glm::vec3 relativeDirection = orientation * direction; + + float t; + if (raySphereIntersect(relativeDirection, relativePosition, 1, &t)){ + result = position + direction * t; + return true; + } + + return false; +} + // Draws the FBO texture for Oculus rift. void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index a64e26ed67..e355665b95 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -33,6 +33,7 @@ public: void computeOculusPickRay(float x, float y, glm::vec3& direction) const; void getClickLocation(int &x, int &y) const; QPoint getOculusPalmClickLocation(const PalmData *palm) const; + bool calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const; // Getters From a785ceb3da8726236875df11ed10320845c06fee Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Wed, 9 Jul 2014 17:33:41 -0700 Subject: [PATCH 14/33] Restored UI fade animation --- interface/src/Application.cpp | 4 ---- interface/src/devices/OculusManager.cpp | 11 +++++------ interface/src/devices/OculusManager.h | 2 +- interface/src/ui/ApplicationOverlay.cpp | 3 +++ 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 06ba3e442e..9842144bff 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2786,10 +2786,6 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { { PerformanceTimer perfTimer("avatars"); - if (OculusManager::isConnected()) { - OculusManager::renderLaserPointer(); - } - _avatarManager.renderAvatars(mirrorMode ? Avatar::MIRROR_RENDER_MODE : Avatar::NORMAL_RENDER_MODE, selfAvatarOnly); } diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index b3c478e5e9..574aa3c6f6 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -269,8 +269,7 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p // We only need to render the overlays to a texture once, then we just render the texture on the hemisphere // PrioVR will only work if renderOverlay is called, calibration is connected to Application::renderingOverlay() applicationOverlay.renderOverlay(true); - const bool displayOverlays = Menu::getInstance()->isOptionChecked(MenuOption::UserInterface); - + //Bind our framebuffer object. If we are rendering the glow effect, we let the glow effect shader take care of it if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) { Application::getInstance()->getGlowEffect()->prepare(); @@ -325,9 +324,7 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p Application::getInstance()->displaySide(*_camera); - if (displayOverlays) { - applicationOverlay.displayOverlayTextureOculus(*_camera); - } + applicationOverlay.displayOverlayTextureOculus(*_camera); } //Wait till time-warp to reduce latency @@ -467,7 +464,8 @@ QSize OculusManager::getRenderTargetSize() { #endif } -void OculusManager::renderLaserPointer() { +//Renders sixense laser pointers for UI selection in the oculus +void OculusManager::renderLaserPointers() { #ifdef HAVE_LIBOVR const float PALM_TIP_ROD_RADIUS = 0.002f; @@ -488,6 +486,7 @@ void OculusManager::renderLaserPointer() { #endif } +//Gets the tip position for the laser pointer glm::vec3 OculusManager::getLaserPointerTipPosition(const PalmData* palm) { #ifdef HAVE_LIBOVR const ApplicationOverlay& applicationOverlay = Application::getInstance()->getApplicationOverlay(); diff --git a/interface/src/devices/OculusManager.h b/interface/src/devices/OculusManager.h index 73ce6ef2d3..871e5d649a 100644 --- a/interface/src/devices/OculusManager.h +++ b/interface/src/devices/OculusManager.h @@ -44,7 +44,7 @@ public: static QSize getRenderTargetSize(); /// Renders a laser pointer for UI picking - static void renderLaserPointer(); + static void renderLaserPointers(); static glm::vec3 getLaserPointerTipPosition(const PalmData* palm); private: diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 6d8af6641f..6324ee03b0 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -340,6 +340,9 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { MyAvatar* myAvatar = application->getAvatar(); + //Render the sixense lasers + OculusManager::renderLaserPointers(); + glActiveTexture(GL_TEXTURE0); glEnable(GL_BLEND); From baf825789e3b51194d607af30cf063bde455ab39 Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Thu, 10 Jul 2014 10:28:56 -0700 Subject: [PATCH 15/33] Made Oculus UI radius not a magic number --- interface/src/ui/ApplicationOverlay.cpp | 14 ++++++++------ interface/src/ui/ApplicationOverlay.h | 1 + 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 6324ee03b0..005858fd4d 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -40,7 +40,8 @@ ApplicationOverlay::ApplicationOverlay() : _framebufferObject(NULL), _textureFov(DEFAULT_OCULUS_UI_ANGULAR_SIZE * RADIANS_PER_DEGREE), _alpha(1.0f), - _crosshairTexture(0) { + _crosshairTexture(0), + _oculusuiRadius(1.0f) { memset(_reticleActive, 0, sizeof(_reticleActive)); memset(_magActive, 0, sizeof(_reticleActive)); @@ -288,9 +289,10 @@ QPoint ApplicationOverlay::getOculusPalmClickLocation(const PalmData *palm) cons //We back the ray up by dir to ensure that it will not start inside the UI. glm::vec3 adjustedPos = tipPos - dir; //Find intersection of crosshair ray. - if (raySphereIntersect(dir, adjustedPos, 1, &t)){ + if (raySphereIntersect(dir, adjustedPos, _oculusuiRadius, &t)){ glm::vec3 collisionPos = adjustedPos + dir * t; - + //Normalize it in case its not a radius of 1 + collisionPos = glm::normalize(collisionPos); //If we hit the back hemisphere, mark it as not a collision if (collisionPos.z > 0) { rv.setX(INT_MAX); @@ -321,7 +323,7 @@ bool ApplicationOverlay::calculateRayUICollisionPoint(const glm::vec3& position, glm::vec3 relativeDirection = orientation * direction; float t; - if (raySphereIntersect(relativeDirection, relativePosition, 1, &t)){ + if (raySphereIntersect(relativeDirection, relativePosition, _oculusuiRadius, &t)){ result = position + direction * t; return true; } @@ -1196,8 +1198,8 @@ void ApplicationOverlay::renderTexturedHemisphere() { glTranslatef(position.x, position.y, position.z); glMultMatrixf(&rotation[0][0]); - - + glScalef(_oculusuiRadius, _oculusuiRadius, _oculusuiRadius); + glDrawRangeElements(GL_TRIANGLES, 0, vertices - 1, indices, GL_UNSIGNED_SHORT, 0); glPopMatrix(); diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index e355665b95..33ba818f40 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -71,6 +71,7 @@ private: float _magSizeMult[NUMBER_OF_MAGNIFIERS]; float _alpha; + float _oculusuiRadius; GLuint _crosshairTexture; }; From 4d591de76276614bb3dd40b50f123081f4281640 Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Thu, 10 Jul 2014 10:52:15 -0700 Subject: [PATCH 16/33] Applied low velocity filter to palm tip position --- interface/src/devices/SixenseManager.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index b9a736887e..f145b8d5be 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -173,8 +173,10 @@ void SixenseManager::update(float deltaTime) { // Use a velocity sensitive filter to damp small motions and preserve large ones with // no latency. float velocityFilter = glm::clamp(1.0f - glm::length(rawVelocity), 0.0f, 1.0f); - palm->setRawPosition(palm->getRawPosition() * velocityFilter + position * (1.0f - velocityFilter)); - palm->setRawRotation(safeMix(palm->getRawRotation(), rotation, 1.0f - velocityFilter)); + position = palm->getRawPosition() * velocityFilter + position * (1.0f - velocityFilter); + rotation = safeMix(palm->getRawRotation(), rotation, 1.0f - velocityFilter); + palm->setRawPosition(position); + palm->setRawRotation(rotation); } else { palm->setRawPosition(position); palm->setRawRotation(rotation); From 45421ffb0e435d0ad61b6d913dd024f0913eb497 Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Thu, 10 Jul 2014 12:06:36 -0700 Subject: [PATCH 17/33] Made palm ball and disk properly use avatar scale --- interface/src/avatar/Hand.cpp | 16 ++++++++++++---- interface/src/devices/OculusManager.cpp | 1 - 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 94f734ba06..7faf1aaadc 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -130,6 +130,9 @@ void Hand::render(bool isMine, Model::RenderMode renderMode) { void Hand::renderHandTargets(bool isMine) { glPushMatrix(); + MyAvatar* myAvatar = Application::getInstance()->getAvatar(); + const float avatarScale = Application::getInstance()->getAvatar()->getScale(); + const float alpha = 1.0f; const glm::vec3 handColor(1.0, 0.0, 0.0); // Color the hand targets red to be different than skin @@ -153,10 +156,10 @@ void Hand::renderHandTargets(bool isMine) { } } - const float PALM_BALL_RADIUS = 0.03f; - const float PALM_DISK_RADIUS = 0.06f; - const float PALM_DISK_THICKNESS = 0.01f; - const float PALM_FINGER_ROD_RADIUS = 0.003f; + const float PALM_BALL_RADIUS = 0.03f * avatarScale; + const float PALM_DISK_RADIUS = 0.06f * avatarScale; + const float PALM_DISK_THICKNESS = 0.01f * avatarScale; + const float PALM_FINGER_ROD_RADIUS = 0.003f * avatarScale; // Draw the palm ball and disk for (size_t i = 0; i < getNumPalms(); ++i) { @@ -165,6 +168,11 @@ void Hand::renderHandTargets(bool isMine) { glColor4f(handColor.r, handColor.g, handColor.b, alpha); glm::vec3 tip = palm.getFingerTipPosition(); glm::vec3 root = palm.getPosition(); + + //Scale the positions based on avatar scale + tip = myAvatar->getPosition() + avatarScale * (tip - myAvatar->getPosition()); + root = myAvatar->getPosition() + avatarScale * (root - myAvatar->getPosition()); + Avatar::renderJointConnectingCone(root, tip, PALM_FINGER_ROD_RADIUS, PALM_FINGER_ROD_RADIUS); // Render sphere at palm/finger root glm::vec3 offsetFromPalm = root + palm.getNormal() * PALM_DISK_THICKNESS; diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 574aa3c6f6..0ad606a320 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -473,7 +473,6 @@ void OculusManager::renderLaserPointers() { //If the Oculus is enabled, we will draw a blue cursor ray - // Draw the palm ball and disk for (size_t i = 0; i < myAvatar->getHand()->getNumPalms(); ++i) { PalmData& palm = myAvatar->getHand()->getPalms()[i]; if (palm.isActive()) { From fc21f7bbacbcce8009df663aaed2a48287f72c8b Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Thu, 10 Jul 2014 14:21:17 -0700 Subject: [PATCH 18/33] Removed outdated and incorrect getFingerTipPosition() --- interface/src/BuckyBalls.cpp | 2 +- interface/src/avatar/Hand.cpp | 4 ++-- libraries/avatars/src/HandData.cpp | 6 ------ libraries/avatars/src/HandData.h | 1 - 4 files changed, 3 insertions(+), 10 deletions(-) diff --git a/interface/src/BuckyBalls.cpp b/interface/src/BuckyBalls.cpp index 68d1167071..1bc093283a 100644 --- a/interface/src/BuckyBalls.cpp +++ b/interface/src/BuckyBalls.cpp @@ -60,7 +60,7 @@ BuckyBalls::BuckyBalls() { void BuckyBalls::grab(PalmData& palm, float deltaTime) { float penetration; - glm::vec3 fingerTipPosition = palm.getFingerTipPosition(); + glm::vec3 fingerTipPosition = palm.getTipPosition(); if (palm.getControllerButtons() & BUTTON_FWD) { if (!_bballIsGrabbed[palm.getSixenseID()]) { diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 7faf1aaadc..aae9cb0a29 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -145,7 +145,7 @@ void Hand::renderHandTargets(bool isMine) { if (!palm.isActive()) { continue; } - glm::vec3 targetPosition = palm.getFingerTipPosition(); + glm::vec3 targetPosition = palm.getTipPosition(); glPushMatrix(); glTranslatef(targetPosition.x, targetPosition.y, targetPosition.z); @@ -166,7 +166,7 @@ void Hand::renderHandTargets(bool isMine) { PalmData& palm = getPalms()[i]; if (palm.isActive()) { glColor4f(handColor.r, handColor.g, handColor.b, alpha); - glm::vec3 tip = palm.getFingerTipPosition(); + glm::vec3 tip = palm.getTipPosition(); glm::vec3 root = palm.getPosition(); //Scale the positions based on avatar scale diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index e6ef10ed3e..69f9669973 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -108,12 +108,6 @@ glm::quat HandData::getBaseOrientation() const { glm::vec3 HandData::getBasePosition() const { return _owningAvatarData->getPosition(); } - -glm::vec3 PalmData::getFingerTipPosition() const { - glm::vec3 fingerOffset(0.0f, 0.0f, 0.3f); - glm::vec3 palmOffset(0.0f, -0.08f, 0.0f); - return getPosition() + _owningHandData->localToWorldDirection(_rawRotation * (fingerOffset + palmOffset)); -} glm::vec3 PalmData::getFingerDirection() const { const glm::vec3 LOCAL_FINGER_DIRECTION(0.0f, 0.0f, 1.0f); diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index 404d00b0f3..770a44197d 100755 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -140,7 +140,6 @@ public: void getBallHoldPosition(glm::vec3& position) const; // return world-frame: - glm::vec3 getFingerTipPosition() const; glm::vec3 getFingerDirection() const; glm::vec3 getNormal() const; From 8bc92144453e486b614662daea5df829aa8cf416 Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Thu, 10 Jul 2014 14:37:04 -0700 Subject: [PATCH 19/33] Added helper scaling function to Avatar. --- interface/src/avatar/Avatar.cpp | 5 +++++ interface/src/avatar/Avatar.h | 4 ++++ interface/src/avatar/Hand.cpp | 4 ++-- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 3221e75e56..2ebbd55c85 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -970,6 +970,11 @@ glm::quat Avatar::getJointCombinedRotation(const QString& name) const { return rotation; } +void Avatar::scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const { + //Scale a world space vector as if it was relative to the position + positionToScale = _position + _scale * (positionToScale - _position); +} + void Avatar::setFaceModelURL(const QUrl& faceModelURL) { AvatarData::setFaceModelURL(faceModelURL); const QUrl DEFAULT_FACE_MODEL_URL = QUrl::fromLocalFile(Application::resourcesPath() + "meshes/defaultAvatar_head.fst"); diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 8c14fc9ed0..6fb7991c3c 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -152,6 +152,10 @@ public: glm::vec3 getAcceleration() const { return _acceleration; } glm::vec3 getAngularVelocity() const { return _angularVelocity; } + + /// Scales a world space position vector relative to the avatar position and scale + /// \param vector position to be scaled. Will store the result + void scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const; public slots: void updateCollisionGroups(); diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index aae9cb0a29..08e1cf83df 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -170,8 +170,8 @@ void Hand::renderHandTargets(bool isMine) { glm::vec3 root = palm.getPosition(); //Scale the positions based on avatar scale - tip = myAvatar->getPosition() + avatarScale * (tip - myAvatar->getPosition()); - root = myAvatar->getPosition() + avatarScale * (root - myAvatar->getPosition()); + myAvatar->scaleVectorRelativeToPosition(tip); + myAvatar->scaleVectorRelativeToPosition(root); Avatar::renderJointConnectingCone(root, tip, PALM_FINGER_ROD_RADIUS, PALM_FINGER_ROD_RADIUS); // Render sphere at palm/finger root From 4bfd393d028674face241aca774bd379bb8f565a Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Thu, 10 Jul 2014 16:42:00 -0700 Subject: [PATCH 20/33] Proper scaling for oculus UI using avatar scale --- interface/src/devices/OculusManager.cpp | 12 +++++++++- interface/src/ui/ApplicationOverlay.cpp | 31 +++++++++++++++---------- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 0ad606a320..beb18bfc72 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -479,6 +479,10 @@ void OculusManager::renderLaserPointers() { glColor4f(0, 1, 1, 1); glm::vec3 tip = getLaserPointerTipPosition(&palm); glm::vec3 root = palm.getPosition(); + + //Scale the root vector with the avatar scale + myAvatar->scaleVectorRelativeToPosition(root); + Avatar::renderJointConnectingCone(root, tip, PALM_TIP_ROD_RADIUS, PALM_TIP_ROD_RADIUS); } } @@ -492,8 +496,14 @@ glm::vec3 OculusManager::getLaserPointerTipPosition(const PalmData* palm) { const float PALM_TIP_ROD_LENGTH_MULT = 40.0f; glm::vec3 direction = glm::normalize(palm->getTipPosition() - palm->getPosition()); + + glm::vec3 position = palm->getPosition(); + //scale the position with the avatar + Application::getInstance()->getAvatar()->scaleVectorRelativeToPosition(position); + + glm::vec3 result; - if (applicationOverlay.calculateRayUICollisionPoint(palm->getPosition(), direction, result)) { + if (applicationOverlay.calculateRayUICollisionPoint(position, direction, result)) { return result; } diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 005858fd4d..6d1e45df20 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -266,7 +266,7 @@ bool raySphereIntersect(const glm::vec3 &dir, const glm::vec3 &origin, float r, } } - +//Caculate the click location using one of the sixense controllers. Scale is not applied QPoint ApplicationOverlay::getOculusPalmClickLocation(const PalmData *palm) const { Application* application = Application::getInstance(); @@ -289,7 +289,7 @@ QPoint ApplicationOverlay::getOculusPalmClickLocation(const PalmData *palm) cons //We back the ray up by dir to ensure that it will not start inside the UI. glm::vec3 adjustedPos = tipPos - dir; //Find intersection of crosshair ray. - if (raySphereIntersect(dir, adjustedPos, _oculusuiRadius, &t)){ + if (raySphereIntersect(dir, adjustedPos, _oculusuiRadius * myAvatar->getScale(), &t)){ glm::vec3 collisionPos = adjustedPos + dir * t; //Normalize it in case its not a radius of 1 collisionPos = glm::normalize(collisionPos); @@ -313,6 +313,7 @@ QPoint ApplicationOverlay::getOculusPalmClickLocation(const PalmData *palm) cons return rv; } +//Finds the collision point of a world space ray bool ApplicationOverlay::calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const { Application* application = Application::getInstance(); MyAvatar* myAvatar = application->getAvatar(); @@ -323,7 +324,7 @@ bool ApplicationOverlay::calculateRayUICollisionPoint(const glm::vec3& position, glm::vec3 relativeDirection = orientation * direction; float t; - if (raySphereIntersect(relativeDirection, relativePosition, _oculusuiRadius, &t)){ + if (raySphereIntersect(relativeDirection, relativePosition, _oculusuiRadius * myAvatar->getScale(), &t)){ result = position + direction * t; return true; } @@ -862,18 +863,22 @@ void ApplicationOverlay::renderMagnifier(int mouseX, int mouseY, float sizeMult, float newVTop = 1.0 - (newMouseY - newHeight) / widgetHeight; // Project our position onto the hemisphere using the UV coordinates - float lX = sin((newULeft - 0.5f) * _textureFov); - float rX = sin((newURight - 0.5f) * _textureFov); - float bY = sin((newVBottom - 0.5f) * _textureFov); - float tY = sin((newVTop - 0.5f) * _textureFov); + float radius = _oculusuiRadius * application->getAvatar()->getScale(); + float radius2 = radius * radius; + + float lX = radius * sin((newULeft - 0.5f) * _textureFov); + float rX = radius * sin((newURight - 0.5f) * _textureFov); + float bY = radius * sin((newVBottom - 0.5f) * _textureFov); + float tY = radius * sin((newVTop - 0.5f) * _textureFov); float blZ, tlZ, brZ, trZ; float dist; float discriminant; + //Bottom Left dist = sqrt(lX * lX + bY * bY); - discriminant = 1.0f - dist * dist; + discriminant = radius2 - dist * dist; if (discriminant > 0) { blZ = sqrt(discriminant); } else { @@ -881,7 +886,7 @@ void ApplicationOverlay::renderMagnifier(int mouseX, int mouseY, float sizeMult, } //Top Left dist = sqrt(lX * lX + tY * tY); - discriminant = 1.0f - dist * dist; + discriminant = radius2 - dist * dist; if (discriminant > 0) { tlZ = sqrt(discriminant); } else { @@ -889,7 +894,7 @@ void ApplicationOverlay::renderMagnifier(int mouseX, int mouseY, float sizeMult, } //Bottom Right dist = sqrt(rX * rX + bY * bY); - discriminant = 1.0f - dist * dist; + discriminant = radius2 - dist * dist; if (discriminant > 0) { brZ = sqrt(discriminant); } else { @@ -897,7 +902,7 @@ void ApplicationOverlay::renderMagnifier(int mouseX, int mouseY, float sizeMult, } //Top Right dist = sqrt(rX * rX + tY * tY); - discriminant = 1.0f - dist * dist; + discriminant = radius2 - dist * dist; if (discriminant > 0) { trZ = sqrt(discriminant); } else { @@ -1198,7 +1203,9 @@ void ApplicationOverlay::renderTexturedHemisphere() { glTranslatef(position.x, position.y, position.z); glMultMatrixf(&rotation[0][0]); - glScalef(_oculusuiRadius, _oculusuiRadius, _oculusuiRadius); + + const float scale = _oculusuiRadius * myAvatar->getScale(); + glScalef(scale, scale, scale); glDrawRangeElements(GL_TRIANGLES, 0, vertices - 1, indices, GL_UNSIGNED_SHORT, 0); From 71634b4c8dd7fc9d7bb4498ca371805ccab5ddde Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Thu, 10 Jul 2014 16:56:04 -0700 Subject: [PATCH 21/33] Fixed windows compiler warning --- interface/src/ui/ApplicationOverlay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 6d1e45df20..15cb10ec84 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -700,7 +700,7 @@ void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) { MyAvatar* myAvatar = application->getAvatar(); //Controller Pointers - for (int i = 0; i < myAvatar->getHand()->getNumPalms(); i++) { + for (size_t i = 0; i < myAvatar->getHand()->getNumPalms(); i++) { PalmData& palm = myAvatar->getHand()->getPalms()[i]; if (palm.isActive()) { From e658ce8fb939995d99579d3f016baa4982c313db Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Thu, 10 Jul 2014 16:57:46 -0700 Subject: [PATCH 22/33] Fixed ubuntu compiler warning --- interface/src/ui/ApplicationOverlay.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 15cb10ec84..3cc9cf4250 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -40,8 +40,8 @@ ApplicationOverlay::ApplicationOverlay() : _framebufferObject(NULL), _textureFov(DEFAULT_OCULUS_UI_ANGULAR_SIZE * RADIANS_PER_DEGREE), _alpha(1.0f), - _crosshairTexture(0), - _oculusuiRadius(1.0f) { + _oculusuiRadius(1.0f), + _crosshairTexture(0) { memset(_reticleActive, 0, sizeof(_reticleActive)); memset(_magActive, 0, sizeof(_reticleActive)); From 4bf74c1b65c5c7bc2bad97c8db7031ae13d5ee43 Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Thu, 10 Jul 2014 16:59:57 -0700 Subject: [PATCH 23/33] Fixed more ubuntu compiler warnings --- interface/src/ui/ApplicationOverlay.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 3cc9cf4250..fad4a64835 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -272,9 +272,6 @@ QPoint ApplicationOverlay::getOculusPalmClickLocation(const PalmData *palm) cons Application* application = Application::getInstance(); QGLWidget* glWidget = application->getGLWidget(); MyAvatar* myAvatar = application->getAvatar(); - - const int widgetWidth = glWidget->width(); - const int widgetHeight = glWidget->height(); glm::vec3 tip = OculusManager::getLaserPointerTipPosition(palm); glm::vec3 eyePos = myAvatar->getHead()->calculateAverageEyePosition(); @@ -700,13 +697,12 @@ void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) { MyAvatar* myAvatar = application->getAvatar(); //Controller Pointers - for (size_t i = 0; i < myAvatar->getHand()->getNumPalms(); i++) { + for (int i = 0; i < (int)myAvatar->getHand()->getNumPalms(); i++) { PalmData& palm = myAvatar->getHand()->getPalms()[i]; if (palm.isActive()) { glm::vec3 tip = OculusManager::getLaserPointerTipPosition(&palm); glm::quat orientation = glm::inverse(myAvatar->getOrientation()); - glm::vec3 dir = orientation * glm::normalize(eyePos - tip); //direction of ray goes towards camera glm::vec3 tipPos = (tip - eyePos); float length = glm::length(eyePos - tip); From df7f3073dc3efd4ce49f05598e2d1430f16e3459 Mon Sep 17 00:00:00 2001 From: TonyPeng Date: Thu, 10 Jul 2014 17:18:49 -0700 Subject: [PATCH 24/33] 2 local lights as default --- interface/src/avatar/Avatar.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 83105c9022..febbba7536 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -60,9 +60,9 @@ Avatar::Avatar() : _mouseRayDirection(0.0f, 0.0f, 0.0f), _moving(false), _collisionGroups(0), + _numLocalLights(2), _initialized(false), - _shouldRenderBillboard(true), - _numLocalLights(1) + _shouldRenderBillboard(true) { // we may have been created in the network thread, but we live in the main thread moveToThread(Application::getInstance()->thread()); @@ -89,14 +89,14 @@ void Avatar::init() { _localLightDirections[i] = glm::vec3(0.0f, 0.0f, 0.0f); } - glm::vec3 darkGrayColor(0.3f, 0.3f, 0.3f); + glm::vec3 darkGrayColor(0.4f, 0.4f, 0.4f); glm::vec3 greenColor(0.0f, 1.0f, 0.0f); glm::vec3 directionX(1.0f, 0.0f, 0.0f); glm::vec3 directionY(0.0f, 1.0f, 0.0f); // initialize local lights _localLightColors[0] = darkGrayColor; - _localLightColors[1] = greenColor; + _localLightColors[1] = darkGrayColor; _localLightDirections[0] = directionX; _localLightDirections[1] = directionY; From 1781a2d1253692666b03754274222bbd2a73b89b Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Thu, 10 Jul 2014 17:30:43 -0700 Subject: [PATCH 25/33] fixed unused variable warning --- interface/src/ui/ApplicationOverlay.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index fad4a64835..3ccb487716 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -702,7 +702,6 @@ void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) { PalmData& palm = myAvatar->getHand()->getPalms()[i]; if (palm.isActive()) { glm::vec3 tip = OculusManager::getLaserPointerTipPosition(&palm); - glm::quat orientation = glm::inverse(myAvatar->getOrientation()); glm::vec3 tipPos = (tip - eyePos); float length = glm::length(eyePos - tip); From 97165cadcc45443c3f81da10ed92f4c3de8b156b Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Thu, 10 Jul 2014 17:34:10 -0700 Subject: [PATCH 26/33] Removed unneeded variable --- interface/src/ui/ApplicationOverlay.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 3ccb487716..7b3db26d8d 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -166,7 +166,6 @@ void ApplicationOverlay::displayOverlayTexture() { void ApplicationOverlay::computeOculusPickRay(float x, float y, glm::vec3& direction) const { MyAvatar* myAvatar = Application::getInstance()->getAvatar(); - glm::quat rot = myAvatar->getOrientation(); //invert y direction y = 1.0 - y; @@ -179,7 +178,7 @@ void ApplicationOverlay::computeOculusPickRay(float x, float y, glm::vec3& direc float z = -sqrt(1.0f - dist * dist); glm::vec3 relativePosition = myAvatar->getHead()->calculateAverageEyePosition() + - glm::normalize(rot * glm::vec3(x, y, z)); + glm::normalize(myAvatar->getOrientation() * glm::vec3(x, y, z)); //Rotate the UI pick ray by the avatar orientation direction = glm::normalize(relativePosition - Application::getInstance()->getCamera()->getPosition()); From 2347bd7eed458fd80b9fe81836723b69214f4a63 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 11 Jul 2014 10:47:48 -0700 Subject: [PATCH 27/33] Sitting position persists between sessions --- examples/sit.js | 54 +++++++++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/examples/sit.js b/examples/sit.js index 056a65fbf1..f7be681d25 100644 --- a/examples/sit.js +++ b/examples/sit.js @@ -43,7 +43,10 @@ var animationLenght = 2.0; var avatarOldPosition = { x: 0, y: 0, z: 0 }; -var sitting = false; +var sittingSettingsHandle = "SitJsSittingPosition"; +var sitting = Settings.getValue(sittingSettingsHandle, false) == "true"; +print("Original sitting status: " + sitting); +var frame = 0; var seat = new Object(); var hiddingSeats = false; @@ -123,10 +126,12 @@ var goToSeatAnimation = function(deltaTime) { function sitDown() { sitting = true; + Settings.setValue(sittingSettingsHandle, sitting); + print("sitDown sitting status: " + Settings.getValue(sittingSettingsHandle, false)); passedTime = 0.0; startPosition = MyAvatar.position; storeStartPoseAndTransition(); - try{ + try { Script.update.disconnect(standingUpAnimation); } catch(e){ // no need to handle. if it wasn't connected no harm done @@ -138,6 +143,8 @@ function sitDown() { function standUp() { sitting = false; + Settings.setValue(sittingSettingsHandle, sitting); + print("standUp sitting status: " + Settings.getValue(sittingSettingsHandle, false)); passedTime = 0.0; startPosition = MyAvatar.position; try{ @@ -218,33 +225,6 @@ Controller.mousePressEvent.connect(function(event) { try{ Script.update.disconnect(sittingDownAnimation); } catch(e){} Script.update.connect(goToSeatAnimation); } - - - - return; - var intersection = Models.findRayIntersection(pickRay); - - if (intersection.accurate && intersection.intersects && false) { - var properties = intersection.modelProperties; - print("Intersecting with model, let's check for seats."); - - if (properties.sittingPoints.length > 0) { - print("Available seats, going to the first one: " + properties.sittingPoints[0].name); - seat.position = Vec3.sum(properties.position, Vec3.multiplyQbyV(properties.modelRotation, properties.sittingPoints[0].position)); - Vec3.print("Seat position: ", seat.position); - seat.rotation = Quat.multiply(properties.modelRotation, properties.sittingPoints[0].rotation); - Quat.print("Seat rotation: ", seat.rotation); - - passedTime = 0.0; - startPosition = MyAvatar.position; - startRotation = MyAvatar.orientation; - try{ Script.update.disconnect(standingUpAnimation); } catch(e){} - try{ Script.update.disconnect(sittingDownAnimation); } catch(e){} - Script.update.connect(goToSeatAnimation); - } else { - print ("Sorry, no seats here."); - } - } } }) @@ -257,6 +237,22 @@ function update(deltaTime){ Overlays.editOverlay( standUpButton, {x: newX, y: newY} ); Overlays.editOverlay( sitDownButton, {x: newX, y: newY} ); } + + // For a weird reason avatar joint don't update till the 10th frame + // Set the update frame to 20 to be safe + var UPDATE_FRAME = 20; + if (frame <= UPDATE_FRAME) { + if (frame == UPDATE_FRAME) { + if (sitting == true) { + print("Was seated: " + sitting); + storeStartPoseAndTransition(); + updateJoints(1.0); + Overlays.editOverlay(sitDownButton, { visible: false }); + Overlays.editOverlay(standUpButton, { visible: true }); + } + } + frame++; + } if (MyAvatar.position.x != avatarOldPosition.x && MyAvatar.position.y != avatarOldPosition.y && From bd7b17a7878368dcdab23bb3b91c9289f8681a57 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 11 Jul 2014 10:50:11 -0700 Subject: [PATCH 28/33] Added subimage to Billboards overlays --- .../src/ui/overlays/BillboardOverlay.cpp | 51 ++++++++++++++++--- interface/src/ui/overlays/BillboardOverlay.h | 5 +- 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/interface/src/ui/overlays/BillboardOverlay.cpp b/interface/src/ui/overlays/BillboardOverlay.cpp index 8742f19c3d..d88ee6abd2 100644 --- a/interface/src/ui/overlays/BillboardOverlay.cpp +++ b/interface/src/ui/overlays/BillboardOverlay.cpp @@ -14,7 +14,8 @@ #include "BillboardOverlay.h" BillboardOverlay::BillboardOverlay() -: _scale(1.0f), +: _fromImage(-1,-1,-1,-1), + _scale(1.0f), _isFacingAvatar(true) { } @@ -28,6 +29,9 @@ void BillboardOverlay::render() { image = image.convertToFormat(QImage::Format_ARGB32); } _size = image.size(); + if (_fromImage.x() == -1) { + _fromImage.setRect(0, 0, _size.width(), _size.height()); + } _billboardTexture.reset(new Texture()); glBindTexture(GL_TEXTURE_2D, _billboardTexture->getID()); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _size.width(), _size.height(), 0, @@ -58,19 +62,23 @@ void BillboardOverlay::render() { } glScalef(_scale, _scale, _scale); - float maxSize = glm::max(_size.width(), _size.height()); - float x = _size.width() / (2.0f * maxSize); - float y = -_size.height() / (2.0f * maxSize); + float maxSize = glm::max(_fromImage.width(), _fromImage.height()); + float x = _fromImage.width() / (2.0f * maxSize); + float y = -_fromImage.height() / (2.0f * maxSize); glColor3f(1.0f, 1.0f, 1.0f); glBegin(GL_QUADS); { - glTexCoord2f(0.0f, 0.0f); + glTexCoord2f((float)_fromImage.x() / (float)_size.width(), + (float)_fromImage.y() / (float)_size.height()); glVertex2f(-x, -y); - glTexCoord2f(1.0f, 0.0f); + glTexCoord2f(((float)_fromImage.x() + (float)_fromImage.width()) / (float)_size.width(), + (float)_fromImage.y() / (float)_size.height()); glVertex2f(x, -y); - glTexCoord2f(1.0f, 1.0f); + glTexCoord2f(((float)_fromImage.x() + (float)_fromImage.width()) / (float)_size.width(), + ((float)_fromImage.y() + (float)_fromImage.height()) / _size.height()); glVertex2f(x, y); - glTexCoord2f(0.0f, 1.0f); + glTexCoord2f((float)_fromImage.x() / (float)_size.width(), + ((float)_fromImage.y() + (float)_fromImage.height()) / (float)_size.height()); glVertex2f(-x, y); } glEnd(); @@ -93,6 +101,33 @@ void BillboardOverlay::setProperties(const QScriptValue &properties) { setBillboardURL(_url); } + QScriptValue subImageBounds = properties.property("subImage"); + if (subImageBounds.isValid()) { + QRect oldSubImageRect = _fromImage; + QRect subImageRect = _fromImage; + if (subImageBounds.property("x").isValid()) { + subImageRect.setX(subImageBounds.property("x").toVariant().toInt()); + } else { + subImageRect.setX(oldSubImageRect.x()); + } + if (subImageBounds.property("y").isValid()) { + subImageRect.setY(subImageBounds.property("y").toVariant().toInt()); + } else { + subImageRect.setY(oldSubImageRect.y()); + } + if (subImageBounds.property("width").isValid()) { + subImageRect.setWidth(subImageBounds.property("width").toVariant().toInt()); + } else { + subImageRect.setWidth(oldSubImageRect.width()); + } + if (subImageBounds.property("height").isValid()) { + subImageRect.setHeight(subImageBounds.property("height").toVariant().toInt()); + } else { + subImageRect.setHeight(oldSubImageRect.height()); + } + setClipFromSource(subImageRect); + } + QScriptValue scaleValue = properties.property("scale"); if (scaleValue.isValid()) { _scale = scaleValue.toVariant().toFloat(); diff --git a/interface/src/ui/overlays/BillboardOverlay.h b/interface/src/ui/overlays/BillboardOverlay.h index 0037d1a4f7..5efb5767c6 100644 --- a/interface/src/ui/overlays/BillboardOverlay.h +++ b/interface/src/ui/overlays/BillboardOverlay.h @@ -25,7 +25,8 @@ public: virtual void render(); virtual void setProperties(const QScriptValue& properties); - + void setClipFromSource(const QRect& bounds) { _fromImage = bounds; } + private slots: void replyFinished(); @@ -37,6 +38,8 @@ private: QSize _size; QScopedPointer _billboardTexture; + QRect _fromImage; // where from in the image to sample + glm::quat _rotation; float _scale; bool _isFacingAvatar; From a9ceec46270eec7e3b4c56f68bc6442bf969a96a Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 11 Jul 2014 10:50:46 -0700 Subject: [PATCH 29/33] Switched sit.js spheres to billboards --- examples/sit.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/examples/sit.js b/examples/sit.js index f7be681d25..b51d59759a 100644 --- a/examples/sit.js +++ b/examples/sit.js @@ -166,14 +166,16 @@ function SeatIndicator(modelProperties, seatIndex) { modelProperties.sittingPoints[seatIndex].rotation); this.scale = MyAvatar.scale / 12; - this.sphere = Overlays.addOverlay("sphere", { - position: this.position, - size: this.scale, - solid: true, - color: { red: 0, green: 0, blue: 255 }, - alpha: 0.3, - visible: true - }); + this.sphere = Overlays.addOverlay("billboard", { + subImage: { x: 0, y: buttonHeight, width: buttonWidth, height: buttonHeight}, + url: buttonImageUrl, + position: this.position, + scale: this.scale * 4, + solid: true, + color: { red: 0, green: 0, blue: 255 }, + alpha: 0.3, + visible: true + }); this.show = function(doShow) { Overlays.editOverlay(this.sphere, { visible: doShow }); From 22bcb7d7e7040e052f0a386d6b8d5ca9c8384768 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 11 Jul 2014 11:22:06 -0700 Subject: [PATCH 30/33] Billboard overlays disply grey square while image is loading --- .../src/ui/overlays/BillboardOverlay.cpp | 85 ++++++++++--------- 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/interface/src/ui/overlays/BillboardOverlay.cpp b/interface/src/ui/overlays/BillboardOverlay.cpp index d88ee6abd2..4bd854114d 100644 --- a/interface/src/ui/overlays/BillboardOverlay.cpp +++ b/interface/src/ui/overlays/BillboardOverlay.cpp @@ -20,26 +20,25 @@ BillboardOverlay::BillboardOverlay() } void BillboardOverlay::render() { - if (_billboard.isEmpty()) { - return; - } - if (!_billboardTexture) { - QImage image = QImage::fromData(_billboard); - if (image.format() != QImage::Format_ARGB32) { - image = image.convertToFormat(QImage::Format_ARGB32); + if (!_billboard.isEmpty()) { + if (!_billboardTexture) { + QImage image = QImage::fromData(_billboard); + if (image.format() != QImage::Format_ARGB32) { + image = image.convertToFormat(QImage::Format_ARGB32); + } + _size = image.size(); + if (_fromImage.x() == -1) { + _fromImage.setRect(0, 0, _size.width(), _size.height()); + } + _billboardTexture.reset(new Texture()); + glBindTexture(GL_TEXTURE_2D, _billboardTexture->getID()); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _size.width(), _size.height(), 0, + GL_BGRA, GL_UNSIGNED_BYTE, image.constBits()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + } else { + glBindTexture(GL_TEXTURE_2D, _billboardTexture->getID()); } - _size = image.size(); - if (_fromImage.x() == -1) { - _fromImage.setRect(0, 0, _size.width(), _size.height()); - } - _billboardTexture.reset(new Texture()); - glBindTexture(GL_TEXTURE_2D, _billboardTexture->getID()); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _size.width(), _size.height(), 0, - GL_BGRA, GL_UNSIGNED_BYTE, image.constBits()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - } else { - glBindTexture(GL_TEXTURE_2D, _billboardTexture->getID()); } glEnable(GL_ALPHA_TEST); @@ -62,25 +61,35 @@ void BillboardOverlay::render() { } glScalef(_scale, _scale, _scale); - float maxSize = glm::max(_fromImage.width(), _fromImage.height()); - float x = _fromImage.width() / (2.0f * maxSize); - float y = -_fromImage.height() / (2.0f * maxSize); - - glColor3f(1.0f, 1.0f, 1.0f); - glBegin(GL_QUADS); { - glTexCoord2f((float)_fromImage.x() / (float)_size.width(), - (float)_fromImage.y() / (float)_size.height()); - glVertex2f(-x, -y); - glTexCoord2f(((float)_fromImage.x() + (float)_fromImage.width()) / (float)_size.width(), - (float)_fromImage.y() / (float)_size.height()); - glVertex2f(x, -y); - glTexCoord2f(((float)_fromImage.x() + (float)_fromImage.width()) / (float)_size.width(), - ((float)_fromImage.y() + (float)_fromImage.height()) / _size.height()); - glVertex2f(x, y); - glTexCoord2f((float)_fromImage.x() / (float)_size.width(), - ((float)_fromImage.y() + (float)_fromImage.height()) / (float)_size.height()); - glVertex2f(-x, y); - } glEnd(); + if (_billboardTexture) { + float maxSize = glm::max(_fromImage.width(), _fromImage.height()); + float x = _fromImage.width() / (2.0f * maxSize); + float y = -_fromImage.height() / (2.0f * maxSize); + + glColor3f(1.0f, 1.0f, 1.0f); + glBegin(GL_QUADS); { + glTexCoord2f((float)_fromImage.x() / (float)_size.width(), + (float)_fromImage.y() / (float)_size.height()); + glVertex2f(-x, -y); + glTexCoord2f(((float)_fromImage.x() + (float)_fromImage.width()) / (float)_size.width(), + (float)_fromImage.y() / (float)_size.height()); + glVertex2f(x, -y); + glTexCoord2f(((float)_fromImage.x() + (float)_fromImage.width()) / (float)_size.width(), + ((float)_fromImage.y() + (float)_fromImage.height()) / _size.height()); + glVertex2f(x, y); + glTexCoord2f((float)_fromImage.x() / (float)_size.width(), + ((float)_fromImage.y() + (float)_fromImage.height()) / (float)_size.height()); + glVertex2f(-x, y); + } glEnd(); + } else { + glColor4f(0.5f, 0.5f, 0.5f, 1.0f); + glBegin(GL_QUADS); { + glVertex2f(-1.0f, -1.0f); + glVertex2f(1.0f, -1.0f); + glVertex2f(1.0f, 1.0f); + glVertex2f(-1.0f, 1.0f); + } glEnd(); + } } glPopMatrix(); From e067a013a0ee7643f1c2a5a5247a5c0be35aa83f Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 11 Jul 2014 11:22:38 -0700 Subject: [PATCH 31/33] Made sitting point more consistant --- examples/sit.js | 2 +- libraries/models/src/ModelsScriptingInterface.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/sit.js b/examples/sit.js index b51d59759a..c157d4854d 100644 --- a/examples/sit.js +++ b/examples/sit.js @@ -261,7 +261,7 @@ function update(deltaTime){ MyAvatar.position.z != avatarOldPosition.z) { avatarOldPosition = MyAvatar.position; - var SEARCH_RADIUS = 5; + var SEARCH_RADIUS = 10; var foundModels = Models.findModels(MyAvatar.position, SEARCH_RADIUS); // Let's remove indicator that got out of radius for (model in models) { diff --git a/libraries/models/src/ModelsScriptingInterface.cpp b/libraries/models/src/ModelsScriptingInterface.cpp index bac1213071..634039f949 100644 --- a/libraries/models/src/ModelsScriptingInterface.cpp +++ b/libraries/models/src/ModelsScriptingInterface.cpp @@ -69,8 +69,9 @@ ModelItemProperties ModelsScriptingInterface::getModelProperties(ModelItemID mod } if (_modelTree) { _modelTree->lockForRead(); - const ModelItem* model = _modelTree->findModelByID(identity.id, true); + ModelItem* model = const_cast(_modelTree->findModelByID(identity.id, true)); if (model) { + model->setSittingPoints(_modelTree->getGeometryForModel(*model)->sittingPoints); results.copyFromModelItem(*model); } else { results.setIsUnknownID(); From 4c3a1d192e8b4504be67e2575e5756f86c698693 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 11 Jul 2014 11:29:32 -0700 Subject: [PATCH 32/33] fix crash in particle and model server from attempting to edit items that dont exist in the server --- libraries/models/src/ModelItem.cpp | 12 ++++++------ libraries/particles/src/Particle.cpp | 14 ++++++++------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/libraries/models/src/ModelItem.cpp b/libraries/models/src/ModelItem.cpp index 8c061102a0..750af8f1b6 100644 --- a/libraries/models/src/ModelItem.cpp +++ b/libraries/models/src/ModelItem.cpp @@ -331,6 +331,7 @@ ModelItem ModelItem::fromEditPacket(const unsigned char* data, int length, int& newModelItem.setCreatorTokenID(creatorTokenID); newModelItem._newlyCreated = true; + valid = true; } else { // look up the existing modelItem @@ -339,20 +340,19 @@ ModelItem ModelItem::fromEditPacket(const unsigned char* data, int length, int& // copy existing properties before over-writing with new properties if (existingModelItem) { newModelItem = *existingModelItem; + valid = true; } else { // the user attempted to edit a modelItem that doesn't exist - qDebug() << "user attempted to edit a modelItem that doesn't exist..."; + qDebug() << "user attempted to edit a modelItem that doesn't exist... editID=" << editID; + + // NOTE: even though this is a bad editID, we have to consume the edit details, so that + // the buffer doesn't get corrupted for further processing... valid = false; - return newModelItem; } newModelItem._id = editID; newModelItem._newlyCreated = false; } - // if we got this far, then our result will be valid - valid = true; - - // lastEdited memcpy(&newModelItem._lastEdited, dataAt, sizeof(newModelItem._lastEdited)); dataAt += sizeof(newModelItem._lastEdited); diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp index 59265c00dc..4dfe4b588e 100644 --- a/libraries/particles/src/Particle.cpp +++ b/libraries/particles/src/Particle.cpp @@ -385,6 +385,8 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr newParticle._newlyCreated = true; newParticle.setAge(0); // this guy is new! + valid = true; + } else { // look up the existing particle const Particle* existingParticle = tree->findParticleByID(editID, true); @@ -392,20 +394,20 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // copy existing properties before over-writing with new properties if (existingParticle) { newParticle = *existingParticle; + valid = true; + } else { // the user attempted to edit a particle that doesn't exist - qDebug() << "user attempted to edit a particle that doesn't exist..."; + qDebug() << "user attempted to edit a particle that doesn't exist... editID=" << editID; + + // NOTE: even though this is a bad particle ID, we have to consume the edit details, so that + // the buffer doesn't get corrupted for further processing... valid = false; - return newParticle; } newParticle._id = editID; newParticle._newlyCreated = false; } - // if we got this far, then our result will be valid - valid = true; - - // lastEdited memcpy(&newParticle._lastEdited, dataAt, sizeof(newParticle._lastEdited)); dataAt += sizeof(newParticle._lastEdited); From 7ad90ac7bbdb627cecf36565750814c704bfa327 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 11 Jul 2014 11:28:08 -0700 Subject: [PATCH 33/33] When visible is false, don't render billboards/models overlays --- interface/src/ui/overlays/BillboardOverlay.cpp | 4 ++++ interface/src/ui/overlays/ModelOverlay.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/interface/src/ui/overlays/BillboardOverlay.cpp b/interface/src/ui/overlays/BillboardOverlay.cpp index 4bd854114d..e7d5cef3be 100644 --- a/interface/src/ui/overlays/BillboardOverlay.cpp +++ b/interface/src/ui/overlays/BillboardOverlay.cpp @@ -20,6 +20,10 @@ BillboardOverlay::BillboardOverlay() } void BillboardOverlay::render() { + if (!_visible) { + return; + } + if (!_billboard.isEmpty()) { if (!_billboardTexture) { QImage image = QImage::fromData(_billboard); diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index bc0cc720c2..57f098aee3 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -35,6 +35,10 @@ void ModelOverlay::update(float deltatime) { } void ModelOverlay::render() { + if (!_visible) { + return; + } + if (_model.isActive()) { if (_model.isRenderable()) {