Click or drag to resize
DigitalRuneScene Queries

This topic contains the following sections:

What are scene queries?

One main purpose of a scene graph (represented by the interface IScene) is the ability to quickly identify scene nodes that match a certain criterion. For example, all scene nodes within the camera viewing frustum, all light nodes that affect a certain mesh, all mesh nodes that cast shadows from a given light source, ...

The interface IScene provides a QueryT method. This method can be used to get all scene nodes that touch a given scene node, the reference node. For example: If the reference node is the currently active camera node, the QueryT method returns all scene nodes within the viewing frustum. (Checks are performed using the bounding shape of the scene nodes, not the exact geometry.)

The QueryT is a generic method that requires a type parameter. The type parameter specifies the scene query type, which must be a class that implements ISceneQuery. An instance of this scene query type is returned as the result of the method.

Example (C#)
// Get all scene nodes within viewing frustum.
CameraFrustumQuery sceneQuery = scene.Query<CameraFrustumQuery>(cameraNode);

// (The result is stored in sceneQuery.SceneNodes.)

The ISceneQuery can further filter the returned scene nodes, or group them by category. DigitalRune Graphics provides several predefined scene query types: CameraFrustumQuery, FogQuery, LightQuery, ShadowCasterQuery.

Important note Important

Scene queries are cached and reused internally by the Scene. That means, if QueryT is called a second time with the same ISceneQuery type, the same ISceneQuery instance is returned.

User-defined queries

In complex rendering pipelines it can be useful to create a custom scene query. A new scene query type can be created by adding a new class that implements ISceneQuery.

Example: The following scene query sorts scene nodes by category and ignores unsupported scene node types.

C#
public class CustomSceneQuery : ISceneQuery
{
  public SceneNode ReferenceNode { get; private set; }

  public List<SceneNode> DecalNodes { get; private set; }
  public List<SceneNode> Lights { get; private set; }
  public List<SceneNode> LensFlareNodes { get; private set; }
  public List<SceneNode> SkyNodes { get; private set; }
  public List<SceneNode> FogNodes { get; private set; }

  // All other scene nodes where IsRenderable is true (e.g. MeshNodes).
  public List<SceneNode> RenderableNodes { get; private set; }

  public CustomSceneQuery()
  {
    DecalNodes = new List<SceneNode>();
    Lights = new List<SceneNode>();
    LensFlareNodes = new List<SceneNode>();
    SkyNodes = new List<SceneNode>();
    FogNodes = new List<SceneNode>();
    RenderableNodes = new List<SceneNode>();
  }


  public void Reset()
  {
    ReferenceNode = null;

    DecalNodes.Clear();
    Lights.Clear();
    LensFlareNodes.Clear();
    SkyNodes.Clear();
    FogNodes.Clear();
    RenderableNodes.Clear();
  }


  public void Set(SceneNode referenceNode, IList<SceneNode> nodes)
  {
    Reset();
    ReferenceNode = referenceNode;

    for (int i = 0; i < nodes.Count; i++)
    {
      var node = nodes[i];

      if (node is DecalNode)
        DecalNodes.Add(node);
      else if (node is LightNode)
        Lights.Add(node);
      else if (node is LensFlareNode)
        LensFlareNodes.Add(node);
      else if (node is SkyNode)
        SkyNodes.Add(node);
      else if (node is FogNode)
        FogNodes.Add(node);
      else if (node.IsRenderable)
        RenderableNodes.Add(node);

      // Note: Unsupported types are simply ignored.
    }
  }
}

The following line shows how to use the new scene query:

C#
CustomSceneQuery sceneQuery = scene.Query<CustomSceneQuery>(referenceNode);