glm::mat4 CameraOvr::getOrientation(OVR::Quatf orientationQuat, const OVR::Util::Render::StereoEyeParams& eyeParams) { orientationQuat.GetEulerAngles<OVR::Axis_Y, OVR::Axis_X, OVR::Axis_Z>(&_hmdRy, &_hmdRx, &_hmdRz); OVR::Matrix4f orientation = OVR::Matrix4f::RotationY(_hmdRy+_ry) * OVR::Matrix4f::RotationX(_hmdRx+_rx) * OVR::Matrix4f::RotationZ(_hmdRz+_rz); OVR::Matrix4f view = orientation.Inverted() * eyeParams.ViewAdjust; return ovrToGlmMat4(view); }
/// Scale the parallax translation and head pose motion vector by the head size /// dictated by the shader. Thanks to the elegant design decision of putting the /// head's default position at the origin, this is simple. OVR::Matrix4f _MakeModelviewMatrix( ovrPosef eyePose, ovrVector3f viewAdjust, float chassisYaw, ovrVector3f chassisPos, float headScale=1.0f) { const OVR::Matrix4f eyePoseMatrix = OVR::Matrix4f::Translation(OVR::Vector3f(eyePose.Position) * headScale) * OVR::Matrix4f(OVR::Quatf(eyePose.Orientation)); const OVR::Matrix4f view = OVR::Matrix4f::Translation(OVR::Vector3f(viewAdjust) * headScale) * eyePoseMatrix.Inverted() * OVR::Matrix4f::RotationY(chassisYaw) * OVR::Matrix4f::Translation(-OVR::Vector3f(chassisPos)); return view; }
void OVRScene::timestep(double /*absTime*/, double dt) { (void)dt; if (m_pHmd == NULL) return; const ovrTrackingState ts = ovrHmd_GetTrackingState(m_pHmd, ovr_GetTimeInSeconds()); const ovrVector3f& hp = ts.HeadPose.ThePose.Position; glm::vec4 headPt(hp.x, hp.y, hp.z, 1.0f); // Get camera pose as a matrix const ovrPosef& cp = ts.CameraPose; OVR::Matrix4f camMtx = OVR::Matrix4f(); camMtx *= OVR::Matrix4f::Translation(cp.Position) * OVR::Matrix4f(OVR::Quatf(cp.Orientation)); const glm::mat4 gcamMtx = glm::make_mat4(&camMtx.Inverted().Transposed().M[0][0]); headPt = gcamMtx * headPt; m_tanFromCameraCenterline.x = fabs(headPt.x / headPt.z); m_tanFromCameraCenterline.y = fabs(headPt.y / headPt.z); #if 0 std::vector<glm::vec3> txFrustumPts = m_frustumVerts; for (std::vector<glm::vec3>::const_iterator it = txFrustumPts.begin(); it != txFrustumPts.end(); ++it) { glm::vec3 pt = *it; glm::vec4 pt4(pt, 1.0f); pt4 = gcamMtx * pt4; pt.x = pt4.x; pt.y = pt4.y; pt.z = pt4.z; } // Calculate minimum distance to frustum std::vector<glm::ivec3> planeIndices; planeIndices.push_back(glm::ivec3(2, 3, 4)); planeIndices.push_back(glm::ivec3(8, 7, 6)); planeIndices.push_back(glm::ivec3(2, 3, 7)); planeIndices.push_back(glm::ivec3(3, 4, 8)); planeIndices.push_back(glm::ivec3(4, 5, 9)); planeIndices.push_back(glm::ivec3(5, 2, 6)); float minDist = 999.0f; for (std::vector<glm::ivec3>::const_iterator it = planeIndices.begin(); it != planeIndices.end(); ++it) { const glm::ivec3& idxs = *it; // Assume this point has already been transformed // If our indices are out of bounds, we're hosed const glm::vec3& p1 = txFrustumPts[idxs.x]; const glm::vec3& p2 = txFrustumPts[idxs.y]; const glm::vec3& p3 = txFrustumPts[idxs.z]; const glm::vec3 v1 = p1 - p2; const glm::vec3 v2 = p3 - p2; const glm::vec3 norm = glm::normalize(glm::cross(v1, v2)); const glm::vec3 ptDist = headPt - p2; const float dist = fabs(glm::dot(norm, ptDist)); // shouldn't need fabs if ordering is correct minDist = std::min(minDist, dist); } m_distanceToFrustum = minDist; #endif }