private void WalkOctree( PCZCamera camera, ref List<PCZSceneNode> visibleNodeList, RenderQueue queue, Octree octant, VisibleObjectsBoundsInfo visibleBounds, bool foundvisible, bool onlyShadowCasters, bool displayNodes, bool showBoundingBoxes ) { //return immediately if nothing is in the node. if ( octant.NunodeList == 0 ) return; Visibility v = Visibility.None; if ( foundvisible ) { v = Visibility.Full; } else if ( octant == rootOctree ) { v = Visibility.Partial; } else { AxisAlignedBox box = octant.Box; v = camera.GetVisibility( box ); } // if the octant is visible, or if it's the root node... if ( v != Visibility.None ) { //Add stuff to be rendered; bool vis = true; foreach ( PCZSceneNode sn in octant.NodeList.Values ) { // if the scene node is already visible, then we can skip it if ( sn.LastVisibleFrame != mLastVisibleFrame || sn.LastVisibleFromCamera != camera ) { // if this octree is partially visible, manually cull all // scene nodes attached directly to this level. if ( v == Visibility.Partial ) { vis = camera.IsObjectVisible( sn.WorldAABB ); } if ( vis ) { // add the node to the render queue sn.AddToRenderQueue( camera, queue, onlyShadowCasters, visibleBounds ); // add it to the list of visible nodes visibleNodeList.Add( sn ); // if we are displaying nodes, add the node renderable to the queue if ( displayNodes ) { queue.AddRenderable( sn.GetDebugRenderable() ); } // if the scene manager or the node wants the bounding box shown, add it to the queue if ( sn.ShowBoundingBox || showBoundingBoxes ) { sn.AddBoundingBoxToQueue( queue ); } // flag the node as being visible this frame sn.LastVisibleFrame = mLastVisibleFrame; sn.LastVisibleFromCamera = camera; } } } Octree child; bool childfoundvisible = ( v == Visibility.Full ); if ( ( child = octant.Children[ 0, 0, 0 ] ) != null ) WalkOctree( camera, ref visibleNodeList, queue, child, visibleBounds, childfoundvisible, onlyShadowCasters, displayNodes, showBoundingBoxes ); if ( ( child = octant.Children[ 1, 0, 0 ] ) != null ) WalkOctree( camera, ref visibleNodeList, queue, child, visibleBounds, childfoundvisible, onlyShadowCasters, displayNodes, showBoundingBoxes ); if ( ( child = octant.Children[ 0, 1, 0 ] ) != null ) WalkOctree( camera, ref visibleNodeList, queue, child, visibleBounds, childfoundvisible, onlyShadowCasters, displayNodes, showBoundingBoxes ); if ( ( child = octant.Children[ 1, 1, 0 ] ) != null ) WalkOctree( camera, ref visibleNodeList, queue, child, visibleBounds, childfoundvisible, onlyShadowCasters, displayNodes, showBoundingBoxes ); if ( ( child = octant.Children[ 0, 0, 1 ] ) != null ) WalkOctree( camera, ref visibleNodeList, queue, child, visibleBounds, childfoundvisible, onlyShadowCasters, displayNodes, showBoundingBoxes ); if ( ( child = octant.Children[ 1, 0, 1 ] ) != null ) WalkOctree( camera, ref visibleNodeList, queue, child, visibleBounds, childfoundvisible, onlyShadowCasters, displayNodes, showBoundingBoxes ); if ( ( child = octant.Children[ 0, 1, 1 ] ) != null ) WalkOctree( camera, ref visibleNodeList, queue, child, visibleBounds, childfoundvisible, onlyShadowCasters, displayNodes, showBoundingBoxes ); if ( ( child = octant.Children[ 1, 1, 1 ] ) != null ) WalkOctree( camera, ref visibleNodeList, queue, child, visibleBounds, childfoundvisible, onlyShadowCasters, displayNodes, showBoundingBoxes ); } }
/// <summary> /// Overloaded method. /// </summary> /// <param name="camera"></param> /// <param name="queue"></param> public virtual void FindVisibleObjects(Camera camera, RenderQueue queue, VisibleObjectsBoundsInfo visibleBounds) { // call overloaded method FindVisibleObjects(camera, queue, visibleBounds, true, false, false); }
/** Walks through the octree, adding any visible objects to the render queue. @remarks If any octant in the octree if completely within the the view frustum, all subchildren are automatically added with no visibility tests. */ public void WalkOctree(OctreeCamera camera, RenderQueue queue, Octree octant, VisibleObjectsBoundsInfo visibleBounds, bool onlyShadowCasters, bool foundVisible) { //return immediately if nothing is in the node. if(octant.NumNodes == 0) { return; } Visibility v = Visibility.None; if(foundVisible) { v = Visibility.Full; } else if(octant == octree) { v = Visibility.Partial; } else { AxisAlignedBox box = octant.CullBounds; v = camera.GetVisibility(box); } // if the octant is visible, or if it's the root node... if(v != Visibility.None) { if(this.ShowBoundingBoxes) { // TODO: Implement Octree.WireBoundingBox //boxList.Add(octant.WireBoundingBox); } bool vis = true; for(int i = 0; i < octant.NodeList.Count; i++) { OctreeNode node = (OctreeNode)octant.NodeList[i]; // if this octree is partially visible, manually cull all // scene nodes attached directly to this level. if(v == Visibility.Partial) { vis = camera.IsObjectVisible(node.WorldAABB); } if(vis) { numObjects++; node.AddToRenderQueue(camera, queue, onlyShadowCasters, visibleBounds); visible.Add(node); if(DisplayNodes) { GetRenderQueue().AddRenderable(node); } // check if the scene manager or this node wants the bounding box shown. if(node.ShowBoundingBox || this.ShowBoundingBoxes) { node.AddBoundingBoxToQueue(queue); } } } if(octant.Children[0,0,0] != null ) WalkOctree(camera, queue, octant.Children[0,0,0], visibleBounds, onlyShadowCasters, ( v == Visibility.Full ) ); if(octant.Children[1,0,0] != null ) WalkOctree(camera, queue, octant.Children[1,0,0], visibleBounds, onlyShadowCasters, ( v == Visibility.Full ) ); if(octant.Children[0,1,0] != null ) WalkOctree(camera, queue, octant.Children[0,1,0], visibleBounds, onlyShadowCasters, ( v == Visibility.Full ) ); if(octant.Children[1,1,0] != null ) WalkOctree(camera, queue, octant.Children[1,1,0], visibleBounds, onlyShadowCasters, ( v == Visibility.Full ) ); if(octant.Children[0,0,1] != null ) WalkOctree(camera, queue, octant.Children[0,0,1], visibleBounds, onlyShadowCasters, ( v == Visibility.Full ) ); if(octant.Children[1,0,1] != null ) WalkOctree(camera, queue, octant.Children[1,0,1], visibleBounds, onlyShadowCasters, ( v == Visibility.Full ) ); if(octant.Children[0,1,1] != null ) WalkOctree(camera, queue, octant.Children[0,1,1], visibleBounds, onlyShadowCasters, ( v == Visibility.Full ) ); if(octant.Children[1,1,1] != null ) WalkOctree(camera, queue, octant.Children[1,1,1], visibleBounds, onlyShadowCasters, ( v == Visibility.Full ) ); } }
public override void FindVisibleNodes( PCZCamera camera, ref List<PCZSceneNode> visibleNodeList, RenderQueue queue, VisibleObjectsBoundsInfo visibleBounds, bool onlyShadowCasters, bool displayNodes, bool showBoundingBoxes ) { //return immediately if nothing is in the zone. if ( mHomeNodeList.Count == 0 && mVisitorNodeList.Count == 0 && mPortals.Count == 0 ) return; // Else, the zone is automatically assumed to be visible since either // it is the camera the zone is in, or it was reached because // a connecting portal was deemed visible to the camera. // enable sky if called to do so for this zone if ( mHasSky ) { // enable sky mPCZSM.EnableSky( true ); } // Recursively find visible nodes in the zone WalkOctree( camera, ref visibleNodeList, queue, rootOctree, visibleBounds, false, onlyShadowCasters, displayNodes, showBoundingBoxes ); // find visible portals in the zone and recurse into them bool vis; foreach ( Portal portal in mPortals ) { // for portal, check visibility using world bounding sphere & direction FrustumPlane pl = FrustumPlane.None; vis = camera.IsObjectVisible( portal, out pl ); if ( vis ) { // portal is visible. Add the portal as extra culling planes to camera int planes_added = camera.AddPortalCullingPlanes( portal ); // tell target zone it's visible this frame portal.getTargetZone().LastVisibleFrame = mLastVisibleFrame; portal.getTargetZone().LastVisibleFromCamera = camera; // recurse into the connected zone portal.getTargetZone().FindVisibleNodes( camera, ref visibleNodeList, queue, visibleBounds, onlyShadowCasters, displayNodes, showBoundingBoxes ); if ( planes_added > 0 ) { // Then remove the extra culling planes added before going to the next portal in this zone. camera.RemovePortalCullingPlanes( portal ); } } } }
public override void FindVisibleObjects(Camera cam, VisibleObjectsBoundsInfo visibleBounds, bool onlyShadowCasters) { GetRenderQueue().Clear(); boxList.Clear(); visible.Clear(); if(cullCamera) { Camera c = cameraList["CullCamera"]; if(c != null) { cameraInProgress = cameraList["CullCamera"]; } } numObjects = 0; //walk the octree, adding all visible Octreenodes nodes to the render queue. WalkOctree((OctreeCamera)cam, GetRenderQueue(), octree, visibleBounds, onlyShadowCasters, false); // Show the octree boxes & cull camera if required if(this.ShowBoundingBoxes || cullCamera) { if(this.ShowBoundingBoxes) { for(int i = 0; i < boxList.Count; i++) { WireBoundingBox box = (WireBoundingBox)boxList[i]; GetRenderQueue().AddRenderable(box); } } if(cullCamera) { OctreeCamera c = (OctreeCamera)GetCamera("CullCamera"); if(c != null) { GetRenderQueue().AddRenderable(c); } } } }
/// <summary> /// Adds all the attached scenenodes to the render queue. /// </summary> /// <param name="cam"></param> /// <param name="queue"></param> public void AddToRenderQueue(Camera cam, RenderQueue queue, bool onlyShadowCasters, VisibleObjectsBoundsInfo visibleBounds) { // int i; foreach (MovableObject obj in objectList.Values) { obj.NotifyCurrentCamera(cam); if(obj.IsVisible && (!onlyShadowCasters || obj.CastShadows)) { obj.UpdateRenderQueue(queue); if (visibleBounds != null) visibleBounds.Merge(obj.GetWorldBoundingBox(true), obj.GetWorldBoundingSphere(true), cam); } } }
/** Find and add visible objects to the render queue. @remarks Starts with objects in the zone and proceeds through visible portals This is a recursive call (the main call should be to _findVisibleObjects) */ public abstract void FindVisibleNodes( PCZCamera camera, ref List<PCZSceneNode> visibleNodeList, RenderQueue queue, VisibleObjectsBoundsInfo visibleBounds, bool onlyShadowCasters, bool displayNodes, bool showBoundingBoxes );
/// <summary> /// Internal method which parses the scene to find visible objects to render. /// </summary> /// <remarks> /// If you're implementing a custom scene manager, this is the most important method to /// override since it's here you can apply your custom world partitioning scheme. Once you /// have added the appropriate objects to the render queue, you can let the default /// SceneManager objects RenderVisibleObjects handle the actual rendering of the objects /// you pick. /// <p/> /// Any visible objects will be added to a rendering queue, which is indexed by material in order /// to ensure objects with the same material are rendered together to minimise render state changes. /// </remarks> /// <param name="camera"></param> public virtual void FindVisibleObjects(Camera camera, VisibleObjectsBoundsInfo visibleBounds, bool onlyShadowCasters) { // ask the root node to iterate through and find visible objects in the scene rootSceneNode.FindVisibleObjects(camera, GetRenderQueue(), visibleBounds, true, displayNodes, onlyShadowCasters); }
/** Adds the attached objects of this PCZSceneNode into the queue. */ public void AddToRenderQueue( Camera cam, RenderQueue queue, bool onlyShadowCasters, VisibleObjectsBoundsInfo visibleBounds ) { foreach ( KeyValuePair<string, MovableObject> pair in objectsByName ) { pair.Value.NotifyCurrentCamera( cam ); if ( pair.Value.IsVisible && ( !onlyShadowCasters || pair.Value.CastShadows ) ) { pair.Value.UpdateRenderQueue( queue ); if ( !visibleBounds.aabb.IsNull ) { visibleBounds.Merge( pair.Value.GetWorldBoundingBox( true ), pair.Value.GetWorldBoundingSphere( true ), cam ); } } } }
/// <summary> /// Creates a camera to be managed by this scene manager. /// </summary> /// <remarks> /// This camera can be added to the scene at a later time using /// the AttachObject method of the SceneNode class. /// </remarks> /// <param name="name"></param> /// <returns></returns> public virtual Camera CreateCamera(string name) { if (cameraList.ContainsKey(name)) { throw new AxiomException(string.Format("A camera with the name '{0}' already exists in the scene.", name)); } // create the camera and add it to our local list Camera camera = new Camera(name, this); cameraList[name] = camera; // create visible bounds aabb map entry camVisibleObjectsMap[camera] = new VisibleObjectsBoundsInfo(); return camera; }
/// <summary> /// Internal method which locates any visible objects attached to this node and adds them to the passed in queue. /// </summary> /// <param name="camera">Active camera.</param> /// <param name="queue">Queue to which these objects should be added.</param> /// <param name="includeChildren">If true, cascades down to all children.</param> /// <param name="displayNodes">Renders the local axes for the node.</param> /// <param name="onlyShadowCasters"></param> public virtual void FindVisibleObjects(Camera camera, RenderQueue queue, VisibleObjectsBoundsInfo visibleBounds, bool includeChildren, bool displayNodes, bool onlyShadowCasters) { // if we aren't visible, then quit now // TODO: Make sure sphere is calculated properly for all objects, then switch to cull using that if(!camera.IsObjectVisible(worldAABB)) return; // add visible objects to the render queue //objectListMeter.Enter(); foreach (MovableObject obj in objectList.Values) { // tell attached object about current camera in case it wants to know //notifyCameraMeter.Enter(); obj.NotifyCurrentCamera(camera); //notifyCameraMeter.Exit(); // if this object is visible, add it to the render queue if(obj.IsVisible && (!onlyShadowCasters || obj.CastShadows)) { //updateQueueMeter.Enter(); obj.UpdateRenderQueue(queue); //updateQueueMeter.Exit(); // update visible boundaries aab if (visibleBounds != null) visibleBounds.Merge(obj.GetWorldBoundingBox(true), obj.GetWorldBoundingSphere(true), camera); } } //objectListMeter.Exit(); //childListMeter.Enter(); if(includeChildren) { // ask all child nodes to update the render queue with visible objects foreach (SceneNode childNode in childNodes.Values) { if(childNode.Visible) childNode.FindVisibleObjects(camera, queue, visibleBounds, includeChildren, displayNodes, onlyShadowCasters); } } //childListMeter.Exit(); // if we wanna display nodes themself.. if(displayNodes) { // hey, lets just add ourself right to the render queue queue.AddRenderable(this); } // do we wanna show our beautiful bounding box? // do it if either we want it, or the SceneManager dictates it if(showBoundingBox || creator.ShowBoundingBoxes) { AddBoundingBoxToQueue(queue); } }
/// <summary> /// Overloaded method. /// </summary> /// <param name="camera"></param> /// <param name="queue"></param> /// <param name="includeChildren"></param> /// <param name="displayNodes"></param> public virtual void FindVisibleObjects(Camera camera, RenderQueue queue, VisibleObjectsBoundsInfo visibleBounds, bool includeChildren, bool displayNodes) { // call overloaded method FindVisibleObjects(camera, queue, visibleBounds, includeChildren, displayNodes, false); }
// main visibility determination & render queue filling routine // over-ridden from base/default scene manager. This is *the* // main call. public void FindVisibleObjects( Camera cam, VisibleObjectsBoundsInfo visibleBounds, bool onlyShadowCasters ) { // clear the render queue renderQueue.Clear(); // clear the list of visible nodes this.visibleNodes.Clear(); // turn off sky EnableSky( false ); // remove all extra culling planes ( (PCZCamera)cam ).RemoveAllExtraCullingPlanes(); // increment the visibility frame counter //mFrameCount++; this.frameCount = Root.Instance.CurrentFrameCount; // update the camera ( (PCZCamera)cam ).Update(); // get the home zone of the camera PCZone cameraHomeZone = ( (PCZSceneNode)( cam.ParentSceneNode ) ).HomeZone; // walk the zones, starting from the camera home zone, // adding all visible scene nodes to the mVisibles list cameraHomeZone.LastVisibleFrame = this.frameCount; cameraHomeZone.FindVisibleNodes( (PCZCamera)cam, ref this.visibleNodes, renderQueue, visibleBounds, onlyShadowCasters, displayNodes, showBoundingBoxes ); }
/// <summary> /// Internal method which locates any visible objects attached to this node and adds them to the passed in queue. /// </summary> /// <param name="camera">Active camera.</param> /// <param name="queue">Queue to which these objects should be added.</param> /// <param name="includeChildren">If true, cascades down to all children.</param> /// <param name="displayNodes">Renders the local axes for the node.</param> /// <param name="onlyShadowCasters"></param> public virtual void FindVisibleObjects(Camera camera, RenderQueue queue, VisibleObjectsBoundsInfo visibleBounds, bool includeChildren, bool displayNodes, bool onlyShadowCasters) { // if we aren't visible, then quit now // TODO: Make sure sphere is calculated properly for all objects, then switch to cull using that if (!camera.IsObjectVisible(worldAABB)) { return; } // add visible objects to the render queue //objectListMeter.Enter(); foreach (MovableObject obj in objectList.Values) { // tell attached object about current camera in case it wants to know //notifyCameraMeter.Enter(); obj.NotifyCurrentCamera(camera); //notifyCameraMeter.Exit(); // if this object is visible, add it to the render queue if (obj.IsVisible && (!onlyShadowCasters || obj.CastShadows)) { //updateQueueMeter.Enter(); obj.UpdateRenderQueue(queue); //updateQueueMeter.Exit(); // update visible boundaries aab if (visibleBounds != null) { visibleBounds.Merge(obj.GetWorldBoundingBox(true), obj.GetWorldBoundingSphere(true), camera); } } } //objectListMeter.Exit(); //childListMeter.Enter(); if (includeChildren) { // ask all child nodes to update the render queue with visible objects foreach (SceneNode childNode in childNodes.Values) { if (childNode.Visible) { childNode.FindVisibleObjects(camera, queue, visibleBounds, includeChildren, displayNodes, onlyShadowCasters); } } } //childListMeter.Exit(); // if we wanna display nodes themself.. if (displayNodes) { // hey, lets just add ourself right to the render queue queue.AddRenderable(this); } // do we wanna show our beautiful bounding box? // do it if either we want it, or the SceneManager dictates it if (showBoundingBox || creator.ShowBoundingBoxes) { AddBoundingBoxToQueue(queue); } }
public override Camera CreateCamera(string name) { Camera cam = new OctreeCamera(name, this); cameraList.Add(name, cam); // create visible bounds aabb map entry camVisibleObjectsMap[cam] = new VisibleObjectsBoundsInfo(); return cam; }
/* // Recursively walk the zones, adding all visible SceneNodes to the list of visible nodes. */ public override void FindVisibleNodes( PCZCamera camera, ref List<PCZSceneNode> visibleNodeList, RenderQueue queue, VisibleObjectsBoundsInfo visibleBounds, bool onlyShadowCasters, bool displayNodes, bool showBoundingBoxes ) { //return immediately if nothing is in the zone. if ( mHomeNodeList.Count == 0 && mVisitorNodeList.Count == 0 && mPortals.Count == 0 ) return; // Else, the zone is automatically assumed to be visible since either // it is the camera the zone is in, or it was reached because // a connecting portal was deemed visible to the camera. // enable sky if called to do so for this zone if ( HasSky ) { // enable sky mPCZSM.EnableSky( true ); } // find visible nodes at home in the zone bool vis; foreach ( PCZSceneNode pczsn in mHomeNodeList ) { //PCZSceneNode pczsn = *it; // if the scene node is already visible, then we can skip it if ( pczsn.LastVisibleFrame != mLastVisibleFrame || pczsn.LastVisibleFromCamera != camera ) { FrustumPlane fPlane; // for a scene node, check visibility using AABB vis = camera.IsObjectVisible( pczsn.WorldAABB, out fPlane ); if ( vis ) { // add it to the list of visible nodes visibleNodeList.Add( pczsn ); // add the node to the render queue pczsn.AddToRenderQueue( camera, queue, onlyShadowCasters, visibleBounds ); // if we are displaying nodes, add the node renderable to the queue if ( displayNodes ) { queue.AddRenderable( pczsn.GetDebugRenderable() ); } // if the scene manager or the node wants the bounding box shown, add it to the queue if ( pczsn.ShowBoundingBox || showBoundingBoxes ) { pczsn.AddBoundingBoxToQueue( queue ); } // flag the node as being visible this frame pczsn.LastVisibleFrame = mLastVisibleFrame; pczsn.LastVisibleFromCamera = camera; } } } // find visible visitor nodes foreach ( PCZSceneNode pczsn in mVisitorNodeList ) { // if the scene node is already visible, then we can skip it if ( pczsn.LastVisibleFrame != mLastVisibleFrame || pczsn.LastVisibleFromCamera != camera ) { FrustumPlane fPlane; // for a scene node, check visibility using AABB vis = camera.IsObjectVisible( pczsn.WorldAABB, out fPlane ); if ( vis ) { // add it to the list of visible nodes visibleNodeList.Add( pczsn ); // add the node to the render queue pczsn.AddToRenderQueue( camera, queue, onlyShadowCasters, visibleBounds ); // if we are displaying nodes, add the node renderable to the queue if ( displayNodes ) { queue.AddRenderable( pczsn.GetDebugRenderable() ); } // if the scene manager or the node wants the bounding box shown, add it to the queue if ( pczsn.ShowBoundingBox || showBoundingBoxes ) { pczsn.AddBoundingBoxToQueue( queue ); } // flag the node as being visible this frame pczsn.LastVisibleFrame = mLastVisibleFrame; pczsn.LastVisibleFromCamera = camera; } } } // find visible portals in the zone and recurse into them foreach ( Portal portal in mPortals ) { FrustumPlane fPlane; // for portal, check visibility using world bounding sphere & direction vis = camera.IsObjectVisible( portal, out fPlane ); if ( vis ) { // portal is visible. Add the portal as extra culling planes to camera int planes_added = camera.AddPortalCullingPlanes( portal ); // tell target zone it's visible this frame portal.getTargetZone().LastVisibleFrame = mLastVisibleFrame; portal.getTargetZone().LastVisibleFromCamera = camera; // recurse into the connected zone portal.getTargetZone().FindVisibleNodes( camera, ref visibleNodeList, queue, visibleBounds, onlyShadowCasters, displayNodes, showBoundingBoxes ); if ( planes_added > 0 ) { // Then remove the extra culling planes added before going to the next portal in this zone. camera.RemovePortalCullingPlanes( portal ); } } } }
/// <summary> /// /// </summary> /// <param name="camera"></param> public override void FindVisibleObjects(Camera camera, VisibleObjectsBoundsInfo visibleBounds, bool onlyShadowCasters) { base.FindVisibleObjects (camera, visibleBounds, onlyShadowCasters); }