Esempio n. 1
0
 public override bool IsObjectVisible(Sphere bound, out FrustumPlane culledBy)
 {
     if (cullingFrustum != null)
     {
         return(cullingFrustum.IsObjectVisible(bound, out culledBy));
     }
     else
     {
         return(base.IsObjectVisible(bound, out culledBy));
     }
 }
Esempio n. 2
0
 public override bool IsObjectVisible(Vector3 vert, out FrustumPlane culledBy)
 {
     if (cullingFrustum != null)
     {
         return(cullingFrustum.IsObjectVisible(vert, out culledBy));
     }
     else
     {
         return(base.IsObjectVisible(vert, out culledBy));
     }
 }
Esempio n. 3
0
 public override Plane GetFrustumPlane(FrustumPlane plane)
 {
     if (cullingFrustum != null)
     {
         return(cullingFrustum.GetFrustumPlane(plane));
     }
     else
     {
         return(base.GetFrustumPlane(plane));
     }
 }
Esempio n. 4
0
        public override void FindVisibleNodes(PCZCamera camera, ref List <PCZSceneNode> visibleNodeList, RenderQueue queue,
                                              VisibleObjectsBoundsInfo visibleBounds, bool onlyShadowCasters,
                                              bool displayNodes, bool showBoundingBoxes)
        {
            //return immediately if nothing is in the zone.
            if (mHomeNodeList.Count == 0 && mVisitorNodeList.Count == 0 && mPortals.Count == 0)
            {
                return;
            }

            // Else, the zone is automatically assumed to be visible since either
            // it is the camera the zone is in, or it was reached because
            // a connecting portal was deemed visible to the camera.

            // enable sky if called to do so for this zone
            if (mHasSky)
            {
                // enable sky
                mPCZSM.EnableSky(true);
            }

            // Recursively find visible nodes in the zone
            WalkOctree(camera, ref visibleNodeList, queue, this.rootOctree, visibleBounds, false, onlyShadowCasters,
                       displayNodes,
                       showBoundingBoxes);

            // find visible portals in the zone and recurse into them
            bool vis;

            foreach (Portal portal in mPortals)
            {
                // for portal, check visibility using world bounding sphere & direction
                FrustumPlane pl = FrustumPlane.None;
                vis = camera.IsObjectVisible(portal, out pl);
                if (vis)
                {
                    // portal is visible. Add the portal as extra culling planes to camera
                    int planes_added = camera.AddPortalCullingPlanes(portal);
                    // tell target zone it's visible this frame
                    portal.getTargetZone().LastVisibleFrame      = mLastVisibleFrame;
                    portal.getTargetZone().LastVisibleFromCamera = camera;
                    // recurse into the connected zone
                    portal.getTargetZone().FindVisibleNodes(camera, ref visibleNodeList, queue, visibleBounds, onlyShadowCasters,
                                                            displayNodes, showBoundingBoxes);
                    if (planes_added > 0)
                    {
                        // Then remove the extra culling planes added before going to the next portal in this zone.
                        camera.RemovePortalCullingPlanes(portal);
                    }
                }
            }
        }
