# 3D Scene Graph Dynamics

#### <a class="anchor" id="bkmrk--125"></a>Description

Usually all required nodes are already specified and preconfigured via SceneComposer, so in most cases it won't be necessary to make any adaptations within the scene graph loaded from an asset at runtime.

However, some use cases might require such adaptations. This tutorial covers the most common means to manipulate the scene graph structure dynamically.

#### <a class="anchor" id="bkmrk--127"></a>Example Solution

<div class="contents" id="bkmrk-scenegraphdynamicsso"><div class="textblock">- SceneGraphDynamicsSolution\_3D in folder *cgi\_studio\_player/content/Tutorials/03\_SceneGraphAndNodes*

</div></div>#### **Adding and Removing 3D Nodes** 

##### <a class="anchor" id="bkmrk--128"></a>3D Scene Graph Dynamics Example

For creating and adding a new node, the following can be used:

<div class="contents" id="bkmrk-scenegraphdynamicsso-0"><div class="contents"><div class="textblock">- **SceneGraphDynamicsSolution\_3D** from folder *cgi\_studio\_player/content/Tutorials/03\_SceneGraphAndNodes*
- **SceneGraphDynamicsWidget\_3D** (this is used in the example solution - refer to SceneGraphDynamicsWidget\_3D)

</div></div></div>As an example use case, a [Candera::Billboard](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_billboard.html "The class Billboard represents a Plane that can align towards camera automatically, according to the alignment type set. Thus, Billboards are quite often used as "imposters" pretending to be a 3D geometry by showing a 2D image that is always facing the camera. In order to relief distinction between Billboard and PointSprite see following comparison: + Billboards support rectangular dimension and non-uniform scale, + Billboards support different rotation techniques (see Alignment), whereas PointSprites are aligned according to CenterEyeAlignment, exclusively. + Billboards take local rotation and scale into account (see class Transformable), whereas PointSprites ignore Transformable parameters others than position. + PointSprites have a performance advantage due to less geometry (one instead of 4 vertices). Overall recommendation: Use PointSprites for spherical shapes like particles, lens flares, sparkles, dust which are screen aligned (see Billboard::CameraUpAlignment). Further, use Billboards for world up oriented clouds, text, or yaw axis aligned trees, and signs, etc. Note: The Billboard - because of absent normals - does not support lighting. Belows sketch depicts the layout of a Billboard. W U:0,V:1 +-----+ U:1,V:1 H | X | Legend: texture coordinates: U,V; Width: W, Height: H, Local Center: X U:0,V:0 +-----+ U:1,V:0.") can be created, added and removed. Use the SceneGraphDynamicsWidget\_3D properties described below:

<div class="contents" id="bkmrk-addbillboard%3A-if-add"><div class="contents"><div class="contents"><div class="textblock">- **AddBillboard**: If AddBillboard is enabled a new Billboard is created and added to the widget node. If disabled, the Billboard will be removed.

<div class="fragment">  
</div></div></div></div></div>```
        // Definition of WidgetProperty "AddBillboard"
        CdaProperty(AddBillboard, bool, GetAddBillboard, SetAddBillboard)
            CdaDescription("If AddBillboard is enabled a new Billboard is created and added to the widget Candera::Node. If disabled, the Billboard will be removed.")
        <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___meta_info.html#ga119bef57449bd05d8b3c40d7d514e375">CdaPropertyEnd</a>()
        // End Definition of WidgetProperty "AddBillboard"
```

##### <a class="anchor" id="bkmrk--129"></a>Creating a new Billboard

