From 6797174b97ffd3e0cb81ca8d06228b874985da9c Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 14 May 2015 19:15:47 -0700 Subject: [PATCH 1/3] Fix picking in the HMD --- interface/src/Application.cpp | 25 +++++++-------- interface/src/ui/ApplicationOverlay.cpp | 42 ++++++++++++++++++------- interface/src/ui/ApplicationOverlay.h | 2 +- 3 files changed, 42 insertions(+), 27 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 20c93a7ae5..6665e71642 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3077,13 +3077,10 @@ PickRay Application::computePickRay(float x, float y) const { y /= size.y; PickRay result; if (isHMDMode()) { - ApplicationOverlay::computeHmdPickRay(glm::vec2(x, y), result.origin, result.direction); + getApplicationOverlay().computeHmdPickRay(glm::vec2(x, y), result.origin, result.direction); } else { - if (activeRenderingThread) { - getDisplayViewFrustum()->computePickRay(x, y, result.origin, result.direction); - } else { - getViewFrustum()->computePickRay(x, y, result.origin, result.direction); - } + auto frustum = activeRenderingThread ? getDisplayViewFrustum() : getViewFrustum(); + frustum->computePickRay(x, y, result.origin, result.direction); } return result; } @@ -3111,8 +3108,8 @@ QImage Application::renderAvatarBillboard() { ViewFrustum* Application::getViewFrustum() { #ifdef DEBUG if (QThread::currentThread() == activeRenderingThread) { - // FIXME, should this be an assert? - qWarning() << "Calling Application::getViewFrustum() from the active rendering thread, did you mean Application::getDisplayViewFrustum()?"; + // FIXME, figure out a better way to do this + //qWarning() << "Calling Application::getViewFrustum() from the active rendering thread, did you mean Application::getDisplayViewFrustum()?"; } #endif return &_viewFrustum; @@ -3121,8 +3118,8 @@ ViewFrustum* Application::getViewFrustum() { const ViewFrustum* Application::getViewFrustum() const { #ifdef DEBUG if (QThread::currentThread() == activeRenderingThread) { - // FIXME, should this be an assert? - qWarning() << "Calling Application::getViewFrustum() from the active rendering thread, did you mean Application::getDisplayViewFrustum()?"; + // FIXME, figure out a better way to do this + //qWarning() << "Calling Application::getViewFrustum() from the active rendering thread, did you mean Application::getDisplayViewFrustum()?"; } #endif return &_viewFrustum; @@ -3131,8 +3128,8 @@ const ViewFrustum* Application::getViewFrustum() const { ViewFrustum* Application::getDisplayViewFrustum() { #ifdef DEBUG if (QThread::currentThread() != activeRenderingThread) { - // FIXME, should this be an assert? - qWarning() << "Calling Application::getDisplayViewFrustum() from outside the active rendering thread or outside rendering, did you mean Application::getViewFrustum()?"; + // FIXME, figure out a better way to do this + // qWarning() << "Calling Application::getDisplayViewFrustum() from outside the active rendering thread or outside rendering, did you mean Application::getViewFrustum()?"; } #endif return &_displayViewFrustum; @@ -3141,8 +3138,8 @@ ViewFrustum* Application::getDisplayViewFrustum() { const ViewFrustum* Application::getDisplayViewFrustum() const { #ifdef DEBUG if (QThread::currentThread() != activeRenderingThread) { - // FIXME, should this be an assert? - qWarning() << "Calling Application::getDisplayViewFrustum() from outside the active rendering thread or outside rendering, did you mean Application::getViewFrustum()?"; + // FIXME, figure out a better way to do this + // qWarning() << "Calling Application::getDisplayViewFrustum() from outside the active rendering thread or outside rendering, did you mean Application::getViewFrustum()?"; } #endif return &_displayViewFrustum; diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index b65e75923e..e3f9216c13 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -301,9 +301,14 @@ void ApplicationOverlay::displayOverlayTextureHmd(Camera& whichCamera) { //Update and draw the magnifiers MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); const glm::quat& orientation = myAvatar->getOrientation(); - const glm::vec3& position = myAvatar->getDefaultEyePosition(); + // Always display the HMD overlay relative to the camera position but + // remove the HMD pose offset. This results in an overlay that sticks with you + // even in third person mode, but isn't drawn at a fixed distance. + glm::vec3 position = whichCamera.getPosition(); + position -= qApp->getCamera()->getHmdPosition(); const float scale = myAvatar->getScale() * _oculusUIRadius; +// glm::vec3 eyeOffset = setEyeOffsetPosition; glMatrixMode(GL_MODELVIEW); glPushMatrix(); { glTranslatef(position.x, position.y, position.z); @@ -453,19 +458,32 @@ void ApplicationOverlay::displayOverlayTextureStereo(Camera& whichCamera, float glEnable(GL_LIGHTING); } -void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) { - const MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); - cursorPos = 0.5f - cursorPos; - cursorPos *= MOUSE_RANGE; - const glm::quat orientation(glm::vec3(cursorPos, 0.0f)); - const glm::vec3 localDirection = orientation * IDENTITY_FRONT; +void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const { + cursorPos *= qApp->getCanvasSize(); + const glm::vec2 projection = screenToSpherical(cursorPos); + // The overlay space orientation of the mouse coordinates + const glm::quat orientation(glm::vec3(-projection.y, projection.x, 0.0f)); + // FIXME We now have the direction of the ray FROM THE DEFAULT HEAD POSE. + // Now we need to account for the actual camera position relative to the overlay + glm::vec3 overlaySpaceDirection = glm::normalize(orientation * IDENTITY_FRONT); - // Get cursor position - const glm::vec3 cursorDir = myAvatar->getDefaultEyePosition() + myAvatar->getOrientation() * localDirection; - // Ray start where the eye position is and stop where the cursor is - origin = myAvatar->getEyePosition(); - direction = cursorDir - origin; + const glm::vec3& hmdPosition = qApp->getCamera()->getHmdPosition(); + const glm::quat& hmdOrientation = qApp->getCamera()->getHmdRotation(); + + // We need the RAW camera orientation and position, because this is what the overlay is + // rendered relative to + const glm::vec3 overlayPosition = qApp->getCamera()->getPosition() - hmdPosition; + const glm::quat overlayOrientation = qApp->getCamera()->getRotation() * glm::inverse(hmdOrientation); + + // Intersection UI overlay space + glm::vec3 worldSpaceDirection = overlayOrientation * overlaySpaceDirection; + glm::vec3 intersectionWithUi = glm::normalize(worldSpaceDirection) * _oculusUIRadius; + intersectionWithUi += overlayPosition; + + // Intersection in world space + origin = overlayPosition + hmdPosition; + direction = glm::normalize(intersectionWithUi - origin); } //Caculate the click location using one of the sixense controllers. Scale is not applied diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index 62bbfa2747..34beb98682 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -58,12 +58,12 @@ public: glm::vec2 overlayToSpherical(const glm::vec2 & overlayPos) const; glm::vec2 screenToOverlay(const glm::vec2 & screenPos) const; glm::vec2 overlayToScreen(const glm::vec2 & overlayPos) const; + void computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const; static glm::vec2 directionToSpherical(const glm::vec3 & direction); static glm::vec3 sphericalToDirection(const glm::vec2 & sphericalPos); static glm::vec2 screenToSpherical(const glm::vec2 & screenPos); static glm::vec2 sphericalToScreen(const glm::vec2 & sphericalPos); - static void computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction); private: // Interleaved vertex data From bb3d1a6a58031344a1332aa84bc1736f27499d40 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 15 May 2015 13:10:16 -0700 Subject: [PATCH 2/3] rays never pick a line entity. some fixes to pointer.js --- examples/pointer.js | 35 ++++++++++++++----------- libraries/entities/src/LineEntityItem.h | 6 +++++ 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/examples/pointer.js b/examples/pointer.js index 2d7b601baa..d4348e19aa 100644 --- a/examples/pointer.js +++ b/examples/pointer.js @@ -24,23 +24,28 @@ function removeLine() { function createOrUpdateLine(event) { var pickRay = Camera.computePickRay(event.x, event.y); var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking + var props = Entities.getEntityProperties(intersection.entityID); - if (lineIsRezzed) { - Entities.editEntity(lineEntityID, { - position: nearLinePoint(intersection.intersection), - dimensions: Vec3.subtract(intersection.intersection, nearLinePoint(intersection.intersection)), - lifetime: 30 // renew lifetime - }); - + if (intersection.intersects) { + var dim = Vec3.subtract(intersection.intersection, nearLinePoint(intersection.intersection)); + if (lineIsRezzed) { + Entities.editEntity(lineEntityID, { + position: nearLinePoint(intersection.intersection), + dimensions: dim, + lifetime: 60 + props.lifespan // renew lifetime + }); + } else { + lineIsRezzed = true; + lineEntityID = Entities.addEntity({ + type: "Line", + position: nearLinePoint(intersection.intersection), + dimensions: dim, + color: { red: 255, green: 255, blue: 255 }, + lifetime: 60 // if someone crashes while pointing, don't leave the line there forever. + }); + } } else { - lineIsRezzed = true; - lineEntityID = Entities.addEntity({ - type: "Line", - position: nearLinePoint(intersection.intersection), - dimensions: Vec3.subtract(intersection.intersection, nearLinePoint(intersection.intersection)), - color: { red: 255, green: 255, blue: 255 }, - lifetime: 30 // if someone crashes while pointing, don't leave the line there forever. - }); + removeLine(); } } diff --git a/libraries/entities/src/LineEntityItem.h b/libraries/entities/src/LineEntityItem.h index a834fee816..a8bc867bdd 100644 --- a/libraries/entities/src/LineEntityItem.h +++ b/libraries/entities/src/LineEntityItem.h @@ -53,6 +53,12 @@ class LineEntityItem : public EntityItem { virtual ShapeType getShapeType() const { return SHAPE_TYPE_LINE; } + // never have a ray intersection pick a LineEntityItem. + virtual bool supportsDetailedRayIntersection() const { return true; } + virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + void** intersectedObject, bool precisionPicking) const { return false; } + virtual void debugDump() const; protected: From cb0112e14e6edad17133d407dd8f60a06c028e35 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Fri, 15 May 2015 13:21:58 -0700 Subject: [PATCH 3/3] remove line pointers from grab and hockey grab --- examples/example/games/grabHockey.js | 19 ++----------------- examples/grab.js | 16 ---------------- 2 files changed, 2 insertions(+), 33 deletions(-) diff --git a/examples/example/games/grabHockey.js b/examples/example/games/grabHockey.js index 31597ba32d..5e101e1d48 100644 --- a/examples/example/games/grabHockey.js +++ b/examples/example/games/grabHockey.js @@ -13,7 +13,6 @@ var isGrabbing = false; var grabbedEntity = null; -var lineEntityID = null; var prevMouse = {}; var deltaMouse = { z: 0 @@ -39,9 +38,9 @@ var angularVelocity = { var grabSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/CloseClamp.wav"); var releaseSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/ReleaseClamp.wav"); -var VOLUME = 0.10; +var VOLUME = 0.0; -var DROP_DISTANCE = 5.0; +var DROP_DISTANCE = 0.10; var DROP_COLOR = { red: 200, green: 200, @@ -92,14 +91,6 @@ function mousePressEvent(event) { gravity: {x: 0, y: 0, z: 0} }); - lineEntityID = Entities.addEntity({ - type: "Line", - position: nearLinePoint(targetPosition), - dimensions: Vec3.subtract(targetPosition, nearLinePoint(targetPosition)), - color: { red: 255, green: 255, blue: 255 }, - lifetime: 300 // if someone crashes while moving something, don't leave the line there forever. - }); - Audio.playSound(grabSound, { position: props.position, volume: VOLUME @@ -145,8 +136,6 @@ function mouseReleaseEvent() { }); targetPosition = null; - Entities.deleteEntity(lineEntityID); - Audio.playSound(releaseSound, { position: entityProps.position, volume: VOLUME @@ -193,10 +182,6 @@ function mouseMoveEvent(event) { angularVelocity = Vec3.multiply((theta / dT), axisAngle); } - Entities.editEntity(lineEntityID, { - position: nearLinePoint(targetPosition), - dimensions: Vec3.subtract(targetPosition, nearLinePoint(targetPosition)) - }); } prevMouse.x = event.x; prevMouse.y = event.y; diff --git a/examples/grab.js b/examples/grab.js index 019ec2320f..f1e1b6571c 100644 --- a/examples/grab.js +++ b/examples/grab.js @@ -13,7 +13,6 @@ var isGrabbing = false; var grabbedEntity = null; -var lineEntityID = null; var prevMouse = {}; var deltaMouse = { z: 0 @@ -91,14 +90,6 @@ function mousePressEvent(event) { gravity: {x: 0, y: 0, z: 0} }); - lineEntityID = Entities.addEntity({ - type: "Line", - position: nearLinePoint(targetPosition), - dimensions: Vec3.subtract(targetPosition, nearLinePoint(targetPosition)), - color: { red: 255, green: 255, blue: 255 }, - lifetime: 300 // if someone crashes while moving something, don't leave the line there forever. - }); - Audio.playSound(grabSound, { position: props.position, volume: 0.4 @@ -144,8 +135,6 @@ function mouseReleaseEvent() { }); targetPosition = null; - Entities.deleteEntity(lineEntityID); - Audio.playSound(grabSound, { position: entityProps.position, volume: 0.25 @@ -191,11 +180,6 @@ function mouseMoveEvent(event) { axisAngle = Quat.axis(dQ); angularVelocity = Vec3.multiply((theta / dT), axisAngle); } - - Entities.editEntity(lineEntityID, { - position: nearLinePoint(targetPosition), - dimensions: Vec3.subtract(targetPosition, nearLinePoint(targetPosition)) - }); } prevMouse.x = event.x; prevMouse.y = event.y;