Esempio n. 5
0
        //        /// <summary>
        //        ///
        //        /// </summary>
        //        /// <param name="op"></param>
        //        public override void GetRenderOperation(RenderOperation op) {
        //            Vector3[] r = new Vector3[8];
        //
        //            r = this.Corners;
        //
        //            r[0] = GetCorner(FrustumPlane.Far,FrustumPlane.Left,FrustumPlane.Bottom);
        //            r[1] = GetCorner(FrustumPlane.Far,FrustumPlane.Left,FrustumPlane.Top);
        //            r[2] = GetCorner(FrustumPlane.Far,FrustumPlane.Right,FrustumPlane.Top);
        //            r[3] = GetCorner(FrustumPlane.Far,FrustumPlane.Right,FrustumPlane.Bottom);
        //
        //            r[4] = GetCorner(FrustumPlane.Near,FrustumPlane.Right,FrustumPlane.Top);
        //            r[5] = GetCorner(FrustumPlane.Near,FrustumPlane.Left,FrustumPlane.Top);
        //            r[6] = GetCorner(FrustumPlane.Near,FrustumPlane.Left,FrustumPlane.Bottom);
        //            r[7] = GetCorner(FrustumPlane.Near,FrustumPlane.Right,FrustumPlane.Bottom);
        //
        //            this.Corners = r;
        //
        //            UpdateView();
        //
        //            //TODO: VERTEX BUFFER STUFF
        //        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="pp1"></param>
        /// <param name="pp2"></param>
        /// <param name="pp3"></param>
        /// <returns></returns>
        private Vector3 GetCorner(FrustumPlane pp1, FrustumPlane pp2, FrustumPlane pp3)
        {
            Plane p1 = _planes[(int)pp1];
            Plane p2 = _planes[(int)pp1];
            Plane p3 = _planes[(int)pp1];

            Matrix3 mdet;

            mdet.m00 = p1.Normal.x;
            mdet.m01 = p1.Normal.y;
            mdet.m02 = p1.Normal.z;
            mdet.m10 = p2.Normal.x;
            mdet.m11 = p2.Normal.y;
            mdet.m12 = p2.Normal.z;
            mdet.m20 = p3.Normal.x;
            mdet.m21 = p3.Normal.y;
            mdet.m22 = p3.Normal.z;

            float det = mdet.Determinant;

            if (det == 0)
            {
                //TODO: Unsure. The C++ just returned
                return(Vector3.Zero);                //some planes are parallel.
            }

            var mx = new Matrix3(-p1.D, p1.Normal.y, p1.Normal.z, -p2.D, p2.Normal.y, p2.Normal.z, -p3.D, p3.Normal.y,
                                 p3.Normal.z);

            float xdet = mx.Determinant;

            var my = new Matrix3(p1.Normal.x, -p1.D, p1.Normal.z, p2.Normal.x, -p2.D, p2.Normal.z, p3.Normal.x, -p3.D,
                                 p3.Normal.z);

            float ydet = my.Determinant;

            var mz = new Matrix3(p1.Normal.x, p1.Normal.y, -p1.D, p2.Normal.x, p2.Normal.y, -p2.D, p3.Normal.x, p3.Normal.y,
                                 -p3.D);

            float zdet = mz.Determinant;

            var r = new Vector3();

            r.x = xdet / det;
            r.y = ydet / det;
            r.z = zdet / det;

            return(r);
        }
Esempio n. 6
0
        public int IndexOfPlane(FrustumPlane plane)
        {
            switch (plane)
            {
            case FrustumPlane.Front: return(3);

            case FrustumPlane.Back: return(2);

            case FrustumPlane.Left: return(1);

            case FrustumPlane.Right: return(0);

            case FrustumPlane.Top: return(4);

            case FrustumPlane.Bottom: return(5);
            }

            return(-1);
        }
Esempio n. 7
0
        void recalcFrustum()
        {
            // TODO< transform view frustom mesh by rotation of the camera >

            // we transform a mesh which describes the view frustum in global space
            // and then we calculate the normal and distance of the normal of the planes
            MeshWithExplicitFaces frustumMesh = new MeshWithExplicitFaces();

            { // create a VerticesWithAttributes with just positions
                MutableMeshAttribute positionMeshAttribute = MutableMeshAttribute.makeDouble4ByLength(5);
                var positionAccessor = positionMeshAttribute.getDouble4Accessor();
                positionAccessor[0] = new double[] { -1, -1, 1, 1 };
                positionAccessor[1] = new double[] { 1, -1, 1, 1 };
                positionAccessor[2] = new double[] { 1, 1, 1, 1 };
                positionAccessor[3] = new double[] { -1, 1, 1, 1 };
                positionAccessor[4] = new double[] { 0, 0, 0, 1 };

                VerticesWithAttributes verticesWithAttributes = new VerticesWithAttributes(new AbstractMeshAttribute[] { positionMeshAttribute }, 0);
                frustumMesh.verticesWithAttributes = verticesWithAttributes;
            }

            frustumMesh.faces = new MeshWithExplicitFaces.Face[] {
                new MeshWithExplicitFaces.Face(new uint[] { 4, 0, 1 }), // top side
                new MeshWithExplicitFaces.Face(new uint[] { 4, 1, 2 }), // right side
                new MeshWithExplicitFaces.Face(new uint[] { 4, 2, 3 }), // bottom side
                new MeshWithExplicitFaces.Face(new uint[] { 4, 3, 0 }), // left side
            };

            // TODO< use globally transformed vertices >
            // result is 4 component
            SpatialVectorDouble[] planesWith4Component = MeshUtilities.calcAllPlanes(frustumMesh.faces, frustumMesh.getVertexPositionsAsVector3Array());



            // we only have 4 planes because we dont limit the maximal z
            frustum.planes    = new FrustumPlane[4];
            frustum.planes[0] = FrustumPlane.makeFrom4Component(planesWith4Component[0]);
            frustum.planes[1] = FrustumPlane.makeFrom4Component(planesWith4Component[1]);
            frustum.planes[2] = FrustumPlane.makeFrom4Component(planesWith4Component[2]);
            frustum.planes[3] = FrustumPlane.makeFrom4Component(planesWith4Component[3]);
        }
