============
Fundamentals
============

This tutorial is intended to describe the fundamentals of how to use |HPSNOW| in a simple application. It will demonstrate basic segment operations, creating geometry, loading a model, and setting attributes in the scene graph. For C# users, it is recommended that you follow along in the *wpf_sandbox*, as an application framework and rendering context are already setup for you. C++ users should use the *mfc_sandbox*.

The tutorial provides code samples that you can copy and paste into the project source to run in the application. If you are using the WPF sandbox, the example code should be placed in one of the ``Execute`` methods of the ``DemoUser**X**Command`` classes. These classes are found in *DemoUserCommands.cs* and are linked to the buttons in the ribbon control of the sandbox:

.. image:: images/01/t.1.a.png

*The ribbon control which contains the User Code buttons*

If you are using the MFC sandbox, the code samples belong in the ``CHPSView::OnUserCodeX`` methods of *CHPSView.cpp*.

**IMPORTANT:** All |HPSNOW| classes are members of the ``HPS`` namespace. You will need to either prepend the namespace to the beginning of each class name, or declare a namespace in your source so that the compiler can find the classes you're trying to reference. The code snippets provided as examples may not include the namespace identifier for each class.

.. _0101:

1.1 Basic Segment Operations
============================

This section reviews basic segment operations in |HPSNOW|. If you are new to |HPSNOW| or otherwise unfamiliar with the terminology and data structures, you are encouraged to first read :doc:`section 1.1 </prog_guide/0101_database>` as well as :doc:`section 3.1 </prog_guide/0301_core>` of the Programming Guide as a prerequisite to this page.

The sandbox applications both use the :doc:`view hierarchy </prog_guide/0301_core>` for organizing the scene in a window. The Canvas-Layout-View hierarchy is already in place, but you need to create the final piece, the Model. Behind the scenes, the Model is actually a segment, and it can be referenced by a ``HPS::SegmentKey`` object, just like any other segment. After creating the Model, it then gets bound to the View in so that the contents of the Model segment are included in the rendering pipeline.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00730_tutorial1_1.cpp
		   :start-after: //! [create_object_hierarchy]
		   :end-before: //! [create_object_hierarchy]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00730_tutorial1_1.cs
		   :start-after: //! [create_object_hierarchy]
		   :end-before: //! [create_object_hierarchy]

In the code example above, the |HPSNOW| scene graph that describes your model would be built out from the ``myModelKey`` segment. But how is the scene graph actually built? There are two ways that this is done: by creating subsegments and attaching branches.


Creating Subsegments
--------------------

Creating a new subsegment is always done by calling ``SegmentKey::Down`` or ``SegmentKey::Subsegment``. Doing this recursively enables you to make a scene graph of any needed size. 

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00730_tutorial1_1.cpp
		   :start-after: //! [create_subsegments]
		   :end-before: //! [create_subsegments]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00730_tutorial1_1.cs
		   :start-after: //! [create_subsegments]
		   :end-before: //! [create_subsegments]

The code above would produce a scene graph of the following form:

.. image:: images/01/t.1.1.a.png

*A diagram of this segment hierarchy*

When a subsegment is created, it is empty of geometry, but always inherits the attributes of the parent segment. You can override these inherited attributes by setting local attributes on the child segment. Local attributes always override inherited attributes, except in the case of :ref:`attribute lock <prog_guide/0101_database:Attribute locks>`.


Attaching Branches
------------------

Attaching a branch is the second way you can grow your scene graph. In |HPSNOW|, attaching a branch is called *including*, and the object used to do this is called an :ref:`include segment <prog_guide/0101_database:Include segments>`. Include segments are useful because a single instance can be attached at multiple locations in the hierarchy. So if you have model subassemblies that are identical, you can keep one copy of the subassembly, saving memory. Updates are also made easier because any changes in one included branch will be reflected in the others. Let's say you would like to include the root segment in the diagram below under the Model segment:

.. image:: images/01/pre-include.png

*Diagram showing the main segment tree along with a separate root segment structure*

The code sample below demonstrates how to do this:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00730_tutorial1_1.cpp
		   :start-after: //! [include]
		   :end-before: //! [include]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00730_tutorial1_1.cs
		   :start-after: //! [include]
		   :end-before: //! [include]

The resulting scene graph would be arranged as such:

.. image:: images/01/post-include.png

*Diagram showing the scene tree with the segments included*

Segments can also be moved, copied, and deleted using the following commands:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00730_tutorial1_1.cpp
		   :start-after: //! [segment_operations]
		   :end-before: //! [segment_operations]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00730_tutorial1_1.cs
		   :start-after: //! [segment_operations]
		   :end-before: //! [segment_operations]

Note that in a real application, you would probably want to insert intermediate segments between the Model and the include segments in order to set any attributes that would be specific to those branches, such as position or rotation.


.. _0102:

1.2 Creating Geometry
=====================

