예제 #1
0
		/** Indicates whether or not this zone requires zone-specific data for
		*  each scene node
		*/

		/* Add a portal to the zone
		*/
		public override void AddPortal( Portal newPortal )
		{
			if ( null != newPortal )
			{
				// make sure portal is unique (at least in this zone)
				if ( mPortals.Contains( newPortal ) )
				{
					throw new AxiomException( "A portal with the name " + newPortal.getName() + "already exists. DefaultZone._addPortal" );
				}

				// add portal to portals list
				mPortals.Add( newPortal );

				// tell the portal which zone it's currently in
				newPortal.setCurrentHomeZone( this );
			}
		}
예제 #2
0
		/* Recursively check for intersection of the given scene node
		 * with zone portals.  If the node touches a portal, then the
		 * connected zone is assumed to be touched.  The zone adds
		 * the node to its node list and the node adds the zone to
		 * its visiting zone list.
		 *
		 * NOTE: This function assumes that the home zone of the node
		 *       is correct.  The function "_updateHomeZone" in PCZSceneManager
		 *		 takes care of this and should have been called before
		 *		 this function.
		 */

		public override void CheckNodeAgainstPortals( PCZSceneNode pczsn, Portal ignorePortal )
		{
			if ( pczsn == mEnclosureNode ||
				pczsn.AllowToVisit == false )
			{
				// don't do any checking of enclosure node versus portals
				return;
			}

			PCZone connectedZone;
			foreach ( Portal portal in mPortals )
			{
				if ( portal != ignorePortal && portal.intersects( pczsn ) != PortalIntersectResult.NO_INTERSECT )
				{
					connectedZone = portal.getTargetZone();

					if ( connectedZone != pczsn.HomeZone &&
						!pczsn.IsVisitingZone( connectedZone ) )
					{
						pczsn.AddZoneToVisitingZonesMap( connectedZone );

						connectedZone.AddNode( pczsn );

						connectedZone.CheckNodeAgainstPortals( pczsn, portal.getTargetPortal() );
					}
				}
			}
		}
예제 #3
0
		/* Remove a portal from the zone
		*/
		public abstract void RemovePortal( Portal portal );
예제 #4
0
		/** (recursive) check the given light against all portals in the zone
		*/

		public abstract void CheckLightAgainstPortals( PCZLight light, ulong frameCount, PCZFrustum portalFrustum,
		                                               Portal ignorePortal );
예제 #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>
		/// <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;
		}
예제 #6
0
		// remove extra culling planes created from the given portal
		// NOTE: This should only be used during visibility traversal (backing out of a recursion)
		public void RemovePortalCullingPlanes( Portal portal )
		{
			this.extraCullingFrustum.RemovePortalCullingPlanes( portal );
		}
예제 #7
0
		// Create a portal instance
		public Portal CreatePortal( String name, PORTAL_TYPE type )
		{
			var newPortal = new Portal( name, type );
			this.portals.Add( newPortal );
			return newPortal;
		}
예제 #8
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;
		}
