==================
Applying materials
==================

For optimum performance, materials are best used at the segment level, though it is also possible to apply them to individual entities or subentities. Before using a material palette to decorate geometry, it must :ref:`defined <prog_guide/0501_materials_introduction:Defining material palettes>` in a :doc:`portfolio <0401_portfolios_introduction>` and the portfolio must be set as active on the segment. Portfolios inherit from parent to child segment, so a single portfolio can be shared as long as it is made active at some point in the hierarchical ancestry.

The ``MaterialMappingControl`` allows you to set materials "by index". This is a convenient way to apply many materials to a set of objects, or to reuse materials in different parts of your scene using the same palette. The alternative would be to set materials individually using ``MaterialKit``, which is fine when you only need to apply a single material. Otherwise, you would need to keep a reference to the material and pass it between scopes in order to apply it in another part of the scene. Material palettes solve this problem because the materials contained within them are accessible through a portfolio.


.. _applying_materials_levels:

Applying Materials at Various Levels
====================================

Although setting materials at the segment level is the recommended way to apply materials for highest performance, you may find you need finer control over how they are applied. This section discusses how materials are applied at various levels of granularity. 


.. _segment_level:

Assigning Materials at the Segment Level
----------------------------------------

Assigning a material to a segment is similar to setting a simple color on a segment: all geometry within the segment and its subsegments will also inherit the material. To assign a material this way, you need to use a material palette. Material palettes are like an array in that the materials within are indexed by insertion position. To assign a material at the segment level, use one of the ``SetMaterialByIndex`` variants:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_applying_materials.cpp
		   :start-after: //! [mka_segment]
		   :end-before: //! [mka_segment]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_applying_materials.cs
		   :start-after: //! [mka_segment]
		   :end-before: //! [mka_segment]
		   
If you only want to set a simple color on a segment without bothering to set up a ``MaterialKit``, |HPSNOW| offers a simplified interface to achieve this. A segment-level color means that all geometry in a particular segment will have that color. Faces, edges, and vertices can be colored in this way. Using the ``MaterialMappingControl``, you can set segment-level color with the following code:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_applying_materials.cpp
		   :start-after: //! [direct_segment]
		   :end-before: //! [direct_segment]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_applying_materials.cs
		   :start-after: //! [direct_segment]
		   :end-before: //! [direct_segment]
		   

.. _geometry_level:

Assigning Materials at the Geometry Level
-----------------------------------------

Materials can be set for individual geometry if the geometry is a shell or mesh. Setting a material on a particular shell or mesh requires using a ``MaterialMappingKit``. You can set any material property on a ``MaterialMappingKit``, but for this example, we'll keep it simple and just set color. To do this, build a kit and apply it to the particular shell key that you want to be different:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_applying_materials.cpp
		   :start-after: //! [material_mapping]
		   :end-before: //! [material_mapping]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_applying_materials.cs
		   :start-after: //! [material_mapping]
		   :end-before: //! [material_mapping]

Setting material at the geometry level does incur a performance penalty relative to setting materials at the segment level.


.. _subentity_level:

Assigning Materials to Individual Faces and Vertices
----------------------------------------------------

If you need even finer control over materials, |HPSNOW| also allows you to apply them at the subentity level. To do this, you'll need two arrays: one that defines the indices of the faces you'd like to color and another array that indexes the material palette itself. In the following snippet, materials 0, 1, and 2 are applied to shell faces 0, 1, and 2 respectively:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_applying_materials.cpp
		   :start-after: //! [subentity_materials]
		   :end-before: //! [subentity_materials]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_applying_materials.cs
		   :start-after: //! [subentity_materials]
		   :end-before: //! [subentity_materials]
		   
.. image:: images/multiple_materials.png

*A single shell with multiple materials*

Setting materials on individual edges is not supported.


.. _coloring_specific_faces:

Examples Showing How to Color Specific Faces
--------------------------------------------

Often, it is desirable to color a specific face to distinguish it from other faces in the same object. Faces on a shell can be individually colored, however, as mentioned previously, individual faces of cylinders and spheres cannot. Consider the shell pictured below, which is composed of five faces:

