Working with the Scene Graph
Working with the Scene Graph
Every 3D scene in Aspose.3D for .NET is organized as a tree of Node objects. Scene.RootNode is the root of that tree and every piece of geometry, material, and transform lives under it as a child or descendant.
Creating the Scene and Accessing the Root Node
Scene initializes automatically with a root node named "RootNode":
using Aspose.ThreeD;
var scene = new Scene();
Node root = scene.RootNode; // always "RootNode"Adding Child Nodes
Call CreateChildNode() on any node to add a child. The method has three commonly used overloads:
using Aspose.ThreeD;
using Aspose.ThreeD.Entities;
var scene = new Scene();
Node root = scene.RootNode;
// 1. Named node with no entity — useful as a pivot or transform container
Node pivot = root.CreateChildNode("pivot");
// 2. Named node with an entity
var box = new Box(2, 2, 2);
Node boxNode = root.CreateChildNode("box", box);
// 3. Named node with entity and material
var mat = new Aspose.ThreeD.Shading.PhongMaterial("red");
mat.Diffuse = new Vector4(0.8, 0.2, 0.2, 1.0);
Node decorated = pivot.CreateChildNode("red_box", box, mat);To attach a node constructed separately, use AddChildNode():
var detached = new Node("standalone");
root.AddChildNode(detached);Querying Child Nodes
Find a direct child by name or by index, or iterate all direct children:
// By name — returns null if no direct child has that name
Node? found = root.GetChild("box");
if (found != null)
Console.WriteLine("Found: " + found.Name);
// By index
Node first = root.GetChild(0);
// Iterate all direct children
foreach (Node child in root.ChildNodes)
Console.WriteLine(child.Name);
GetChild(string name)searches only direct children, not the full subtree. Use a recursive helper orAccept()to search the entire tree.
Traversing the Full Tree
For a full depth-first walk, iterate ChildNodes recursively:
static void Walk(Node node, int depth = 0)
{
Console.WriteLine(new string(' ', depth * 2) + node.Name);
foreach (var child in node.ChildNodes)
Walk(child, depth + 1);
}
Walk(scene.RootNode);For early-exit traversal, node.Accept(NodeVisitor) is available and calls the visitor on every descendant until the visitor returns false.
Using Group to Organize Related Objects
Group is a container entity that logically organizes nodes without adding geometry. Attach it to a node whose children represent a logical unit:
using Aspose.ThreeD;
using Aspose.ThreeD.Entities;
var scene = new Scene();
// A group node for all furniture in a room
var furnitureGroup = new Group("furniture");
Node roomNode = scene.RootNode.CreateChildNode("living_room", furnitureGroup);
// Child nodes under the group node
Node sofaNode = roomNode.CreateChildNode("sofa", new Box(3, 1, 1));
Node tableNode = roomNode.CreateChildNode("coffee_table", new Box(2, 0.5, 1));Moving roomNode transforms all furniture together because the children inherit its Transform.
Controlling Visibility and Export Exclusion
Nodes can be hidden or excluded from export without being removed from the hierarchy:
Node ground = scene.RootNode.CreateChildNode("ground_plane", new Box(100, 0.1, 100));
ground.Visible = false; // hidden in viewport / renderer
Node helperNode = scene.RootNode.CreateChildNode("debug_arrow", new Box());
helperNode.Excluded = true; // omitted from all export operationsVisible = false is a display hint. Excluded = true prevents the node from appearing in exported files regardless of format.
Attaching Multiple Entities to One Node
A node has a primary entity (Entity property), but can hold additional entities through AddEntity(). This is useful when different mesh pieces share a single transform:
var bodyMesh = new Mesh("body");
var wheelMesh = new Mesh("wheel");
Node carNode = scene.RootNode.CreateChildNode("car");
carNode.AddEntity(bodyMesh);
carNode.AddEntity(wheelMesh);
// Retrieve all entities on this node
foreach (Entity ent in carNode.Entities)
Console.WriteLine(ent.GetType().Name + ": " + ent.Name);Merging Nodes
Merge() moves all children, entities, and materials from a source node into the target node. The source node is left empty:
Node lod0 = scene.RootNode.CreateChildNode("lod0");
lod0.CreateChildNode("mesh_high", new Box(1, 1, 1));
Node lod1 = scene.RootNode.CreateChildNode("lod1");
lod1.CreateChildNode("mesh_low", new Box(1, 1, 1));
// Consolidate lod0 children into lod1
lod1.Merge(lod0);
// lod1 now has both mesh_high and mesh_low; lod0 is emptyNext Steps
- Applying Transforms — position, rotate, and scale any node using its
Transform - Creating Primitive Geometry — use
Box,Sphere, andCylinderas scene entities - Creating and Working with Meshes — build polygon geometry and attach it to nodes
API Quick Reference
| Member | Description |
|---|---|
scene.RootNode | Root of the scene tree; always present after new Scene() |
node.CreateChildNode(name) | Create a named child node with no entity |
node.CreateChildNode(name, entity) | Create a named child node with an entity |
node.CreateChildNode(name, entity, material) | Create a named child node with entity and material |
node.AddChildNode(node) | Attach a separately constructed Node |
node.GetChild(name) | Find a direct child by name; returns null if not found |
node.GetChild(index) | Get the direct child at a given index |
node.ChildNodes | IList<Node> of all direct children |
node.Accept(visitor) | Walk this node and all descendants depth-first |
node.AddEntity(entity) | Attach an additional entity to the node |
node.Entities | IList<Entity> of all entities on this node |
node.Visible | Show or hide the node |
node.Excluded | Include or exclude the node from export |
node.Merge(other) | Move all children and entities from other into this node |
new Group(name) | Container entity for logically grouping child nodes |