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 ); }
/// <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; }
/// <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 ); } }
/// <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(); }
public abstract void FindNodes( Sphere t, ref List<PCZSceneNode> nodes, List<Portal> portals, bool includeVisitors, bool recurseThruPortals, PCZSceneNode exclude );
public void FindNodes( Sphere sphere, SceneNodeCollection sceneNodeList, SceneNode exclude, bool full, Octree octant ) { //TODO: Implement }
/// <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 ); }
public void Merge( AxisAlignedBox boxBounds, Sphere sphereBounds, Camera cam ) { Merge( boxBounds, sphereBounds, cam, true ); }
/// <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; }
//--------------------------------------------------------------------- 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? } }
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 ); } } }
/// <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 ); }
/// <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); } }
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 ); }
/// <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; }
/// <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)); }
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 ); } }
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 ); } } } } }
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 ); }
/// <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 ) ); }
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; } }
/** 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; } }
// 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; }
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 ); } }
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 ); } } } } }
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; }
/// <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; }
public new bool IsObjectVisible( Sphere sphere ) { if ( null != CullFrustum ) { return CullFrustum.IsObjectVisible( sphere ); } else { return base.IsObjectVisible( sphere ); } }
/// <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 ); }
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 ); } }
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 ); } } } }
/// <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)); }