Esempio n. 8
0
        // this version checks against extra culling planes
        public new bool IsObjectVisible(AxisAlignedBox bound, out FrustumPlane culledBy)
        {
            culledBy = FrustumPlane.None;

            // Null boxes always invisible
            if (bound.IsNull)
            {
                return(false);
            }

            // infinite boxes always visible
            if (bound.IsInfinite)
            {
                return(true);
            }

            // Make any pending updates to the calculated frustum planes
            UpdateFrustumPlanes();

            // check extra culling planes
            bool extraResults;

            extraResults = this.extraCullingFrustum.IsObjectVisible(bound);
            if (!extraResults)
            {
                return(false);
            }

            // check "regular" camera frustum
            bool regcamresults = base.IsObjectVisible(bound, out culledBy);

            if (!regcamresults)
            {
                // culled by regular culling planes
                return(regcamresults);
            }


            return(true);
        }
Esempio n. 9
0
		// this version checks against extra culling planes
		public new bool IsObjectVisible( AxisAlignedBox bound, out FrustumPlane culledBy )
		{
			culledBy = FrustumPlane.None;

			// Null boxes always invisible
			if ( bound.IsNull )
			{
				return false;
			}

			// infinite boxes always visible
			if ( bound.IsInfinite )
			{
				return true;
			}

			// Make any pending updates to the calculated frustum planes
			UpdateFrustumPlanes();

			// check extra culling planes
			bool extraResults;
			extraResults = this.extraCullingFrustum.IsObjectVisible( bound );
			if ( !extraResults )
			{
				return false;
			}

			// check "regular" camera frustum
			bool regcamresults = base.IsObjectVisible( bound, out culledBy );

			if ( !regcamresults )
			{
				// culled by regular culling planes
				return regcamresults;
			}


			return true;
		}
Esempio n. 10
0
		/// <summary>
		///		Tests whether the given sphere is in the viewing frustum.
		/// </summary>
		/// <param name="sphere">Bounding sphere to be checked.</param>
		/// <param name="culledBy">
		///		Optional FrustrumPlane params which will be filled by the plane which culled
		///		the box if the result was false.
		///	</param>
		/// <returns>True if the box is visible, otherwise false.</returns>
		public bool IsObjectVisible( Sphere sphere, out FrustumPlane culledBy )
		{
			// Make any pending updates to the calculated frustum
			UpdateFrustumPlanes();

			// For each plane, see if sphere is on negative side
			// If so, object is not visible
			for ( var plane = 0; plane < 6; plane++ )
			{
				if ( this._farDistance == 0 && plane == (int)FrustumPlane.Far )
				{
					continue;
				}

				// If the distance from sphere center to plane is negative, and 'more negative'
				// than the radius of the sphere, sphere is outside frustum
				if ( this._planes[ plane ].GetDistance( sphere.Center ) < -sphere.Radius )
				{
					// ALL corners on negative side therefore out of view
					culledBy = (FrustumPlane)plane;
					return false;
				}
			}

			// sphere is not culled
			culledBy = FrustumPlane.None;
			return true;
		}
Esempio n. 11
0
 public Plane this[FrustumPlane plane]
 {
     get { return(planes[IndexOfPlane(plane)]); }
 }
Esempio n. 12
0
		public new virtual bool IsVisible( Vector3 vert, FrustumPlane culledBy )
		{
			return true;
		}
Esempio n. 13
0
		public Plane GetFrustumPlane( FrustumPlane plane )
		{
			return this.frustumPlanes[ plane ];
		}