예제 #9
0
파일: Portal.cs 프로젝트: WolfgangSt/axiom
		/* 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;
		}
예제 #10
0
파일: PCPlane.cs 프로젝트: WolfgangSt/axiom
		public PCPlane()
		{
			mPortal = null;
		}
예제 #11
0
파일: Portal.cs 프로젝트: WolfgangSt/axiom
		// Set the Portal the Portal connects to
		public void setTargetPortal( Portal p )
		{
			mTargetPortal = p;
		}
예제 #12
0
파일: Portal.cs 프로젝트: WolfgangSt/axiom
		public Portal( string name, PORTAL_TYPE type )
		{
			mType = type;
			mName = name;
			mTargetZone = null;
			mCurrentHomeZone = null;
			mNewHomeZone = null;
			mTargetPortal = null;
			mNode = null;
			mRadius = 0.0;
			mDirection = Math.Vector3.UnitZ;
			mLocalsUpToDate = false;
			mDerivedSphere = new Sphere();
			mDerivedPlane = new Plane();
			// set prevWorldTransform to a zero'd out matrix
			prevWorldTransform = Math.Matrix4.Zero;
			// default to open
			mOpen = true;
			switch ( mType )
			{
				default:
				case PORTAL_TYPE.PORTAL_TYPE_QUAD:
					mCorners = new Vector3[ 4 ];
					mDerivedCorners = new Vector3[ 4 ];
					break;
				case PORTAL_TYPE.PORTAL_TYPE_AABB:
					mCorners = new Vector3[ 2 ];
					mDerivedCorners = new Vector3[ 2 ];
					break;
				case PORTAL_TYPE.PORTAL_TYPE_SPHERE:
					mCorners = new Vector3[ 2 ];
					mDerivedCorners = new Vector3[ 2 ];
					break;
			}
		}
예제 #13
0
파일: Portal.cs 프로젝트: WolfgangSt/axiom
		// check if portal is close to another portal.
		// Note, both portals are assumed to be stationary
		// and DerivedCP is the current position.
		// this function is INTENTIONALLY NOT EXACT because
		// it is used by PCZSM::connectPortalsToTargetZonesByLocation
		// which is a utility function to link up nearby portals
		//
		public bool closeTo( Portal otherPortal )
		{
			// only portals of the same type can be "close to" each other.
			if ( mType != otherPortal.Type )
			{
				return false;
			}
			bool close = false;
			switch ( mType )
			{
				default:
				case PORTAL_TYPE.PORTAL_TYPE_QUAD:
					{
						// quad portals must be within 1/4 sphere of each other
						Sphere quarterSphere1 = mDerivedSphere;
						quarterSphere1.Radius = quarterSphere1.Radius * 0.25f;
						Sphere quarterSphere2 = otherPortal.getDerivedSphere();
						quarterSphere2.Radius = quarterSphere2.Radius * 0.25f;
						close = quarterSphere1.Intersects( quarterSphere2 );
					}
					break;
				case PORTAL_TYPE.PORTAL_TYPE_AABB:
					// NOTE: AABB's must match perfectly
					if ( mDerivedCP == otherPortal.getDerivedCP() &&
						mCorners[ 0 ] == otherPortal.getCorner( 0 ) &&
						mCorners[ 1 ] == otherPortal.getCorner( 1 ) )
					{
						close = true;
					}
					break;
				case PORTAL_TYPE.PORTAL_TYPE_SPHERE:
					// NOTE: Spheres must match perfectly
					if ( mDerivedCP == otherPortal.getDerivedCP() &&
						mRadius == otherPortal.getRadius() )
					{
						close = true;
					}
					break;
			}
			return close;
		}
예제 #14
0
		// Set the Portal the Portal connects to
		public void setTargetPortal( Portal p )
		{
			this.mTargetPortal = p;
		}
예제 #15
0
		// delete a portal instance by pointer
		public void DestroyPortal( Portal p )
		{
			// remove the portal from it's target portal
			Portal targetPortal = p.getTargetPortal();
			if ( null != targetPortal )
			{
				targetPortal.setTargetPortal( null );
				// the targetPortal will still have targetZone value, but targetPortal will be invalid
			}
			// remove the Portal from it's home zone
			PCZone homeZone = p.getCurrentHomeZone();
			if ( null != homeZone )
			{
				// inform zone of portal change. Do here since PCZone is abstract
				homeZone.PortalsUpdated = true;
				homeZone.RemovePortal( p );
			}

			// remove the portal from the master portal list
			this.portals.Remove( p );
		}
예제 #16
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;
		}
예제 #17
0
		public void SetFromAxiomPlane( Plane axiomPlane )
		{
			this.plane = new Plane( this.plane );
			this.mPortal = null;
		}
예제 #18
0
		// remove culling planes created from the given portal
		public void RemovePortalCullingPlanes( Portal portal )
		{
			for ( int i = 0; i < mActiveCullingPlanes.Count; i++ )
			{
				PCPlane plane = mActiveCullingPlanes[ i ];
				if ( plane.Portal == portal )
				{
					mCullingPlaneReservoir.Add( plane );
					mActiveCullingPlanes.Remove( plane );
				}
			}
		}
예제 #19
0
		public PCPlane()
		{
			this.mPortal = null;
		}
예제 #20
0
		// calculate extra culling planes from portal and camera
		// origin and add to list of extra 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 )
		{
			// add the extra culling planes from the portal
			return this.extraCullingFrustum.AddPortalCullingPlanes( portal );
		}
예제 #21
0
		public PCPlane( Plane plane )
		{
			this.plane = new Plane( plane );
			this.mPortal = null;
		}
예제 #22
0
		/* Add a portal to the zone
		*/
		public abstract void AddPortal( Portal portal );
