####################
Colors and Materials
####################

In PRC, colors can exist in two places.
If the model's vertices are colored individually, then those color values are embedded with the model's tessellation.
Otherwise, the colors will be indexed at the product occurrence level.
In the latter case, the global material library contains the actual color values.
The following subsections demonstrate how to get color values.

***************************
Finding Color for an Entity
***************************

Recall that all entities have an associated *root base*  which encapsulates fields common to all entities.
If the entity has graphical information, it will also have a *root base with graphics*  node.
This is the case for product occurrences and representation items.
As you are parsing, get a reference to the graphical information in the following way:

.. code-block:: c

   A3DRootBaseWithGraphicsData rbwgData = A3D_MAKE_DATA(A3DRootBaseWithGraphicsData);
   A3DRootBaseWithGraphicsGet(po, &rbwgData);

   if (rbwgData.m_pGraphics != NULL)
   {
           // this entity has an attached graphics object
           A3DGraphicsData graphicsData = A3D_MAKE_DATA(A3DGraphicsData);
           A3DGraphicsGet(rbwgData.m_pGraphics, &graphicsData);

When color is set at the entity level, it will have an associated *style* .
You can use the `graphicsData` object to get the entity's style information.

.. code-block:: c

   if (graphicsData.m_uiStyleIndex == A3D_DEFAULT_STYLE_INDEX)
           // entity is unstyled
   else
           // note style index
           styleIndex = graphicsData.m_uiStyleIndex;

Note the special identifier \ref A3D_DEFAULT_STYLE_INDEX.
If the style index is equal to this constant, then it effectively means the entity has no style information of its own.
If the style index is equal to any other value, then that value is an index into the global style array.
See the next section for information on how to get the color value from the global array.

Reading Colors From the Material Library
========================================

In HOOPS Exchange, global data is embedded in a special node.
This node is not part of the model assembly, but its contents are indexed by nodes in the assembly tree.
The global information node contains all the defined colors, styles, materials, line patterns, textures, and fill patterns used by the model.

You can get a reference to the node and its data using the following code:

.. code-block:: c

   // get global data
   A3DGlobalGetPointer(&pGlobal);

   A3DGlobalData globalData = A3D_MAKE_DATA(A3DGlobalData);
   A3DGlobalGet(pGlobal, &globalData);


.. _getting_global_style_information:

Getting Global Style Information
================================

When color is set at the entity level, it will have an associated *style* .
Global style data is kept in a simple array, and can be accessed in the following way.
Note the `m_bMaterial` field, which indicates whether the style points to a material or a color:

.. code-block:: c

   int numStyles = globalData.m_uiStylesSize;
   A3DGraphStyleData styleData = A3D_MAKE_DATA(A3DGraphStyleData);

   for (size_t n = 0; n < numStyles; ++n)
   {
           // get the nth style from the global data
           A3DGlobalGetGraphStyleData(n, &styleData);

           if (styleData.m_bMaterial == A3D_TRUE)
                // the style points to a material
           else
                // the style points to a color
   }

See the next sections for information on how to get the actual color or material values.

Getting Colors
==============

PRC uses indexed colors, which are defined in an array in the material library.
To get the colors, we'll use the `A3DGraphRgbColorData` structure with the `styleData.m_uiRgbColorIndex` field from the previous subsection.
Colors are stored sequentially as RGB triplets, each of type `A3DDouble`.
The relationship looks like this:

.. image:: /_assets/images/arrays.png


.. code-block:: c

   A3DGraphRgbColorData sColorData = A3D_MAKE_DATA(A3DGraphRgbColorData);

   A3DGlobalGetGraphRgbColorData(styleData.m_uiRgbColorIndex, &sColorData);

   // red component
   sColorData.m_dRed;

   // green component
   sColorData.m_dGreen;

   // blue component
   sColorData.m_dBlue;

Alternatively, if you need to get a list of all defined colors, you could do this:

.. code-block:: c

   A3DGraphRgbColorData sColorData = A3D_MAKE_DATA(A3DGraphRgbColorData);

   for (size_t i = 0; i < globalData.m_uiColorsSize; ++i)
   {
           A3DGlobalGetGraphRgbColorData(i * 3, &ColorData);

           // red component
           sColorData.m_dRed;

           // green component
           sColorData.m_dGreen;

           // blue component
           sColorData.m_dBlue;
   }

Thus, as you are parsing a PRC entity, note its style index and use it to get the applied color by following the procedure above.

.. _pg_get_materials_and_textures:

Getting Materials and Textures
==============================

HOOPS Exchange considers textures to be a type of material.
If the model you're parsing uses either a material or a texture, its :cpp:struct:`A3DGraphStyleData::m_bMaterial` field will be `A3D_TRUE`.
You can determine whether the style is a material or a texture by using the following code:

.. code-block:: c

   if (styleData.m_bMaterial == A3D_TRUE)
   {
           A3DBool isTexture = A3D_FALSE;

           A3DGlobalIsMaterialTexture(graphicsData.m_uiRgbColorIndex, &isTexture);

           if (isTexture == A3D_TRUE)
              // style is a texture
           else
              // style is a material

All images, including those used as textures, are stored in a global array separate from the texture definitions.
To get the image data associated with a texture, you need to follow the chain from style index to texture definition to picture data.
The following example assumes you already have the style index from the previous sections:

.. code-block:: c

   A3DGraphTextureDefinitionData tdd = A3D_MAKE_DATA(A3DGraphTextureDefinitionData);

   // get texture definition associated with the style index
   A3DGlobalGetGraphTextureDefinitionData(graphicsData.m_uiStyleIndex, &tdd);

   // get the picture index used by the texture definition
   A3DGraphPictureData pictureData = A3D_MAKE_DATA(A3DGraphPictureData);
   A3DGlobalGetGraphPictureData(tdd.m_uiPictureIndex, &pictureData);

   // picture size
   pictureData.m_uiSize;

   // picture pixels
   pictureData.p_ucBinaryData;

Alternatively, if your style is a material, you may need to get the material properties associated with it.
Material properties include ambient, diffuse, emissive, specular, and shininess components.
Be aware that there are separate components for the color channels and the alpha channel.
The material properties are accessed in this way:

.. code-block:: c

   A3DGraphMaterialData gmd = A3D_MAKE_DATA(A3DGraphMaterialData);
   A3DGlobalGetGraphMaterialData(graphicsData.m_uiStyleIndex, &gmd);

   gmd.m_uiAmbient; // ambient component
   gmd.m_dDiffuseAlpha; // diffuse alpha channel
   gmd.m_dShininess; // get material shininess

Retrieving Informations About Entity Materials
==============================================

When the input entity is a Representation Item or aPart Definition, material data can be retrieved using :func:`A3DMiscGetMaterialProperties`.
This example prints the name of a entity's material:

.. code-block:: c

   A3DStatus PrintMaterialName(const A3DEntity* in_pEntity)
   {
           A3DMiscMaterialPropertiesData sData = A3D_MAKE_DATA(A3DMiscMaterialPropertiesData);
           A3DStatus iRet = A3DMiscGetMaterialProperties(in_pEntity, &sData);
           if(iRet == A3D_SUCCESS)
           {
                   printf("Material Name: %s\n", sData.m_pcMaterialName);
           }
           A3DMiscGetMaterialProperties(NULL, &sData);
           return iRet;
   }

Effects of Entity References
============================

It should be noted that computed values for inheritance can be supplanted by entity references.
Entity references have the effect of replacing an entity's computed attribute values with those of another entity, or applying attributes to subentities such as individual faces.
Entity references are explained in :doc:`/guide/metadata/managing_attribute_inheritance`.