Esempio n. 14
0
        /// <summary>
        ///     IsObjectVisible() function for portals.
        /// </summary>
        /// <remarks>
        ///     Everything needs to be updated spatially before this function is
        ///     called including portal corners, frustum planes, etc.
        /// </remarks>
        /// <param name="portal">
        ///     The <see cref="Portal"/> to check visibility against.
        /// </param>
        /// <param name="culledBy">
        ///     The <see cref="FrustumPlane"/> that the Portal is in.
        /// </param>
        /// <returns>
        ///     true if the Portal is visible.
        /// </returns>
        public bool IsObjectVisible(Portal portal, out FrustumPlane culledBy)
        {
            culledBy = FrustumPlane.None;

            // if portal isn't open, it's not visible
            if (!portal.IsOpen)
            {
                return(false);
            }

            // check the extra frustum first
            if (!this.extraCullingFrustum.IsObjectVisible(portal))
            {
                return(false);
            }

            // if portal is of type AABB or Sphere, then use simple bound check against planes
            if (portal.Type == PORTAL_TYPE.PORTAL_TYPE_AABB)
            {
                var aabb = new AxisAlignedBox(portal.getDerivedCorner(0), portal.getDerivedCorner(1));
                return(base.IsObjectVisible(aabb, out culledBy));
            }
            else if (portal.Type == PORTAL_TYPE.PORTAL_TYPE_SPHERE)
            {
                return(base.IsObjectVisible(portal.getDerivedSphere(), out culledBy));
            }

            // check if the portal norm is facing the camera
            Vector3 cameraToPortal  = portal.getDerivedCP() - DerivedPosition;
            Vector3 portalDirection = portal.getDerivedDirection();
            Real    dotProduct      = cameraToPortal.Dot(portalDirection);

            if (dotProduct > 0)
            {
                // portal is faced away from camera
                return(false);
            }
            // check against regular frustum planes
            bool visible_flag;

            if (null != CullFrustum)
            {
                // For each frustum plane, see if all points are on the negative side
                // If so, object is not visible
                // NOTE: We skip the NEAR plane (plane #0) because Portals need to
                // be visible no matter how close you get to them.

                for (int plane = 1; plane < 6; ++plane)
                {
                    // set the visible flag to false
                    visible_flag = false;
                    // Skip far plane if infinite view frustum
                    if ((FrustumPlane)plane == FrustumPlane.Far && _farDistance == 0)
                    {
                        continue;
                    }

                    // we have to check each corner of the portal
                    for (int corner = 0; corner < 4; corner++)
                    {
                        PlaneSide side = CullFrustum.FrustumPlanes[plane].GetSide(portal.getDerivedCorner(corner));
                        if (side != PlaneSide.Negative)
                        {
                            visible_flag = true;
                        }
                    }
                    // if the visible_flag is still false, then this plane
                    // culled all the portal points
                    if (visible_flag == false)
                    {
                        // ALL corners on negative side therefore out of view
                        if (culledBy != FrustumPlane.None)
                        {
                            culledBy = (FrustumPlane)plane;
                        }
                        return(false);
                    }
                }
            }
            else
            {
                // Make any pending updates to the calculated frustum planes
                UpdateFrustumPlanes();

                // For each frustum plane, see if all points are on the negative side
                // If so, object is not visible
                // NOTE: We skip the NEAR plane (plane #0) because Portals need to
                // be visible no matter how close you get to them.
                // BUGBUG: This can cause a false positive situation when a portal is
                // behind the camera but close.  This could be fixed by having another
                // culling plane at the camera location with normal same as camera direction.
                for (int plane = 1; plane < 6; ++plane)
                {
                    // set the visible flag to false
                    visible_flag = false;
                    // Skip far plane if infinite view frustum
                    if ((FrustumPlane)plane == FrustumPlane.Far && _farDistance == 0)
                    {
                        continue;
                    }

                    // we have to check each corner of the portal
                    for (int corner = 0; corner < 4; corner++)
                    {
                        PlaneSide side = _planes[plane].GetSide(portal.getDerivedCorner(corner));
                        if (side != PlaneSide.Negative)
                        {
                            visible_flag = true;
                        }
                    }
                    // if the visible_flag is still false, then this plane
                    // culled all the portal points
                    if (visible_flag == false)
                    {
                        // ALL corners on negative side therefore out of view
                        if (culledBy != FrustumPlane.None)
                        {
                            culledBy = (FrustumPlane)plane;
                        }
                        return(false);
                    }
                }
            }
            // no plane culled all the portal points and the norm
            // was facing the camera, so this portal is visible
            return(true);
        }
Esempio n. 15
0
 public override bool IsObjectVisible(Vector3 vert, out FrustumPlane culledBy)
 {
     if (cullingFrustum != null)
         return cullingFrustum.IsObjectVisible(vert, out culledBy);
     else
         return base.IsObjectVisible(vert, out culledBy);
 }
Esempio n. 16
0
		public new virtual bool IsVisible( Sphere bound, FrustumPlane culledBy )
		{
			return true;
		}
Esempio n. 17
0
		public new bool IsObjectVisible( Sphere sphere, out FrustumPlane culledBy )
		{
			if ( null != CullFrustum )
			{
				return CullFrustum.IsObjectVisible( sphere, out culledBy );
			}
			else
			{
				return base.IsObjectVisible( sphere, out culledBy );
			}
		}