예제 #23
0
		public PCPlane( Vector3 rkNormal, Vector3 rkPoint )
		{
			this.plane = new Plane( rkNormal, rkPoint );
			this.mPortal = null;
		}
예제 #24
0
		/** (recursive) check the given node against all portals in the zone
		*/
		public abstract void CheckNodeAgainstPortals( PCZSceneNode pczsn, Portal ignorePortal );
예제 #25
0
		public PCPlane( Vector3 rkPoint0, Vector3 rkPoint1, Vector3 rkPoint2 )
		{
			this.plane = new Plane( rkPoint0, rkPoint1, rkPoint2 );
			this.mPortal = null;
		}
예제 #26
0
		public virtual Portal FindMatchingPortal( Portal portal )
		{
			// look through all the portals in zone2 for a match

			foreach ( Portal portal2 in this.mPortals )
			{
				//portal2 = pi2;
				//portal2->updateDerivedValues();
				if ( portal2.getTargetZone() == null && portal2.closeTo( portal ) &&
				     portal2.getDerivedDirection().Dot( portal.getDerivedDirection() ) < -0.9 )
				{
					// found a match!
					return portal2;
				}
			}

			return null;
		}
예제 #27
0
		public override void RemovePortal( Portal portal )
		{
			if ( null != portal )
			{
				mPortals.Remove( portal );
			}
		}
예제 #28
0
		/* Remove a portal from the zone (does not erase the portal object, just removes reference)
		*/
		public override void RemovePortal( Portal removePortal )
		{
			if ( null != removePortal && mPortals.Contains( removePortal ) )
			{
				mPortals.Remove( removePortal );
			}
		}
예제 #29
0
		public override void CheckNodeAgainstPortals( PCZSceneNode pczsn, Portal ignorePortal )
		{
			if ( pczsn == mEnclosureNode ||
				pczsn.AllowToVisit == false )
			{
				// don't do any checking of enclosure node versus portals
				return;
			}

			PCZone connectedZone;
			foreach ( Portal p in mPortals )
			{
				//Check if the portal intersects the node
				if ( p != ignorePortal &&
					p.intersects( pczsn ) != PortalIntersectResult.NO_INTERSECT )
				{
					// node is touching this portal
					connectedZone = p.getTargetZone();
					// add zone to the nodes visiting zone list unless it is the home zone of the node
					if ( connectedZone != pczsn.HomeZone &&
						!pczsn.IsVisitingZone( connectedZone ) )
					{
						pczsn.AddZoneToVisitingZonesMap( connectedZone );
						// tell the connected zone that the node is visiting it
						connectedZone.AddNode( pczsn );
						//recurse into the connected zone
						connectedZone.CheckNodeAgainstPortals( pczsn, p.getTargetPortal() );
					}
				}
			}
		}