The following code snippet generates a basic [Candera::Billboard](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_billboard.html "The class Billboard represents a Plane that can align towards camera automatically, according to the alignment type set. Thus, Billboards are quite often used as "imposters" pretending to be a 3D geometry by showing a 2D image that is always facing the camera. In order to relief distinction between Billboard and PointSprite see following comparison: + Billboards support rectangular dimension and non-uniform scale, + Billboards support different rotation techniques (see Alignment), whereas PointSprites are aligned according to CenterEyeAlignment, exclusively. + Billboards take local rotation and scale into account (see class Transformable), whereas PointSprites ignore Transformable parameters others than position. + PointSprites have a performance advantage due to less geometry (one instead of 4 vertices). Overall recommendation: Use PointSprites for spherical shapes like particles, lens flares, sparkles, dust which are screen aligned (see Billboard::CameraUpAlignment). Further, use Billboards for world up oriented clouds, text, or yaw axis aligned trees, and signs, etc. Note: The Billboard - because of absent normals - does not support lighting. Belows sketch depicts the layout of a Billboard. W U:0,V:1 +-----+ U:1,V:1 H | X | Legend: texture coordinates: U,V; Width: W, Height: H, Local Center: X U:0,V:0 +-----+ U:1,V:0.") (size 30 x 30) with a [Candera::Material](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_material.html "The class Material describes the color attributes of an object's surface and is primarily used for li...") and a matching [Candera::Shader](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_shader.html "The class Shader is an Appearance component representing a graphical processing unit (GPU) program..."). The Shader has to be provided in the asset and is delivered through the AssetProvider by its name. Further, some translation is applied to the new Billboard.

```
        // Create and init a new Billboard

        SharedPointer<Appearance> myAppearance = <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___v_i_s_u_a_l_i_z_a_t_i_o_n.html#ggaf0e93dc4242f607c3c8d13dafd036af9aaabfa5309af24986d3111a092449f857">Appearance::Create</a>();
        SharedPointer<Material> myMaterial = <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___v_i_s_u_a_l_i_z_a_t_i_o_n.html#ggaf0e93dc4242f607c3c8d13dafd036af9aaabfa5309af24986d3111a092449f857">Material::Create</a>();
        myMaterial->SetEmissive(<a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___behaviors_control.html#ggae7abc816df647d0ecbc280480fefb788a6d1d4da086e381cb2c5a5ce6a2513ebd">Color</a>(0.5F, 0.0F, 0.0F, 1.0F));
        myAppearance->SetMaterial(myMaterial);
        myAppearance->SetShader(Base::GetAssetProvider()->GetShader(CgiAssetNames::RefTransLight1_RefColor));
        myAppearance->SetName("Generated Appearance");

        m_billboard = <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___v_i_s_u_a_l_i_z_a_t_i_o_n.html#ggaf0e93dc4242f607c3c8d13dafd036af9aaabfa5309af24986d3111a092449f857">Billboard::Create</a>(30.0F, 30.0F);
        m_billboard->SetAppearance(myAppearance);
        m_billboard->Translate(Vector3(30.0F, 0.0F, 0.0F));

        // end Create and init a new Billboard
```

##### <a class="anchor" id="bkmrk--130"></a>Adding the new Billboard to the scene graph

Next the Billboard is uploaded to VRAM and appended to the node associated with the widget.

```
        // Add Billboard

        static_cast<void>(m_billboard->Upload());
        static_cast<void>(node->AddChild(m_billboard));

        // end Add Billboard
```

##### <a class="anchor" id="bkmrk--131"></a>Removing and destructing the Billboard