Esempio n. 18
0
		//        /// <summary>
		//        ///
		//        /// </summary>
		//        /// <param name="op"></param>
		//        public override void GetRenderOperation(RenderOperation op) {
		//            Vector3[] r = new Vector3[8];
		//
		//            r = this.Corners;
		//
		//            r[0] = GetCorner(FrustumPlane.Far,FrustumPlane.Left,FrustumPlane.Bottom);
		//            r[1] = GetCorner(FrustumPlane.Far,FrustumPlane.Left,FrustumPlane.Top);
		//            r[2] = GetCorner(FrustumPlane.Far,FrustumPlane.Right,FrustumPlane.Top);
		//            r[3] = GetCorner(FrustumPlane.Far,FrustumPlane.Right,FrustumPlane.Bottom);
		//
		//            r[4] = GetCorner(FrustumPlane.Near,FrustumPlane.Right,FrustumPlane.Top);
		//            r[5] = GetCorner(FrustumPlane.Near,FrustumPlane.Left,FrustumPlane.Top);
		//            r[6] = GetCorner(FrustumPlane.Near,FrustumPlane.Left,FrustumPlane.Bottom);
		//            r[7] = GetCorner(FrustumPlane.Near,FrustumPlane.Right,FrustumPlane.Bottom);
		//
		//            this.Corners = r;
		//
		//            UpdateView();
		//
		//            //TODO: VERTEX BUFFER STUFF
		//        }

		/// <summary>
		///
		/// </summary>
		/// <param name="pp1"></param>
		/// <param name="pp2"></param>
		/// <param name="pp3"></param>
		/// <returns></returns>
		private Vector3 GetCorner( FrustumPlane pp1, FrustumPlane pp2, FrustumPlane pp3 )
		{
			Plane p1 = _planes[ (int)pp1 ];
			Plane p2 = _planes[ (int)pp1 ];
			Plane p3 = _planes[ (int)pp1 ];

			Matrix3 mdet;

			mdet.m00 = p1.Normal.x;
			mdet.m01 = p1.Normal.y;
			mdet.m02 = p1.Normal.z;
			mdet.m10 = p2.Normal.x;
			mdet.m11 = p2.Normal.y;
			mdet.m12 = p2.Normal.z;
			mdet.m20 = p3.Normal.x;
			mdet.m21 = p3.Normal.y;
			mdet.m22 = p3.Normal.z;

			float det = mdet.Determinant;

			if ( det == 0 )
			{
				//TODO: Unsure. The C++ just returned
				return Vector3.Zero; //some planes are parallel.
			}

			var mx = new Matrix3( -p1.D, p1.Normal.y, p1.Normal.z, -p2.D, p2.Normal.y, p2.Normal.z, -p3.D, p3.Normal.y,
			                      p3.Normal.z );

			float xdet = mx.Determinant;

			var my = new Matrix3( p1.Normal.x, -p1.D, p1.Normal.z, p2.Normal.x, -p2.D, p2.Normal.z, p3.Normal.x, -p3.D,
			                      p3.Normal.z );

			float ydet = my.Determinant;

			var mz = new Matrix3( p1.Normal.x, p1.Normal.y, -p1.D, p2.Normal.x, p2.Normal.y, -p2.D, p3.Normal.x, p3.Normal.y,
			                      -p3.D );

			float zdet = mz.Determinant;

			var r = new Vector3();
			r.x = xdet/det;
			r.y = ydet/det;
			r.z = zdet/det;

			return r;
		}
Esempio n. 19
0
		/// <summary>
		///		Tests whether the given box is visible in the Frustum.
		///	 </summary>
		/// <param name="box"> Bounding box to be checked.</param>
		/// <param name="culledBy">
		///		Optional FrustrumPlane params which will be filled by the plane which culled
		///		the box if the result was false.
		///	</param>
		/// <returns>True if the box is visible, otherwise false.</returns>
		public bool IsObjectVisible( AxisAlignedBox box, out FrustumPlane culledBy )
		{
			culledBy = FrustumPlane.None;

			// Null boxes are always invisible
			if ( box.IsNull )
			{
				return false;
			}

			// Infinite Boxes are always visible
			if ( box.IsInfinite )
			{
				return true;
			}

			// Make any pending updates to the calculated frustum
			UpdateFrustumPlanes();

			// Get corners of the box
			var corners = box.Corners;

			// For each plane, see if all points are on the negative side
			// If so, object is not visible
			for ( var plane = 0; plane < 6; plane++ )
			{
				// skip far plane if infinite view frustum
				if ( this._farDistance == 0 && plane == (int)FrustumPlane.Far )
				{
					continue;
				}

				if ( this._planes[ plane ].GetSide( corners[ 0 ] ) == PlaneSide.Negative &&
				     this._planes[ plane ].GetSide( corners[ 1 ] ) == PlaneSide.Negative &&
				     this._planes[ plane ].GetSide( corners[ 2 ] ) == PlaneSide.Negative &&
				     this._planes[ plane ].GetSide( corners[ 3 ] ) == PlaneSide.Negative &&
				     this._planes[ plane ].GetSide( corners[ 4 ] ) == PlaneSide.Negative &&
				     this._planes[ plane ].GetSide( corners[ 5 ] ) == PlaneSide.Negative &&
				     this._planes[ plane ].GetSide( corners[ 6 ] ) == PlaneSide.Negative &&
				     this._planes[ plane ].GetSide( corners[ 7 ] ) == PlaneSide.Negative )
				{
					// ALL corners on negative side therefore out of view
					culledBy = (FrustumPlane)plane;
					return false;
				}
			}

			// box is not culled
			return true;
		}
