Material Object


Introduction

The graphic attributes of a 3D object are encapsulated into an object structure of type XintView3DMaterial. The application must create a material object that must be assigned to an object before it is attached to a viewer.

A material object is created using function XintCreateMaterial.

    XintView3DCreateMaterial *XintView3DCreateMaterial( char *name, 
                                            XintView3DMaterialType type,
                                            XintView3DMaterialColor *color,
                                            unsigned long mask,
                                            XintView3DMaterialAttributes *attr);

This function allows the application to define the following attributes:


Material Color Specification

Arguments type and color are used to specify the color attributes. The material type specifies which color model is used to render the object. To specify a color or a set of colors to be used to display an object, you must specify a material type and fill the material color structure as explained below.

View3D provides a very sophisticated and comprehensive method for handling color attributes. Objects can be rendered using a single color, using a range of colors, using a color scale scheme, or by assigning directly a color or a color index for each vertex. In addition, color ranges and color scales can be based on any vertex attribute, including the X, Y, Z component and possibly a 4th attribute in the case of Mesh Surface, Point and Raster objects.

The material type can be set to the following values:

Not all of the listed material types are supported for every object. For example, the marker object only supports the XintMATERIAL_SINGLE_COLOR material type. See each object description for more information about the supported material types.

Material Color

The material color specification is based on the material type. Structure XintView3DMaterialColor is a structure that contains a member for each of the material types supported. You must fill the member corresponding to the material type selected.

    typedef struct {
                    XintColor4           single;  /* One color type          */
                    XintView3DColorRange range;   /* Range color type        */
                    XintView3DColorScale scale;   /* Color scale information */
                    XintView3DColorIndex index;   /* Color index information */
                    XintView3DColorMulti multi;   /* Multi color data        */
    } XintView3DMaterialColor;

Specifying a color for material type XintMATERIAL_SINGLE_COLOR

The color for a single material color is specified directly using data type XintColor4, which is used to store a color (red, green, blue and transparency values), as floating point numbers between 0 and 1.

     typedef float XintColor4[4];

The following code sample illustrates how to create a single color material.

    XintView3DMaterial *single_material;
    XintView3DMaterialColor color;

    ....

    /* Specify color */
    color.single[0] = 1.0;    /* red component              */
    color.single[1] = 0.0;    /* green component            */
    color.single[2] = 0.0;    /* blue component             */
    color.single[3] = 1.0;    /* transparency, 1.0 = opaque */

    /* Create material */
    single_material = XintCreateMaterial("single_material",
                                         XintMATERIAL_SINGLE_COLOR,
                                         &color, 0, NULL);

Specifying a color for material type XintMATERIAL_RANGE_COLOR

The color for a material of type XintMATERIAL_RANGE_COLOR is specified using structure XintView3DColorRange and is defined as follows:

    typedef struct {
                    unsigned int                  range_direction;
                    XintView3DInterpolationMethod interp_method;
                    Boolean                       across_object;
                    XintView3DColorModel          color_model;
                    XintColor4                    min_color;
                    XintColor4                    max_color;
    } XintView3DColorRange;

Member range_direction specifies the component used for the interpolation. You can specify XintINTERPOLATE_X, XintINTERPOLATE_Y, XintINTERPOLATE_Z or a combination of those (XintINTERPOLATE_X + XintINTERPOLATE_Y for example).

Member interp_method describes the interpolation method, you can specify XintINTERPOLATE_LINEAR, XintINTERPOLATE_EXPONENTIAL, XintINTERPOLATE_LOGARITHMIC, XintINTERPOLATE_RANDOM.

Member across_object specifies whether the interpolation is performed within the object range (True) or within the limits of the coordinate system (False).

Member color_model specifies in which color model space to perform the interpolation. You can specify XintCOLOR_MODEL_RGB (Red/Green/Blue) or XintCOLOR_MODEL_HSV (Hue/Saturation/Value). Finally, members min_color and max_color specify the two colors to interpolate between.

The following code sample illustrates how to create a color range material.

    XintView3DMaterial *range_material;
    XintView3DMaterialColor color;

    ....

    /* specify interpolation */
    color.range.range_direction = XintINTERPOLATE_Z;
    color.range.interp_method = XintINTERPOLATE_LINEAR;
    color.range.across_object = False;
    color.range.color_model = XintCOLOR_MODEL_HSV;
    
    /* Specify minimum color */
    color.range.min_color[0] = 1.0; /* red component   */
    color.range.min_color[1] = 0.0; /* green component */
    color.range.min_color[2] = 0.0; /* blue component  */
    color.range.min_color[3] = 1.0; /* transparency    */
    
    /* specify maximum color */
    color.range.max_color[0] = 0.0; /* red component   */
    color.range.max_color[1] = 1.0; /* green component */
    color.range.max_color[2] = 0.0; /* blue component  */
    color.range.max_color[3] = 1.0; /* transparency    */

    /* Create material */
    range_material = XintCreateMaterial("range_material", 
                                        XintMATERIAL_RANGE_COLOR,
                                        &color, 0, NULL);

