ISceneQuery Interface |
Namespace: DigitalRune.Graphics.SceneGraph
The ISceneQuery type exposes the following members.
Name | Description | |
---|---|---|
ReferenceNode |
Gets the reference node.
|
A scene query returns all scene nodes that touch a given reference node. Queries can be performed by calling QueryT(SceneNode, RenderContext) of a IScene. Here are a few examples of scene queries:
Scene nodes where IsEnabled is are ignored and do not show up in the query results.
Notes to Implementors: Classes that implement ISceneQuery must have a parameterless constructor.
The following examples demonstrates how to create a scene query that collects MeshNodes.
using System.Collections.Generic; using DigitalRune.Graphics; using DigitalRune.Graphics.SceneGraph; namespace Samples { public class MeshQuery : ISceneQuery { public SceneNode ReferenceNode { get; private set; } public List<SceneNode> Meshes { get; private set; } public MeshQuery() { Meshes = new List<SceneNode>(); } public void Reset() { ReferenceNode = null; Meshes.Clear(); } public void Set(SceneNode referenceNode, IList<SceneNode> nodes, RenderContext context) { Reset(); ReferenceNode = referenceNode; for (int i = 0; i < nodes.Count; i++) { var node = nodes[i]; if (node is MeshNode) Meshes.Add(node); } } } }
The query can, for example, be used to get all meshes within the camera frustum.
ISceneQuery query = myScene.Query<MeshQuery>(cameraNode, renderContext);
Distance Culling:
The following example shows how to implement a scene query that performs distance
culling of scene nodes.
using System.Collections.Generic; using DigitalRune.Graphics; using DigitalRune.Graphics.SceneGraph; using DigitalRune.Mathematics; namespace Samples { public class SceneQueryWithDistanceCulling : ISceneQuery { public SceneNode ReferenceNode { get; private set; } public List<SceneNode> Nodes { get; private set; } public SceneQueryWithDistanceCulling() { Nodes = new List<SceneNode>(); } public void Reset() { ReferenceNode = null; Nodes.Clear(); } public void Set(SceneNode referenceNode, IList<SceneNode> nodes, RenderContext context) { Reset(); ReferenceNode = referenceNode; var cameraNode = context.LodCameraNode; if (cameraNode == null) throw new GraphicsException("LOD camera node needs to be set in render context."); for (int i = 0; i < nodes.Count; i++) { var node = nodes[i]; // Calculate view-normalized distance of scene node. float distance = GraphicsHelper.GetViewNormalizedDistance(node, cameraNode); distance *= cameraNode.LodBias * context.LodBias; // Distance Culling: Check whether scene node is within MaxDistance. if (Numeric.IsPositiveFinite(node.MaxDistance) && distance >= node.MaxDistance) continue; // Ignore scene node. Nodes.Add(node); } } } }
Level of Detail:
Level of detail (see LodGroupNode) needs to be evaluated by the scene query. The
following example implements distance culling and LOD selection.
using System.Collections.Generic; using DigitalRune.Graphics; using DigitalRune.Graphics.SceneGraph; using DigitalRune.Mathematics; namespace Samples { public class SceneQueryWithLod : ISceneQuery { public SceneNode ReferenceNode { get; private set; } public List<SceneNode> Nodes { get; private set; } public SceneQueryWithLod() { Nodes = new List<SceneNode>(); } public void Reset() { ReferenceNode = null; Nodes.Clear(); } public void Set(SceneNode referenceNode, IList<SceneNode> nodes, RenderContext context) { Reset(); ReferenceNode = referenceNode; if (context.LodCameraNode == null) throw new GraphicsException("LOD camera node needs to be set in render context."); for (int i = 0; i < nodes.Count; i++) AddNode(nodes[i], context); } private void AddNode(SceneNode node, RenderContext context) { var cameraNode = context.LodCameraNode; // Calculate view-normalized distance. float distance = GraphicsHelper.GetViewNormalizedDistance(node, cameraNode); distance *= cameraNode.LodBias * context.LodBias; // Distance Culling: Check whether scene node is within MaxDistance. if (Numeric.IsPositiveFinite(node.MaxDistance) && distance >= node.MaxDistance) return; // Ignore scene node. var lodGroupNode = node as LodGroupNode; if (lodGroupNode != null) { // Evaluate LOD group. var lodSelection = lodGroupNode.SelectLod(context, distance); AddSubtree(lodSelection.Current, context); } else { Nodes.Add(node); } } private void AddSubtree(SceneNode node, RenderContext context) { if (node.IsEnabled) { AddNode(node, context); if (node.Children != null) foreach (var childNode in node.Children) AddSubtree(childNode, context); } } } }