Esempio n. 20
0
        /// <summary>
        ///		Internal method for calculating the clip volumes outside of the
        ///		frustum which can be used to determine which objects are casting
        ///		shadow on the frustum as a whole.
        /// </summary>
        /// <remarks>
        ///		Each of the volumes is a pyramid for a point/spot light and
        ///		a cuboid for a directional light.
        /// </remarks>
        /// <param name="camera"></param>
        /// <returns></returns>
        internal List <PlaneBoundedVolume> GetFrustumClipVolumes(Camera camera)
        {
            // Homogenous light position
            Vector4 lightPos = GetAs4DVector();

            // 3D version (not the same as DerivedPosition, is -direction for
            // directional lights)
            Vector3 lightPos3 = new Vector3(lightPos.x, lightPos.y, lightPos.z);
            Vector3 lightDir;

            Vector3[] clockwiseVerts = new Vector3[4];

            Matrix4 eyeToWorld = camera.ViewMatrix.Inverse();

            // Get worldspace frustum corners
            Vector3[] corners = camera.WorldSpaceCorners;

            bool infiniteViewDistance = (camera.Far == 0);

            frustumClipVolumes.Clear();

            for (int n = 0; n < 6; n++)
            {
                FrustumPlane frustumPlane = (FrustumPlane)n;

                // skip far plane if infinite view frustum
                if (infiniteViewDistance && (frustumPlane == FrustumPlane.Far))
                {
                    continue;
                }

                Plane plane = camera[frustumPlane];

                Vector4 planeVec = new Vector4(plane.Normal.x, plane.Normal.y, plane.Normal.z, plane.D);

                // planes face inwards, we need to know if light is on negative side
                float d = planeVec.Dot(lightPos);

                if (d < -1e-06f)
                {
                    // Ok, this is a valid one
                    // clockwise verts mean we can cross-product and always get normals
                    // facing into the volume we create
                    frustumClipVolumes.Add(new PlaneBoundedVolume());
                    PlaneBoundedVolume vol =
                        (PlaneBoundedVolume)frustumClipVolumes[frustumClipVolumes.Count - 1];

                    switch (frustumPlane)
                    {
                    case (FrustumPlane.Near):
                        clockwiseVerts[0] = corners[3];
                        clockwiseVerts[1] = corners[2];
                        clockwiseVerts[2] = corners[1];
                        clockwiseVerts[3] = corners[0];
                        break;

                    case (FrustumPlane.Far):
                        clockwiseVerts[0] = corners[7];
                        clockwiseVerts[1] = corners[6];
                        clockwiseVerts[2] = corners[5];
                        clockwiseVerts[3] = corners[4];
                        break;

                    case (FrustumPlane.Left):
                        clockwiseVerts[0] = corners[2];
                        clockwiseVerts[1] = corners[6];
                        clockwiseVerts[2] = corners[5];
                        clockwiseVerts[3] = corners[1];
                        break;

                    case (FrustumPlane.Right):
                        clockwiseVerts[0] = corners[7];
                        clockwiseVerts[1] = corners[3];
                        clockwiseVerts[2] = corners[0];
                        clockwiseVerts[3] = corners[4];
                        break;

                    case (FrustumPlane.Top):
                        clockwiseVerts[0] = corners[0];
                        clockwiseVerts[1] = corners[1];
                        clockwiseVerts[2] = corners[5];
                        clockwiseVerts[3] = corners[4];
                        break;

                    case (FrustumPlane.Bottom):
                        clockwiseVerts[0] = corners[7];
                        clockwiseVerts[1] = corners[6];
                        clockwiseVerts[2] = corners[2];
                        clockwiseVerts[3] = corners[3];
                        break;
                    }

                    // Build a volume
                    // Iterate over world points and form side planes
                    Vector3 normal;

                    for (int i = 0; i < 4; i++)
                    {
                        // Figure out light dir
                        lightDir = lightPos3 - (clockwiseVerts[i] * lightPos.w);

                        // Cross with anticlockwise corner, therefore normal points in
                        // Note: C++ mod returns 3 for the first case where C# returns -1
                        int test = i > 0 ? ((i - 1) % 4) : 3;

                        // Cross with anticlockwise corner, therefore normal points in
                        normal = (clockwiseVerts[i] - clockwiseVerts[test]).Cross(lightDir);
                        normal.Normalize();

                        // NB last param to Plane constructor is negated because it's -d
                        vol.planes.Add(new Plane(normal, normal.Dot(clockwiseVerts[i])));
                    }

                    // Now do the near plane (this is the plane of the side we're
                    // talking about, with the normal inverted (d is already interpreted as -ve)
                    vol.planes.Add(new Plane(-plane.Normal, plane.D));

                    // Finally, for a point/spot light we can add a sixth plane
                    // This prevents false positives from behind the light
                    if (type != LightType.Directional)
                    {
                        // re-use our own plane normal
                        // remember the -d negation in plane constructor
                        vol.planes.Add(new Plane(plane.Normal, plane.Normal.Dot(lightPos3)));
                    }
                }
            }

            return(frustumClipVolumes);
        }
