void Navigation::scaleAtMouse( const QPoint & mouse , float scale) { const QVector3D ln = m_camera.eye(); const QVector3D lf = m_camera.center(); bool intersects; QVector3D i = mouseRayPlaneIntersection(intersects, mouse); if(!intersects && !NavigationMath::validDepth(m_coordsProvider->depthAt(mouse))) return; // scale the distance between the pointed position in the scene and the // camera position - using ray constraints, the center is scaled appropriately. if (scale > 0.0) scale = 1.0 / (1.0 - scale) - 1.0; // ensure that scaling consistent in both direction // enforceScaleConstraints(scale, i); const QVector3D eye = ln + scale * (ln - i); m_camera.setEye(eye); // the center needs to be constrained to the ground plane, so calc the new // center based on the intersection with the scene and use this to obtain // the new viewray-groundplane intersection as new center. const QVector3D center = lf + scale * (lf - i); m_camera.setCenter(NavigationMath::rayPlaneIntersection(intersects, eye, center)); m_camera.update(); }
void Navigation::panningProcess(const QPoint & mouse) { assert(PanInteraction == m_mode); // The first click of the interaction yields a object space position m_i0. // this point is our constraint for panning, that means for every mouse // position there has to be an appropriate positioning for the scene, so // that the point under the mouse remains m_i0. // With this point and the up normal we build a plane, that defines the // panning space. For panning, a ray is created, pointing from the screen // pixel into the view frustum. This ray then is converted to object space // and used to intersect with the plane at p. // The delta of m_i0 and p is the translation required for panning. // constrain mouse interaction to viewport (if disabled, could lead to mishaps) const QPoint clamped( clamp(0, m_camera.viewport().width(), mouse.x()) , clamp(0, m_camera.viewport().height(), mouse.y())); bool intersects; m_i1 = mouseRayPlaneIntersection(intersects, clamped, m_i0, m_viewProjectionInverted); if (intersects) pan(m_i0 - m_i1); }
void WorldInHandNavigation::scaleAtMouse( const glm::ivec2 & mouse , float scaleDelta) { const glm::vec3 eye = m_cameraCapability.eye(); const glm::vec3 center = m_cameraCapability.center(); bool intersects = false; glm::vec3 intersectPoint = mouseRayPlaneIntersection(intersects, mouse); if (!intersects && !DepthExtractor::isValidDepth(m_coordProvider.depthAt(mouse))) return; // scale the distance between the pointed position in the scene and the // camera position - using ray constraints, the center is scaled appropriately. float scale = glm::clamp(scaleDelta, - 1.f, 1.f); if (scale > 0.f) scale = 1.f / (1.f - scale) - 1.f; // ensure that scaling consistent in both direction // enforceScaleConstraints(scale, i); const glm::vec3 newEye = eye + scale * (intersectPoint - eye); m_cameraCapability.setEye(newEye); // the center needs to be constrained to the ground plane, so calc the new // center based on the intersection with the scene and use this to obtain // the new viewray-groundplane intersection as new center. const glm::vec3 newCenter = center + scale * (intersectPoint - center); m_cameraCapability.setCenter(navigationmath::rayPlaneIntersection(intersects, newEye, newCenter)); }
void WorldInHandNavigation::panProcess(const glm::ivec2 & mouse) { if (PanInteraction != m_mode || !m_refPositionValid) return; // The first click of the interaction yields an object space position m_referencePosition. // this point is our constraint for panning, that means for every mouse // position there has to be an appropriate positioning for the scene, so // that the point under the mouse remains m_referencePosition. // With this point and the up normal we build a plane, that defines the // panning space. For panning, a ray is created, pointing from the screen // pixel into the view frustum. This ray then is converted to object space // and used to intersect with the plane at p. // The delta of m_referencePosition and p is the translation required for panning. // constrain mouse interaction to viewport (if disabled, could lead to mishaps) const glm::ivec2 clamped( glm::clamp(mouse.x, 0, m_viewportCapability.width()), glm::clamp(mouse.y, 0, m_viewportCapability.height())); bool intersects = false; m_modifiedPosition = mouseRayPlaneIntersection(intersects, clamped, m_referencePosition, glm::vec3(0.f, 1.f, 0.f)); if (intersects) pan(m_referencePosition - m_modifiedPosition); }
const QVector3D Navigation::mouseRayPlaneIntersection( bool & intersects , const QPoint & mouse) const { const float depth = m_coordsProvider->depthAt(mouse); // no scene object was picked - simulate picking on xz-plane if (depth >= 1.0 - std::numeric_limits<float>::epsilon()) return mouseRayPlaneIntersection(intersects, mouse, QVector3D()); return m_coordsProvider->objAt(mouse, depth); }
void Navigation::rotatingBegin(const QPoint & mouse) { assert(NoInteraction == m_mode); m_mode = RotateInteraction; bool intersects; m_i0 = mouseRayPlaneIntersection(intersects, mouse); m_i0Valid = intersects && NavigationMath::validDepth(m_coordsProvider->depthAt(mouse)); m_m0 = mouse; m_eye = m_camera.eye(); m_center = m_camera.center(); }
void Navigation::panningBegin(const QPoint & mouse) { assert(NoInteraction == m_mode); m_mode = PanInteraction; m_viewProjectionInverted = m_camera.viewProjectionInverted(); bool intersects; m_i0 = mouseRayPlaneIntersection(intersects, mouse); m_i0Valid = intersects && NavigationMath::validDepth(m_coordsProvider->depthAt(mouse)); m_eye = m_camera.eye(); m_center = m_camera.center(); }
const glm::vec3 WorldInHandNavigation::mouseRayPlaneIntersection( bool & intersects , const glm::ivec2 & mouse) const { const float depth = m_coordProvider.depthAt(mouse); // no scene object was picked - simulate picking on xz-plane if (depth >= 1.0 - std::numeric_limits<float>::epsilon()) // use current center to construct reference plane return mouseRayPlaneIntersection(intersects, mouse, m_cameraCapability.center(), glm::vec3(0.f, 1.f, 0.f)); intersects = true; return m_coordProvider.unproject(mouse, depth); }
void WorldInHandNavigation::rotateBegin(const glm::ivec2 & mouse) { if (NoInteraction != m_mode) return; m_mode = RotateInteraction; bool intersects = false; m_referencePosition = mouseRayPlaneIntersection(intersects, mouse); const float depth = m_coordProvider.depthAt(mouse); m_refPositionValid = intersects && DepthExtractor::isValidDepth(depth); m_m0 = mouse; m_eye = m_cameraCapability.eye(); m_center = m_cameraCapability.center(); }
void WorldInHandNavigation::resetScaleAtMouse(const glm::ivec2 & mouse) { const glm::vec3 ln = m_cameraCapability.eye(); const glm::vec3 lf = m_cameraCapability.center(); // set the distance between pointed position in the scene and camera to // default distance bool intersects = false; glm::vec3 i = mouseRayPlaneIntersection(intersects, mouse); if (!intersects && !DepthExtractor::isValidDepth(m_coordProvider.depthAt(mouse))) return; float scale = (DEFAULT_DISTANCE / static_cast<float>((ln - i).length())); //enforceScaleConstraints(scale, i); m_cameraCapability.setEye(i - scale * (i - ln)); m_cameraCapability.setCenter(i - scale * (i - lf)); }
void Navigation::resetScaleAtMouse(const QPoint & mouse) { const QVector3D ln = m_camera.eye(); const QVector3D lf = m_camera.center(); // set the distance between pointed position in the scene and camera to // default distance bool intersects; QVector3D i = mouseRayPlaneIntersection(intersects, mouse); if (!intersects && !NavigationMath::validDepth(m_coordsProvider->depthAt(mouse))) return; float scale = (DEFAULT_DISTANCE / (ln - i).length()); //enforceScaleConstraints(scale, i); m_camera.setEye(i - scale * (i - ln)); m_camera.setCenter(i - scale * (i - lf)); m_camera.update(); }