SceneNode.cs :  » Game » RealmForge » Axiom » Core » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Game » RealmForge 
RealmForge » Axiom » Core » SceneNode.cs
#region LGPL License
/*
Axiom Game Engine Library
Copyright (C) 2003  Axiom Project Team

The overall design, and a majority of the core engine and rendering code 
contained within this library is a derivative of the open source Object Oriented 
Graphics Engine OGRE, which can be found at http://ogre.sourceforge.net.  
Many thanks to the OGRE team for maintaining such a high quality project.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#endregion

using System;
using System.Diagnostics;
using Axiom.Collections;
using Axiom.MathLib;
using Axiom.Graphics;

namespace Axiom.Core{
  /// <summary>
  ///    Represents a node in a scene graph.
  /// </summary>
  /// <remarks>
  ///    A SceneNode is a type of Node which is used to organize objects in a scene.
  ///    It has the same hierarchical transformation properties of the generic Node class,
  ///    but also adds the ability to attach world objects to the node, and stores hierarchical
  ///    bounding volumes of the nodes in the tree.
  ///    Child nodes are contained within the bounds of the parent, and so on down the
  ///    tree, allowing for fast culling.
  /// </remarks>
  public class SceneNode : Node {
    #region Fields

    /// <summary>
    ///    A collection of all objects attached to this scene node.
    ///  </summary>
    protected SceneObjectCollection objectList = new SceneObjectCollection();
    /// <summary>
    ///    Reference to the scene manager who created me.
    ///  </summary>
    protected SceneManager creator;
    /// <summary>
    ///    Renderable bounding box for this node.
    ///  </summary>
    protected WireBoundingBox wireBox;
    /// <summary>
    ///    Whether or not to display this node's bounding box.
    ///  </summary>
    protected bool showBoundingBox;
    /// <summary>
    ///    Bounding box. Updated through Update.
    ///  </summary>
    protected AxisAlignedBox worldAABB = AxisAlignedBox.Null;
    /// <summary>
    ///    Word bounding sphere surrounding this node.
    /// </summary>
    protected Sphere worldBoundingSphere = new Sphere();
    public Sphere WorldBoundingSphere { get { return worldBoundingSphere; } }
    /// <summary>
    ///    List of lights within range of this node.
    /// </summary>
    protected LightList lightList = new LightList();
    /// <summary>
    ///    Keeps track of whether the list of lights located near this node needs updating.
    /// </summary>
    protected bool lightListDirty;
    /// <summary>
    ///    Where to yaw around a fixed axis.
    /// </summary>
    protected bool isYawFixed;
    /// <summary>
    ///    Fixed axis to yaw around.
    /// </summary>
    protected Vector3 yawFixedAxis;
    /// <summary>
    ///    Auto tracking target.
    /// </summary>
    protected SceneNode autoTrackTarget;
    /// <summary>
    ///    Tracking offset for fine tuning.
    /// </summary>
    protected Vector3 autoTrackOffset = Vector3.Zero;
    /// <summary>
    ///    Local 'normal' direction vector.
    /// </summary>
    protected Vector3 autoTrackLocalDirection = Vector3.NegativeUnitY;
    /// <summary>
    ///    Determines whether node and children are visible or not.
    /// </summary>
    protected bool visible = true;

    #endregion

    #region Constructors

    /// <summary>
    ///    Basic constructor.  Takes a scene manager reference to record the creator.
    /// </summary>
    /// <remarks>
    ///    Can be created manually, but should be left the Create* Methods.
    /// </remarks>
    /// <param name="creator"></param>
    public SceneNode(SceneManager creator) : base() {
      this.creator = creator;

      NeedUpdate();

      lightListDirty = true;
    }

    /// <summary>
    ///    Overloaded constructor.  Takes a scene manager reference to record the creator, and a name for the node.
    /// </summary>
    /// <param name="creator"></param>
    /// <param name="name"></param>
    public SceneNode(SceneManager creator, string name) : base(name) {
      this.creator = creator;

      NeedUpdate();

      lightListDirty = true;
    }

    #endregion

    #region Properties

    /// <summary>
    ///    Gets the number of SceneObjects currently attached to this node.
    /// </summary>
    public int ObjectCount {
      get {
        return objectList.Count;
      }
    }

    /// <summary>
    ///    Gets/Sets whether or not to display the bounding box for this node.
    /// </summary>
    public bool ShowBoundingBox {
      get { 
        return showBoundingBox; 
      }
      set { 
        showBoundingBox = value; 
      }
    }

    /// <summary>
    ///    Gets a reference to the SceneManager that created this node.
    /// </summary>
    public SceneManager Creator {
      get { 
        return creator; 
      }
    }

    /// <summary>
    ///    Gets the axis-aligned bounding box of this node (and hence all child nodes).
    /// </summary>
    /// <remarks>
    ///    Usage not recommended unless you are extending a SceneManager, because the bounding box returned
    ///    from this method is only up to date after the SceneManager has called Update.
    /// </remarks>
    public AxisAlignedBox WorldAABB {
      get { 
        return worldAABB; 
      }
    }

    /// <summary>
    ///    Gets the offset at which this node is tracking another node, if the node is auto tracking..
    /// </summary>
    public Vector3 AutoTrackOffset {
      get { return autoTrackOffset; }
      set { autoTrackOffset = value; }
    }

    /// <summary>
    ///    Get the auto tracking local direction for this node, if it is auto tracking.
    /// </summary>
    public Vector3 AutoTrackLocalDirection {
      get { return autoTrackLocalDirection; }
      set{ autoTrackLocalDirection = value; }
    }

    /// <summary>
    ///    Gets the SceneNode that this node is currently tracking, if any.
    /// </summary>
    public SceneNode AutoTrackTarget {
      get { return autoTrackTarget; }
      set{ autoTrackTarget = value;
        creator.NotifyAutoTrackingSceneNode(this,value != null);
      }
    }

    /// <summary>
    ///    Sets visibility for this node. If invisible, child nodes will be invisible, too.
    /// </summary>
    public bool Visible {
      get { return this.visible; }
      set { this.visible = value; }
    }
    
    #endregion

    #region Methods

    /// <summary>
    ///    Attaches a SceneObject to this scene node.
    /// </summary>
    /// <remarks>
    ///    A SceneObject will not show up in the scene until it is attached to a SceneNode.
    /// </remarks>
    /// <param name="obj"></param>
    public virtual void AttachObject(SceneObject obj) {
      Debug.Assert(obj != null, "obj != null");

      objectList.Add(obj);

      // notify the object that it was attached to us
      obj.NotifyAttached(this);

      // make sure bounds get updated
      NeedUpdate();
    }

    /// <summary>
    ///    Need to clear list of child objects in addition to base class functionality.
    /// </summary>
    public override void Clear() {
      base.Clear();

      objectList.Clear();
    }


    /// <summary>
    ///    Creates a new name child node.
    /// </summary>
    /// <param name="name"></param>
    public virtual SceneNode CreateChildSceneNode(string name) {
      return CreateChildSceneNode(name, Vector3.Zero, Quaternion.Identity);
    }

    /// <summary>
    ///    Creates a new named child scene node.
    /// </summary>
    /// <param name="name">Name of the node.</param>
    /// <param name="translate">A vector to specify the position relative to the parent.</param>
    /// <returns></returns>
    public virtual SceneNode CreateChildSceneNode(string name, Vector3 translate) {
      return CreateChildSceneNode(name, translate, Quaternion.Identity);
    }

    /// <summary>
    ///    Creates a new named child scene node.
    /// </summary>
    /// <param name="name">Name of the node.</param>
    /// <param name="translate">A vector to specify the position relative to the parent.</param>
    /// <param name="rotate">A quaternion to specify the orientation relative to the parent.</param>
    /// <returns></returns>
    public virtual SceneNode CreateChildSceneNode(string name, Vector3 translate, Quaternion rotate) {
      return (SceneNode)CreateChild(name, translate, rotate);
    }

    /// <summary>
    ///    Creates a new child scene node.
    /// </summary>
    public virtual SceneNode CreateChildSceneNode() {
      return CreateChildSceneNode(Vector3.Zero, Quaternion.Identity);
    }

    /// <summary>
    ///    Creates a new child scene node.
    /// </summary>
    /// <param name="translate">A vector to specify the position relative to the parent.</param>
    /// <returns></returns>
    public virtual SceneNode CreateChildSceneNode(Vector3 translate) {
      return CreateChildSceneNode(translate, Quaternion.Identity);
    }

    /// <summary>
    ///    Creates a new child scene node.
    /// </summary>
    /// <param name="translate">A vector to specify the position relative to the parent.</param>
    /// <param name="rotate">A quaternion to specify the orientation relative to the parent.</param>
    /// <returns></returns>
    public virtual SceneNode CreateChildSceneNode(Vector3 translate, Quaternion rotate) {
      return (SceneNode)CreateChild(translate, rotate);
    }

    /// <summary>
    ///    Removes all currently attached SceneObjects from this SceneNode.
    /// </summary>
    /// <remarks>
    ///    Bounds for this SceneNode are also updated.
    /// </remarks>
    public virtual void DetachAllObjects() {
      objectList.Clear();

      UpdateBounds();
    }

    /// <summary>
    ///    Removes the specifed object from this scene node.
    /// </summary>
    /// <remarks>
    ///    Bounds for this SceneNode are also updated.
    /// </remarks>
    /// <param name="index">Index of the object to remove.</param>
    public virtual SceneObject DetachObject(int index) {
      Debug.Assert(index < objectList.Count, "index < objectList.Count");

      SceneObject obj = objectList[index];

      objectList.Remove(obj);

      // notify the object that it was removed (sending in null sets its parent scene node to null)
      obj.NotifyAttached(null);

      // Make sure bounds get updated (must go right to the top)
      NeedUpdate();

      return obj;
    }

    /// <summary>
    /// Rekeys the scene object using its new Name
    /// </summary>
    /// <param name="obj"></param>
    public virtual void NotifyAttachedObjectNameChanged(SceneObject obj) {
      objectList.Remove(obj);
      objectList.Add(obj);
    }

    /// <summary>
    ///    Removes the specifed object from this scene node.
    /// </summary>
    /// <remarks>
    ///    Bounds for this SceneNode are also updated.
    /// </remarks>
    /// <param name="obj">Reference to the object to remove.</param>
    public virtual void DetachObject(SceneObject obj) 
    {
      Debug.Assert(obj != null, "obj != null");

      objectList.Remove(obj);

      // notify the object that it was removed (sending in null sets its parent scene node to null)
      obj.NotifyAttached(null);

      // Make sure bounds get updated (must go right to the top)
      NeedUpdate();
    }

    /// <summary>
    /// Returns a scene object attached to this node by name. Node that this method
    /// is O(n), whereas the integer overload of this method is O(1). Use the integer
    /// version of this method if speed is important.
    /// </summary>
    /// <param name="name">The name of the object to return.</param>
    /// <returns>SceneObject if found. Throws exception of not found.</returns>
    public SceneObject GetObject(string name) {
      foreach(SceneObject obj in this.objectList) {
        if(obj.Name == name)
          return obj;
      }
      throw new IndexOutOfRangeException("Invalid key specified.");
    }

    public SceneObject GetObject(int index) {
      if(objectList.Count <= index) return null;
      return objectList[index];
    }

    /// <summary>
    ///    Internal method to update the Node.
    /// </summary>
    /// <remarks>
    ///    Updates this scene node and any relevant children to incorporate transforms etc.
    ///    Don't call this yourself unless you are writing a SceneManager implementation.
    /// </remarks>
    /// <param name="updateChildren"></param>
    /// <param name="hasParentChanged"></param>
    protected internal override void Update(bool updateChildren, bool hasParentChanged) {
      // call base class method
      base.Update(updateChildren, hasParentChanged);

      UpdateBounds();

      lightListDirty = true;
    }

    /// <summary>
    ///    Overloaded method.
    /// </summary>
    /// <param name="camera"></param>
    /// <param name="queue"></param>
    public virtual void FindVisibleObjects(Camera camera, RenderQueue queue) {
      // call overloaded method
      FindVisibleObjects(camera, queue, true, false, false);
    }

    /// <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, bool includeChildren, bool displayNodes) {
      // call overloaded method
      FindVisibleObjects(camera, queue, includeChildren, displayNodes, false);
    }

    /// <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, 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
      for(int i = 0; i < objectList.Count; i++) {
        SceneObject obj = objectList[i];

        // tell attached object about current camera in case it wants to know
        obj.NotifyCurrentCamera(camera);

        // if this object is visible, add it to the render queue
        if(obj.IsVisible &&
          (!onlyShadowCasters || obj.CastShadows)) {
          obj.UpdateRenderQueue(queue);
        }
      }

      if(includeChildren) {
        // ask all child nodes to update the render queue with visible objects
        for(int i = 0; i < childNodes.Count; i++) {
          SceneNode childNode = (SceneNode)childNodes[i];
          if(childNode.Visible)
            childNode.FindVisibleObjects(camera, queue, includeChildren, displayNodes, onlyShadowCasters);
        }
      }

      // 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>
    ///    Adds this nodes bounding box (wireframe) to the RenderQueue.
    /// </summary>
    /// <param name="queue"></param>
    public void AddBoundingBoxToQueue(RenderQueue queue) {
      if(wireBox == null)
        wireBox = new WireBoundingBox();

      // add the wire bounding box to the render queue
      wireBox.InitAABB(worldAABB);
      queue.AddRenderable(wireBox);
    }

    /// <summary>
    ///    Tell the SceneNode to update the world bound info it stores.
    /// </summary>
    protected virtual void UpdateBounds() {
      // reset bounds
      worldAABB.IsNull = true;
      worldBoundingSphere.Center = this.DerivedPosition;
      float radius = worldBoundingSphere.Radius = 0;

      // update bounds from attached objects
      for(int i = 0; i < objectList.Count; i++) {
        SceneObject obj = objectList[i];

        // update
        worldAABB.Merge(obj.GetWorldBoundingBox(true));

        radius = MathUtil.Max(obj.BoundingRadius, radius);
      }

      // merge with Children
      for(int i = 0; i < childNodes.Count; i++) {
        SceneNode child = (SceneNode)childNodes[i];

        // merge our bounding box with that of the child node
        worldAABB.Merge(child.worldAABB);
        radius = MathUtil.Max(child.worldBoundingSphere.Radius, radius);
      }
      worldBoundingSphere.Radius = radius;

    }

    /// <summary>
    ///    Tells the node whether to yaw around it's own local Y axis or a fixed axis of choice.
    /// </summary>
    /// <remarks>
    ///    This method allows you to change the yaw behavior of the node - by default, it
    ///    yaws around it's own local Y axis when told to yaw with <see cref="TransformSpace.Local"/>, 
    ///    this makes it yaw around a fixed axis. 
    ///    You only really need this when you're using auto tracking (<see cref="SetAutoTracking"/>,
    ///    because when you're manually rotating a node you can specify the <see cref="TransformSpace"/>
    ///    in which you wish to work anyway.
    /// </remarks>
    /// <param name="useFixed">
    ///    If true, the axis passed in the second parameter will always be the yaw axis no
    ///    matter what the node orientation. If false, the node returns to it's default behavior.
    /// </param>
    /// <param name="fixedAxis">The axis to use if the first parameter is true.</param>
    public void SetFixedYawAxis(bool useFixed, Vector3 fixedAxis) {
      isYawFixed = useFixed;
      yawFixedAxis = fixedAxis;
    }

    /// <summary>
    ///    Sets a default fixed yaw axis of Y.
    /// </summary>
    /// <param name="useFixed"></param>
    public void SetFixedYawAxis(bool useFixed) {
      SetFixedYawAxis(useFixed, Vector3.UnitY);
    }

    /// <summary>
    ///    Overridden to apply fixed yaw axis behavior.
    /// </summary>
    /// <param name="degrees"></param>
    public override void Yaw(float degrees) {
      Vector3 yAxis;

      if(isYawFixed) {
        // Rotate around fixed yaw axis
        yAxis = yawFixedAxis;
      }
      else {
        // Rotate around local Y axis
        yAxis = orientation * Vector3.UnitY;
      }

      Rotate(yAxis, degrees);
    }


    /// <summary>
    ///    Points the local Z direction of this node at a point in space.
    /// </summary>
    /// <param name="target">A vector specifying the look at point.</param>
    /// <param name="relativeTo">The space in which the point resides.</param>
    /// <param name="localDirection">
    ///    The vector which normally describes the natural direction of the node, usually -Z.
    ///  </param>
    public void LookAt(Vector3 target, TransformSpace relativeTo, Vector3 localDirection) {
      SetDirection(target - this.DerivedPosition, relativeTo, localDirection);
    }

    public void LookAt(Vector3 target, TransformSpace relativeTo) {
      LookAt(target, relativeTo, Vector3.NegativeUnitZ);
    }

    /// <summary>
    ///    Enables / disables automatic tracking of another SceneNode.
    /// </summary>
    /// <remarks>
    ///    If you enable auto-tracking, this SceneNode will automatically rotate to
    ///    point it's -Z at the target SceneNode every frame, no matter how 
    ///    it or the other SceneNode move. Note that by default the -Z points at the 
    ///    origin of the target SceneNode, if you want to tweak this, provide a 
    ///    vector in the 'offset' parameter and the target point will be adjusted.
    /// </remarks>
    /// <param name="enabled">
    ///    If true, tracking will be enabled and the 'target' cannot be null. 
    ///    If false tracking will be disabled and the current orientation will be maintained.
    /// </param>
    /// <param name="target">
    ///    Reference to the SceneNode to track. Can be null if and only if the enabled param is false.
    /// </param>
    /// <param name="localDirection">
    ///    The local vector considered to be the usual 'direction'
    ///    of the node; normally the local -Z but can be another direction.
    /// </param>
    /// <param name="offset">
    ///    If supplied, this is the target point in local space of the target node
    ///    instead of the origin of the target node. Good for fine tuning the look at point.
    /// </param>
    public void SetAutoTracking(bool enabled, SceneNode target, Vector3 localDirection, Vector3 offset) {
      if(enabled) {
        autoTrackTarget = target;
        autoTrackOffset = offset;
        autoTrackLocalDirection = localDirection;
      }
      else {
        autoTrackTarget = null;
      }

      if(creator != null) {
        creator.NotifyAutoTrackingSceneNode(this, enabled);
      }
    }

    public void SetAutoTracking(bool enabled, SceneNode target, Vector3 localDirection) {
      SetAutoTracking(enabled, target, localDirection, Vector3.Zero);
    }

    public void SetAutoTracking(bool enabled, SceneNode target) {
      SetAutoTracking(enabled, target, Vector3.NegativeUnitZ, Vector3.Zero);
    }

    public void SetAutoTracking(bool enabled) {
      SetAutoTracking(enabled, null, Vector3.NegativeUnitZ, Vector3.Zero);
    }

    /// <summary>
    ///    Sets the node's direction vector ie it's local -z.
    /// </summary>
    /// <remarks>
    ///    Note that the 'up' vector for the orientation will automatically be 
    ///    recalculated based on the current 'up' vector (i.e. the roll will 
    ///    remain the same). If you need more control, use the <see cref="Orientation"/>
    ///    property.
    /// </remarks>
    /// <param name="vec">The direction vector.</param>
    /// <param name="relativeTo">The space in which this direction vector is expressed.</param>
    /// <param name="localDirection">The vector which normally describes the natural direction 
    ///    of the node, usually -Z.
    ///  </param>
    public void SetDirection(Vector3 vec, TransformSpace relativeTo, Vector3 localDirection) {
      // Do nothing if given a zero vector
      if (vec == Vector3.Zero) { 
        return;
      }

      // Adjust vector so that it is relative to local Z
      Vector3 zAdjustVec;

      if (localDirection == Vector3.NegativeUnitZ) {
        zAdjustVec = -vec;
      }
      else {
        Quaternion localToUnitZ = localDirection.GetRotationTo(Vector3.UnitZ);
        zAdjustVec = localToUnitZ * vec;
      }

      zAdjustVec.Normalize();

      Quaternion targetOrientation = Quaternion.Identity;

      if(isYawFixed ) {
        Vector3 xVec = yawFixedAxis.Cross(zAdjustVec);
        xVec.Normalize();

        Vector3 yVec = zAdjustVec.Cross(xVec);
        yVec.Normalize();
              
        targetOrientation.FromAxes(xVec, yVec, zAdjustVec);
      }
      else {
        Vector3 xAxis, yAxis, zAxis;

        // Get axes from current quaternion
        // get the vector components of the derived orientation vector
        this.DerivedOrientation.ToAxes(out xAxis, out yAxis, out zAxis);

        Quaternion rotationQuat;

        if ((zAxis + zAdjustVec).LengthSquared < 0.00000001f) {
          // Oops, a 180 degree turn (infinite possible rotation axes)
          // Default to yaw i.e. use current UP
          rotationQuat = Quaternion.FromAngleAxis(MathUtil.PI, yAxis);
        }
        else {
          // Derive shortest arc to new direction
          rotationQuat = zAxis.GetRotationTo(zAdjustVec);
        }

        targetOrientation = rotationQuat * orientation;
      }

      if (relativeTo == TransformSpace.Local || parent != null) {
        orientation = targetOrientation;
      }
      else {
        if (relativeTo == TransformSpace.Parent) {
          orientation = targetOrientation * parent.Orientation.Inverse();
        }
        else if (relativeTo == TransformSpace.World) {
          orientation = targetOrientation * parent.DerivedOrientation.Inverse();
        }
      }
    }

    /// <summary>
    ///    Allows retrieval of the nearest lights to the center of this SceneNode.
    /// </summary>
    /// <remarks>
    ///    This method allows a list of lights, ordered by proximity to the center of
    ///    this SceneNode, to be retrieved. Multiple access to this method when neither 
    ///    the node nor the lights have moved will result in the same list being returned
    ///    without recalculation. Can be useful when implementing IRenderable.Lights.
    /// </remarks>
    /// <param name="radius">Parameter to specify lights intersecting a given radius of
    ///    this SceneNode's centre</param>
    /// <returns></returns>
    public virtual LightList FindLights(float radius) {
      // TEMP FIX
      // If a scene node is static and lights have moved, light list won't change
      // can't use a simple global boolean flag since this is only called for
      // visible nodes, so temporarily visible nodes will not be updated
      // Since this is only called for visible nodes, skip the check for now
      //if(lightListDirty) {
      creator.PopulateLightList(this.DerivedPosition, radius, lightList);
      lightListDirty = false;
      //}

      return lightList;
    }

    /// <summary>
    ///    Internal method used to update auto-tracking scene nodes.
    /// </summary>
    internal void AutoTrack() {
      if(autoTrackTarget != null) {
        LookAt(
          autoTrackTarget.DerivedPosition + autoTrackOffset,
          TransformSpace.World,
          autoTrackLocalDirection);

        // update self and children
        Update(true, true);
      }
    }

    #endregion

    #region Implementation of Node

    /// <summary>
    ///    
    /// </summary>
    /// <returns></returns>
    protected override Node CreateChildImpl() {
      return creator.CreateSceneNode();
    }
  
    /// <summary>
    ///    
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    protected override Node CreateChildImpl(string name) {
      SceneNode newNode = creator.CreateSceneNode(name);
      return newNode;
    }

    /// <summary>
    ///    Allows retrieval of the nearest lights to the center of this SceneNode.
    /// </summary>
    /// <remarks>
    ///    This method allows a list of lights, ordered by proximity to the center of
    ///    this SceneNode, to be retrieved. Multiple access to this method when neither 
    ///    the node nor the lights have moved will result in the same list being returned
    ///    without recalculation. Can be useful when implementing IRenderable.Lights.
    /// </remarks>
    /// <returns></returns>
    public override LightList Lights {
      get {
        return FindLights(0);
      }
    }
    
    #endregion
  }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.