Esempio n. 21
0
 /// <summary>
 ///  获得视见体的裁减平面
 /// </summary>
 /// <param name="fp"></param>
 /// <param name="pl"></param>
 public void GetPlane(FrustumPlane fp, out Plane pl)
 {
     pl = this.planes[(int)fp];
 }
Esempio n. 22
0
		/// <summary>
		///		Tests whether the given 3D point is in the viewing frustum.
		/// </summary>
		/// <param name="vertex">3D point to check for frustum visibility.</param>
		/// <param name="culledBy">
		///		Optional FrustrumPlane params which will be filled by the plane which culled
		///		the box if the result was false.
		///	</param>
		/// <returns>True if the box is visible, otherwise false.</returns>
		public bool IsObjectVisible( Vector3 vertex, out FrustumPlane culledBy )
		{
			// Make any pending updates to the calculated frustum
			UpdateFrustumPlanes();

			// For each plane, see if all points are on the negative side
			// If so, object is not visible
			for ( var plane = 0; plane < 6; plane++ )
			{
				if ( this._farDistance == 0 && plane == (int)FrustumPlane.Far )
				{
					continue;
				}

				if ( this._planes[ plane ].GetSide( vertex ) == PlaneSide.Negative )
				{
					// ALL corners on negative side therefore out of view
					culledBy = (FrustumPlane)plane;
					return false;
				}
			}

			// vertex is not culled
			culledBy = FrustumPlane.None;
			return true;
		}
Esempio n. 23
0
		/// <summary>
		///		An indexer that accepts a FrustumPlane enum value and return the appropriate plane side of the Frustum.
		/// </summary>
		public Plane this[ FrustumPlane plane ]
		{
			get
			{
				// make any pending updates to the calculated frustum
				UpdateFrustumPlanes();

				// convert the incoming plan enum type to a int
				var index = (int)plane;

				// access the planes array by index
				return this._planes[ index ];
			}
		}