Every piece of geometry has one and only one segment associated with it. Geometry cannot be shared among segments, nor can it exist independently of a segment. The most common types of geometry typically used in a |HPSNOW| scene are :doc:`shells </prog_guide/0201_shells>` and :doc:`meshes </prog_guide/0202_meshes>`. |HPSNOW| also contains two 3D geometric primitives, :doc:`spheres </prog_guide/0209_spheres>` and :doc:`cylinders </prog_guide/0210_cylinders>`, as well as 2D :doc:`lines </prog_guide/0205_lines>`, :doc:`curves </prog_guide/0206_curves>`, and :doc:`text </prog_guide/0203_text>`. In order to eventually build up to the subsection on attributes, we will insert some examples of geometry into the scene graph structure from snippet t.1.1.b.


Shells
------

Shells are the basic building blocks of most 3D geometry. To create a shell, you need to specify its vertices and face list. For a basic shell, such as a triangle, this is rather simple. The code below will create a triangular shell out of three vertices and a face list.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00730_tutorial1_1.cpp
		   :start-after: //! [insert_shell]
		   :end-before: //! [insert_shell]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00730_tutorial1_1.cs
		   :start-after: //! [insert_shell]
		   :end-before: //! [insert_shell]

Shells can be made with any number of vertices or faces by increasing the points and face lists. However, for complex shells with many vertices and faces it is usually easier to build the model in an external modelling program and :doc:`import </prog_guide/0901_importing_files>` it into |HPSNOW| at run time.


2D-Geometry
-----------

|HPSNOW| supports 2D geometry such as lines, curves, and arcs. All lines are polylines, even if they consist of a single segment. Ellipses and circles are the only types of 2D geometry that are considered to be logically closed and facetted. Inserting a circle and a line can be done using the following code (note that line visibility may be off by default - you need to enable it):

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00730_tutorial1_1.cpp
		   :start-after: //! [2d_geometry]
		   :end-before: //! [2d_geometry]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00730_tutorial1_1.cs
		   :start-after: //! [2d_geometry]
		   :end-before: //! [2d_geometry]


Primitives
----------

3D primitives are inserted in a similar way:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00730_tutorial1_1.cpp
		   :start-after: //! [primitives]
		   :end-before: //! [primitives]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00730_tutorial1_1.cs
		   :start-after: //! [primitives]
		   :end-before: //! [primitives]


At this point, the geometry is represented by the following scene graph:

.. image:: images/01/tutorial 1 segment diagram.png

*Segment structure*

If you compile and run the code snippets from this section, you would end up with something like this:

.. image:: images/01/t.1.2.a.png

*The example geometry*

This geometry is hard to visualize because it is only drawn in silhouette. We'll add some attributes in the next subsection to improve the appearance.


.. _0103:

1.3 Setting Attributes
======================

:ref:`Attributes <prog_guide/0101_database:Attributes>` are what give geometry its particular appearance. For example, color, edge weight, and visibility are all configurable attributes. All attributes have a default value - the reason the geometry all appears in black in the image above is because black is the segment's default color. Attributes are inherited from parent to children, and with this in mind, we can begin to assign new attributes to the segments we created earlier.

First, let's turn off faces on the cylinder to get a better idea of its orientation. We can make this setting in the Model segment or in the cylinder's segment, and the effect would be the same for the cylinder. However, since attributes inherit, disabling face visibility in the Model segment would also cause faces to disappear in all the child segments as well.

Let's set the edge color to red in the Model segment and disable face visibility in the cylinder segment:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00730_tutorial1_1.cpp
		   :start-after: //! [setting_attributes]
		   :end-before: //! [setting_attributes]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00730_tutorial1_1.cs
		   :start-after: //! [setting_attributes]
		   :end-before: //! [setting_attributes]
		   
Running the code above, we get the following result:

.. image:: images/01/t.1.3.a.png

*Setting the edge color and disabling faces*

What happened to the cylinder? And why didn't the edges of the other geometry turn red? The reason is that edge visibility is an attribute that is disabled by default. |HPSNOW| assigns a :doc:`default value </prog_guide/appendix_default_attribute_values>` to all attributes at the root of the scene graph, and this value was inherited all the way down to the cylinder segment. Let's fix this by enabling edge visibility in the model segment:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00730_tutorial1_1.cpp
		   :start-after: //! [visibility]
		   :end-before: //! [visibility]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00730_tutorial1_1.cs
		   :start-after: //! [visibility]
		   :end-before: //! [visibility]

.. image:: images/01/t.1.3.b.png

*The scene with edge visibility enabled*

Much better. We see the triangular shell and the circle have a border. Why didn't the line change to red? In |HPSNOW|, lines and edges are separate types of entities. Lines are used to form line segments and arcs. Edges form the borders of facetted geometry. We only modified the color of the edges, so the line retained its original black color. Now lets add some colors and experiment with the line weights:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00730_tutorial1_1.cpp
		   :start-after: //! [line_settings]
		   :end-before: //! [line_settings]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00730_tutorial1_1.cs
		   :start-after: //! [line_settings]
		   :end-before: //! [line_settings]

