From bf2959675fd537ffcbfee9acfa19985baf9395a5 Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Thu, 3 Jul 2014 16:09:54 -0700 Subject: [PATCH] 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); }