//Caculate the click location using one of the sixense controllers. Scale is not applied QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { Application* application = Application::getInstance(); GLCanvas* glWidget = application->getGLWidget(); MyAvatar* myAvatar = application->getAvatar(); glm::vec3 tip = myAvatar->getLaserPointerTipPosition(palm); glm::vec3 eyePos = myAvatar->getHead()->getEyePosition(); glm::quat invOrientation = glm::inverse(myAvatar->getOrientation()); //direction of ray goes towards camera glm::vec3 dir = invOrientation * glm::normalize(application->getCamera()->getPosition() - tip); glm::vec3 tipPos = invOrientation * (tip - eyePos); QPoint rv; if (OculusManager::isConnected()) { float 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, _oculusUIRadius * myAvatar->getScale(), &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); rv.setY(INT_MAX); } else { 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); } } else { glm::dmat4 projection; application->getProjectionMatrix(&projection); glm::vec4 clipSpacePos = glm::vec4(projection * glm::dvec4(tipPos, 1.0)); glm::vec3 ndcSpacePos; if (clipSpacePos.w != 0) { ndcSpacePos = glm::vec3(clipSpacePos) / clipSpacePos.w; } rv.setX(((ndcSpacePos.x + 1.0) / 2.0) * glWidget->width()); rv.setY((1.0 - ((ndcSpacePos.y + 1.0) / 2.0)) * glWidget->height()); } return rv; }
ngl::Real SphericalObstacle::findPossibleCollisionPoint(const MovingObject* _object, ngl::Vec4& o_iPoint, ngl::Vec4& o_iNormal) const { ngl::Real distSqr = std::numeric_limits<ngl::Real>::max(); ngl::Vec4 rPos =_object->getPosition(); ngl::Vec4 rDir = _object->getHeadingDir(); ngl::Vec4 sPos = this->getPosition(); ngl::Real sInflatedRadius = this->getBoundingRadius() + _object->getBoundingRadius(); distSqr = raySphereIntersect(rPos, rDir, sPos, sInflatedRadius, o_iPoint, o_iNormal); return distSqr; }
//Finds the collision point of a world space ray bool ApplicationCompositor::calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const { MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar(); glm::quat inverseOrientation = glm::inverse(myAvatar->getOrientation()); glm::vec3 relativePosition = inverseOrientation * (position - myAvatar->getDefaultEyePosition()); glm::vec3 relativeDirection = glm::normalize(inverseOrientation * direction); float t; if (raySphereIntersect(relativeDirection, relativePosition, _oculusUIRadius * myAvatar->getScale(), &t)){ result = position + direction * t; return true; } return false; }
//Finds the collision point of a world space ray bool CompositorHelper::calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const { auto UITransform = getUiTransform(); auto relativePosition4 = glm::inverse(UITransform) * vec4(position, 1); auto relativePosition = vec3(relativePosition4) / relativePosition4.w; auto relativeDirection = glm::inverse(glm::quat_cast(UITransform)) * direction; float uiRadius = _hmdUIRadius; // * myAvatar->getUniformScale(); // FIXME - how do we want to handle avatar scale float instersectionDistance; if (raySphereIntersect(relativeDirection, relativePosition, uiRadius, &instersectionDistance)){ result = position + glm::normalize(direction) * instersectionDistance; return true; } return false; }
//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(); glm::quat orientation = myAvatar->getOrientation(); glm::vec3 relativePosition = orientation * (position - myAvatar->getDefaultEyePosition()); glm::vec3 relativeDirection = orientation * direction; float t; if (raySphereIntersect(relativeDirection, relativePosition, _oculusUIRadius * myAvatar->getScale(), &t)){ result = position + direction * t; return true; } return false; }
/* If something is hit, returns the finite intersection point p, the normal vector n to the surface at that point, and the surface material m. If no hit, returns an infinite point (p->w = 0.0) */ void firstHit(ray* r, point* p, vector* n, material* *m) { int i; int index; int flag_cyl, flag_hyp; double t = 0; /* parameter value at first hit */ int hit = FALSE; //SURFACE_TYPE objects[objnum] = { PLAIN, SPHERE, SPHERE, SPHERE, CYLINDER, HYPERBOLOID }; int hits[objnum] = { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }; double tvalues[objnum] = { -1.0, -1.0, -1.0, -1.0, -1.0, -1.0 }; for (i = 0; i < objnum; ++i) { switch (i) { case 0: hits[i] = rayPlainIntersect(r,pln1,&tvalues[i]); if (hits[i]) { index = i; hit = TRUE; } break; case 1: hits[i] = raySphereIntersect(r,sph0,&tvalues[i]); if (hits[i]) { index = i; hit = TRUE; } break; case 2: hits[i] = raySphereIntersect(r,sph1,&tvalues[i]); if (hits[i]) { index = i; hit = TRUE; } break; case 3: hits[i] = raySphereIntersect(r,sph2,&tvalues[i]); if (hits[i]) { index = i; hit = TRUE; } break; case 4: hits[i] = rayCylinderIntersect(r,cyl0,&tvalues[i],&flag_cyl); if (hits[i]) { index = i; hit = TRUE; } break; case 5: hits[i] = rayHyperbolIntersect(r,hyp0,&tvalues[i],&flag_hyp); if (hits[i]) { index = i; hit = TRUE; } break; default: break; } } if ( hit ) { findMin(tvalues, objnum, &t, &index); findPointOnRay(r, t, p); switch (index) { case 0: *m = pln1->m; findPlainNormal(pln1,p,n); break; case 1: *m = sph0->m; findSphereNormal(sph0,p,n); break; case 2: *m = sph1->m; findSphereNormal(sph1,p,n); break; case 3: *m = sph2->m; findSphereNormal(sph2,p,n); break; case 4: *m = cyl0->m; findCylinderNormal(cyl0,p,n,flag_cyl); break; case 5: *m = hyp0->m; findHyperbolNormal(hyp0,p,n,flag_hyp); break; default: break; } } else { /* no hit */ p->w = 0.0; } }