Esempio n. 24
0
		/// <summary>
		///     IsObjectVisible() function for portals.
		/// </summary>
		/// <remarks>
		///     Everything needs to be updated spatially before this function is
		///     called including portal corners, frustum planes, etc.
		/// </remarks>
		/// <param name="portal">
		///     The <see cref="Portal"/> to check visibility against.
		/// </param>
		/// <param name="culledBy">
		///     The <see cref="FrustumPlane"/> that the Portal is in.
		/// </param>
		/// <returns>
		///     true if the Portal is visible.
		/// </returns>
		public bool IsObjectVisible( Portal portal, out FrustumPlane culledBy )
		{
			culledBy = FrustumPlane.None;

			// if portal isn't open, it's not visible
			if ( !portal.IsOpen )
			{
				return false;
			}

			// check the extra frustum first
			if ( !this.extraCullingFrustum.IsObjectVisible( portal ) )
			{
				return false;
			}

			// if portal is of type AABB or Sphere, then use simple bound check against planes
			if ( portal.Type == PORTAL_TYPE.PORTAL_TYPE_AABB )
			{
				var aabb = new AxisAlignedBox( portal.getDerivedCorner( 0 ), portal.getDerivedCorner( 1 ) );
				return base.IsObjectVisible( aabb, out culledBy );
			}
			else if ( portal.Type == PORTAL_TYPE.PORTAL_TYPE_SPHERE )
			{
				return base.IsObjectVisible( portal.getDerivedSphere(), out culledBy );
			}

			// check if the portal norm is facing the camera
			Vector3 cameraToPortal = portal.getDerivedCP() - DerivedPosition;
			Vector3 portalDirection = portal.getDerivedDirection();
			Real dotProduct = cameraToPortal.Dot( portalDirection );
			if ( dotProduct > 0 )
			{
				// portal is faced away from camera
				return false;
			}
			// check against regular frustum planes
			bool visible_flag;
			if ( null != CullFrustum )
			{
				// For each frustum plane, see if all points are on the negative side
				// If so, object is not visible
				// NOTE: We skip the NEAR plane (plane #0) because Portals need to
				// be visible no matter how close you get to them.

				for ( int plane = 1; plane < 6; ++plane )
				{
					// set the visible flag to false
					visible_flag = false;
					// Skip far plane if infinite view frustum
					if ( (FrustumPlane)plane == FrustumPlane.Far && _farDistance == 0 )
					{
						continue;
					}

					// we have to check each corner of the portal
					for ( int corner = 0; corner < 4; corner++ )
					{
						PlaneSide side = CullFrustum.FrustumPlanes[ plane ].GetSide( portal.getDerivedCorner( corner ) );
						if ( side != PlaneSide.Negative )
						{
							visible_flag = true;
						}
					}
					// if the visible_flag is still false, then this plane
					// culled all the portal points
					if ( visible_flag == false )
					{
						// ALL corners on negative side therefore out of view
						if ( culledBy != FrustumPlane.None )
						{
							culledBy = (FrustumPlane)plane;
						}
						return false;
					}
				}
			}
			else
			{
				// Make any pending updates to the calculated frustum planes
				UpdateFrustumPlanes();

				// For each frustum plane, see if all points are on the negative side
				// If so, object is not visible
				// NOTE: We skip the NEAR plane (plane #0) because Portals need to
				// be visible no matter how close you get to them.
				// BUGBUG: This can cause a false positive situation when a portal is
				// behind the camera but close.  This could be fixed by having another
				// culling plane at the camera location with normal same as camera direction.
				for ( int plane = 1; plane < 6; ++plane )
				{
					// set the visible flag to false
					visible_flag = false;
					// Skip far plane if infinite view frustum
					if ( (FrustumPlane)plane == FrustumPlane.Far && _farDistance == 0 )
					{
						continue;
					}

					// we have to check each corner of the portal
					for ( int corner = 0; corner < 4; corner++ )
					{
						PlaneSide side = _planes[ plane ].GetSide( portal.getDerivedCorner( corner ) );
						if ( side != PlaneSide.Negative )
						{
							visible_flag = true;
						}
					}
					// if the visible_flag is still false, then this plane
					// culled all the portal points
					if ( visible_flag == false )
					{
						// ALL corners on negative side therefore out of view
						if ( culledBy != FrustumPlane.None )
						{
							culledBy = (FrustumPlane)plane;
						}
						return false;
					}
				}
			}
			// no plane culled all the portal points and the norm
			// was facing the camera, so this portal is visible
			return true;
		}
Esempio n. 25
0
 public override Plane GetFrustumPlane(FrustumPlane plane)
 {
     if (cullingFrustum != null)
         return cullingFrustum.GetFrustumPlane(plane);
     else
         return base.GetFrustumPlane(plane);
 }
Esempio n. 26
0
		public new bool IsObjectVisible( AxisAlignedBox box, out FrustumPlane culledBy )
		{
			if ( null != CullFrustum )
			{
				return CullFrustum.IsObjectVisible( box, out culledBy );
			}
			else
			{
				return base.IsObjectVisible( box, out culledBy );
			}
		}
Esempio n. 27
0
 public override bool IsObjectVisible(Sphere bound, out FrustumPlane culledBy)
 {
     if (cullingFrustum != null)
         return cullingFrustum.IsObjectVisible(bound, out culledBy);
     else
         return base.IsObjectVisible(bound, out culledBy);
 }
Esempio n. 28
0
		public new bool IsObjectVisible( Vector3 vertex, out FrustumPlane culledBy )
		{
			if ( null != CullFrustum )
			{
				return CullFrustum.IsObjectVisible( vertex, out culledBy );
			}
			else
			{
				return base.IsObjectVisible( vertex, out culledBy );
			}
		}
Esempio n. 29
0
		/// <summary>
		/// 
		/// </summary>
		/// <param name="bound"></param>
		/// <param name="culledBy">Default is Near</param>
		/// <returns></returns>
		public new virtual bool IsVisible( AxisAlignedBox bound, FrustumPlane culledBy )
		{
			return true;
		}