예제 #30
0
		/** (recursive) check the given light against all portals in the zone
		* NOTE: This is the default implementation, which doesn't take advantage
		*       of any zone-specific optimizations for checking portal visibility
		*/
		public override void CheckLightAgainstPortals( PCZLight light, ulong frameCount, PCZFrustum portalFrustum, Portal ignorePortal )
		{
			foreach ( Portal p in mPortals )
			{
				//Portal * p = *it;
				if ( p != ignorePortal )
				{
					// calculate the direction vector from light to portal
					Vector3 lightToPortal = p.getDerivedCP() - light.GetDerivedPosition();
					if ( portalFrustum.IsObjectVisible( p ) )
					{
						// portal is facing the light, but some light types need to
						// check illumination radius too.
						PCZone targetZone = p.getTargetZone();
						switch ( light.Type )
						{
							case LightType.Point:
								// point lights - just check if within illumination range
								if ( lightToPortal.Length <= light.AttenuationRange )
								{
									// if portal is quad portal it must be pointing towards the light
									if ( ( p.Type == PORTAL_TYPE.PORTAL_TYPE_QUAD && lightToPortal.Dot( p.getDerivedDirection() ) < 0.0 ) ||
										( p.Type != PORTAL_TYPE.PORTAL_TYPE_QUAD ) )
									{
										if ( !light.AffectsZone( targetZone ) )
										{
											light.AddZoneToAffectedZonesList( targetZone );
											if ( targetZone.LastVisibleFrame == frameCount )
											{
												light.AffectsVisibleZone = true;
											}
											// set culling frustum from the portal
											portalFrustum.AddPortalCullingPlanes( p );
											// recurse into the target zone of the portal
											p.getTargetZone().CheckLightAgainstPortals( light,
																						frameCount,
																						portalFrustum,
																						p.getTargetPortal() );
											// remove the planes added by this portal
											portalFrustum.RemovePortalCullingPlanes( p );
										}
									}
								}
								break;
							case LightType.Directional:
								// directionals have infinite range, so just make sure
								// the direction is facing the portal
								if ( lightToPortal.Dot( light.DerivedDirection ) >= 0.0 )
								{
									// if portal is quad portal it must be pointing towards the light
									if ( ( p.Type == PORTAL_TYPE.PORTAL_TYPE_QUAD && lightToPortal.Dot( p.getDerivedDirection() ) < 0.0 ) ||
										( p.Type == PORTAL_TYPE.PORTAL_TYPE_QUAD ) )
									{
										if ( !light.AffectsZone( targetZone ) )
										{
											light.AddZoneToAffectedZonesList( targetZone );
											if ( targetZone.LastVisibleFrame == frameCount )
											{
												light.AffectsVisibleZone = true;
											}
											// set culling frustum from the portal
											portalFrustum.AddPortalCullingPlanes( p );
											// recurse into the target zone of the portal
											p.getTargetZone().CheckLightAgainstPortals( light,
																						frameCount,
																						portalFrustum,
																						p.getTargetPortal() );
											// remove the planes added by this portal
											portalFrustum.RemovePortalCullingPlanes( p );
										}
									}
								}
								break;
							case LightType.Spotlight:
								// spotlights - just check if within illumination range
								// Technically, we should check if the portal is within
								// the cone of illumination, but for now, we'll leave that
								// as a future optimisation.
								if ( lightToPortal.Length <= light.AttenuationRange )
								{
									// if portal is quad portal it must be pointing towards the light
									if ( ( p.Type == PORTAL_TYPE.PORTAL_TYPE_QUAD && lightToPortal.Dot( p.getDerivedDirection() ) < 0.0 ) ||
										( p.Type != PORTAL_TYPE.PORTAL_TYPE_QUAD ) )
									{
										if ( !light.AffectsZone( targetZone ) )
										{
											light.AddZoneToAffectedZonesList( targetZone );
											if ( targetZone.LastVisibleFrame == frameCount )
											{
												light.AffectsVisibleZone = true;
											}
											// set culling frustum from the portal
											portalFrustum.AddPortalCullingPlanes( p );
											// recurse into the target zone of the portal
											p.getTargetZone().CheckLightAgainstPortals( light,
																						frameCount,
																						portalFrustum,
																						p.getTargetPortal() );
											// remove the planes added by this portal
											portalFrustum.RemovePortalCullingPlanes( p );
										}
									}
								}
								break;
						}
					}
				}
			}
		}
