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 ); } } } } }
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; } } } } } }
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 ); } } }
public abstract void FindNodes( PlaneBoundedVolume t, ref List<PCZSceneNode> list, List<Portal> visitedPortals, bool includeVisitors, bool recurseThruPortals, PCZSceneNode exclude );
/// <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 ); } }
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; } }
/// <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; }
/// <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 ] ) ); } }
/** 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; } }
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 ); } }
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 ); } } } } }
/// <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)); }
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 ); } } }
/// <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 ); }
// 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; }