Praca z grafem sceny
Praca z grafem sceny
Każda scena 3D w Aspose.3D dla .NET jest zorganizowana jako drzewo Node obiektów. Scene.RootNode jest korzeniem tego drzewa i każdy element geometrii, materiału i przekształcenia znajduje się pod nim jako dziecko lub potomek.
Tworzenie sceny i dostęp do węzła korzenia
Scene inicjalizuje się automatycznie z węzłem głównym o nazwie "RootNode":
using Aspose.ThreeD;
var scene = new Scene();
Node root = scene.RootNode; // always "RootNode"Dodawanie węzłów potomnych
Call CreateChildNode() na dowolnym węźle, aby dodać dziecko. Metoda ma trzy powszechnie używane przeciążenia:
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);Aby dołączyć węzeł utworzony osobno, użyj AddChildNode():
var detached = new Node("standalone");
root.AddChildNode(detached);Odpytywanie węzłów potomnych
Znajdź bezpośredniego potomka po nazwie lub indeksie, lub iteruj wszystkie bezpośrednie potomki:
// 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) przeszukuje tylko bezpośrednie dzieci, nie pełne poddrzewo. Użyj rekurencyjnego pomocnika lub Accept() aby przeszukać całe drzewo.
Przechodzenie pełnego drzewa
Aby wykonać pełne przejście wgłąb, iteruj ChildNodes rekursywnie:
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);Dla przeglądania z wczesnym zakończeniem, node.Accept(NodeVisitor) jest dostępne i wywołuje odwiedzającego na każdym potomku, aż odwiedzający zwróci false.
Używanie Group do organizacji powiązanych obiektów
Group jest encją kontenera, która logicznie organizuje węzły bez dodawania geometrii. Dołącz ją do węzła, którego dzieci reprezentują jednostkę logiczną:
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));Przemieszczanie roomNode transformuje wszystkie meble razem, ponieważ dzieci dziedziczą jego Transform.
Kontrola widoczności i wykluczanie z eksportu
Węzły mogą być ukryte lub wykluczone z eksportu bez usuwania ich z hierarchii:
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 jest wskazówką wyświetlania. Excluded = true zapobiega pojawieniu się węzła w wyeksportowanych plikach, niezależnie od formatu.
Dołączanie wielu encji do jednego węzła
Węzeł ma podstawowy entity (Entity property), ale może przechowywać dodatkowe encje poprzez AddEntity(). Jest to przydatne, gdy różne części siatki współdzielą pojedynczą transformację:
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);Scalanie węzłów
Merge() przenosi wszystkie dzieci, encje i materiały z węzła źródłowego do węzła docelowego. Węzeł źródłowy pozostaje pusty:
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 emptyKolejne kroki
- Stosowanie transformacji — pozycjonuj, obracaj i skaluj dowolny węzeł przy użyciu jego
Transform - Tworzenie prymitywnej geometrii — użyj
Box,Sphere, orazCylinderjako encje sceny - Tworzenie i praca z siatkami — buduj geometrię wielokąta i dołącz ją do węzłów
Szybkie odniesienie do API
| Członek | Opis |
|---|---|
scene.RootNode | Korzeń drzewa sceny; zawsze obecny po new Scene() |
node.CreateChildNode(name) | Utwórz nazwany węzeł potomny bez encji |
node.CreateChildNode(name, entity) | Utwórz nazwany węzeł potomny z encją |
node.CreateChildNode(name, entity, material) | Utwórz nazwany węzeł potomny z encją i materiałem |
node.AddChildNode(node) | Dołącz osobno skonstruowany Node |
node.GetChild(name) | Znajdź bezpośredniego potomka po nazwie; zwraca null jeśli nie znaleziono |
node.GetChild(index) | Pobierz bezpośredniego potomka pod danym indeksem |
node.ChildNodes | IList<Node> wszystkich bezpośrednich dzieci |
node.Accept(visitor) | Przejdź po tym węźle i wszystkich potomkach w kolejności głębokościowej |
node.AddEntity(entity) | Dołącz dodatkową encję do węzła |
node.Entities | IList<Entity> wszystkich encji na tym węźle |
node.Visible | Pokaż lub ukryj węzeł |
node.Excluded | Dołącz lub wyklucz węzeł z eksportu |
node.Merge(other) | Przenieś wszystkie dzieci i encje z other do tego węzła |
new Group(name) | Encja kontenerowa do logicznego grupowania węzłów potomnych |