Represents a convex volume bounded by planes.
Пример #1
0
		public override void FindNodes( PlaneBoundedVolume t,
									  ref List<PCZSceneNode> list,
									  List<Portal> visitedPortals,
									  bool includeVisitors,
									  bool recurseThruPortals,
									  PCZSceneNode exclude )
		{
			// if this zone has an enclosure, check against the enclosure AABB first
			if ( null != mEnclosureNode )
			{
				if ( !t.Intersects( mEnclosureNode.WorldAABB ) )
				{
					// AABB of zone does not intersect t, just return.
					return;
				}
			}

			// check nodes at home in this zone
			foreach ( PCZSceneNode pczsn in mHomeNodeList )
			{
				if ( pczsn != exclude )
				{
					// make sure node is not already in the list (might have been added in another
					// zone it was visiting)
					if ( !list.Contains( pczsn ) )
					{
						bool nsect = t.Intersects( pczsn.WorldAABB );
						if ( nsect )
						{
							list.Add( pczsn );
						}
					}
				}
			}

			if ( includeVisitors )
			{
				// check visitor nodes
				foreach ( PCZSceneNode pczsn in mVisitorNodeList )
				{
					if ( pczsn != exclude )
					{
						// make sure node is not already in the list (might have been added in another
						// zone it was visiting)
						if ( !list.Contains( pczsn ) )
						{
							bool nsect = t.Intersects( pczsn.WorldAABB );
							if ( nsect )
							{
								list.Add( pczsn );
							}
						}
					}
				}
			}

			// if asked to, recurse through portals
			if ( recurseThruPortals )
			{
				foreach ( Portal portal in mPortals )
				{
					// check portal versus boundign box
					if ( portal.intersects( t ) )
					{
						// make sure portal hasn't already been recursed through
						if ( !visitedPortals.Contains( portal ) )
						{
							// save portal to the visitedPortals list
							visitedPortals.Add( portal );
							// recurse into the connected zone
							portal.getTargetZone().FindNodes( t,
																ref list,
																visitedPortals,
																includeVisitors,
																recurseThruPortals,
																exclude );
						}
					}
				}
			}

		}
Пример #2
0
		private void CheckShadowCasters( IList casters,
										 PlaneBoundedVolume nearClipVol,
										 Light light,
										 bool extrudeInSoftware,
										 bool finiteExtrude,
										 bool zfailAlgo,
										 Camera camera,
										 float extrudeDistance,
										 bool stencil2sided,
										 LightList tmpLightList )
		{
			int flags;
			for ( int i = 0; i < casters.Count; i++ )
			{
				ShadowCaster caster = (ShadowCaster)casters[ i ];

				if ( nearClipVol.Intersects( caster.GetWorldBoundingBox() ) )
				{
					// We have a zfail case, we must use zfail for all objects
					zfailAlgo = true;

					break;
				}
			}

			for ( int ci = 0; ci < casters.Count; ci++ )
			{
				ShadowCaster caster = (ShadowCaster)casters[ ci ];
				flags = 0;

				if ( light.Type != LightType.Directional )
				{
					extrudeDistance = caster.GetPointExtrusionDistance( light );
				}

				if ( !extrudeInSoftware && !finiteExtrude )
				{
					// hardware extrusion, to infinity (and beyond!)
					flags |= (int)ShadowRenderableFlags.ExtrudeToInfinity;
				}

				if ( zfailAlgo )
				{
					// We need to include the light and / or dark cap
					// But only if they will be visible
					if ( camera.IsObjectVisible( caster.GetLightCapBounds() ) )
					{
						flags |= (int)ShadowRenderableFlags.IncludeLightCap;
					}
				}

				// Dark cap (no dark cap for directional lights using
				// hardware extrusion to infinity)
				if ( !( ( flags & (int)ShadowRenderableFlags.ExtrudeToInfinity ) != 0 &&
						light.Type == LightType.Directional ) &&
					 camera.IsObjectVisible( caster.GetDarkCapBounds( light, extrudeDistance ) ) )
				{
					flags |= (int)ShadowRenderableFlags.IncludeDarkCap;
				}

				// get shadow renderables
				IEnumerator renderables = caster.GetShadowVolumeRenderableEnumerator(
					this.shadowTechnique, light, this.shadowIndexBuffer, extrudeInSoftware, extrudeDistance, flags );

				// If using one-sided stencil, render the first pass of all shadow
				// renderables before all the second passes
				for ( int i = 0; i < ( stencil2sided ? 1 : 2 ); i++ )
				{
					if ( i == 1 )
					{
						renderables = caster.GetLastShadowVolumeRenderableEnumerator();
					}

					while ( renderables.MoveNext() )
					{
						ShadowRenderable sr = (ShadowRenderable)renderables.Current;

						// omit hidden renderables
						if ( sr.IsVisible )
						{
							// render volume, including dark and (maybe) light caps
							this.RenderSingleShadowVolumeToStencil( sr,
																	zfailAlgo,
																	stencil2sided,
																	tmpLightList,
																	( i > 0 ) );

							// optionally render separate light cap
							if ( sr.IsLightCapSeperate
								 && ( ( flags & (int)ShadowRenderableFlags.IncludeLightCap ) ) > 0 )
							{
								// must always fail depth check
								this.targetRenderSystem.DepthBufferFunction = CompareFunction.AlwaysFail;

								Debug.Assert( sr.LightCapRenderable != null,
											  "Shadow renderable is missing a separate light cap renderable!" );

								this.RenderSingleShadowVolumeToStencil( sr.LightCapRenderable,
																		zfailAlgo,
																		stencil2sided,
																		tmpLightList,
																		( i > 0 ) );
								// reset depth function
                                this.targetRenderSystem.DepthBufferFunction = CompareFunction.Less;
							}
						}
					}
				}
			}
		}