.. image:: images/simple_shell.png

*A simple shell*

Now, assume the fourth face needs to be highlighted. Using the shell key, |HPSNOW| only needs the face number and the color that is desired. In the code below, note that the fourth face is being altered using the parameter '3'. This is because shell face lists are always zero-based.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_applying_materials_example1.cpp
		   :start-after: //! [040302_a]
		   :end-before: //! [040302_a]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_applying_materials_example1.cs
		   :start-after: //! [040302_a]
		   :end-before: //! [040302_a]
		   
.. image:: images/one_face_colored.png

*A simple shell with one face colored*

Proceeding with this example, it is becomes relatively simple to assign arbitrary colors to arbitrary faces. Use the alternative version of *SetFaceColors* that accepts a face index array and a color array.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_applying_materials_example1.cpp
		   :start-after: //! [040302_b]
		   :end-before: //! [040302_b]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_applying_materials_example1.cs
		   :start-after: //! [040302_b]
		   :end-before: //! [040302_b]
		   
.. image:: images/arbitrarily_colored_faces.png

*Shell with arbitrarily colored faces*

It is also possible to set color on a range of faces. For instance, to change color on the first three faces, call *SetFaceColors* with the start face index and the number of faces to color.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_applying_materials_example1.cpp
		   :start-after: //! [040302_c]
		   :end-before: //! [040302_c]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_applying_materials_example1.cs
		   :start-after: //! [040302_c]
		   :end-before: //! [040302_c]
		   
.. image:: images/color_range.png

*Shell with colors set on a range of faces*

**NOTE:** To set face colors that are partially or fully transparent, **the use of a material palette is required**. See the discussion on this topic :ref:`here <prog_guide/0501_materials_introduction:Defining material palettes>`.


.. _coloring_specific_vertices:

Example Showing How to Color Vertices
-------------------------------------

Color can be applied to individual vertices in a shell or mesh. There are many ways to do this using any of the ``SetVertexColors`` overloads. In the example below, the color of the first four vertices of the shell have been modified, as specified in the ``vertexIndices`` array. The ``vertexIndices`` array contains the specified colors. The vertex color will override any color set on the face at a higher level.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_4_3_3_a.cpp
		   :start-after: //! [040303_a]
		   :end-before: //! [040303_a]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_4_3_3_a.cs
		   :start-after: //! [040303_a]
		   :end-before: //! [040303_a]
		   
.. image:: images/coloring_vertices.png

*Shell with vertex colors set*


.. _textures_as_materials:

Using Textures as Materials
===========================

Textures are used as materials in the same way that ``RGBAColor``-defined materials are. Load and define the texture as discussed on :doc:`this page <0503_textures>`. Once the texture is loaded and named, use the name to define the material. After you have the name, the process is as simple as assigning it to a material:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_4_2_4_a.cpp
		   :start-after: //! [040204_a]
		   :end-before: //! [040204_a]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_4_2_4_a.cs
		   :start-after: //! [040204_a]
		   :end-before: //! [040204_a]
		   
.. image:: images/textured_face.png

*A single shell with a texture on one face only*

Note that when texturing faces, you are still required to apply the texture coordinates to the vertices as if you were texturing a whole shell. In |HPSNOW|, there is no way to programmatically apply an alpha value to a texture. If your texture requires alpha transparency, it must be baked in to the texture itself. Fractional material index values are not supported for textures.


.. _interpolating_materials:

Interpolating Materials
=======================

Note that the ``materialIndices`` array above is a ``float`` array. Using a float array enables colors to be interpolated across faces. For example, if you have two materials defined and a strip of shell faces, you can use the  array to specify a fractional color for the intermediate faces. Here, red and yellow are used to form a color strip:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_4_2_3_a.cpp
		   :start-after: //! [040203_a]
		   :end-before: //! [040203_a]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_4_2_3_a.cs
		   :start-after: //! [040203_a]
		   :end-before: //! [040203_a]
		   
.. image:: images/interpolating_materials.png

*A single shell with a material interpolated across its faces*