.. image:: images/01/t.1.3.c.png

*The scene with a few modified attributes*

The first two modifications seem easy enough to understand. But why was the process of changing the :doc:`line pattern </prog_guide/0406_line_patterns>` so lengthy? The reason for this is that a line pattern is considered to be a *defined* attribute. This means that you must supply the definition (in this case, a dashed definition) before it can be used in a scene. Along with all other defined attributes, such as textures and glyphs, line patterns exist in a collection called a  :doc:`portfolio </prog_guide/0401_portfolios_introduction>`. Portfolios must be created and explicitly set on segments before their contents can be used, hence the longer process to get the line pattern to appear.

So far, we've been working with each piece of geometry in its own segment. This is fine for demonstration purposes, but in a production application, you will want to organize your segment hierarchy so that segments with common attributes are grouped together. This will ensure :doc:`performance </prog_guide/0703_performance_considerations>` is at the highest possible level. For example, if you decided you wanted to make the circle blue, you wouldn't want to set the color in the circle's segment, as this would create redundant overhead. You can just make the circle segment into a child of the shell segment (or, ideally, just move the circle itself into the shell segment). The color of the shell will inherit to the circle, grouping the attributes into a common branch and keeping performance as high as possible.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00730_tutorial1_1.cpp
		   :start-after: //! [circle_segment]
		   :end-before: //! [circle_segment]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00730_tutorial1_1.cs
		   :start-after: //! [circle_segment]
		   :end-before: //! [circle_segment]

.. image:: images/01/t.1.3.d.png

*The circle is a child of the triangular shell, and thus inherits its color*

It may not always be feasible to group geometry with common attributes, as sometimes attributes will conflict. But keep in mind that this is the ideal structure and your scene graph should be structured this way when possible.

After the circle segment was moved to become a child of the triangle segment, the scene graph is reorganized in this way:

.. image:: images/01/tutorial_1_segment_diagram_reorg.png

*Scene graph reorganized*


.. _0104:

1.4 Loading a Model
===================

Section 1.2 dealt with dynamic geometry creation. However, most models loaded into |HPSNOW| will be imported from an external file. The |HPSNOW| native file format is the HOOPS Stream File, or HSF. An HSF file stores within it all of a model's attributes and geometric data as well as the scene graph used to organize it. All of the rules about setting attributes and modifying the scene graph described in the previous section still apply to a model loaded from a file.

In |HPSNOW|, the call to import a file returns a *notifier*. A notifier is an object that can be used to query the loading progress of an external file. In general, you should make sure a file is completely loaded before trying to manipulate it.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00730_tutorial1_1.cpp
		   :start-after: //! [file_import]
		   :end-before: //! [file_import]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00730_tutorial1_1.cs
		   :start-after: //! [file_import]
		   :end-before: //! [file_import]
		   
Snippet t.1.4 references *bnc.hsf*, which can be found in the *samples/data* directory in your |HPSNOW| installation.

In this case, the code will use the notifier to wait for the file to finish loading. Then, it will call ``FitWorld`` to zoom the camera to the object extents. Finally, ``Update`` is called to draw the scene. If you run this application and click the "User Code 1" button, it should look like this:

.. image:: images/01/t.1.4.a.png

*A model loaded into the tutorial application*


.. _0105:

1.5 Visual Effects
==================

Adding visual effects is a simple operation in |HPSNOW|. For example, to show the model using a hidden line mode rendering, use ``SetRenderMode`` in the following code snippet. Clicking the "User Code 2" button will toggle the effect.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00730_tutorial1_1.cpp
		   :start-after: //! [set_rendering_mode]
		   :end-before: //! [set_rendering_mode]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00730_tutorial1_1.cs
		   :start-after: //! [set_rendering_mode]
		   :end-before: //! [set_rendering_mode]
		   
.. image:: images/01/t.1.5.a.png

*The model shown with hidden line mode enabled*

Similarly, the part can be shown with a drop-shadow using simple shadows and a shadow plane by clicking "User Code 3":

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00730_tutorial1_1.cpp
		   :start-after: //! [shadows]
		   :end-before: //! [shadows]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00730_tutorial1_1.cs
		   :start-after: //! [shadows]
		   :end-before: //! [shadows]
		   
This code uses the ``HPS::VisualEffectsKit`` to enable this effect. Many |HPSNOW| attributes are set using their associated kit. For more on attribute controls, see the :ref:`attribute section <prog_guide/0101_database:Attributes>` of the Programming Guide.

.. image:: images/01/t.1.5.b.png

*The model shown with a drop shadow*

This is the end of the first tutorial. If you'd like to experiment with |HPSNOW|, replace the code in any of the "User Code" buttons to execute other commands. Refer to the Programming Guide for more detailed information on the |HPSNOW| API.
