getDerivedCorner() public method

public getDerivedCorner ( int index ) : Vector3
index int
return Vector3
Esempio n. 1
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. 2
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>
		/// <returns>
		///     true if the Portal is visible.
		/// </returns>
		public bool IsObjectVisible( Portal portal )
		{
			// if portal isn't open, it's not visible
			if ( !portal.IsOpen )
			{
				return false;
			}

			// if the frustum has no planes, just return true
			if ( mActiveCullingPlanes.Count == 0 )
			{
				return true;
			}
			// check if this portal is already in the list of active culling planes (avoid
			// infinite recursion case)
			foreach ( PCPlane plane in mActiveCullingPlanes )
			{
				if ( plane.Portal == 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 )
			{
				AxisAlignedBox aabb = new AxisAlignedBox();
				aabb.SetExtents( portal.getDerivedCorner( 0 ), portal.getDerivedCorner( 1 ) );
				return IsObjectVisible( aabb );
			}
			else if ( portal.Type == PORTAL_TYPE.PORTAL_TYPE_SPHERE )
			{
				return IsObjectVisible( portal.getDerivedSphere() );
			}

			// check if the portal norm is facing the frustum
			Vector3 frustumToPortal = portal.getDerivedCP() - mOrigin;
			Vector3 portalDirection = portal.getDerivedDirection();
			Real dotProduct = frustumToPortal.Dot( portalDirection );
			if ( dotProduct > 0 )
			{
				// portal is faced away from Frustum
				return false;
			}

			// check against frustum culling planes
			bool visible_flag;

			// Check originPlane if told to
			if ( mUseOriginPlane )
			{
				// set the visible flag to false
				visible_flag = false;
				// we have to check each corner of the portal
				for ( int corner = 0; corner < 4; corner++ )
				{
					PlaneSide side = mOriginPlane.GetSide( portal.getDerivedCorner( corner ) );
					if ( side != PlaneSide.Negative )
					{
						visible_flag = true;
					}
				}
				// if the visible_flag is still false, then the origin plane
				// culled all the portal points
				if ( visible_flag == false )
				{
					// ALL corners on negative side therefore out of view
					return false;
				}
			}

			// For each active culling plane, see if all portal points are on the negative
			// side. If so, the portal is not visible
			foreach ( PCPlane plane in mActiveCullingPlanes )
			{
				visible_flag = false;
				// we have to check each corner of the portal
				for ( int corner = 0; corner < 4; corner++ )
				{
					PlaneSide side = 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
					return false;
				}

			}

			// no plane culled all the portal points and the norm
			// was facing the frustum, so this portal is visible
			return true;
		}
Esempio n. 3
0
		// calculate  culling planes from portal and frustum
		// origin and add to list of culling planes
		// NOTE: returns 0 if portal was completely culled by existing planes
		//		 returns > 0 if culling planes are added (# is planes added)
		public int AddPortalCullingPlanes( Portal portal )
		{
			int addedcullingplanes = 0;

			// If portal is of type aabb or sphere, add a plane which is same as frustum
			// origin plane (ie. redundant).  We do this because we need the plane as a flag
			// to prevent infinite recursion
			if ( portal.Type == PORTAL_TYPE.PORTAL_TYPE_AABB ||
				portal.Type == PORTAL_TYPE.PORTAL_TYPE_SPHERE )
			{
				PCPlane newPlane = GetUnusedCullingPlane();
				newPlane.SetFromAxiomPlane( mOriginPlane );
				newPlane.Portal = portal;
				mActiveCullingPlanes.Add( newPlane );
				addedcullingplanes++;
				return addedcullingplanes;
			}

			// For portal Quads: Up to 4 planes can be added by the sides of a portal quad.
			// Each plane is created from 2 corners (world space) of the portal and the
			// frustum origin (world space).
			int i, j;
			PlaneSide pt0_side, pt1_side;
			bool visible;
			for ( i = 0; i < 4; i++ )
			{
				// first check if both corners are outside of one of the existing planes
				j = i + 1;
				if ( j > 3 )
				{
					j = 0;
				}
				visible = true;

				foreach ( PCPlane plane in mActiveCullingPlanes )
				{
					pt0_side = plane.GetSide( portal.getDerivedCorner( i ) );
					pt1_side = plane.GetSide( portal.getDerivedCorner( j ) );
					if ( pt0_side == PlaneSide.Negative &&
						pt1_side == PlaneSide.Negative )
					{
						// the portal edge was actually completely culled by one of  culling planes
						visible = false;
					}
				}
				if ( visible )
				{
					// add the plane created from the two portal corner points and the frustum location
					// to the  culling plane
					PCPlane newPlane = GetUnusedCullingPlane();
					if ( projType == Projection.Orthographic ) // use camera direction if projection is orthographic.
					{
						newPlane.Redefine( portal.getDerivedCorner( j ) + mOriginPlane.Normal,
							portal.getDerivedCorner( j ), portal.getDerivedCorner( i ) );
					}
					else
					{
						newPlane.Redefine( mOrigin, portal.getDerivedCorner( j ), portal.getDerivedCorner( i ) );
					}
					newPlane.Portal = portal;
					mActiveCullingPlanes.Add( newPlane );
					addedcullingplanes++;
				}
			}
			// if we added ANY planes from the quad portal, we should add the plane of the
			// portal itself as an additional culling plane.
			if ( addedcullingplanes > 0 )
			{
				PCPlane newPlane = GetUnusedCullingPlane();
				newPlane.Redefine( portal.getDerivedCorner( 2 ), portal.getDerivedCorner( 1 ), portal.getDerivedCorner( 0 ) );
				newPlane.Portal = portal;
				mActiveCullingPlanes.Add( newPlane );
				addedcullingplanes++;
			}
			return addedcullingplanes;
		}
Esempio n. 4
0
        // calculate  culling planes from portal and frustum
        // origin and add to list of culling planes
        // NOTE: returns 0 if portal was completely culled by existing planes
        //		 returns > 0 if culling planes are added (# is planes added)
        public int AddPortalCullingPlanes(Portal portal)
        {
            int addedcullingplanes = 0;

            // If portal is of type aabb or sphere, add a plane which is same as frustum
            // origin plane (ie. redundant).  We do this because we need the plane as a flag
            // to prevent infinite recursion
            if (portal.Type == PORTAL_TYPE.PORTAL_TYPE_AABB || portal.Type == PORTAL_TYPE.PORTAL_TYPE_SPHERE)
            {
                PCPlane newPlane = GetUnusedCullingPlane();
                newPlane.SetFromAxiomPlane(this.mOriginPlane);
                newPlane.Portal = portal;
                this.mActiveCullingPlanes.Add(newPlane);
                addedcullingplanes++;
                return(addedcullingplanes);
            }

            // For portal Quads: Up to 4 planes can be added by the sides of a portal quad.
            // Each plane is created from 2 corners (world space) of the portal and the
            // frustum origin (world space).
            int       i, j;
            PlaneSide pt0_side, pt1_side;
            bool      visible;

            for (i = 0; i < 4; i++)
            {
                // first check if both corners are outside of one of the existing planes
                j = i + 1;
                if (j > 3)
                {
                    j = 0;
                }
                visible = true;

                foreach (PCPlane plane in this.mActiveCullingPlanes)
                {
                    pt0_side = plane.GetSide(portal.getDerivedCorner(i));
                    pt1_side = plane.GetSide(portal.getDerivedCorner(j));
                    if (pt0_side == PlaneSide.Negative && pt1_side == PlaneSide.Negative)
                    {
                        // the portal edge was actually completely culled by one of  culling planes
                        visible = false;
                    }
                }
                if (visible)
                {
                    // add the plane created from the two portal corner points and the frustum location
                    // to the  culling plane
                    PCPlane newPlane = GetUnusedCullingPlane();
                    if (this.projType == Projection.Orthographic)                       // use camera direction if projection is orthographic.
                    {
                        newPlane.Redefine(portal.getDerivedCorner(j) + this.mOriginPlane.Normal, portal.getDerivedCorner(j),
                                          portal.getDerivedCorner(i));
                    }
                    else
                    {
                        newPlane.Redefine(this.mOrigin, portal.getDerivedCorner(j), portal.getDerivedCorner(i));
                    }
                    newPlane.Portal = portal;
                    this.mActiveCullingPlanes.Add(newPlane);
                    addedcullingplanes++;
                }
            }
            // if we added ANY planes from the quad portal, we should add the plane of the
            // portal itself as an additional culling plane.
            if (addedcullingplanes > 0)
            {
                PCPlane newPlane = GetUnusedCullingPlane();
                newPlane.Redefine(portal.getDerivedCorner(2), portal.getDerivedCorner(1), portal.getDerivedCorner(0));
                newPlane.Portal = portal;
                this.mActiveCullingPlanes.Add(newPlane);
                addedcullingplanes++;
            }
            return(addedcullingplanes);
        }
Esempio n. 5
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>
        /// <returns>
        ///     true if the Portal is visible.
        /// </returns>
        public bool IsObjectVisible(Portal portal)
        {
            // if portal isn't open, it's not visible
            if (!portal.IsOpen)
            {
                return(false);
            }

            // if the frustum has no planes, just return true
            if (this.mActiveCullingPlanes.Count == 0)
            {
                return(true);
            }
            // check if this portal is already in the list of active culling planes (avoid
            // infinite recursion case)
            foreach (PCPlane plane in this.mActiveCullingPlanes)
            {
                if (plane.Portal == 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();
                aabb.SetExtents(portal.getDerivedCorner(0), portal.getDerivedCorner(1));
                return(IsObjectVisible(aabb));
            }
            else if (portal.Type == PORTAL_TYPE.PORTAL_TYPE_SPHERE)
            {
                return(IsObjectVisible(portal.getDerivedSphere()));
            }

            // check if the portal norm is facing the frustum
            Vector3 frustumToPortal = portal.getDerivedCP() - this.mOrigin;
            Vector3 portalDirection = portal.getDerivedDirection();
            Real    dotProduct      = frustumToPortal.Dot(portalDirection);

            if (dotProduct > 0)
            {
                // portal is faced away from Frustum
                return(false);
            }

            // check against frustum culling planes
            bool visible_flag;

            // Check originPlane if told to
            if (this.mUseOriginPlane)
            {
                // set the visible flag to false
                visible_flag = false;
                // we have to check each corner of the portal
                for (int corner = 0; corner < 4; corner++)
                {
                    PlaneSide side = this.mOriginPlane.GetSide(portal.getDerivedCorner(corner));
                    if (side != PlaneSide.Negative)
                    {
                        visible_flag = true;
                    }
                }
                // if the visible_flag is still false, then the origin plane
                // culled all the portal points
                if (visible_flag == false)
                {
                    // ALL corners on negative side therefore out of view
                    return(false);
                }
            }

            // For each active culling plane, see if all portal points are on the negative
            // side. If so, the portal is not visible
            foreach (PCPlane plane in this.mActiveCullingPlanes)
            {
                visible_flag = false;
                // we have to check each corner of the portal
                for (int corner = 0; corner < 4; corner++)
                {
                    PlaneSide side = 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
                    return(false);
                }
            }

            // no plane culled all the portal points and the norm
            // was facing the frustum, so this portal is visible
            return(true);
        }
Esempio n. 6
0
        /* This function check if *this* portal "crossed over" the other portal.
         */

        public bool crossedPortal(Portal otherPortal)
        {
            // Only check if portal is open
            if (otherPortal.mOpen)
            {
                // we model both portals as line swept spheres (mPrevDerivedCP to mDerivedCP).
                // intersection test is then between the capsules.
                // BUGBUG! This routine needs to check for case where one or both objects
                //         don't move - resulting in simple sphere tests
                // BUGBUG! If one (or both) portals are aabb's this is REALLY not accurate.
                Capsule portalCapsule, otherPortalCapsule;

                portalCapsule = new Capsule();
                portalCapsule.Set(getPrevDerivedCP(), getDerivedCP(), getRadius());

                otherPortalCapsule = new Capsule();
                otherPortalCapsule.Set(otherPortal.mPrevDerivedCP, otherPortal.mDerivedCP, otherPortal.mRadius);

                if (portalCapsule.Intersects(otherPortalCapsule))
                {
                    // the portal intersected the other portal at some time from last frame to this frame.
                    // Now check if this portal "crossed" the other portal
                    switch (otherPortal.Type)
                    {
                    case PORTAL_TYPE.PORTAL_TYPE_QUAD:
                        // a crossing occurs if the "side" of the final position of this portal compared
                        // to the final position of the other portal is negative AND the initial position
                        // of this portal compared to the initial position of the other portal is non-negative
                        // NOTE: This function assumes that this portal is the smaller portal potentially crossing
                        //       over the otherPortal which is larger.
                        if (otherPortal.getDerivedPlane().GetSide(this.mDerivedCP) == PlaneSide.Negative &&
                            otherPortal.getPrevDerivedPlane().GetSide(this.mPrevDerivedCP) != PlaneSide.Negative)
                        {
                            // crossing occurred!
                            return(true);
                        }
                        break;

                    case PORTAL_TYPE.PORTAL_TYPE_AABB:
                    {
                        // for aabb's we check if the center point went from being inside to being outside
                        // the aabb (or vice versa) for crossing.
                        var aabb = new AxisAlignedBox(otherPortal.getDerivedCorner(0), otherPortal.getDerivedCorner(1));
                        //bool previousInside = aabb.contains(mPrevDerivedCP);
                        bool currentInside = aabb.Contains(this.mDerivedCP);
                        if (otherPortal.getDerivedDirection() == Vector3.UnitZ)
                        {
                            // portal norm is "outward" pointing, look for going from outside to inside
                            //if (previousInside == false &&
                            if (currentInside == true)
                            {
                                return(true);
                            }
                        }
                        else
                        {
                            // portal norm is "inward" pointing, look for going from inside to outside
                            //if (previousInside == true &&
                            if (currentInside == false)
                            {
                                return(true);
                            }
                        }
                    }
                    break;

                    case PORTAL_TYPE.PORTAL_TYPE_SPHERE:
                    {
                        // for spheres we check if the center point went from being inside to being outside
                        // the sphere surface (or vice versa) for crossing.
                        //Real previousDistance2 = mPrevDerivedCP.squaredDistance(otherPortal->getPrevDerivedCP());
                        Real currentDistance2 = this.mDerivedCP.DistanceSquared(otherPortal.getDerivedCP());
                        Real mRadius2         = System.Math.Sqrt(otherPortal.getRadius());
                        if (otherPortal.getDerivedDirection() == Vector3.UnitZ)
                        {
                            // portal norm is "outward" pointing, look for going from outside to inside
                            //if (previousDistance2 >= mRadius2 &&
                            if (currentDistance2 < mRadius2)
                            {
                                return(true);
                            }
                        }
                        else
                        {
                            // portal norm is "inward" pointing, look for going from inside to outside
                            //if (previousDistance2 < mRadius2 &&
                            if (currentDistance2 >= mRadius2)
                            {
                                return(true);
                            }
                        }
                    }
                    break;
                    }
                }
            }
            // there was no crossing of the portal by this portal. It might be touching
            // the other portal (but we don't care currently)
            return(false);
        }
Esempio n. 7
0
		/* This function check if *this* portal "crossed over" the other portal.
		*/
		public bool crossedPortal( Portal otherPortal )
		{
			// Only check if portal is open
			if ( otherPortal.mOpen )
			{
				// we model both portals as line swept spheres (mPrevDerivedCP to mDerivedCP).
				// intersection test is then between the capsules.
				// BUGBUG! This routine needs to check for case where one or both objects
				//         don't move - resulting in simple sphere tests
				// BUGBUG! If one (or both) portals are aabb's this is REALLY not accurate.
				Capsule portalCapsule, otherPortalCapsule;

				portalCapsule = new Capsule();
				portalCapsule.Set( this.getPrevDerivedCP(), this.getDerivedCP(), this.getRadius() );

				otherPortalCapsule = new Capsule();
				otherPortalCapsule.Set( otherPortal.mPrevDerivedCP,
									   otherPortal.mDerivedCP,
									   otherPortal.mRadius );

				if ( portalCapsule.Intersects( otherPortalCapsule ) )
				{
					// the portal intersected the other portal at some time from last frame to this frame.
					// Now check if this portal "crossed" the other portal
					switch ( otherPortal.Type )
					{
						case PORTAL_TYPE.PORTAL_TYPE_QUAD:
							// a crossing occurs if the "side" of the final position of this portal compared
							// to the final position of the other portal is negative AND the initial position
							// of this portal compared to the initial position of the other portal is non-negative
							// NOTE: This function assumes that this portal is the smaller portal potentially crossing
							//       over the otherPortal which is larger.
							if ( otherPortal.getDerivedPlane().GetSide( mDerivedCP ) == PlaneSide.Negative &&
								otherPortal.getPrevDerivedPlane().GetSide( mPrevDerivedCP ) != PlaneSide.Negative )
							{
								// crossing occurred!
								return true;
							}
							break;
						case PORTAL_TYPE.PORTAL_TYPE_AABB:
							{
								// for aabb's we check if the center point went from being inside to being outside
								// the aabb (or vice versa) for crossing.
								AxisAlignedBox aabb = new AxisAlignedBox( otherPortal.getDerivedCorner( 0 ), otherPortal.getDerivedCorner( 1 ) );
								//bool previousInside = aabb.contains(mPrevDerivedCP);
								bool currentInside = aabb.Contains( mDerivedCP );
								if ( otherPortal.getDerivedDirection() == Vector3.UnitZ )
								{
									// portal norm is "outward" pointing, look for going from outside to inside
									//if (previousInside == false &&
									if ( currentInside == true )
									{
										return true;
									}
								}
								else
								{
									// portal norm is "inward" pointing, look for going from inside to outside
									//if (previousInside == true &&
									if ( currentInside == false )
									{
										return true;
									}
								}
							}
							break;
						case PORTAL_TYPE.PORTAL_TYPE_SPHERE:
							{
								// for spheres we check if the center point went from being inside to being outside
								// the sphere surface (or vice versa) for crossing.
								//Real previousDistance2 = mPrevDerivedCP.squaredDistance(otherPortal->getPrevDerivedCP());
								Real currentDistance2 = mDerivedCP.DistanceSquared( otherPortal.getDerivedCP() );
								Real mRadius2 = System.Math.Sqrt( otherPortal.getRadius() );
								if ( otherPortal.getDerivedDirection() == Vector3.UnitZ )
								{
									// portal norm is "outward" pointing, look for going from outside to inside
									//if (previousDistance2 >= mRadius2 &&
									if ( currentDistance2 < mRadius2 )
									{
										return true;
									}
								}
								else
								{
									// portal norm is "inward" pointing, look for going from inside to outside
									//if (previousDistance2 < mRadius2 &&
									if ( currentDistance2 >= mRadius2 )
									{
										return true;
									}
								}
							}
							break;
					}
				}
			}
			// there was no crossing of the portal by this portal. It might be touching
			// the other portal (but we don't care currently)
			return false;
		}
Esempio n. 8
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);
        }