OrthographicCamera.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / Core / CSharp / System / Windows / Media3D / OrthographicCamera.cs / 1 / OrthographicCamera.cs

                            //---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
//--------------------------------------------------------------------------- 
 
using System;
using System.Diagnostics; 
using System.Windows;
using MS.Internal.Media3D;
using System.ComponentModel.Design.Serialization;
using System.Windows.Markup; 
using CultureInfo = System.Globalization.CultureInfo;
 
namespace System.Windows.Media.Media3D 
{
    ///  
    ///     Encapsulates an orthagraphic projection camera.
    /// 
    public partial class OrthographicCamera : ProjectionCamera
    { 
        //-----------------------------------------------------
        // 
        //  Constructors 
        //
        //----------------------------------------------------- 

        ///
        public OrthographicCamera() {}
 
        ///
        public OrthographicCamera(Point3D position, Vector3D lookDirection, Vector3D upDirection, double width) 
        { 
            Position = position;
            LookDirection = lookDirection; 
            UpDirection = upDirection;
            Width = width;
        }
 
        //------------------------------------------------------
        // 
        //  Public Methods 
        //
        //----------------------------------------------------- 

        //------------------------------------------------------
        //
        //  Public Properties 
        //
        //------------------------------------------------------ 
 
        //-----------------------------------------------------
        // 
        //  Internal Methods
        //
        //------------------------------------------------------
 
        #region Internal Methods
 
        internal Matrix3D GetProjectionMatrix(double aspectRatio, double zn, double zf) 
        {
            double w = Width; 
            double h = w/aspectRatio;

            double m22 = 1/(zn-zf);
            double m32 = zn*m22; 

            return new Matrix3D( 
                2/w,   0,    0,  0, 
                0,   2/h,    0,  0,
                0,     0,  m22,  0, 
                0,     0,  m32,  1);
        }

        internal override Matrix3D GetProjectionMatrix(double aspectRatio) 
        {
            return GetProjectionMatrix(aspectRatio, NearPlaneDistance, FarPlaneDistance); 
        } 

        internal override RayHitTestParameters RayFromViewportPoint(Point p, Size viewSize, Rect3D boundingRect, out double distanceAdjustment) 
        {
            // The camera may be animating.  Take a snapshot of the current value
            // and get the property values we need. (Window OS #992662)
            Point3D position = Position; 
            Vector3D lookDirection = LookDirection;
            Vector3D upDirection = UpDirection; 
            double zn = NearPlaneDistance; 
            double zf = FarPlaneDistance;
            double width = Width; 

            //
            //  Compute rayParameters
            // 

            // Find the point on the projection plane in post-projective space where 
            // the viewport maps to a 2x2 square from (-1,1)-(1,-1). 
            Point np = M3DUtil.GetNormalizedPoint(p, viewSize);
 
            double aspectRatio = M3DUtil.GetAspectRatio(viewSize);
            double w = width;
            double h = w/aspectRatio;
 
            // Direction is always perpendicular to the viewing surface.
            Vector3D direction = new Vector3D(0, 0, -1); 
 
            // Apply the inverse of the view matrix to our ray.
            Matrix3D viewMatrix = CreateViewMatrix(Transform, ref position, ref lookDirection, ref upDirection); 
            Matrix3D invView = viewMatrix;
            invView.Invert();

            // We construct our ray such that the origin resides on the near 
            // plane.  If our near plane is too far from our the bounding box
            // of our scene then the results will be inaccurate.  (e.g., 
            // OrthographicCameras permit negative near planes, so the near 
            // plane could be at -Inf.)
            // 
            // However, it is permissable to move the near plane nearer to
            // the scene bounds without changing what the ray intersects.
            // If the near plane is sufficiently far from the scene bounds
            // we make this adjustment below to increase precision. 

            Rect3D transformedBoundingBox = 
                M3DUtil.ComputeTransformedAxisAlignedBoundingBox( 
                    ref boundingRect,
                    ref viewMatrix); 

            // DANGER:  The NearPlaneDistance property is specified as a
            //          distance from the camera position along the
            //          LookDirection with (Near < Far). 
            //
            //          However, when we transform our scene bounds so that 
            //          the camera is aligned with the negative Z-axis the 
            //          relationship inverts (Near > Far) as illustrated
            //          below: 
            //
            //            NearPlane    Y                      FarPlane
            //                |        ^                          |
            //                |        |                          | 
            //                |        | (rect.Z + rect.SizeZ)    |
            //                |        |           o____          | 
            //                |        |           |    |         | 
            //                |        |           |    |         |
            //                |        |            ____o         | 
            //                |        |             (rect.Z)     |
            //                |     Camera ->                     |
            //          +Z  <----------+----------------------------> -Z
            //                |        0                          | 
            //
            //          It is surprising, but its the "far" side of the 
            //          transformed scene bounds that determines the near 
            //          plane distance.
 
            double zn2 = - AddEpsilon(transformedBoundingBox.Z+transformedBoundingBox.SizeZ);

            if (zn2 > zn)
            { 
                //
                // Our near plane is far from our children. Construct a new 
                // near plane that's closer. Note that this will modify our 
                // distance computations, so we have to be sure to adjust our
                // distances appropriately. 
                //
                distanceAdjustment = zn2 - zn;

                zn = zn2; 
            }
            else 
            { 
                //
                // Our near plane is either close to or in front of our 
                // children, so let's keep it -- no distance adjustment needed.
                //
                distanceAdjustment = 0.0;
            } 

            // Our origin is the point normalized to the front of our viewing volume. 
            // To find our origin's x/y we just need to scale the normalize point by our 
            // width/height.  In camera space we are looking down the negative Z axis
            // so we just set Z to be -zn which puts us on the projection plane 
            // (Windows OS #1005064).
            Point3D origin = new Point3D(np.X*(w/2), np.Y*(h/2), -zn);

            invView.MultiplyPoint(ref origin); 
            invView.MultiplyVector(ref direction);
 
            RayHitTestParameters rayParameters = new RayHitTestParameters(origin, direction); 

            // 
            //  Compute HitTestProjectionMatrix
            //

            Matrix3D projectionMatrix = GetProjectionMatrix(aspectRatio, zn, zf); 

            // The projectionMatrix takes camera-space 3D points into normalized clip 
            // space. 

            // The viewportMatrix will take normalized clip space into 
            // viewport coordinates, with an additional 2D translation
            // to put the ray at the origin.
            Matrix3D viewportMatrix = new Matrix3D();
            viewportMatrix.TranslatePrepend(new Vector3D(-p.X, viewSize.Height-p.Y, 0)); 
            viewportMatrix.ScalePrepend(new Vector3D(viewSize.Width/2, -viewSize.Height/2, 1));
            viewportMatrix.TranslatePrepend(new Vector3D(1, 1, 0)); 
 
            // `First world-to-camera, then camera's projection, then normalized clip space to viewport.
            rayParameters.HitTestProjectionMatrix = 
                viewMatrix *
                projectionMatrix *
                viewportMatrix;
 
            return rayParameters;
 
        } 

