///@param [out] planePt Intersection point on plane in local normalized coordinates ///@return true if ray hits pane quad, false otherwise bool Pane::GetPaneRayIntersectionCoordinates( glm::vec3 origin3, ///< [in] Ray origin glm::vec3 dir3, ///< [in] Ray direction(normalized) glm::vec2& planePtOut, ///< [out] Intersection point in XY plane coordinates float& tParamOut) ///< [out] t parameter of ray intersection (ro + t*dt) { if (m_visible == false) return false; const std::vector<glm::vec3> pts = GetTransformedPanePoints(); glm::vec3 retval1(0.0f); glm::vec3 retval2(0.0f); const bool hit1 = glm::intersectLineTriangle(origin3, dir3, pts[0], pts[1], pts[2], retval1); const bool hit2 = glm::intersectLineTriangle(origin3, dir3, pts[0], pts[2], pts[3], retval2); if ( !(hit1||hit2) ) return false; glm::vec3 hitval(0.0f); glm::vec3 cartesianpos(0.0f); if (hit1) { hitval = retval1; // At this point, retval1 or retval2 contains hit data returned from glm::intersectLineTriangle. // This does not appear to be raw - y and z appear to be barycentric coordinates. // Fill out the x coord with the barycentric identity then convert using simple weighted sum. cartesianpos = (1.0f - hitval.y - hitval.z) * pts[0] + hitval.y * pts[1] + hitval.z * pts[2]; } else if (hit2) { hitval = retval2; cartesianpos = (1.0f - hitval.y - hitval.z) * pts[0] + hitval.y * pts[2] + hitval.z * pts[3]; } // Store the t param along controller ray of the hit in the Transformation // Did you know that x stores the t param val? I couldn't find this in docs anywhere. const float tParam = hitval.x; m_tx.m_controllerTParamAtClick = tParam; tParamOut = tParam; if (tParam < 0.0f) return false; // Behind the origin const glm::vec3 v1 = pts[1] - pts[0]; // x axis const glm::vec3 v2 = pts[3] - pts[0]; // y axis const float len = glm::length(v1); // v2 length should be equal const glm::vec3 vh = (cartesianpos - pts[0]) / len; planePtOut = glm::vec2( glm::dot(v1/len, vh), 1.0f - glm::dot(v2/len, vh) // y coord flipped by convention ); return true; }
///@param [out] planePt Intersection point on plane in local normalized coordinates ///@return true if ray hits pane quad, false otherwise bool Pane::GetPaneRayIntersectionCoordinates(glm::vec3 origin3, glm::vec3 dir3, glm::vec2& planePt) { std::vector<glm::vec3> pts = GetTransformedPanePoints(); glm::vec3 retval1(0.0f); glm::vec3 retval2(0.0f); const bool hit1 = glm::intersectLineTriangle(origin3, dir3, pts[0], pts[1], pts[2], retval1); const bool hit2 = glm::intersectLineTriangle(origin3, dir3, pts[0], pts[2], pts[3], retval2); if ( !(hit1||hit2) ) return false; glm::vec3 hitval(0.0f); glm::vec3 cartesianpos(0.0f); if (hit1) { hitval = retval1; // At this point, retval1 or retval2 contains hit data returned from glm::intersectLineTriangle. // This does not appear to be raw - y and z appear to be barycentric coordinates. // Fill out the x coord with the barycentric identity then convert using simple weighted sum. hitval.x = 1.0f - hitval.y - hitval.z; cartesianpos = hitval.x * pts[0] + hitval.y * pts[1] + hitval.z * pts[2]; } else if (hit2) { hitval = retval2; hitval.x = 1.0f - hitval.y - hitval.z; cartesianpos = hitval.x * pts[0] + hitval.y * pts[2] + hitval.z * pts[3]; } // Store the t param along controller ray of the hit in the Transformation if (m_tx.m_controllerTParamAtClick <= 0.0f) { const glm::vec3 originToHitPt = cartesianpos - origin3; const float tParam = glm::length(originToHitPt); m_tx.m_controllerTParamAtClick = tParam; } const glm::vec3 v1 = pts[1] - pts[0]; // x axis const glm::vec3 v2 = pts[3] - pts[0]; // y axis const float len = glm::length(v1); // v2 length should be equal const glm::vec3 vh = (cartesianpos - pts[0]) / len; planePt = glm::vec2( glm::dot(v1/len, vh), 1.0f - glm::dot(v2/len, vh) // y coord flipped by convention ); return true; }
// Check for hits against floor plane bool Scene::RayIntersects( const float* pRayOrigin, const float* pRayDirection, float* pTParameter, // [inout] float* pHitLocation, // [inout] float* pHitNormal // [inout] ) const { const glm::vec3 origin3 = glm::make_vec3(pRayOrigin); const glm::vec3 dir3 = glm::make_vec3(pRayDirection); const glm::vec3 minPt(-10.f, 0.f, -10.f); const glm::vec3 maxPt( 10.f, 0.f, 10.f); std::vector<glm::vec3> pts; pts.push_back(glm::vec3(minPt.x, minPt.y, minPt.z)); pts.push_back(glm::vec3(minPt.x, minPt.y, maxPt.z)); pts.push_back(glm::vec3(maxPt.x, minPt.y, maxPt.z)); pts.push_back(glm::vec3(maxPt.x, minPt.y, minPt.z)); glm::vec3 retval1(0.0f); glm::vec3 retval2(0.0f); const bool hit1 = glm::intersectLineTriangle(origin3, dir3, pts[0], pts[1], pts[2], retval1); const bool hit2 = glm::intersectLineTriangle(origin3, dir3, pts[0], pts[2], pts[3], retval2); if ( !(hit1||hit2) ) return false; glm::vec3 cartesianpos(0.f); if (hit1) { // At this point, retval1 or retval2 contains hit data returned from glm::intersectLineTriangle. // This does not appear to be raw - y and z appear to be barycentric coordinates. // X coordinate of retval1 appears to be the t parameter of the intersection point along dir3. // Fill out the x coord with the barycentric identity then convert using simple weighted sum. if (retval1.x < 0.f) // Hit behind origin return false; *pTParameter = retval1.x; const float bary_x = 1.f - retval1.y - retval1.z; cartesianpos = bary_x * pts[0] + retval1.y * pts[1] + retval1.z * pts[2]; } else if (hit2) { if (retval2.x < 0.f) // Hit behind origin return false; *pTParameter = retval2.x; const float bary_x = 1.f - retval2.y - retval2.z; cartesianpos = bary_x * pts[0] + retval2.y * pts[2] + retval2.z * pts[3]; } const glm::vec3 hitPos = origin3 + *pTParameter * dir3; pHitLocation[0] = hitPos.x; pHitLocation[1] = hitPos.y; pHitLocation[2] = hitPos.z; pHitNormal[0] = 0.f; pHitNormal[1] = 1.f; pHitNormal[2] = 0.f; return true; }
///@param [out] planePtOut Intersection point on plane in local normalized coordinates ///@param [out] tParamOut T parameter value along intersection ray ///@return true if ray hits pane quad, false otherwise bool HudQuad::GetPaneRayIntersectionCoordinates( const glm::mat4& quadPoseMatrix, ///< [in] Quad's pose in world space glm::vec3 origin3, ///< [in] Ray origin glm::vec3 dir3, ///< [in] Ray direction(normalized) glm::vec2& planePtOut, ///< [out] Intersection point in XY plane coordinates float& tParamOut) ///< [out] t parameter of ray intersection (ro + t*dt) { if (m_showQuadInWorld == false) return false; // Standard Oculus quad layer coordinates glm::vec3 pts[] = { glm::vec3(-.5f*m_quadSize.x, -.5f*m_quadSize.y, 0.f), glm::vec3( .5f*m_quadSize.x, -.5f*m_quadSize.y, 0.f), glm::vec3( .5f*m_quadSize.x, .5f*m_quadSize.y, 0.f), glm::vec3(-.5f*m_quadSize.x, .5f*m_quadSize.y, 0.f), }; for (int i = 0; i < 4; ++i) { glm::vec4 p4 = glm::vec4(pts[i], 1.f); p4 = quadPoseMatrix * p4; pts[i] = glm::vec3(p4); } glm::vec3 retval1(0.f); glm::vec3 retval2(0.f); const bool hit1 = glm::intersectLineTriangle(origin3, dir3, pts[0], pts[1], pts[2], retval1); const bool hit2 = glm::intersectLineTriangle(origin3, dir3, pts[0], pts[2], pts[3], retval2); if (!(hit1 || hit2)) return false; glm::vec3 hitval(0.f); glm::vec3 cartesianpos(0.f); if (hit1) { hitval = retval1; // At this point, retval1 or retval2 contains hit data returned from glm::intersectLineTriangle. // This does not appear to be raw - y and z appear to be barycentric coordinates. // Fill out the x coord with the barycentric identity then convert using simple weighted sum. cartesianpos = (1.f - hitval.y - hitval.z) * pts[0] + hitval.y * pts[1] + hitval.z * pts[2]; } else if (hit2) { hitval = retval2; cartesianpos = (1.f - hitval.y - hitval.z) * pts[0] + hitval.y * pts[2] + hitval.z * pts[3]; } // Store the t param along controller ray of the hit in the Transformation // Did you know that x stores the t param val? I couldn't find this in docs anywhere. const float tParam = hitval.x; tParamOut = tParam; if (tParam < 0.f) return false; // Behind the origin const glm::vec3 v1 = pts[1] - pts[0]; // x axis const glm::vec3 v2 = pts[3] - pts[0]; // y axis const float len = glm::length(v1); // v2 length should be equal const glm::vec3 vh = (cartesianpos - pts[0]) / len; planePtOut = glm::vec2( glm::dot(v1 / len, vh), 1.f - glm::dot(v2 / len, vh) // y coord flipped by convention ); return true; }