Esempio n. 1
0
        public void FitBounds(double minX, double minY, double minZ,
				double maxX, double maxY, double maxZ)
        {
            BoundingPlane boundsRight = new BoundingPlane();
            BoundingPlane boundsLeft = new BoundingPlane();
            BoundingPlane boundsTop = new BoundingPlane();
            BoundingPlane boundsBottom = new BoundingPlane();
            BoundingPlane boundsNear = new BoundingPlane();
            BoundingPlane boundsFar = new BoundingPlane();
            msgVectorStruct boundsMax = new msgVectorStruct();
            msgVectorStruct boundsMin = new msgVectorStruct();
            msgVectorStruct vecCenter = new msgVectorStruct();
            msgVectorStruct[] vertices = new msgVectorStruct[8];
            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i] = new msgVectorStruct();
            }

            msgVectorStruct vecOffset = new msgVectorStruct();
            msgMatrix matrix = new msgMatrix();
            double focalLength = 0;
            double fDepthWidth = 0;
            double fDepthHeight = 0;
            double rx = 0;
            double ry = 0;
            double rz = 0;
            double fTan = 0;
            double fx = 0;
            double fz = 0;

            fTan = (double)Math.Tan((float)Utils.Radiansf(m_fFovY/2));

            // Get the cameras rotatiom about the LookAt position, as we
            // will use this to restore the rotation values after we move
            // the camera and it's focal length.
            GetRotationAboutLookAt(ref rx, ref ry, ref rz);

            // Copy the bounds to our local variable
            boundsMin.x = minX;	boundsMin.y = minY;	boundsMin.z = minZ;
            boundsMax.x = maxX;	boundsMax.y = maxY;	boundsMax.z = maxZ;

            double spanX, spanY, spanZ;

            spanX = Utils.Diff(boundsMax.x, boundsMin.x);
            spanY = Utils.Diff(boundsMax.y, boundsMin.y);
            spanZ = Utils.Diff(boundsMax.z, boundsMin.z);

            vecCenter.x = boundsMax.x - Math.Abs(spanX)/2;
            vecCenter.y = boundsMax.y - Math.Abs(spanY)/2;
            vecCenter.z = boundsMax.z - Math.Abs(spanZ)/2;

            boundsMax.x = spanX/2;
            boundsMax.y = spanY/2;
            boundsMax.z = spanZ/2;

            boundsMin.x = -spanX/2;
            boundsMin.y = -spanY/2;
            boundsMin.z = -spanZ/2;

            // Given the bounding box, fill in the missing vertices to complete our
            // cube
            vertices[0] = boundsMax;	// Left
            vertices[1].x = boundsMax.x; vertices[1].y = boundsMax.y; vertices[1].z = boundsMin.x;
            vertices[2].x = boundsMax.x; vertices[2].y = boundsMin.y; vertices[2].z = boundsMin.x;
            vertices[3].x = boundsMax.x; vertices[3].y = boundsMin.y; vertices[3].z = boundsMax.x;

            vertices[4] = boundsMin;
            vertices[5].x = boundsMin.x; vertices[5].y = boundsMin.y; vertices[5].z = boundsMax.x;
            vertices[6].x = boundsMin.x; vertices[6].y = boundsMax.y; vertices[6].z = boundsMax.x;
            vertices[7].x = boundsMin.x; vertices[7].y = boundsMax.y; vertices[7].z = boundsMin.x;

            // Get the cameras rotation matrix
            GetRotationMatrix(ref matrix);

            for(int i=0; i<8; i++)
            {
                // Transform the vertice by the camera rotation matrix.  Since we define the
                // default 'Up' camera position as Z-axis Up, the coordinates map as follows:
                //		X maps to Width,
                //		Y maps to Depth
                //		Z mpas to Height
                zero_p.x  = zero_p.y  =zero_p.z  =0.0;
                matrix.ApplyMatrixToVector(zero_p, vertices[i]);

                // Calculate the focal length needed to fit the near bounding plane
                fDepthWidth  = (Math.Abs(vertices[i].x)/fTan/m_fAspect)-vertices[i].y;
                fDepthHeight = (Math.Abs(vertices[i].z) / fTan) - vertices[i].y;

                // Calculate the Near clipping bounds.  This will be used to fit Isometric views and
                // for calculating the Near/Far clipping m_fFrustum.
                if(vertices[i].y<0)
                {
                    if (Math.Abs(vertices[i].x) > Math.Abs(boundsNear.vec.x) ||
                       (Math.Abs(vertices[i].x) == boundsNear.vec.x && Math.Abs(vertices[i].y) > Math.Abs(boundsNear.vec.z)))
                    {
                        boundsNear.vec.x = Math.Abs(vertices[i].x);
                        boundsNear.vec.z = Math.Abs(vertices[i].y);
                    }

                    if (Math.Abs(vertices[i].z) > Math.Abs(boundsNear.vec.y) ||
                       (Math.Abs(vertices[i].z) == boundsNear.vec.y))
                    {
                        boundsNear.vec.y = Math.Abs(vertices[i].z);
                        //boundsNear.vec[W] = fabs(vertices[i].y);
                    }

                    // Get the bounding depth closest to the viewer
                    if(fDepthWidth < boundsNear.fDepth || boundsNear.fDepth == 0)
                        boundsNear.fDepth = fDepthWidth;
                    if(fDepthHeight < boundsNear.fDepth || boundsNear.fDepth == 0)
                        boundsNear.fDepth = fDepthHeight;
                }
                else
                {
                    if( Math.Abs(vertices[i].x) > Math.Abs(boundsFar.vec.x) ||
                       (Math.Abs(vertices[i].x) == boundsFar.vec.x && Math.Abs(vertices[i].y) < Math.Abs(boundsFar.vec.z)) )
                    {
                        boundsFar.vec.x = vertices[i].x;
                        boundsFar.vec.z = vertices[i].y;
                    }

                    if( Math.Abs(vertices[i].z) > Math.Abs(boundsFar.vec.y) ||
                       (Math.Abs(vertices[i].z) == Math.Abs(boundsFar.vec.y)) )
                    {
                        boundsFar.vec.y = vertices[i].z;
                        //boundsFar.vec[W] = vertices[i].y;
                    }

                    // Get the bounding depth furtherest from the viewer
                    if(fDepthWidth > boundsFar.fDepth)
                        boundsFar.fDepth = fDepthWidth;
                    if(fDepthHeight > boundsFar.fDepth)
                        boundsFar.fDepth = fDepthHeight;
                }

                // Calculate the Right, Left, Top and Bottom clipping bounds.  This will be used to fit
                // Perspective views.
                if(vertices[i].x > 0)
                {
                    if(fDepthWidth > boundsRight.fDepth)
                    {
                        boundsRight.fDepth = fDepthWidth;
                        boundsRight.vec.x = vertices[i].x;
                        //boundsRight.vec[W] = vertices[i].y;
                    }
                }
                if(vertices[i].x <= 0)
                {
                    if(fDepthWidth > boundsLeft.fDepth)
                    {
                        boundsLeft.fDepth = fDepthWidth;
                        boundsLeft.vec.x = vertices[i].x;
                        //boundsLeft.vec[W] = vertices[i].y;
                    }
                }
                if(vertices[i].z > 0)
                {
                    if(fDepthHeight > boundsTop.fDepth)
                    {
                        boundsTop.fDepth = fDepthHeight;
                        boundsTop.vec.x = vertices[i].x;
                        //boundsTop.vec[W] = vertices[i].y;
                    }
                }
                if(vertices[i].z <= 0)
                {
                    if(fDepthHeight > boundsBottom.fDepth)
                    {
                        boundsBottom.fDepth = fDepthHeight;
                        boundsBottom.vec.x = vertices[i].x;
                        //boundsBottom.vec[W] = vertices[i].y;
                    }
                }
            }

            // Now that we have the view clipping bounds, we can calculate the focal depth
            // required to fit the volumn and the offset necessary to center the volumn.
            if (m_bPerspective)
            {
                msgMatrix invMatrix = new msgMatrix();

                if (boundsRight.fDepth == boundsLeft.fDepth &&
                   boundsTop.fDepth == boundsBottom.fDepth)
                {
                    // Front, Side or Top view

                    //  Since the bounds are symetric, just use the Right and Top focal depth.
                    fx = boundsRight.fDepth;
                    fz = boundsTop.fDepth;

                    // No offset necessary
                    vecOffset.x = vecOffset.y = vecOffset.z = 0.0;
                }
                else
                {
                    // Calculate the average focal length needed to fit the bounding box
                    fx = (boundsRight.fDepth + boundsLeft.fDepth) / 2;
                    fz = (boundsTop.fDepth + boundsBottom.fDepth) / 2;

                    // Calculate the offset necessary to center the bounding box.  Note that we
                    // use a scaling factor for centering the non-limiting bounds to achieve a
                    // more visually appealing center.
                    if (fx > fz)
                    {
                        double fScale = Math.Sqrt(boundsTop.fDepth / boundsBottom.fDepth);
                        double fTop = fTan * fx - fTan * boundsTop.fDepth;
                        double fBottom = fTan * fx - fTan * boundsBottom.fDepth;

                        vecOffset.x = (fTan * m_fAspect * boundsRight.fDepth - fTan * m_fAspect * fx);
                        vecOffset.z = (fBottom - fTop * fScale) / 2;
                    }
                    else
                    {
                        double fScale = Math.Sqrt(boundsLeft.fDepth / boundsRight.fDepth);
                        double fRight = fTan * m_fAspect * fz - fTan * m_fAspect * boundsRight.fDepth;
                        double fLeft = fTan * m_fAspect * fz - fTan * m_fAspect * boundsLeft.fDepth;

                        vecOffset.z = (fTan * boundsTop.fDepth - fTan * fz);
                        vecOffset.x = (fLeft - fRight * fScale) / 2;
                    }
                }

                // Now that we have the offsets necessary to center the bounds, we must rotate
                // the vertices (camera coordinates) by the cameras inverse rotation matrix to
                // convert the offsets to world coordinates.
                GetInvRotationMatrix(ref invMatrix);
                zero_p.x = zero_p.y = zero_p.z = 0.0;

                invMatrix.ApplyMatrixToVector(zero_p, vecOffset);
            }
            else
            {
                // Isometric View
                // Calculate the focal length needed to fit the near bounding plane
                if (m_iScreenWidth <= m_iScreenHeight)
                {
                    fx = boundsNear.vec.x / Math.Tan((float)Utils.Radiansf(m_fFovY / 2));
                    fz = boundsNear.vec.y / Math.Tan((float)Utils.Radiansf(m_fFovY / 2)) / ((double)m_iScreenHeight / (double)m_iScreenWidth);
                }
                else
                {
                    fx = boundsNear.vec.x / Math.Tan((float)Utils.Radiansf(m_fFovY / 2)) / m_fAspect;
                    fz = boundsNear.vec.y / Math.Tan((float)Utils.Radiansf(m_fFovY / 2));
                }
            }

            // Set the focal length equal to the largest length required to fit either the
            // Width (Horizontal) or Height (Vertical)
            focalLength = (fx > fz ? fx : fz);

            // Set the camera's new LookAt position to focus on the center
            // of the bounding box.
            SetLookAtPos(vecCenter.x + vecOffset.x, vecCenter.y + vecOffset.y, vecCenter.z + vecOffset.z);

            // Set the camera focal Length
            if (focalLength > m_fNear)
                SetFocalLength(focalLength, true);

            // Adjust the Near clipping plane if necessary
            //	if((boundsNear.fDepth/2) > 0.5f)
            //		m_fNear = boundsNear.fDepth/2;

            // Adjust the Far clipping plane if necessary
            if (focalLength + boundsFar.fDepth > m_fFar)
                m_fFar = focalLength + boundsFar.fDepth;

            // Recalculate the camera view m_fFrustum;
            ResetView(0, 0);

            // Restore the cameras rotation about the LookAt position
            SetRotationAboutLookAt(rx, ry, rz);
        }
