osg::Vec3d ViewingCore::findDeltaOnPanPlane(double ndcX1, double ndcY1, double ndcX2, double ndcY2) { // Get the view volume far plane value, and the distance from // the near to far plane. double zNear, zFar; osg::Matrixd p = computeProjection(); if( getOrtho() ) { double l, r, b, t; p.getOrtho( l, r, b, t, zNear, zFar ); } else { double fovy, aspect; p.getPerspective( fovy, aspect, zNear, zFar ); } const double distance = zFar - zNear; // Create two points, both in NDC space, and lying on the far plane at the back // of the view volume. One is the xy origin, the other with the passed xy parameters. osg::Vec4d farPoint0 = osg::Vec4d( ndcX1, ndcY1, 1., 1. ); osg::Vec4d farPoint1 = osg::Vec4d( ndcX2, ndcY2, 1., 1. ); if( !getOrtho() ) { // Not ortho, so w != 1.0. Multiply by the far plane distance. // This yields values in clip coordinates. farPoint0 *= zFar; farPoint1 *= zFar; } // Get inverse view & proj matrices to back-transform the // two clip coord far points into world space. osg::Matrixd v = getMatrix(); p.invert( p ); osg::Vec4d wc0 = farPoint0 * p * v; osg::Vec4d wc1 = farPoint1 * p * v; // Intersect the two world coord points with the pan plane. osg::Vec3d result0, result1; osg::Vec3d p1( wc0.x(), wc0.y(), wc0.z() ); osg::Vec3d p0 = getOrtho() ? p1 - ( _viewDir * distance ) : getEyePosition(); intersectPlaneRay( result0, _panPlane, p0, p1 ); p1 = osg::Vec3d( wc1.x(), wc1.y(), wc1.z() ); p0 = getOrtho() ? p1 - ( _viewDir * distance ) : getEyePosition(); intersectPlaneRay( result1, _panPlane, p0, p1 ); // Subtract the two plane intersection points to get the delta world coord // motion return return result1 - result0; }
void ViewingCore::pan( const double ndcX, const double ndcY ) { // Get the view volume far plane value, and the distance from // the near to far plane. double zNear, zFar; osg::Matrixd p; getZNearZFarProj(zNear, zFar, p); const double distance = zFar - zNear; // Create two points, both in NDC space, and lying on the far plane at the back // of the view volume. One is the xy origin, the other with the passed xy parameters. osg::Vec4d farPoint0 = osg::Vec4d( 0., 0., 1., 1. ); osg::Vec4d farPoint1 = osg::Vec4d( ndcX, ndcY, 1., 1. ); if( !getOrtho() ) { // Not ortho, so w != 1.0. Multiply by the far plane distance. // This yields values in clip coordinates. farPoint0 *= zFar; farPoint1 *= zFar; } // Get inverse view & proj matrices to back-transform the // two clip coord far points into world space. osg::Matrixd v = getMatrix(); p.invert( p ); osg::Vec4d wc0 = farPoint0 * p * v; osg::Vec4d wc1 = farPoint1 * p * v; // Intersect the two world coord points with the pan plane. osg::Vec3d result0, result1; osg::Vec3d p1( wc0.x(), wc0.y(), wc0.z() ); osg::Vec3d p0 = getOrtho() ? p1 - ( _viewDir * distance ) : getEyePosition(); intersectPlaneRay( result0, _panPlane, p0, p1 ); p1 = osg::Vec3d( wc1.x(), wc1.y(), wc1.z() ); p0 = getOrtho() ? p1 - ( _viewDir * distance ) : getEyePosition(); intersectPlaneRay( result1, _panPlane, p0, p1 ); // Subtract the two plane intersection points to get the delta world coord // motion and move the view center accordingly. osg::Vec3d delta = result1 - result0; osg::notify( osg::DEBUG_FP ) << " delta " << delta << std::endl; _viewCenter -= delta; }
bool calcDistToLine(const Ray3f &lineSegmentRay, const Ray3f &ray, float32 &distQuad, float32 &rayParam, float32 &lineSegParam) { Vector3f distNormal = lineSegmentRay.direction.crossProduct(ray.direction); if (distNormal*distNormal < EPSILON * EPSILON) return false; Vector3f planeRayNormal = ray.direction.crossProduct(distNormal); bool iFound = intersectPlaneRay(lineSegmentRay, planeRayNormal, ray.origin, lineSegParam); if (!iFound || lineSegParam < 0 || lineSegParam > 1) { return false; } Vector3f planeLineSegNormal = lineSegmentRay.direction.crossProduct(distNormal); iFound = intersectPlaneRay(ray, planeLineSegNormal, lineSegmentRay.origin, rayParam); if (iFound) { Vector3f dist = lineSegmentRay.origin + lineSegmentRay.direction * lineSegParam - (ray.origin + ray.direction * rayParam); distQuad = dist*dist; return true; } return false; }