Пример #3
0
		protected virtual void ProcessLeaf( BspNode leaf )
		{
			//Check sphere against objects
			foreach ( MovableObject obj in leaf.Objects.Values )
			{
				// Skip this object if collision not enabled
				if ( ( obj.QueryFlags & queryMask ) == 0 )
				{
					continue;
				}

				//Test object as bounding box
				if ( sphere.Intersects( obj.GetWorldBoundingBox() ) )
				{
					if ( !this.foundIntersections.Contains( obj ) )
					{
						this.listener.OnQueryResult( obj );
						this.foundIntersections.Add( obj );
					}
				}
			}

			var boundedVolume = new PlaneBoundedVolume( PlaneSide.Positive );

			// Check ray against brushes
			for ( int brushPoint = 0; brushPoint < leaf.SolidBrushes.Length; brushPoint++ )
			{
				BspBrush brush = leaf.SolidBrushes[ brushPoint ];
				if ( brush == null )
				{
					continue;
				}

				boundedVolume.planes = brush.Planes;
				if ( boundedVolume.Intersects( sphere ) )
				{
					this.listener.OnQueryResult( brush.Fragment );
				}
			}
		}
Пример #4
0
		public abstract void FindNodes( PlaneBoundedVolume t, ref List<PCZSceneNode> list, List<Portal> visitedPortals,
		                                bool includeVisitors, bool recurseThruPortals, PCZSceneNode exclude );
Пример #5
0
		/// <summary>
		/// private method for selection object that creates a box from the SelectionRectangle, stop variable is passed in
		/// </summary>
		/// <param name="first">Vector2</param>
		/// <param name="second">Vector2</param>
		private void PerformSelectionWithSelectionBox( Math.Vector2 first, Math.Vector2 second )
		{
			Log( "MouseSelector: " + _name + " performing selection." );

			float left = first.x, right = second.x,
			top = first.y, bottom = second.y;

			if ( left > right )
				Utility.Swap( ref left, ref right );

			if ( top > bottom )
				Utility.Swap( ref top, ref bottom );

			if ( ( right - left ) * ( bottom - top ) < 0.0001 )
				return;

			Ray topLeft = _Camera.GetCameraToViewportRay( left, top );
			Ray topRight = _Camera.GetCameraToViewportRay( right, top );
			Ray bottomLeft = _Camera.GetCameraToViewportRay( left, bottom );
			Ray bottomRight = _Camera.GetCameraToViewportRay( right, bottom );

			Math.PlaneBoundedVolume vol = new PlaneBoundedVolume();
			vol.planes.Add( new Math.Plane( topLeft.GetPoint( 3 ), topRight.GetPoint( 3 ), bottomRight.GetPoint( 3 ) ) );         // front plane
			vol.planes.Add( new Math.Plane( topLeft.Origin, topLeft.GetPoint( 100 ), topRight.GetPoint( 100 ) ) );         // top plane
			vol.planes.Add( new Math.Plane( topLeft.Origin, bottomLeft.GetPoint( 100 ), topLeft.GetPoint( 100 ) ) );       // left plane
			vol.planes.Add( new Math.Plane( bottomLeft.Origin, bottomRight.GetPoint( 100 ), bottomLeft.GetPoint( 100 ) ) );   // bottom plane
			vol.planes.Add( new Math.Plane( topRight.Origin, topRight.GetPoint( 100 ), bottomRight.GetPoint( 100 ) ) );     // right plane

			PlaneBoundedVolumeList volList = new PlaneBoundedVolumeList();
			volList.Add( vol );

			PlaneBoundedVolumeListSceneQuery volQuery;

			volQuery = Root.Instance.SceneManager.CreatePlaneBoundedVolumeQuery( new PlaneBoundedVolumeList() );
			volQuery.Volumes = volList;
			SceneQueryResult result = volQuery.Execute();

			foreach ( MovableObject obj in result.objects )
			{
				SelectObject( obj );
			}
		}
Пример #6
0
		protected virtual void ProcessLeaf( BspNode leaf, Ray tracingRay, float maxDistance, float traceDistance )
		{
			//Check ray against objects
			foreach ( MovableObject obj in leaf.Objects.Values )
			{
				// Skip this object if collision not enabled
				if ( ( obj.QueryFlags & queryMask ) == 0 )
				{
					continue;
				}

				//Test object as bounding box
				IntersectResult result = tracingRay.Intersects( obj.GetWorldBoundingBox() );
				// if the result came back positive and intersection point is inside
				// the node, fire the event handler
				if ( result.Hit && result.Distance <= maxDistance )
				{
					this.listener.OnQueryResult( obj, result.Distance + traceDistance );
				}
			}

			var boundedVolume = new PlaneBoundedVolume( PlaneSide.Positive );
			BspBrush intersectBrush = null;
			float intersectBrushDist = float.PositiveInfinity;

			if ( ( QueryTypeMask & (ulong)SceneQueryTypeMask.WorldGeometry ) != 0 )
			{
				// Check ray against brushes
				if ( ( QueryTypeMask & (ulong)SceneQueryTypeMask.WorldGeometry ) != 0 )
				{
					for ( int brushPoint = 0; brushPoint < leaf.SolidBrushes.Length; brushPoint++ )
					{
						BspBrush brush = leaf.SolidBrushes[ brushPoint ];

						if ( brush == null )
						{
							continue;
						}

						boundedVolume.planes = brush.Planes;

						IntersectResult result = tracingRay.Intersects( boundedVolume );
						// if the result came back positive and intersection point is inside
						// the node, check if this brush is closer
						if ( result.Hit && result.Distance <= maxDistance )
						{
							if ( result.Distance < intersectBrushDist )
							{
								intersectBrushDist = result.Distance;
								intersectBrush = brush;
							}
						}
					}

					if ( intersectBrush != null )
					{
						this.listener.OnQueryResult( intersectBrush.Fragment, intersectBrushDist + traceDistance );
						this.StopRayTracing = true;
					}
				}
			}

			if ( intersectBrush != null )
			{
				this.listener.OnQueryResult( intersectBrush.Fragment, intersectBrushDist + traceDistance );
				this.StopRayTracing = true;
			}
		}
Пример #7
0
		/// <summary>
		/// Gets a world-space list of planes enclosing a volume based on a viewport rectangle.
		/// </summary>
		/// <param name="screenLeft">the left bound of the on-screen rectangle, expressed in normalized screen coordinates [0,1]</param>
		/// <param name="screenTop">the upper bound of the on-screen rectangle, expressed in normalized screen coordinates [0,1]</param>
		/// <param name="screenRight">the right bound of the on-screen rectangle, expressed in normalized screen coordinates [0,1]</param>
		/// <param name="screenBottom">the lower bound of the on-screen rectangle, expressed in normalized screen coordinates [0,1]</param>
		/// <param name="includeFarPlane">whether to include the far frustum plane</param>
		/// <remarks>
		/// Can be useful for populating a <see cref="PlaneBoundedVolumeListSceneQuery"/>, e.g. for a rubber-band selection.
		/// </remarks>
		/// <returns></returns>
		public PlaneBoundedVolume GetCameraToViewportBoxVolume( Real screenLeft, Real screenTop, Real screenRight,
		                                                        Real screenBottom, bool includeFarPlane )
		{
			var vol = new PlaneBoundedVolume();
			GetCameraToViewportBoxVolume( screenLeft, screenTop, screenRight, screenBottom, vol, includeFarPlane );
			return vol;
		}
Пример #8
0
		/// <summary>
		/// Gets a world-space list of planes enclosing a volume based on a viewport rectangle.
		/// </summary>
		/// <param name="screenLeft">the left bound of the on-screen rectangle, expressed in normalized screen coordinates [0,1]</param>
		/// <param name="screenTop">the upper bound of the on-screen rectangle, expressed in normalized screen coordinates [0,1]</param>
		/// <param name="screenRight">the right bound of the on-screen rectangle, expressed in normalized screen coordinates [0,1]</param>
		/// <param name="screenBottom">the lower bound of the on-screen rectangle, expressed in normalized screen coordinates [0,1]</param>
		/// <param name="outVolume">The plane list to populate with the result</param>
		/// <param name="includeFarPlane">whether to include the far frustum plane</param>
		/// <remarks>
		/// Can be useful for populating a <see cref="PlaneBoundedVolumeListSceneQuery"/>, e.g. for a rubber-band selection.
		/// </remarks>
		/// <returns></returns>
		public void GetCameraToViewportBoxVolume( Real screenLeft, Real screenTop, Real screenRight, Real screenBottom,
		                                          PlaneBoundedVolume outVolume, bool includeFarPlane )
		{
			outVolume.planes.Clear();

			if ( ProjectionType == Projection.Perspective )
			{
				// Use the corner rays to generate planes
				var ul = GetCameraToViewportRay( screenLeft, screenTop );
				var ur = GetCameraToViewportRay( screenRight, screenTop );
				var bl = GetCameraToViewportRay( screenLeft, screenBottom );
				var br = GetCameraToViewportRay( screenRight, screenBottom );

				// top plane
				var normal = ul.Direction.Cross( ur.Direction );
				normal.Normalize();
				outVolume.planes.Add( new Plane( normal, DerivedPosition ) );

				// right plane
				normal = ur.Direction.Cross( br.Direction );
				normal.Normalize();
				outVolume.planes.Add( new Plane( normal, DerivedPosition ) );

				// bottom plane
				normal = br.Direction.Cross( bl.Direction );
				normal.Normalize();
				outVolume.planes.Add( new Plane( normal, DerivedPosition ) );

				// left plane
				normal = bl.Direction.Cross( ul.Direction );
				normal.Normalize();
				outVolume.planes.Add( new Plane( normal, DerivedPosition ) );
			}
			else
			{
				// ortho planes are parallel to frustum planes

				var ul = GetCameraToViewportRay( screenLeft, screenTop );
				var br = GetCameraToViewportRay( screenRight, screenBottom );

				UpdateFrustumPlanes();
				outVolume.planes.Add( new Plane( FrustumPlanes[ (int)FrustumPlane.Top ].Normal, ul.Origin ) );
				outVolume.planes.Add( new Plane( FrustumPlanes[ (int)FrustumPlane.Right ].Normal, br.Origin ) );
				outVolume.planes.Add( new Plane( FrustumPlanes[ (int)FrustumPlane.Bottom ].Normal, br.Origin ) );
				outVolume.planes.Add( new Plane( FrustumPlanes[ (int)FrustumPlane.Left ].Normal, ul.Origin ) );
			}

			// near/far planes applicable to both projection types
			outVolume.planes.Add( new Plane( FrustumPlanes[ (int)FrustumPlane.Near ] ) );
			if ( includeFarPlane )
			{
				outVolume.planes.Add( new Plane( FrustumPlanes[ (int)FrustumPlane.Far ] ) );
			}
		}
Пример #9
0
		/** Checks how the axis aligned box intersects with the plane bounded volume
		*/

		private static Intersection intersect( PlaneBoundedVolume one, AxisAlignedBox two )
		{
			// Null box?
			if ( two.IsNull )
			{
				return Intersection.OUTSIDE;
			}
			// Infinite box?
			if ( two.IsInfinite )
			{
				return Intersection.INTERSECT;
			}

			// Get centre of the box
			Vector3 centre = two.Center;
			// Get the half-size of the box
			Vector3 halfSize = two.HalfSize;

			// For each plane, see if all points are on the negative side
			// If so, object is not visible.
			// If one or more are, it's partial.
			// If all aren't, full
			bool all_inside = true;


			foreach ( Plane plane in one.planes )
			{
				PlaneSide side = plane.GetSide( centre, halfSize );
				if ( side == one.outside )
				{
					return Intersection.OUTSIDE;
				}
				if ( side == PlaneSide.Both )
				{
					all_inside = false;
				}
			}

			if ( all_inside )
			{
				return Intersection.INSIDE;
			}
			else
			{
				return Intersection.INTERSECT;
			}
		}
Пример #10
0
		public void _findNodes( PlaneBoundedVolume t, ref List<PCZSceneNode> list, PCZSceneNode exclude, bool includeVisitors,
		                        bool full )
		{
			if ( !full )
			{
				AxisAlignedBox obox;
				_getCullBounds( out obox );

				Intersection isect = intersect( t, obox );

				if ( isect == Intersection.OUTSIDE )
				{
					return;
				}

				full = ( isect == Intersection.INSIDE );
			}


			foreach ( PCZSceneNode on in this.nodeList.Values )
			{
				if ( on != exclude && ( on.HomeZone == this.zone || includeVisitors ) )
				{
					if ( full )
					{
						// make sure the node isn't already on the list
						list.Add( on );
					}

					else
					{
						Intersection nsect = intersect( t, on.WorldAABB );

						if ( nsect != Intersection.OUTSIDE )
						{
							// make sure the node isn't already on the list
							list.Add( on );
						}
					}
				}
			}

			Octree child;

			if ( ( child = this.Children[ 0, 0, 0 ] ) != null )
			{
				child._findNodes( t, ref list, exclude, includeVisitors, full );
			}

			if ( ( child = this.Children[ 1, 0, 0 ] ) != null )
			{
				child._findNodes( t, ref list, exclude, includeVisitors, full );
			}

			if ( ( child = this.Children[ 0, 1, 0 ] ) != null )
			{
				child._findNodes( t, ref list, exclude, includeVisitors, full );
			}

			if ( ( child = this.Children[ 1, 1, 0 ] ) != null )
			{
				child._findNodes( t, ref list, exclude, includeVisitors, full );
			}

			if ( ( child = this.Children[ 0, 0, 1 ] ) != null )
			{
				child._findNodes( t, ref list, exclude, includeVisitors, full );
			}

			if ( ( child = this.Children[ 1, 0, 1 ] ) != null )
			{
				child._findNodes( t, ref list, exclude, includeVisitors, full );
			}

			if ( ( child = this.Children[ 0, 1, 1 ] ) != null )
			{
				child._findNodes( t, ref list, exclude, includeVisitors, full );
			}

			if ( ( child = this.Children[ 1, 1, 1 ] ) != null )
			{
				child._findNodes( t, ref list, exclude, includeVisitors, full );
			}
		}
Пример #11
0
		public override void FindNodes( PlaneBoundedVolume t, ref List<PCZSceneNode> list, List<Portal> visitedPortals, bool includeVisitors, bool recurseThruPortals, PCZSceneNode exclude )
		{
			// if this zone has an enclosure, check against the enclosure AABB first
			if ( null != mEnclosureNode )
			{
				if ( !t.Intersects( mEnclosureNode.WorldAABB ) )
				{
					// AABB of zone does not intersect t, just return.
					return;
				}
			}

			// use the Octree to more efficiently find nodes intersecting the plane bounded volume
			rootOctree._findNodes( t, ref list, exclude, includeVisitors, false );

			// if asked to, recurse through portals
			if ( recurseThruPortals )
			{
				foreach ( Portal portal in mPortals )
				{
					// check portal versus boundign box
					if ( portal.intersects( t ) )
					{
						// make sure portal hasn't already been recursed through

						if ( !visitedPortals.Contains( portal ) )
						{
							// save portal to the visitedPortals list
							visitedPortals.Add( portal );
							// recurse into the connected zone
							portal.getTargetZone().FindNodes( t,
															  ref list,
															  visitedPortals,
															  includeVisitors,
															  recurseThruPortals,
															  exclude );
						}
					}
				}
			}

		}
Пример #12
0
 /// <summary>
 ///		Tests whether this ray intersects the given PlaneBoundedVolume.
 /// </summary>
 /// <param name="volume"></param>
 /// <returns>
 ///		Struct containing info on whether there was a hit, and the distance from the
 ///		origin of this ray where the intersect happened.
 ///	</returns>
 public IntersectResult Intersects(PlaneBoundedVolume volume)
 {
     return(Utility.Intersects(this, volume));
 }
Пример #13
0
		public void FindNodesIn( PlaneBoundedVolume volumes, ref List<PCZSceneNode> list, PCZone startZone,
		                         PCZSceneNode exclude )
		{
			var visitedPortals = new List<Portal>();
			if ( null != startZone )
			{
				// start in startzone, and recurse through portals if necessary
				startZone.FindNodes( volumes, ref list, visitedPortals, true, true, exclude );
			}
			else
			{
				// no start zone specified, so check all zones
				foreach ( PCZone zone in this.zones )
				{
					zone.FindNodes( volumes, ref list, visitedPortals, false, false, exclude );
				}
			}
		}
Пример #14
0
 /// <summary>
 ///		Tests whether this ray intersects the given PlaneBoundedVolume. 
 /// </summary>
 /// <param name="volume"></param>
 /// <returns>
 ///		Struct containing info on whether there was a hit, and the distance from the 
 ///		origin of this ray where the intersect happened.
 ///	</returns>
 public IntersectResult Intersects( PlaneBoundedVolume volume )
 {
     return Utility.Intersects( this, volume );
 }
Пример #15
0
		// Check if a portal intersects a plane bounded volume
		// NOTE: This check is not exact.
		// NOTE: UNTESTED as of 5/30/07 (EC)
		public bool intersects( PlaneBoundedVolume pbv )
		{
			// Only check if portal is open
			if ( mOpen )
			{
				switch ( mType )
				{
					case PORTAL_TYPE.PORTAL_TYPE_QUAD:
						{
							// first check sphere of the portal
							if ( !pbv.Intersects( mDerivedSphere ) )
							{
								return false;
							}
							// if the portal corners are all outside one of the planes of the pbv,
							// then the portal does not intersect the pbv. (this can result in
							// some false positives, but it's the best I can do for now)
							foreach ( Plane plane in pbv.planes )
							{
								bool allOutside = true;
								for ( int i = 0; i < 4; i++ )
								{
									if ( plane.GetSide( mDerivedCorners[ i ] ) != pbv.outside )
									{
										allOutside = false;
									}
								}
								if ( allOutside )
								{
									return false;
								}

							}
						}
						break;
					case PORTAL_TYPE.PORTAL_TYPE_AABB:
						{
							AxisAlignedBox aabb = new AxisAlignedBox( mDerivedCorners[ 0 ], mDerivedCorners[ 1 ] );
							if ( !pbv.Intersects( aabb ) )
							{
								return false;
							}
						}
						break;
					case PORTAL_TYPE.PORTAL_TYPE_SPHERE:
						if ( !pbv.Intersects( mDerivedSphere ) )
						{
							return false;
						}
						break;
				}
			}
			return false;
		}