Specifying a color for material type XintMATERIAL_MULTI_COLOR

Material type XintMATERIAL_MULTI_COLOR allows the application to specify a different color for each vertex of an object. The number of colors specified must equal the number of vertices in the object it is created for. This type of material can be used in conjunction with any object type except Marker objects. The color for a multi color material is specified using structure XintView3DColorMulti, defined as follows:

    typedef struct {
                    int num_colors;     /* Number of colors */
                    XintColor4 *colors; /* Color list       */
    } XintView3DColorMulti;

The following code sample illustrates how to create a multi color material.

    XintView3DMaterial *multi_material;
    XintView3DMaterialColor color;
    XintColor4 *colors;
    int num_vertices;
    register int i;

    ....

    /* Allocate and fill color list */
    colors = (XintColor4 *) XtMalloc(sizeof(XintColor4) * num_vertices);
    for (i=0; i < num_vertices; i++) {
         colors[i][0] = ...; /* red          */
         colors[i][1] = ...; /* green        */
         colors[i][2] = ...; /* blue         */
         colors[i][3] = ...; /* transparency */
    }
    
    /* Specify color */
    color.multi.colors = colors;
    color.multi.num_colors = num_vertices;
    
    /* Create material */
    multi_material = XintCreateMaterial("multi_material",
                                        XintMATERIAL_MULTI_COLOR,
                                        &color, 0, NULL);

    /* free colors */
    XtFree((char *) colors);

Specifying a color for material type XintMATERIAL_COLOR_SCALE

Material type XintMATERIAL_COLOR_SCALE allows the application to specify a list of colors and a list of intervals. Each vertex is assigned a color from the list based on its data value (X, Y, Z or 4D component) and where it belongs in the range. This material type is specified using structure XintView3DColorScale, described below:

    typedef struct {
                    XintView3DColorScaleOrientation orientation; /*orientation*/
                    XintReal   *range;                  /* Data intervals for */
                    int        num_colors;              /* Number of colors   */
                    XintColor4 *colors;                 /* Colors in scale    */
    } XintView3DColorScale;

Member orientation specifies which vertex component is used to assign the color. Specify XintCOLOR_SCALE_ORIENTATION_X to use the X coordinate, XintCOLOR_SCALE_ORIENTATION_Y for the Y coordinate, XintCOLOR_SCALE_ORIENTATION_Z for the Z coordinate, and XintCOLOR_SCALE_ORIENTATION_4D to use the 4th component specified at object creation time (see function XintCreateMeshSurface for an example). Member range is an array of size num_colors-1 and is used to specify the data intervals. For example, if member num_colors is 4 and range contains the values {10, 20, 30}, then the first color will be assigned to vertices which data component is less than 10, the second color will be assigned to vertices which data component is between 10 and 20. etc.

The following code sample illustrates how to create a color scale material.

    XintView3DMaterial *scale_material;
    XintView3DMaterialColor color;
    XintColor4 *colors;
    XintReal *range;
    int ncolors;
    register int i;

    ....

    /* Allocate and fill color list */
    colors = (XintColor4 *) XtMalloc(sizeof(XintColor4) * ncolors);
    for (i=0; i < ncolors; i++) {
      colors[i][0] = ...; /* red          */
      colors[i][1] = ...; /* green        */
      colors[i][2] = ...; /* blue         */
      colors[i][3] = ...; /* transparency */
    }

    /* Allocate range */
    range = (XintReal *) XtMalloc(sizeof(double) * (ncolors-1));

    /* We want a linear range from 0 to 100 */
    for (i=0; i < ncolors-1; i++)
         range[i] = (float) i * 100./ncolors;

    /* set color structure */
    color.scale.orientation = XintCOLOR_SCALE_ORIENTATION_Z;
    color.scale.range = range;
    color.scale.colors = colors;
    color.scale.num_colors = ncolors;

    /* Create material */
    scale_material = XintCreateMaterial("scale_material",
                                        XintMATERIAL_COLOR_SCALE,
                                        &color, 0, NULL);

    /* Free memory */
    XtFree((char *) range);
    XtFree((char *) colors);

Specifying a color for material type XintMATERIAL_COLOR_INDEX

Material type XintMATERIAL_COLOR_INDEX is used to specify colors as an index into a color table. This type of material allows the application to specify a single color for the entire object (similar to XintMATERIAL_SINGLE_COLOR) or a color for each node (similar to XintMATERIAL_MULTI_COLOR). Unlike the other material types, however, with material type XintMATERIAL_COLOR_INDEX the object color can simply be changed by updating the colors in the color table and forcing a redraw using function XintView3DRedraw. This type of material is also more memory efficient because it only requires storing an integer index for a color rather than four floating point color components.

    typedef struct {
                    XintView3DColorTable *table;      /* Color table       */
                    int                  num_indices; /* Number of indices */
                    int                  *index;      /* Index list        */
    } XintView3DColorIndex;

