This section assumes your familarity with previous topics related to group nodes. If you haven't done it yet, you may want to read the Transformations section first. Examples from the transformation section will be continued here.
It is common for many applications to handle more complex scenes than a single triangle. Complicated objects are often assembled from several less complex objects. A group represents the root node of such more complicated objects. Its children are organized within a subtree of objects – or possibly other sub-subtrees.
In ILNumerics, handling such structures is very simple. Any node from a scene can be reused for an arbitrary number of times. For group nodes, this corresponds to the whole subtree being reused.
The simple triangle from the Transformations section is sufficient to demonstrate that concept. In the following example, we will repeatedly duplicate, shrink and distribute a triangle and all of its content to each of its corners. Eventually, this results in the Sierpinski Triangle of order 7:
There are several aspects to this function which require some attention. We start with a single triangle which exists under a group node. In each iteration the subtree of group1 is added three times to a new root node, creating 3 copies of group1. Every copy is scaled down and distributed to each of the corners of the large triangle. The iteration then continues with the new root.
By scaling down the copy of the root node, all the contained objects are scaled down as well. Individual transformations are retained. In each group within the tree structure, only the scaling by 0.5 and the translation by 1 exists. However, since several of those transforms accumulate on the way from the root to any triangle child, the triangles at the end are rendered much smaller than that.
Nodes in the scene graph derive their transformations from the parent node.
Another important concept worth remembering from the example is related to buffer management. Let’s find out, how many objects have been created and drawn:
Our scene consists out of 2187 wireframe triangles. But we essentially created the vertices for exactly one triangle! All triangles rendered use the same set of vertices: the same Positions buffer. We did not pay any special attention to share those buffers. The scene graph did everything transparently for us in Group.Add:
As discussed, this creates a clone of the subtree below group1. However, while the scene graph nodes are cloned, the underlying buffers are not! All shapes in the clone still refer to the same vertex buffers as those of group1. If we altered the vertex buffer for any triangle in the clone, it would affect all shapes in the scene, using the same buffer:
In the zoomed output, one can clearly identify that the scene is built from many small triangles. We only changed the lower left vertex position of the first triangle in the scene. It is moved from (-1,-1, 0) to (-5, 0, 0). Since all triangles are created by duplicating subscenes, they all share the same buffers. Hence, all triangles appear modified.
In some situations this is not what we want. And it is easy to prevent: A shape can be detached from all related buffers before the buffer is modified.
Detaching a shape will stop sharing any buffers. The shape can be modified afterwards without affecting any other shapes. What‘s left to remember:
Duplicating a subtree results in a clone of the subtree being created. The shapes of the clone share their vertex buffers (positions, colors, indices and normals) with the original subtree. In order to prevent buffer sharing, the Detach() function is used (See Buffers to learn more about creating clones in ILNumerics).