Esempio n. 2
0
        public void FitBounds(double minX, double minY, double minZ,
                              double maxX, double maxY, double maxZ)
        {
            BoundingPlane   boundsRight  = new BoundingPlane();
            BoundingPlane   boundsLeft   = new BoundingPlane();
            BoundingPlane   boundsTop    = new BoundingPlane();
            BoundingPlane   boundsBottom = new BoundingPlane();
            BoundingPlane   boundsNear   = new BoundingPlane();
            BoundingPlane   boundsFar    = new BoundingPlane();
            msgVectorStruct boundsMax    = new msgVectorStruct();
            msgVectorStruct boundsMin    = new msgVectorStruct();
            msgVectorStruct vecCenter    = new msgVectorStruct();

            msgVectorStruct[] vertices = new msgVectorStruct[8];
            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i] = new msgVectorStruct();
            }

            msgVectorStruct vecOffset    = new msgVectorStruct();
            msgMatrix       matrix       = new msgMatrix();
            double          focalLength  = 0;
            double          fDepthWidth  = 0;
            double          fDepthHeight = 0;
            double          rx           = 0;
            double          ry           = 0;
            double          rz           = 0;
            double          fTan         = 0;
            double          fx           = 0;
            double          fz           = 0;

            fTan = (double)Math.Tan((float)Utils.Radiansf(m_fFovY / 2));


            // Get the cameras rotatiom about the LookAt position, as we
            // will use this to restore the rotation values after we move
            // the camera and it's focal length.
            GetRotationAboutLookAt(ref rx, ref ry, ref rz);

            // Copy the bounds to our local variable
            boundsMin.x = minX;     boundsMin.y = minY;     boundsMin.z = minZ;
            boundsMax.x = maxX;     boundsMax.y = maxY;     boundsMax.z = maxZ;

            double spanX, spanY, spanZ;

            spanX = Utils.Diff(boundsMax.x, boundsMin.x);
            spanY = Utils.Diff(boundsMax.y, boundsMin.y);
            spanZ = Utils.Diff(boundsMax.z, boundsMin.z);

            vecCenter.x = boundsMax.x - Math.Abs(spanX) / 2;
            vecCenter.y = boundsMax.y - Math.Abs(spanY) / 2;
            vecCenter.z = boundsMax.z - Math.Abs(spanZ) / 2;

            boundsMax.x = spanX / 2;
            boundsMax.y = spanY / 2;
            boundsMax.z = spanZ / 2;

            boundsMin.x = -spanX / 2;
            boundsMin.y = -spanY / 2;
            boundsMin.z = -spanZ / 2;

            // Given the bounding box, fill in the missing vertices to complete our
            // cube
            vertices[0]   = boundsMax;                  // Left
            vertices[1].x = boundsMax.x; vertices[1].y = boundsMax.y; vertices[1].z = boundsMin.x;
            vertices[2].x = boundsMax.x; vertices[2].y = boundsMin.y; vertices[2].z = boundsMin.x;
            vertices[3].x = boundsMax.x; vertices[3].y = boundsMin.y; vertices[3].z = boundsMax.x;

            vertices[4]   = boundsMin;
            vertices[5].x = boundsMin.x; vertices[5].y = boundsMin.y; vertices[5].z = boundsMax.x;
            vertices[6].x = boundsMin.x; vertices[6].y = boundsMax.y; vertices[6].z = boundsMax.x;
            vertices[7].x = boundsMin.x; vertices[7].y = boundsMax.y; vertices[7].z = boundsMin.x;

            // Get the cameras rotation matrix
            GetRotationMatrix(ref matrix);

            for (int i = 0; i < 8; i++)
            {
                // Transform the vertice by the camera rotation matrix.  Since we define the
                // default 'Up' camera position as Z-axis Up, the coordinates map as follows:
                //		X maps to Width,
                //		Y maps to Depth
                //		Z mpas to Height
                zero_p.x = zero_p.y = zero_p.z = 0.0;
                matrix.ApplyMatrixToVector(zero_p, vertices[i]);

                // Calculate the focal length needed to fit the near bounding plane
                fDepthWidth  = (Math.Abs(vertices[i].x) / fTan / m_fAspect) - vertices[i].y;
                fDepthHeight = (Math.Abs(vertices[i].z) / fTan) - vertices[i].y;


                // Calculate the Near clipping bounds.  This will be used to fit Isometric views and
                // for calculating the Near/Far clipping m_fFrustum.
                if (vertices[i].y < 0)
                {
                    if (Math.Abs(vertices[i].x) > Math.Abs(boundsNear.vec.x) ||
                        (Math.Abs(vertices[i].x) == boundsNear.vec.x && Math.Abs(vertices[i].y) > Math.Abs(boundsNear.vec.z)))
                    {
                        boundsNear.vec.x = Math.Abs(vertices[i].x);
                        boundsNear.vec.z = Math.Abs(vertices[i].y);
                    }

                    if (Math.Abs(vertices[i].z) > Math.Abs(boundsNear.vec.y) ||
                        (Math.Abs(vertices[i].z) == boundsNear.vec.y))
                    {
                        boundsNear.vec.y = Math.Abs(vertices[i].z);
                        //boundsNear.vec[W] = fabs(vertices[i].y);
                    }

                    // Get the bounding depth closest to the viewer
                    if (fDepthWidth < boundsNear.fDepth || boundsNear.fDepth == 0)
                    {
                        boundsNear.fDepth = fDepthWidth;
                    }
                    if (fDepthHeight < boundsNear.fDepth || boundsNear.fDepth == 0)
                    {
                        boundsNear.fDepth = fDepthHeight;
                    }
                }
                else
                {
                    if (Math.Abs(vertices[i].x) > Math.Abs(boundsFar.vec.x) ||
                        (Math.Abs(vertices[i].x) == boundsFar.vec.x && Math.Abs(vertices[i].y) < Math.Abs(boundsFar.vec.z)))
                    {
                        boundsFar.vec.x = vertices[i].x;
                        boundsFar.vec.z = vertices[i].y;
                    }

                    if (Math.Abs(vertices[i].z) > Math.Abs(boundsFar.vec.y) ||
                        (Math.Abs(vertices[i].z) == Math.Abs(boundsFar.vec.y)))
                    {
                        boundsFar.vec.y = vertices[i].z;
                        //boundsFar.vec[W] = vertices[i].y;
                    }

                    // Get the bounding depth furtherest from the viewer
                    if (fDepthWidth > boundsFar.fDepth)
                    {
                        boundsFar.fDepth = fDepthWidth;
                    }
                    if (fDepthHeight > boundsFar.fDepth)
                    {
                        boundsFar.fDepth = fDepthHeight;
                    }
                }


                // Calculate the Right, Left, Top and Bottom clipping bounds.  This will be used to fit
                // Perspective views.
                if (vertices[i].x > 0)
                {
                    if (fDepthWidth > boundsRight.fDepth)
                    {
                        boundsRight.fDepth = fDepthWidth;
                        boundsRight.vec.x  = vertices[i].x;
                        //boundsRight.vec[W] = vertices[i].y;
                    }
                }
                if (vertices[i].x <= 0)
                {
                    if (fDepthWidth > boundsLeft.fDepth)
                    {
                        boundsLeft.fDepth = fDepthWidth;
                        boundsLeft.vec.x  = vertices[i].x;
                        //boundsLeft.vec[W] = vertices[i].y;
                    }
                }
                if (vertices[i].z > 0)
                {
                    if (fDepthHeight > boundsTop.fDepth)
                    {
                        boundsTop.fDepth = fDepthHeight;
                        boundsTop.vec.x  = vertices[i].x;
                        //boundsTop.vec[W] = vertices[i].y;
                    }
                }
                if (vertices[i].z <= 0)
                {
                    if (fDepthHeight > boundsBottom.fDepth)
                    {
                        boundsBottom.fDepth = fDepthHeight;
                        boundsBottom.vec.x  = vertices[i].x;
                        //boundsBottom.vec[W] = vertices[i].y;
                    }
                }
            }

            // Now that we have the view clipping bounds, we can calculate the focal depth
            // required to fit the volumn and the offset necessary to center the volumn.
            if (m_bPerspective)
            {
                msgMatrix invMatrix = new msgMatrix();

                if (boundsRight.fDepth == boundsLeft.fDepth &&
                    boundsTop.fDepth == boundsBottom.fDepth)
                {
                    // Front, Side or Top view

                    //  Since the bounds are symetric, just use the Right and Top focal depth.
                    fx = boundsRight.fDepth;
                    fz = boundsTop.fDepth;

                    // No offset necessary
                    vecOffset.x = vecOffset.y = vecOffset.z = 0.0;
                }
                else
                {
                    // Calculate the average focal length needed to fit the bounding box
                    fx = (boundsRight.fDepth + boundsLeft.fDepth) / 2;
                    fz = (boundsTop.fDepth + boundsBottom.fDepth) / 2;

                    // Calculate the offset necessary to center the bounding box.  Note that we
                    // use a scaling factor for centering the non-limiting bounds to achieve a
                    // more visually appealing center.
                    if (fx > fz)
                    {
                        double fScale  = Math.Sqrt(boundsTop.fDepth / boundsBottom.fDepth);
                        double fTop    = fTan * fx - fTan * boundsTop.fDepth;
                        double fBottom = fTan * fx - fTan * boundsBottom.fDepth;

                        vecOffset.x = (fTan * m_fAspect * boundsRight.fDepth - fTan * m_fAspect * fx);
                        vecOffset.z = (fBottom - fTop * fScale) / 2;
                    }
                    else
                    {
                        double fScale = Math.Sqrt(boundsLeft.fDepth / boundsRight.fDepth);
                        double fRight = fTan * m_fAspect * fz - fTan * m_fAspect * boundsRight.fDepth;
                        double fLeft  = fTan * m_fAspect * fz - fTan * m_fAspect * boundsLeft.fDepth;

                        vecOffset.z = (fTan * boundsTop.fDepth - fTan * fz);
                        vecOffset.x = (fLeft - fRight * fScale) / 2;
                    }
                }

                // Now that we have the offsets necessary to center the bounds, we must rotate
                // the vertices (camera coordinates) by the cameras inverse rotation matrix to
                // convert the offsets to world coordinates.
                GetInvRotationMatrix(ref invMatrix);
                zero_p.x = zero_p.y = zero_p.z = 0.0;

                invMatrix.ApplyMatrixToVector(zero_p, vecOffset);
            }
            else
            {
                // Isometric View
                // Calculate the focal length needed to fit the near bounding plane
                if (m_iScreenWidth <= m_iScreenHeight)
                {
                    fx = boundsNear.vec.x / Math.Tan((float)Utils.Radiansf(m_fFovY / 2));
                    fz = boundsNear.vec.y / Math.Tan((float)Utils.Radiansf(m_fFovY / 2)) / ((double)m_iScreenHeight / (double)m_iScreenWidth);
                }
                else
                {
                    fx = boundsNear.vec.x / Math.Tan((float)Utils.Radiansf(m_fFovY / 2)) / m_fAspect;
                    fz = boundsNear.vec.y / Math.Tan((float)Utils.Radiansf(m_fFovY / 2));
                }
            }

            // Set the focal length equal to the largest length required to fit either the
            // Width (Horizontal) or Height (Vertical)
            focalLength = (fx > fz ? fx : fz);

            // Set the camera's new LookAt position to focus on the center
            // of the bounding box.
            SetLookAtPos(vecCenter.x + vecOffset.x, vecCenter.y + vecOffset.y, vecCenter.z + vecOffset.z);

            // Set the camera focal Length
            if (focalLength > m_fNear)
            {
                SetFocalLength(focalLength, true);
            }

            // Adjust the Near clipping plane if necessary
            //	if((boundsNear.fDepth/2) > 0.5f)
            //		m_fNear = boundsNear.fDepth/2;

            // Adjust the Far clipping plane if necessary
            if (focalLength + boundsFar.fDepth > m_fFar)
            {
                m_fFar = focalLength + boundsFar.fDepth;
            }

            // Recalculate the camera view m_fFrustum;
            ResetView(0, 0);

            // Restore the cameras rotation about the LookAt position
            SetRotationAboutLookAt(rx, ry, rz);
        }