        #endregion Internal Methods 

        //-----------------------------------------------------
        //
        //  Private Methods 
        //
        //----------------------------------------------------- 
 
        private double AddEpsilon(double x)
        { 
            //
            // x is either close to 0 or not. If it's close to 0, then 1.0 is
            // sufficiently large to act as an epsilon.  If it's not, then
            // 0.1*Math.Abs(x) sufficiently large. 
            //
            return x + 0.1*Math.Abs(x) + 1.0; 
        } 

        //----------------------------------------------------- 
        //
        //  Private Fields
        //
        //------------------------------------------------------ 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
//--------------------------------------------------------------------------- 
 
using System;
using System.Diagnostics; 
using System.Windows;
using MS.Internal.Media3D;
using System.ComponentModel.Design.Serialization;
using System.Windows.Markup; 
using CultureInfo = System.Globalization.CultureInfo;
 
namespace System.Windows.Media.Media3D 
{
    ///  
    ///     Encapsulates an orthagraphic projection camera.
    /// 
    public partial class OrthographicCamera : ProjectionCamera
    { 
        //-----------------------------------------------------
        // 
        //  Constructors 
        //
        //----------------------------------------------------- 

        ///
        public OrthographicCamera() {}
 
        ///
        public OrthographicCamera(Point3D position, Vector3D lookDirection, Vector3D upDirection, double width) 
        { 
            Position = position;
            LookDirection = lookDirection; 
            UpDirection = upDirection;
            Width = width;
        }
 
        //------------------------------------------------------
        // 
        //  Public Methods 
        //
        //----------------------------------------------------- 

        //------------------------------------------------------
        //
        //  Public Properties 
        //
        //------------------------------------------------------ 
 
        //-----------------------------------------------------
        // 
        //  Internal Methods
        //
        //------------------------------------------------------
 
        #region Internal Methods
 
        internal Matrix3D GetProjectionMatrix(double aspectRatio, double zn, double zf) 
        {
            double w = Width; 
            double h = w/aspectRatio;

            double m22 = 1/(zn-zf);
            double m32 = zn*m22; 

            return new Matrix3D( 
                2/w,   0,    0,  0, 
                0,   2/h,    0,  0,
                0,     0,  m22,  0, 
                0,     0,  m32,  1);
        }

        internal override Matrix3D GetProjectionMatrix(double aspectRatio) 
        {
            return GetProjectionMatrix(aspectRatio, NearPlaneDistance, FarPlaneDistance); 
        } 