예제 #31
0
        /** (recursive) check the given light against all portals in the zone
         * NOTE: This is the default implementation, which doesn't take advantage
         *       of any zone-specific optimizations for checking portal visibility
         */

        public override void CheckLightAgainstPortals(PCZLight light, ulong frameCount, PCZFrustum portalFrustum,
                                                      Portal ignorePortal)
        {
            foreach (Portal p in mPortals)
            {
                //Portal * p = *it;
                if (p != ignorePortal)
                {
                    // calculate the direction vector from light to portal
                    Vector3 lightToPortal = p.getDerivedCP() - light.GetDerivedPosition();
                    if (portalFrustum.IsObjectVisible(p))
                    {
                        // portal is facing the light, but some light types need to
                        // check illumination radius too.
                        PCZone targetZone = p.getTargetZone();
                        switch (light.Type)
                        {
                        case LightType.Point:
                            // point lights - just check if within illumination range
                            if (lightToPortal.Length <= light.AttenuationRange)
                            {
                                // if portal is quad portal it must be pointing towards the light
                                if ((p.Type == PORTAL_TYPE.PORTAL_TYPE_QUAD && lightToPortal.Dot(p.getDerivedDirection()) < 0.0) ||
                                    (p.Type != PORTAL_TYPE.PORTAL_TYPE_QUAD))
                                {
                                    if (!light.AffectsZone(targetZone))
                                    {
                                        light.AddZoneToAffectedZonesList(targetZone);
                                        if (targetZone.LastVisibleFrame == frameCount)
                                        {
                                            light.AffectsVisibleZone = true;
                                        }
                                        // set culling frustum from the portal
                                        portalFrustum.AddPortalCullingPlanes(p);
                                        // recurse into the target zone of the portal
                                        p.getTargetZone().CheckLightAgainstPortals(light, frameCount, portalFrustum, p.getTargetPortal());
                                        // remove the planes added by this portal
                                        portalFrustum.RemovePortalCullingPlanes(p);
                                    }
                                }
                            }
                            break;

                        case LightType.Directional:
                            // directionals have infinite range, so just make sure
                            // the direction is facing the portal
                            if (lightToPortal.Dot(light.DerivedDirection) >= 0.0)
                            {
                                // if portal is quad portal it must be pointing towards the light
                                if ((p.Type == PORTAL_TYPE.PORTAL_TYPE_QUAD && lightToPortal.Dot(p.getDerivedDirection()) < 0.0) ||
                                    (p.Type == PORTAL_TYPE.PORTAL_TYPE_QUAD))
                                {
                                    if (!light.AffectsZone(targetZone))
                                    {
                                        light.AddZoneToAffectedZonesList(targetZone);
                                        if (targetZone.LastVisibleFrame == frameCount)
                                        {
                                            light.AffectsVisibleZone = true;
                                        }
                                        // set culling frustum from the portal
                                        portalFrustum.AddPortalCullingPlanes(p);
                                        // recurse into the target zone of the portal
                                        p.getTargetZone().CheckLightAgainstPortals(light, frameCount, portalFrustum, p.getTargetPortal());
                                        // remove the planes added by this portal
                                        portalFrustum.RemovePortalCullingPlanes(p);
                                    }
                                }
                            }
                            break;

                        case LightType.Spotlight:
                            // spotlights - just check if within illumination range
                            // Technically, we should check if the portal is within
                            // the cone of illumination, but for now, we'll leave that
                            // as a future optimisation.
                            if (lightToPortal.Length <= light.AttenuationRange)
                            {
                                // if portal is quad portal it must be pointing towards the light
                                if ((p.Type == PORTAL_TYPE.PORTAL_TYPE_QUAD && lightToPortal.Dot(p.getDerivedDirection()) < 0.0) ||
                                    (p.Type != PORTAL_TYPE.PORTAL_TYPE_QUAD))
                                {
                                    if (!light.AffectsZone(targetZone))
                                    {
                                        light.AddZoneToAffectedZonesList(targetZone);
                                        if (targetZone.LastVisibleFrame == frameCount)
                                        {
                                            light.AffectsVisibleZone = true;
                                        }
                                        // set culling frustum from the portal
                                        portalFrustum.AddPortalCullingPlanes(p);
                                        // recurse into the target zone of the portal
                                        p.getTargetZone().CheckLightAgainstPortals(light, frameCount, portalFrustum, p.getTargetPortal());
                                        // remove the planes added by this portal
                                        portalFrustum.RemovePortalCullingPlanes(p);
                                    }
                                }
                            }
                            break;
                        }
                    }
                }
            }
        }