Member table is a pointer to an opaque structure of type XintView3DColorTable that stores a color table description. A set of convenience functions, such as XintView3DCreateColorTable or XintView3DUpdateColorTable is available to create or modify color tables.

Member num_indices specifies the list of indices in index. You can specify 1 or a number equal to the number of vertices in the object this material will be used for. Specifying 1 basically defines a single color for the object. The values contained in the array index are indices in the color table. Their value should be between 0 and ncolors-1, where ncolors is the number of colors in the color table.

The following code sample illustrates how to create a color index material.

    XintView3DMaterial      *index_material;
    XintView3DMaterialColor color;
    XintView3DColorTable    *color_table;
    int num_vertices;
    int ncolors;
    register int i;

    ....

    /* Create color table from a file */
    color_table = XintView3DReadColorTable(NULL, "rgb.cmp");
    
    /* Get number of colors in color table */
    (void) XintView3DColorTableData (color_table, &ncolors);
    
    /* Allocate array to contain indices */
    indices = (int *) XtMalloc(sizeof(int) * num_vertices);
    
    /* Build list of indices (between 0 and ncolors-1) */
    for (i=0; i < num_vertices; i++)
         indices[i] = ...;
    
    /* Specify color */
    color.index.table = color_table;
    color.index.num_indices = num_vertices;
    color.index.indices = indices;

    /* Create material */
    index_material = XintCreateMaterial("index_material",
                                        XintMATERIAL_COLOR_INDEX,
                                        &color, 0, NULL);
    
    /* free indices */
    XtFree((char *) indices);


Material Attributes Specification

The non color attributes of a material are specified by setting an attribute mask and filling the corresponding members in a data structure of type XintView3DMaterialAttributes, defined as follows:

    typedef struct {
                    Boolean   light;
                    int       shade_model;
                    int       draw_mode;
                    Boolean   draw_grid;
                    Booleam   image_flag;
    } XintView3DMaterialAttributes;

You only need to set the components that you want to change. The following table lists the structure members, the default values and the corresponding mask.

MemberDefaultMask
lightTrueXintMA_LIGHT
shade_modelXintSMOOTHXintMA_SHADE_MODEL
draw_modeXintDRAW_FILLXintMA_DRAW_MODE
draw_gridFalseXintMA_DRAW_GRID
image_flagFalseXintMA_IMAGE_FLAG

The following code sample shows how to create a single color material where the light attribute is turned off and the draw mode is set to draw lines.

    XintView3DMaterialAttributes attributes;
    XintView3DMaterialColor      color;

    ...

    color.single[0] = .67;
    color.single[1] = 1.0;
    color.single[2] = 0.5;
    color.single[3] = 1.0;
 
    attributes.light = False;
    attributes.draw_mode = XintDRAW_LINE;

    material = XintView3DCreateMaterial("smaterial", XintMATERIAL_SINGLE_COLOR,
                                        &color, XintMA_LIGHT | XintMA_DRAW_MODE,
                                        &attributes);


Drawing Mode

The drawing mode attribute specifies how an object is drawn. It can be set to the following values: XintDRAW_FILL, XintDRAW_LINE, XintDRAW_POINT or XintDRAW_HIDDEN_LINE.






Lighting

The lighting attribute specifies whether or not an object is subject to lighting. This attribute does not apply to Line, Marker and Point objects. The example below shows the same surface with lighting turned on and off.


By default, a head light is always turned on to illuminate the scene in a View3D widget. Up to 8 additional light sources can be added to control the lighting in a View3D widget.


Shade Model

The shade model attribute specifies which shade model to use. It only applies if attribute lighting is set to True. It can be set to XintSMOOTH or XintFLAT. Use XintSMOOTH to obtain a smooth shading across the entire object. Use XintFLAT to have a uniform shading inside each surface building block (triangle, quadrilateral or polygon, depending on the surface type).



Grid Lines

The grid line attribute, when set to True, allows superimposing of mesh grid lines on top of a surface object drawn with mode XintDRAW_FILL. This attribute is only meaningful for Mesh Surface objects.


Warning: This feature is implemented using the OpenGL polygon offset extension. If you are using the Mesa library, versions prior to 1.2.4 do not support the polygon offset extension. As a result, this feature will not work properly with old Mesa libraries (grid lines look discontinuous). We highly recommend that you acquire the latest version of the Mesa library (1.2.7 as of the writing of this document).


Image Flag

The image flag attribute must be set to True when the material is created to be used in conjunction with a Raster Image object. If attribute image_flag is set for a particular material, the material can only be used for Raster Image objects.