        internal override RayHitTestParameters RayFromViewportPoint(Point p, Size viewSize, Rect3D boundingRect, out double distanceAdjustment) 
        {
            // The camera may be animating.  Take a snapshot of the current value
            // and get the property values we need. (Window OS #992662)
            Point3D position = Position; 
            Vector3D lookDirection = LookDirection;
            Vector3D upDirection = UpDirection; 
            double zn = NearPlaneDistance; 
            double zf = FarPlaneDistance;
            double width = Width; 

            //
            //  Compute rayParameters
            // 

            // Find the point on the projection plane in post-projective space where 
            // the viewport maps to a 2x2 square from (-1,1)-(1,-1). 
            Point np = M3DUtil.GetNormalizedPoint(p, viewSize);
 
            double aspectRatio = M3DUtil.GetAspectRatio(viewSize);
            double w = width;
            double h = w/aspectRatio;
 
            // Direction is always perpendicular to the viewing surface.
            Vector3D direction = new Vector3D(0, 0, -1); 
 
            // Apply the inverse of the view matrix to our ray.
            Matrix3D viewMatrix = CreateViewMatrix(Transform, ref position, ref lookDirection, ref upDirection); 
            Matrix3D invView = viewMatrix;
            invView.Invert();

            // We construct our ray such that the origin resides on the near 
            // plane.  If our near plane is too far from our the bounding box
            // of our scene then the results will be inaccurate.  (e.g., 
            // OrthographicCameras permit negative near planes, so the near 
            // plane could be at -Inf.)
            // 
            // However, it is permissable to move the near plane nearer to
            // the scene bounds without changing what the ray intersects.
            // If the near plane is sufficiently far from the scene bounds
            // we make this adjustment below to increase precision. 

            Rect3D transformedBoundingBox = 
                M3DUtil.ComputeTransformedAxisAlignedBoundingBox( 
                    ref boundingRect,
                    ref viewMatrix); 

            // DANGER:  The NearPlaneDistance property is specified as a
            //          distance from the camera position along the
            //          LookDirection with (Near < Far). 
            //
            //          However, when we transform our scene bounds so that 
            //          the camera is aligned with the negative Z-axis the 
            //          relationship inverts (Near > Far) as illustrated
            //          below: 
            //
            //            NearPlane    Y                      FarPlane
            //                |        ^                          |
            //                |        |                          | 
            //                |        | (rect.Z + rect.SizeZ)    |
            //                |        |           o____          | 
            //                |        |           |    |         | 
            //                |        |           |    |         |
            //                |        |            ____o         | 
            //                |        |             (rect.Z)     |
            //                |     Camera ->                     |
            //          +Z  <----------+----------------------------> -Z
            //                |        0                          | 
            //
            //          It is surprising, but its the "far" side of the 
            //          transformed scene bounds that determines the near 
            //          plane distance.
 
            double zn2 = - AddEpsilon(transformedBoundingBox.Z+transformedBoundingBox.SizeZ);

            if (zn2 > zn)
            { 
                //
                // Our near plane is far from our children. Construct a new 
                // near plane that's closer. Note that this will modify our 
                // distance computations, so we have to be sure to adjust our
                // distances appropriately. 
                //
                distanceAdjustment = zn2 - zn;

                zn = zn2; 
            }
            else 
            { 
                //
                // Our near plane is either close to or in front of our 
                // children, so let's keep it -- no distance adjustment needed.
                //
                distanceAdjustment = 0.0;
            } 

            // Our origin is the point normalized to the front of our viewing volume. 
            // To find our origin's x/y we just need to scale the normalize point by our 
            // width/height.  In camera space we are looking down the negative Z axis
            // so we just set Z to be -zn which puts us on the projection plane 
            // (Windows OS #1005064).
            Point3D origin = new Point3D(np.X*(w/2), np.Y*(h/2), -zn);

            invView.MultiplyPoint(ref origin); 
            invView.MultiplyVector(ref direction);
 
            RayHitTestParameters rayParameters = new RayHitTestParameters(origin, direction); 

            // 
            //  Compute HitTestProjectionMatrix
            //

            Matrix3D projectionMatrix = GetProjectionMatrix(aspectRatio, zn, zf); 

            // The projectionMatrix takes camera-space 3D points into normalized clip 
            // space. 

            // The viewportMatrix will take normalized clip space into 
            // viewport coordinates, with an additional 2D translation
            // to put the ray at the origin.
            Matrix3D viewportMatrix = new Matrix3D();
            viewportMatrix.TranslatePrepend(new Vector3D(-p.X, viewSize.Height-p.Y, 0)); 
            viewportMatrix.ScalePrepend(new Vector3D(viewSize.Width/2, -viewSize.Height/2, 1));
            viewportMatrix.TranslatePrepend(new Vector3D(1, 1, 0)); 
 
            // `First world-to-camera, then camera's projection, then normalized clip space to viewport.
            rayParameters.HitTestProjectionMatrix = 
                viewMatrix *
                projectionMatrix *
                viewportMatrix;
 
            return rayParameters;
 
        } 

        #endregion Internal Methods 

        //-----------------------------------------------------
        //
        //  Private Methods 
        //
        //----------------------------------------------------- 
 
        private double AddEpsilon(double x)
        { 
            //
            // x is either close to 0 or not. If it's close to 0, then 1.0 is
            // sufficiently large to act as an epsilon.  If it's not, then
            // 0.1*Math.Abs(x) sufficiently large. 
            //
            return x + 0.1*Math.Abs(x) + 1.0; 
        } 

        //----------------------------------------------------- 
        //
        //  Private Fields
        //
        //------------------------------------------------------ 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK