A standard sphere, used mostly for bounds checking.
A sphere in math texts is normally represented by the function x^2 + y^2 + z^2 = r^2 (for sphere's centered on the origin). We store spheres simply as a center point and a radius.
Пример #1
0
		public void Merge( AxisAlignedBox boxBounds, Sphere sphereBounds, Camera cam, bool receiver )
		{
			aabb.Merge( boxBounds );
			if ( receiver )
				receiverAabb.Merge( boxBounds );
			Real camDistToCenter = ( cam.DerivedPosition - sphereBounds.Center ).Length;
			minDistance = System.Math.Min( minDistance, System.Math.Max( (Real)0, camDistToCenter - sphereBounds.Radius ) );
			maxDistance = System.Math.Max( maxDistance, camDistToCenter + sphereBounds.Radius );
		}
Пример #2
0
		/// <summary>
		///		Creates a <see cref="SphereRegionSceneQuery"/> for this scene manager.
		/// </summary>
		/// <remarks>
		///		This method creates a new instance of a query object for this scene manager,
		///		for querying for objects within a spherical region.
		/// </remarks>
		/// <param name="sphere">Sphere to use for the region query.</param>
		/// <param name="mask">Custom user defined flags to use for the query.</param>
		/// <returns>A specialized implementation of SphereRegionSceneQuery for this scene manager.</returns>
		public virtual SphereRegionSceneQuery CreateSphereRegionQuery( Sphere sphere, uint mask )
		{
			DefaultSphereRegionSceneQuery query = new DefaultSphereRegionSceneQuery( this );
			query.Sphere = sphere;
			query.QueryMask = mask;

			return query;
		}
Пример #3
0
		/// <summary>
		///		Internal method for rendering all the objects for a given light into the stencil buffer.
		/// </summary>
		/// <param name="light">The light source.</param>
		/// <param name="camera">The camera being viewed from.</param>
		protected virtual void RenderShadowVolumesToStencil( Light light, Camera camera )
		{
			// get the shadow caster list
			IList casters = this.FindShadowCastersForLight( light, camera );
			if ( casters.Count == 0 )
			{
				// No casters, just do nothing
				return;
			}

			// Set up scissor test (point & spot lights only)
			bool scissored = false;
			if ( light.Type != LightType.Directional &&
				 this.targetRenderSystem.Capabilities.HasCapability( Capabilities.ScissorTest ) )
			{
				// Project the sphere onto the camera
				float left, right, top, bottom;
				Sphere sphere = new Sphere( light.DerivedPosition, light.AttenuationRange );
				if ( camera.ProjectSphere( sphere, out left, out top, out right, out bottom ) )
				{
					scissored = true;
					// Turn normalised device coordinates into pixels
					int iLeft, iTop, iWidth, iHeight;
					this.currentViewport.GetActualDimensions( out iLeft, out iTop, out iWidth, out iHeight );
					int szLeft, szRight, szTop, szBottom;

					szLeft = (int)( iLeft + ( ( left + 1 ) * 0.5f * iWidth ) );
					szRight = (int)( iLeft + ( ( right + 1 ) * 0.5f * iWidth ) );
					szTop = (int)( iTop + ( ( -top + 1 ) * 0.5f * iHeight ) );
					szBottom = (int)( iTop + ( ( -bottom + 1 ) * 0.5f * iHeight ) );

					this.targetRenderSystem.SetScissorTest( true, szLeft, szTop, szRight, szBottom );
				}
			}

			this.targetRenderSystem.UnbindGpuProgram( GpuProgramType.Fragment );

			// Can we do a 2-sided stencil?
			bool stencil2sided = false;

			if ( this.targetRenderSystem.Capabilities.HasCapability( Capabilities.TwoSidedStencil ) &&
				 this.targetRenderSystem.Capabilities.HasCapability( Capabilities.StencilWrap ) )
			{
				// enable
				stencil2sided = true;
			}

			// Do we have access to vertex programs?
			bool extrudeInSoftware = true;

			bool finiteExtrude = !this.shadowUseInfiniteFarPlane ||
								 !this.targetRenderSystem.Capabilities.HasCapability(
									  Capabilities.InfiniteFarPlane );

			if ( this.targetRenderSystem.Capabilities.HasCapability( Capabilities.VertexPrograms ) )
			{
				extrudeInSoftware = false;
				this.EnableHardwareShadowExtrusion( light, finiteExtrude );
			}
			else
			{
				this.targetRenderSystem.UnbindGpuProgram( GpuProgramType.Vertex );
			}

			// Add light to internal list for use in render call
			tmpLightList.Clear();
			tmpLightList.Add( light );

			// Turn off color writing and depth writing
			this.targetRenderSystem.SetColorBufferWriteEnabled( false, false, false, false );
			this.targetRenderSystem.DepthBufferWriteEnabled = false;
			this.targetRenderSystem.StencilCheckEnabled = true;
			this.targetRenderSystem.DepthBufferFunction = CompareFunction.Less;

			// Calculate extrusion distance
			float extrudeDistance = 0;
			if ( light.Type == LightType.Directional )
			{
				extrudeDistance = this.shadowDirLightExtrudeDist;
			}

			// get the near clip volume
			PlaneBoundedVolume nearClipVol = light.GetNearClipVolume( camera );

			// Determine whether zfail is required
			// We need to use zfail for ALL objects if we find a single object which
			// requires it
			bool zfailAlgo = false;

			this.CheckShadowCasters( casters,
									 nearClipVol,
									 light,
									 extrudeInSoftware,
									 finiteExtrude,
									 zfailAlgo,
									 camera,
									 extrudeDistance,
									 stencil2sided,
									 tmpLightList );
			// revert colour write state
			this.targetRenderSystem.SetColorBufferWriteEnabled( true, true, true, true );
			// revert depth state
			this.targetRenderSystem.SetDepthBufferParams();

			this.targetRenderSystem.StencilCheckEnabled = false;

			this.targetRenderSystem.UnbindGpuProgram( GpuProgramType.Vertex );

			if ( scissored )
			{
				// disable scissor test
				this.targetRenderSystem.SetScissorTest( false );
			}
		}
Пример #4
0
		/// <summary>
		///		Internal method for locating a list of lights which could be affecting the frustum.
		/// </summary>
		/// <remarks>
		///		Custom scene managers are encouraged to override this method to make use of their
		///		scene partitioning scheme to more efficiently locate lights, and to eliminate lights
		///		which may be occluded by word geometry.
		/// </remarks>
		/// <param name="camera">Camera to find lights within it's view.</param>
		protected virtual void FindLightsAffectingFrustum( Camera camera )
		{
			// Basic iteration for this scene manager
			this.lightsAffectingFrustum.Clear();

			MovableObjectCollection lightList = this.GetMovableObjectCollection( LightFactory.TypeName );

			// sphere to use for testing
			Sphere sphere = new Sphere();

			foreach ( Light light in lightList.Values )
			{
				if ( light.IsVisible )
				{
					if ( light.Type == LightType.Directional )
					{
						// Always visible
						this.lightsAffectingFrustum.Add( light );
					}
					else
					{
						// treating spotlight as point for simplicity
						// Just see if the lights attenuation range is within the frustum
						sphere.Center = light.DerivedPosition;
						sphere.Radius = light.AttenuationRange;

						if ( camera.IsObjectVisible( sphere ) )
						{
							this.lightsAffectingFrustum.Add( light );
						}
					}
				}
			}

			// notify light dirty, so all movable objects will re-populate
			// their light list next time
			NotifyLightsDirty();
		}
Пример #5
0
		public abstract void FindNodes( Sphere t, ref List<PCZSceneNode> nodes, List<Portal> portals, bool includeVisitors,
		                                bool recurseThruPortals, PCZSceneNode exclude );
Пример #6
0
		public void FindNodes( Sphere sphere, SceneNodeCollection sceneNodeList, SceneNode exclude, bool full, Octree octant )
		{
			//TODO: Implement
		}
Пример #7
0
 /// <summary>
 ///		Tests whether this box intersects a sphere.
 /// </summary>
 /// <param name="sphere"></param>
 /// <returns>True if the sphere intersects, false otherwise.</returns>
 public bool Intersects( Sphere sphere )
 {
     return Utility.Intersects( sphere, this );
 }
Пример #8
0
		public void Merge( AxisAlignedBox boxBounds, Sphere sphereBounds, Camera cam )
		{
			Merge( boxBounds, sphereBounds, cam, true );
		}
Пример #9
0
		/// <summary>
		///		Intersection test with <see cref="Sphere"/>.
		/// </summary>
		/// <param name="sphere">Sphere to test.</param>
		/// <returns>True if the sphere intersects this volume, and false otherwise.</returns>
		public bool Intersects( Sphere sphere )
		{
			for ( int i = 0; i < planes.Count; i++ )
			{
				Plane plane = (Plane)planes[ i ];

				// Test which side of the plane the sphere is
				Real d = plane.GetDistance( sphere.Center );

				// Negate d if planes point inwards
				if ( outside == PlaneSide.Negative )
				{
					d = -d;
				}

				if ( ( d - sphere.Radius ) > 0 )
				{
					return false;
				}
			}

			// assume intersecting
			return true;
		}
Пример #10
0
		//---------------------------------------------------------------------
		protected override void FindLightsAffectingFrustum( Camera camera )
		{
			base.FindLightsAffectingFrustum( camera );
			return;
			// Similar to the basic SceneManager, we iterate through
			// lights to see which ones affect the frustum.  However,
			// since we have camera & lights partitioned by zones,
			// we can check only those lights which either affect the
			// zone the camera is in, or affect zones which are visible to
			// the camera

			MovableObjectCollection lights = GetMovableObjectCollection( PCZLightFactory.TypeName );

			lock ( lights )
			{
				foreach ( PCZLight l in lights.Values )
				{
					if ( l.IsVisible /* && l.AffectsVisibleZone */ )
					{
						LightInfo lightInfo;
						lightInfo.light = l;
						lightInfo.type = (int)l.Type;
						if ( lightInfo.type == (int)LightType.Directional )
						{
							// Always visible
							lightInfo.position = Vector3.Zero;
							lightInfo.range = 0;
							this.mTestLightInfos.Add( lightInfo );
						}
						else
						{
							// NB treating spotlight as point for simplicity
							// Just see if the lights attenuation range is within the frustum
							lightInfo.range = l.AttenuationRange;
							lightInfo.position = l.GetDerivedPosition();
							var sphere = new Sphere( lightInfo.position, lightInfo.range );
							if ( camera.IsObjectVisible( sphere ) )
							{
								this.mTestLightInfos.Add( lightInfo );
							}
						}
					}
				}
			} // release lock on lights collection

			base.FindLightsAffectingFrustum( camera );

			// from here on down this function is same as Ogre::SceneManager

			// Update lights affecting frustum if changed
			if ( this.mCachedLightInfos != this.mTestLightInfos )
			{
				//mLightsAffectingFrustum.resize(mTestLightInfos.size());
				//LightInfoList::const_iterator i;
				//LightList::iterator j = mLightsAffectingFrustum.begin();
				//for (i = mTestLightInfos.begin(); i != mTestLightInfos.end(); ++i, ++j)
				//{
				//    *j = i->light;
				//    // add cam distance for sorting if texture shadows
				//    if (isShadowTechniqueTextureBased())
				//    {
				//        (*j)->tempSquareDist =
				//            (camera->getDerivedPosition() - (*j)->getDerivedPosition()).squaredLength();
				//    }
				//}

				foreach ( LightInfo i in this.mTestLightInfos )
				{
					if ( IsShadowTechniqueTextureBased )
					{
						i.light.TempSquaredDist = ( camera.DerivedPosition - i.light.GetDerivedPosition() ).LengthSquared;
					}
				}

				if ( IsShadowTechniqueTextureBased )
				{
				}

				// Sort the lights if using texture shadows, since the first 'n' will be
				// used to generate shadow textures and we should pick the most appropriate
				//if (IsShadowTechniqueTextureBased)
				//{
				//    // Allow a ShadowListener to override light sorting
				//    // Reverse iterate so last takes precedence
				//    bool overridden = false;
				//    foreach(object o in base.)
				//    for (ListenerList::reverse_iterator ri = mListeners.rbegin();
				//        ri != mListeners.rend(); ++ri)
				//    {
				//        overridden = (*ri)->sortLightsAffectingFrustum(mLightsAffectingFrustum);
				//        if (overridden)
				//            break;
				//    }
				//    if (!overridden)
				//    {
				//        // default sort (stable to preserve directional light ordering
				//        std::stable_sort(
				//            mLightsAffectingFrustum.begin(), mLightsAffectingFrustum.end(),
				//            lightsForShadowTextureLess());
				//    }

				//}

				// Use swap instead of copy operator for efficiently
				//mCachedLightInfos.swap(mTestLightInfos);
				this.mCachedLightInfos = this.mTestLightInfos;

				// notify light dirty, so all movable objects will re-populate
				// their light list next time
				//_notifyLightsDirty();
				//Check: do we have something like this here?
			}
		}
Пример #11
0
		public void FindNodesIn( Sphere sphere, 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( sphere, ref list, visitedPortals, true, true, exclude );
			}
			else
			{
				// no start zone specified, so check all zones
				foreach ( PCZone zone in this.zones )
				{
					zone.FindNodes( sphere, ref list, visitedPortals, false, false, exclude );
				}
			}
		}
Пример #12
0
 /// <summary>
 ///		Tests whether this ray intersects the given sphere. 
 /// </summary>
 /// <param name="sphere"></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( Sphere sphere )
 {
     return Utility.Intersects( this, sphere );
 }
Пример #13
0
 /// <summary>
 /// /
 /// </summary>
 /// <param name="sphere"></param>
 /// <param name="terrainList"></param>
 public void SphereIntersects(Sphere sphere, out List<Terrain> terrainList)
 {
     terrainList = new List<Terrain>();
     foreach (TerrainSlot i in _terrainSlots.Values)
     {
         if (i.Instance != null && sphere.Intersects(i.Instance.WorldAABB))
             terrainList.Add(i.Instance);
     }
 }
Пример #14
0
		public virtual bool ProjectSphere( Sphere sphere, out float left, out float top, out float right, out float bottom )
		{
			// initialise
			left = bottom = -1.0f;
			right = top = 1.0f;

			// Transform light position into camera space
			var eyeSpacePos = ViewMatrix.TransformAffine( sphere.Center );

			if ( eyeSpacePos.z < 0 )
			{
				float r = sphere.Radius;
				// early-exit
				if ( eyeSpacePos.LengthSquared <= r*r )
				{
					return false;
				}

				var screenSpacePos = ProjectionMatrix*eyeSpacePos;

				// perspective attenuate
				var spheresize = new Vector3( r, r, eyeSpacePos.z );
				spheresize = ProjectionMatrixRSDepth*spheresize;

				float possLeft = screenSpacePos.x - spheresize.x;
				float possRight = screenSpacePos.x + spheresize.x;
				float possTop = screenSpacePos.y + spheresize.y;
				float possBottom = screenSpacePos.y - spheresize.y;

				left = Utility.Max( -1.0f, possLeft );
				right = Utility.Min( 1.0f, possRight );
				top = Utility.Min( 1.0f, possTop );
				bottom = Utility.Max( -1.0f, possBottom );
			}

			return ( left != -1.0f ) || ( top != 1.0f ) || ( right != 1.0f ) || ( bottom != -1.0f );
		}
Пример #15
0
		/// <summary>
		///		Tests whether the given sphere is in the viewing frustum.
		/// </summary>
		/// <param name="sphere">Bounding sphere to be checked.</param>
		/// <param name="culledBy">
		///		Optional FrustrumPlane params which will be filled by the plane which culled
		///		the box if the result was false.
		///	</param>
		/// <returns>True if the box is visible, otherwise false.</returns>
		public bool IsObjectVisible( Sphere sphere, out FrustumPlane culledBy )
		{
			// Make any pending updates to the calculated frustum
			UpdateFrustumPlanes();

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

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

			// sphere is not culled
			culledBy = FrustumPlane.None;
			return true;
		}
Пример #16
0
 /// <summary>
 ///		Tests for intersection between this sphere and another sphere.
 /// </summary>
 /// <param name="sphere">Other sphere.</param>
 /// <returns>True if the spheres intersect, false otherwise.</returns>
 public bool Intersects(Sphere sphere)
 {
     return((sphere.center - this.center).Length <= (sphere.radius + this.radius));
 }
Пример #17
0
		public override bool ProjectSphere( Sphere sphere, out float left, out float top, out float right, out float bottom )
		{
			if ( null != CullFrustum )
			{
				return CullFrustum.ProjectSphere( sphere, out left, out top, out right, out bottom );
			}
			//else
			{
				return base.ProjectSphere( sphere, out left, out top, out right, out bottom );
			}
		}
Пример #18
0
		public override void FindNodes( Sphere 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 ( !mEnclosureNode.WorldAABB.Intersects( t ) )
				{
					// AABB of zone does not intersect t, just return.
					return;
				}
			}

			// use the Octree to more efficiently find nodes intersecting the sphere
			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 );
						}
					}
				}
			}
		}
Пример #19
0
		public override bool FrameRenderingQueued( FrameEventArgs evt )
		{
			if ( this.mode != Mode.Normal )
			{
				// fire ray
				Ray ray;
				ray = TrayManager.GetCursorRay( Camera );

				var rayResult = this.terrainGroup.RayIntersects( ray );
				if ( rayResult.Hit )
				{
					this.editMarker.IsVisible = true;
					this.editNode.Position = rayResult.Position;

					// figure out which terrains this affects
					List<Axiom.Components.Terrain.Terrain> terrainList;
					var brushSizeWorldSpace = TerrainWorldSize*this.brushSizeTerrainSpace;
					var sphere = new Sphere( rayResult.Position, brushSizeWorldSpace );
					this.terrainGroup.SphereIntersects( sphere, out terrainList );

					foreach ( var ti in terrainList )
					{
						DoTerrainModify( ti, rayResult.Position, evt.TimeSinceLastFrame );
					}
				}
				else
				{
					this.editMarker.IsVisible = false;
				}
			}

			if ( !this.fly )
			{
				// clamp to terrain
				var camPos = Camera.Position;
				var ray = new Ray( new Vector3( camPos.x, this.terrainPos.y + 10000, camPos.z ), Vector3.NegativeUnitY );

				TerrainGroup.RayResult rayResult = this.terrainGroup.RayIntersects( ray );
				Real distanceAboveTerrain = 50;
				Real fallSpeed = 300;
				Real newy = camPos.y;
				if ( rayResult.Hit )
				{
					if ( camPos.y > rayResult.Position.y + distanceAboveTerrain )
					{
						this.fallVelocity += evt.TimeSinceLastFrame*20;
						this.fallVelocity = Utility.Min( this.fallVelocity, fallSpeed );
						newy = camPos.y - this.fallVelocity*evt.TimeSinceLastFrame;
					}
					newy = Utility.Max( rayResult.Position.y + distanceAboveTerrain, newy );
					Camera.Position = new Vector3( camPos.x, newy, camPos.z );
				}
			}

			if ( this.heightUpdateCountDown > 0 )
			{
				this.heightUpdateCountDown -= evt.TimeSinceLastFrame;
				if ( this.heightUpdateCountDown <= 0 )
				{
					this.terrainGroup.Update();
					this.heightUpdateCountDown = 0;
				}
			}

			if ( this.terrainGroup.IsDerivedDataUpdateInProgress )
			{
				TrayManager.MoveWidgetToTray( this.infoLabel, TrayLocation.Top, 0 );
				this.infoLabel.Show();
				if ( this.terrainsImported )
				{
					this.infoLabel.Caption = "Building terrain, please wait...";
				}
				else
				{
					this.infoLabel.Caption = "Updating textures, patience...";
				}
			}
			else
			{
				TrayManager.RemoveWidgetFromTray( this.infoLabel );
				this.infoLabel.Hide();
				if ( this.terrainsImported )
				{
					SaveTerrains( true );
					this.terrainsImported = false;
				}
			}

			return base.FrameRenderingQueued( evt );
		}
Пример #20
0
		/// <summary>
		///		Tests for intersection between this sphere and another sphere.
		/// </summary>
		/// <param name="sphere">Other sphere.</param>
		/// <returns>True if the spheres intersect, false otherwise.</returns>
		public bool Intersects( Sphere sphere )
		{
			return ( ( sphere.center - this.center ).Length <= ( sphere.radius + this.radius ) );
		}
Пример #21
0
		public Intersection Intersect( Sphere sphere, AxisAlignedBox box )
		{
			intersect++;
			float Radius = sphere.Radius;
			Vector3 Center = sphere.Center;
			Vector3[] Corners = box.Corners;
			float s = 0;
			float d = 0;
			int i;
			bool Partial;

			Radius *= Radius;

			Vector3 MinDistance = ( Corners[ 0 ] - Center );
			Vector3 MaxDistance = ( Corners[ 4 ] - Center );

			if ( ( MinDistance.LengthSquared < Radius ) && ( MaxDistance.LengthSquared < Radius ) )
			{
				return Intersection.Inside;
			}

			//find the square of the distance
			//from the sphere to the box
			for ( i = 0; i < 3; i++ )
			{
				if ( Center[ i ] < Corners[ 0 ][ i ] )
				{
					s = Center[ i ] - Corners[ 0 ][ i ];
					d += s * s;
				}

				else if ( Center[ i ] > Corners[ 4 ][ i ] )
				{
					s = Center[ i ] - Corners[ 4 ][ i ];
					d += s * s;
				}
			}

			Partial = ( d <= Radius );

			if ( !Partial )
			{
				return Intersection.Outside;
			}
			else
			{
				return Intersection.Intersect;
			}
		}
Пример #22
0
		/** Checks how the box intersects with the sphere.
		*/

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

			float sradius = one.Radius;

			sradius *= sradius;

			Vector3 scenter = one.Center;

			Vector3 twoMin = two.Minimum;
			Vector3 twoMax = two.Maximum;

			float s, d = 0;

			Vector3 mndistance = ( twoMin - scenter );
			Vector3 mxdistance = ( twoMax - scenter );

			if ( mndistance.LengthSquared < sradius && mxdistance.LengthSquared < sradius )
			{
				return Intersection.INSIDE;
			}

			//find the square of the distance
			//from the sphere to the box
			for ( int i = 0; i < 3; i++ )
			{
				if ( scenter[ i ] < twoMin[ i ] )
				{
					s = scenter[ i ] - twoMin[ i ];
					d += s*s;
				}

				else if ( scenter[ i ] > twoMax[ i ] )
				{
					s = scenter[ i ] - twoMax[ i ];
					d += s*s;
				}
			}

			bool partial = ( d <= sradius );

			if ( !partial )
			{
				return Intersection.OUTSIDE;
			}

			else
			{
				return Intersection.INTERSECT;
			}
		}
Пример #23
0
		// TODO: Scene queries.
		/// <summary>
		///		Creates an AxisAlignedBoxSceneQuery for this scene manager.
		/// </summary>
		/// <remarks>
		///		This method creates a new instance of a query object for this scene manager,
		///		for an axis aligned box region. See SceneQuery and AxisAlignedBoxSceneQuery
		///		for full details.
		///		<p/>
		///		The instance returned from this method must be destroyed by calling
		///		SceneManager.DestroyQuery when it is no longer required.
		/// </remarks>
		/// <param name="box">Details of the box which describes the region for this query.</param>
		/*public virtual AxisAlignedBoxSceneQuery CreateAABBQuery(AxisAlignedBox box)
		{
			return CreateAABBQuery(box, 0xFFFFFFFF);
		}

		/// <summary>
		///		Creates an AxisAlignedBoxSceneQuery for this scene manager.
		/// </summary>
		/// <remarks>
		///		This method creates a new instance of a query object for this scene manager,
		///		for an axis aligned box region. See SceneQuery and AxisAlignedBoxSceneQuery
		///		for full details.
		///		<p/>
		///		The instance returned from this method must be destroyed by calling
		///		SceneManager.DestroyQuery when it is no longer required.
		/// </remarks>
		/// <param name="box">Details of the box which describes the region for this query.</param>
		/// <param name="mask">The query mask to apply to this query; can be used to filter out certain objects; see SceneQuery for details.</param>
		public virtual AxisAlignedBoxSceneQuery CreateAABBQuery(AxisAlignedBox box, ulong mask)
		{
			// TODO:
			return null;
		}*/
		/// <summary>
		///		Creates a SphereSceneQuery for this scene manager.
		/// </summary>
		/// <remarks>
		/// 	This method creates a new instance of a query object for this scene manager,
		///		for a spherical region. See SceneQuery and SphereSceneQuery
		///		for full details.
		/// </remarks>
		/// <param name="sphere">Details of the sphere which describes the region for this query.</param>
		/// <param name="mask">The query mask to apply to this query; can be used to filter out	certain objects; see SceneQuery for details.</param>
		public override SphereRegionSceneQuery CreateSphereRegionQuery( Sphere sphere, uint mask )
		{
			var q = new BspSphereRegionSceneQuery( this );
			q.Sphere = sphere;
			q.QueryMask = mask;

			return q;
		}
Пример #24
0
		public void _findNodes( Sphere 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 );
			}
		}
Пример #25
0
		public override void FindNodes( Sphere 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 ( !mEnclosureNode.WorldAABB.Intersects( t ) )
				{
					// 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 );
						}
					}
				}
			}

		}
Пример #26
0
		public bool IsObjectVisible( Sphere bound )
		{
			// Check originplane if told to
			if ( mUseOriginPlane )
			{
				PlaneSide side = mOriginPlane.GetSide( bound.Center );
				if ( side == PlaneSide.Negative )
				{
					Real dist = mOriginPlane.GetDistance( bound.Center );
					if ( dist > bound.Radius )
					{
						return false;
					}
				}
			}

			// For each extra active culling plane, see if the entire sphere is on the negative side
			// If so, object is not visible
			foreach ( PCPlane plane in mActiveCullingPlanes )
			{
				PlaneSide xside = plane.GetSide( bound.Center );
				if ( xside == PlaneSide.Negative )
				{
					float dist = mOriginPlane.GetDistance( bound.Center );
					if ( dist > bound.Radius )
					{
						return false;
					}
				}

			}

			return true;
		}
Пример #27
0
		/// <summary>
		///		Internal method for locating a list of shadow casters which
		///		could be affecting the frustum for a given light.
		/// </summary>
		/// <remarks>
		///		Custom scene managers are encouraged to override this method to add optimizations,
		///		and to add their own custom shadow casters (perhaps for world geometry)
		/// </remarks>
		/// <param name="light"></param>
		/// <param name="camera"></param>
		protected virtual IList FindShadowCastersForLight( Light light, Camera camera )
		{
			this.shadowCasterList.Clear();

			if ( light.Type == LightType.Directional )
			{
				// Basic AABB query encompassing the frustum and the extrusion of it
				AxisAlignedBox aabb = new AxisAlignedBox();
				Vector3[] corners = camera.WorldSpaceCorners;
				Vector3 min, max;
				Vector3 extrude = light.DerivedDirection * -this.shadowDirLightExtrudeDist;
				// do first corner
				min = max = corners[ 0 ];
				min.Floor( corners[ 0 ] + extrude );
				max.Ceil( corners[ 0 ] + extrude );
				for ( int c = 1; c < 8; ++c )
				{
					min.Floor( corners[ c ] );
					max.Ceil( corners[ c ] );
					min.Floor( corners[ c ] + extrude );
					max.Ceil( corners[ c ] + extrude );
				}
				aabb.SetExtents( min, max );

				if ( this.shadowCasterAABBQuery == null )
				{
					this.shadowCasterAABBQuery = this.CreateAABBRegionQuery( aabb );
				}
				else
				{
					this.shadowCasterAABBQuery.Box = aabb;
				}
				// Execute, use callback
				this.shadowCasterQueryListener.Prepare( false,
														light.GetFrustumClipVolumes( camera ),
														light,
														camera,
														this.shadowCasterList,
														light.ShadowFarDistanceSquared );
				this.shadowCasterAABBQuery.Execute( this.shadowCasterQueryListener );
			}
			else
			{
				Sphere s = new Sphere( light.DerivedPosition, light.AttenuationRange );

				// eliminate early if camera cannot see light sphere
				if ( camera.IsObjectVisible( s ) )
				{
					// create or init a sphere region query
					if ( this.shadowCasterSphereQuery == null )
					{
						this.shadowCasterSphereQuery = this.CreateSphereRegionQuery( s );
					}
					else
					{
						this.shadowCasterSphereQuery.Sphere = s;
					}

					// check if the light is within view of the camera
					bool lightInFrustum = camera.IsObjectVisible( light.DerivedPosition );

					PlaneBoundedVolumeList volumeList = null;

					// Only worth building an external volume list if
					// light is outside the frustum
					if ( !lightInFrustum )
					{
						volumeList = light.GetFrustumClipVolumes( camera );
					}

					// prepare the query and execute using the callback
					this.shadowCasterQueryListener.Prepare(
						lightInFrustum,
						volumeList,
						light,
						camera,
						this.shadowCasterList,
						light.ShadowFarDistanceSquared );

					this.shadowCasterSphereQuery.Execute( this.shadowCasterQueryListener );
				}
			}

			return this.shadowCasterList;
		}
Пример #28
0
		public new bool IsObjectVisible( Sphere sphere )
		{
			if ( null != CullFrustum )
			{
				return CullFrustum.IsObjectVisible( sphere );
			}
			else
			{
				return base.IsObjectVisible( sphere );
			}
		}
Пример #29
0
		/// <summary>
		///		Creates a <see cref="SphereRegionSceneQuery"/> for this scene manager.
		/// </summary>
		/// <remarks>
		///		This method creates a new instance of a query object for this scene manager,
		///		for querying for objects within a spherical region.
		/// </remarks>
		/// <param name="sphere">Sphere to use for the region query.</param>
		/// <returns>A specialized implementation of SphereRegionSceneQuery for this scene manager.</returns>
		public SphereRegionSceneQuery CreateSphereRegionQuery( Sphere sphere )
		{
			return this.CreateSphereRegionQuery( sphere, 0xffffffff );
		}
Пример #30
0
		public new bool IsObjectVisible( Sphere sphere, out FrustumPlane culledBy )
		{
			if ( null != CullFrustum )
			{
				return CullFrustum.IsObjectVisible( sphere, out culledBy );
			}
			else
			{
				return base.IsObjectVisible( sphere, out culledBy );
			}
		}
Пример #31
0
		public override void Execute( ISceneQueryListener listener )
		{
			Sphere testSphere = new Sphere();

			MovableObjectFactoryMap factories = Root.Instance.MovableObjectFactories;
			foreach ( KeyValuePair<string, MovableObjectFactory> map in factories )
			{
				MovableObjectCollection movableObjects = this.creator.GetMovableObjectCollection( map.Value.Type );
				foreach ( MovableObject movableObject in movableObjects.Values )
				{
					// skip group if query type doesn't match
					if ( ( this.QueryTypeMask & movableObject.TypeFlags ) == 0 )
					{
						break;
					}

					// skip if unattached or filtered out by query flags
					if ( !movableObject.IsAttached || ( movableObject.QueryFlags & this.queryMask ) == 0 )
					{
						continue;
					}

					testSphere.Center = movableObject.ParentNode.DerivedPosition;
					testSphere.Radius = movableObject.BoundingRadius;

					// if the results came back positive, fire the event handler
					if ( this.sphere.Intersects( testSphere ) )
					{
						listener.OnQueryResult( movableObject );
					}
				}
			}
		}
Пример #32
0
 /// <summary>
 ///		Tests whether this ray intersects the given sphere.
 /// </summary>
 /// <param name="sphere"></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(Sphere sphere)
 {
     return(Utility.Intersects(this, sphere));
 }