To remove the Billboard simply from the scene graph, use [Candera::Node::RemoveChild](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_node.html#a7748ed9b2f0e87acebf7de84b78b4095). If the Billboard will be used for further operations e.g. attaching it to an other node removing would be enough. Since in this example the Billboard isn't used further it should not only be removed but also be destructed completely (freeing the resources).

The following code snippet removes the previously generated billboard from its parents, unloads the Billboard from VRAM and frees with [Candera::Node::Dispose](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_node.html#a4dd4cc45a36bfb6b461d6a8af096e650) the resources.

```
        // Remove previously generated billboard and destruct it

        Node* parent = m_billboard->GetParent();
        if (parent != 0){
            static_cast<void>(parent->RemoveChild(m_billboard));
            FEATSTD_LOG_ERROR("- Node %s removed from parent %s ...\n", m_billboard->GetName(), parent->GetName());
        }
        // Destruct node

        static_cast<void>(m_billboard->Unload());
        m_billboard->Dispose();
        m_billboard = 0;

        // end Destruct node

        // end Remove previously generated billboard and destruct it
```

As [Candera::Node::Dispose](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_node.html#a4dd4cc45a36bfb6b461d6a8af096e650) internally calls the [Candera::Node::RemoveChild](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_node.html#a7748ed9b2f0e87acebf7de84b78b4095) on parent node following code would be enough for removing and destructing a node.

```
        // Destruct node

        static_cast<void>(m_billboard->Unload());
        m_billboard->Dispose();
        m_billboard = 0;

        // end Destruct node
```

<p class="callout info">In SceneComposer the newly added Node does not appear in the Scene Tree view because it is only added dynamically by the widget.  
- The used Shader for the generated Billboard in the widget has to be included when generating an asset from the solution - ensure that "Always include in asset" flag is marked at the Shaders properties.  
- The widget must control memory and VRAM management of its internal dynamic subtree autonomously.</p>

##### <a class="anchor" id="bkmrk--132"></a>Widget Interaction in the Player

First, the asset must be exported and loaded in the Player. Then, one of the two existing *SceneGraphDynamicsWidget\_3D* widgets must be selected for the 3D scene. After, **ChangeAppearance**, **CloneOperation** and **AddBillboard** properties can be enabled/disabled (1/0) to obtain different results.

#### **Changing Appearance and other 3D Node Attachments** 

For changing the appearance of a node, the following property of the SceneGraphDynamicsWidget\_3D can be used:

<div class="contents" id="bkmrk-changeappearance%3A-if"><div class="contents"><div class="contents"><div class="textblock">- **ChangeAppearance**: If ChangeAppearance is enabled, the appearance of the widgets associated node will be changed to a new generated appearance. If disabled, the previous appearance will be restored.

<div class="fragment">  
</div></div></div></div></div>```
        // Definition of WidgetProperty "ChangeAppearance"
        CdaProperty(ChangeAppearance, bool, GetChangeAppearance, SetChangeAppearance)
            CdaDescription("If ChangeAppearance is enabled, the appearance will be exchanged to a new generated appearance. If disabled, the previus appearance will be restored.")
        <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___meta_info.html#ga119bef57449bd05d8b3c40d7d514e375">CdaPropertyEnd</a>()
        // End Definition of WidgetProperty "ChangeAppearance"
```

Try the ChangeAppearance property at the SceneGraphDynamics\_3D\_Billboard widget in the example solution to change the Billboards appearance from a texture appearance to a material appearance.

##### <a class="anchor" id="bkmrk--133"></a>Creating and changing an Appearance

The following code snippet generates a basic [Candera::Appearance](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_appearance.html "The class Appearance groups following render attributes: Material, Textures, RenderMode, and Shader. Render attributes define the distinctive visualization of a geometry like Mesh, Billboard, and PointSprite. Further, render attributes can be shared across multiple objects, which conserves memory and enables sharing of appearance characteristics. An Appearance object is mandatory for any object in order to get rendered. Per default all render attributes are initialized to null, which is a valid setting. If the Appearance is activated, all render attributes that are set become activated. If no RenderMode is defined (null), then the default RenderMode is used instead;."). A [Candera::Material](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_material.html "The class Material describes the color attributes of an object's surface and is primarily used for li...") is created and its emissive color is set to a light green. The material and a proper shader is set to the Appearance. The shader has to be provided in the asset and is delivered through the AssetProvider by its name.

```
    // Create and set a new Appearance

    SharedPointer<Appearance> myAppearance = <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___v_i_s_u_a_l_i_z_a_t_i_o_n.html#ggaf0e93dc4242f607c3c8d13dafd036af9aaabfa5309af24986d3111a092449f857">Appearance::Create</a>();
    myAppearance->SetMaterial(<a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___v_i_s_u_a_l_i_z_a_t_i_o_n.html#ggaf0e93dc4242f607c3c8d13dafd036af9aaabfa5309af24986d3111a092449f857">Material::Create</a>());
    myAppearance->GetMaterial()->SetEmissive(<a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___behaviors_control.html#ggae7abc816df647d0ecbc280480fefb788a6d1d4da086e381cb2c5a5ce6a2513ebd">Color</a>(0.0F, 0.5F, 0.0F, 1.0F));
    myAppearance->SetShader(Base::GetAssetProvider()->GetShader(CgiAssetNames::RefTransLight1_RefColor));
    myAppearance->SetName("Generated Appearance");

    // end Create and set new Appearance
```

In the next step the node's previous Appearance is saved (for restoring purpose) and the new generated appearance is set to the node associated with the widget.

```
    // Change Appearance

    m_previousAppearance = node->GetAppearance();
    node->SetAppearance(myAppearance);
    static_cast<void>(myAppearance->Upload());

    // end Change Appearance
```

##### <a class="anchor" id="bkmrk--134"></a>Restoring / releasing an Appearance

Restore the previous Appearance and destruct the dynamically generated appearance.

```
        // Restoring appearance and destructing

        SharedPointer<Appearance> currentAppearance = node->GetAppearance();
        static_cast<void>(currentAppearance->Unload());
        currentAppearance.Release();
        node->SetAppearance(m_previousAppearance);

        // end Restoring appearance and destructing
```

<p class="callout info">In SceneComposer the changed Appearance does not appear in the Appearance panel because it is only changed dynamically by the widget.  
- The used shader for the generated Billboard in the widget has to be included when generating an asset from the solution - ensure that "Always include in asset" flag is marked at the Shaders properties.  
- The widget must control memory and VRAM management of dynamically created node attachments autonomously.</p>

#### **Cloning 3D Nodes** 

For cloning a node, the following property of the SceneGraphDynamicsWidget\_3D can be used:

<div class="contents" id="bkmrk-nodetoclone%3A-select-"><div class="contents"><div class="contents"><div class="textblock">- **NodeToClone**: Select an arbitrary node in the scene graph, which shall be cloned and added to the widget node

<div class="fragment">  
</div></div></div></div></div>```
        // Definition of WidgetProperty "NodeToClone"
        CdaProperty(NodeToClone, <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_node.html" title="The class Node is an abstract base class for all scene graph nodes. Each Node defines a local coordin...">Candera::Node</a>*, GetNodeToClone, SetNodeToClone)
            CdaDescription("Select a Candera::Node which shall be cloned and added to the widget Candera::Node. The Candera::Node must be a child of this widget's scene.")
        <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___meta_info.html#ga119bef57449bd05d8b3c40d7d514e375">CdaPropertyEnd</a>()
        // End Definition of WidgetProperty "NodeToClone"
```

<div class="contents" id="bkmrk-cloneoperation%3A-if-e"><div class="contents"><div class="contents"><div class="textblock">- **CloneOperation**: If enabled, the clone operation will be executed and the cloned node will be added to the widget node.

<div class="fragment">  
</div></div></div></div></div>```
        // Definition of WidgetProperty "CloneOperation"
        CdaProperty(CloneOperation, bool, GetCloneOperation, SetCloneOperation)
            CdaDescription("If CloneOperation is enabled, the Candera::Node to clone will be cloned and added to the widget Candera::Node. If disabled, the clone will be removed.")
        <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___meta_info.html#ga119bef57449bd05d8b3c40d7d514e375">CdaPropertyEnd</a>()
        // End Definition of WidgetProperty "CloneOperation"
```

For the cloning operation, refer to [Candera::Node::Clone](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_node.html#a0c1909b131003514664878e065f7802b). The following code snippets illustrate, what the SceneGraphDynamicsWidget\_3D is actually doing for cloning a node and destructing it again.

##### <a class="anchor" id="bkmrk--135"></a>Validating Node to Clone

This example should allow to clone nodes, which are part of the scene graph the widget is linked to. The scene graph can be traversed from a given node up to its actual top level scene node to check whether it is part of the scene graph.

```
    // Search the parent scene of a given node

    Node* currentNode = node;

    while (currentNode != 0) {
        if (currentNode->IsTypeOf(Scene::GetTypeId())) {
            return static_cast<Scene*>(currentNode);
        }
        currentNode = currentNode->GetParent();
    }
    return 0;

    // end Search the parent scene of a given node
```

##### <a class="anchor" id="bkmrk--136"></a>Creating and Adding Clone

If the widget node and the node to clone have same top level scene, the node can be cloned and added to the widget node according to the following code snippet.

```
        // Clone the node and add it to the widgets associated node

        m_clonedNode = <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___cloning3_d.html#gaf1781cbf2a3e09d5d24d63bdf3685145" title="Specialization of TreeClonerBase for use with Node.">TreeCloner</a>().CreateClone(*m_nodeToClone);
        static_cast<void>(node->AddChild(m_clonedNode));
        static_cast<void>(m_clonedNode->UploadAll());
        m_clonedNode->SetName("Clone");

        // end Clone the node and add it to the widgets associated node
```

<div class="contents" id="bkmrk-nodes-can-be-attache"><div class="contents"><div class="textblock"><dl class="note"><dd><p class="callout info">Nodes can be attached to any 3D node.</p>

</dd></dl></div></div></div>##### <a class="anchor" id="bkmrk--137"></a>TreeCloner and Cloning Strategies

For more complex cloning see [Candera::TreeCloner](http://dev.doc.cgistudio.at/APILINK/group___cloning3_d.html#gaf1781cbf2a3e09d5d24d63bdf3685145 "Specialization of TreeClonerBase for use with Node.") and [Candera::TreeCloneStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_tree_clone_strategy.html "This is an interface for strategies used during cloning by TreeCloner."). [Candera::TreeClonerBase](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_tree_cloner_base.html "This class clones scene subtrees.") is provided for cloning trees.

<div class="contents" id="bkmrk-the-default-clone-st"><div class="contents"><div class="textblock">- The default clone strategy is to call the Clone interface on each node, and build the clone tree with the same node pattern as the original tree.
- For deeper cloning, TreeClonerBase supports attaching a [Candera::TreeCloneStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_tree_clone_strategy.html "This is an interface for strategies used during cloning by TreeCloner."). This TreeCloneStrategy is typically aware of different types of nodes, and delegates to other strategies.

</div></div></div>##### <a class="anchor" id="bkmrk--138"></a>Removing and Destructing Clone

Analogous to <span style="color: rgb(230, 126, 35);">[Removing and destructing the Billboard](https://doc316en.candera.eu/link/449#bkmrk-removing-and-destruc)</span> (removing/destructing a 3D node) the cloned node is destructed.

```
        // Remove a previously cloned node

        static_cast<void>(m_clonedNode->UnloadAll());
        m_clonedNode->Dispose();
        m_clonedNode = 0;

        // end Remove a previously cloned node
```

<div class="contents" id="bkmrk--17"><div class="textblock"><dl class="note"></dl>  
</div></div><p class="callout info">In SceneComposer the newly added node clone does not appear in the Scene Tree view because it is only added dynamically by the widget.  
- It is not allowed to modify the scene graph maintained by SceneComposer outside of the subtree owned by the widget!  
- The widget must control memory and VRAM management of its internal dynamic subtree autonomously.</p>