Using references (mental ray)

Reference parameter enables a shader to receive a list of objects from the scene that it can then grab data off of (such as translation, visibility flags, or geometry) to use insider the shader.

A reference parameter uses the reference widget for picking objects in the UI and the commands AddObjectsToShader (http://softimage.wiki.avid.com/sdkdocs/AddObjectsToShader.htm) and RemoveObjectsFromShader (http://softimage.wiki.avid.com/sdkdocs/RemoveObjectsFromShader.htm) to modify the same list from scripting.

Table of contents

Using it in a SPDL

A reference parameter can be specified in a SPDL like this:

Parameter "object_list"
{
    GUID = "{7636CC21-51CE-11D4-AEE8-0090275AE282}";
    Type = Reference;
 }

To ensure that the reference widget is being used, the parameter's UI definition in the Defaults section of the SPDL should be defined like this:

Defaults
{
    object_list
    {
        UIType = "ReferenceWidget.ReferenceWidget.1";
    }
}

The ReferenceWidget widget takes a couple of optional parameters which are described below.

Single- or multi-selection

The optional parameter "mode" can be used to set the reference widget to multi- or single-selection by setting it to the string "multi" or "single", respectively. By default the widget is in multi-selection mode.

Here's an example of how to set the reference widget to a single selection mode:

Defaults
{
    object_list
    {
        UIType = "ReferenceWidget.ReferenceWidget.1"
        {
            "mode" = "single";
        }
    }
}
Image:Notewriting.png
Note that there's no semi-colon after the closing brace of the parameter block


Object filter

There's another optional parameter, "filter", that can be used to control which objects should be included in the picking list. It takes a single GUID. Unfortunately it is, for some reason lost in the mist of time, based on interface ID, rather than object IDs. A list of common interface IDs to filter in common object types is listed below.

Here's an example of how to set the reference widget to filter for objects only:

Defaults
{
    object_list
    {
        UIType = "ReferenceWidget.ReferenceWidget.1"
        {
            "filter" = "{6B579D20-3DC5-11D0-9449-00AA006D3165}";
        }
    }
}

Here's a list of common object types in XSI and their corresponding interface IDs:

Type Interface ID
Any 3DObject {6B579D20-3DC5-11D0-9449-00AA006D3165}
Null {7DD91AA4-89D8-11D0-A75C-00AA00BB6238}
Camera {1152E9B0-545E-11D0-8466-00A024C7919C}
Light {E9F25E60-520D-11d0-8298-00A0243E366B}


Hierarchy mode

It has a single optional UI flag which controls whether the each object reference is a reference to only the object picked or the object and its children. By default, only the object itself is given. To get the object hierarchy instead, the reference parameter can be declared thus:

Parameter "object_list"
{
    GUID = "{7636CC21-51CE-11D4-AEE8-0090275AE282}";
    Type = Reference;
    UI "hierarchy" = true;
 }

Using object lists in a mental ray shader

Using the object list in mental ray is relatively straightforward. The only thing that needs to be taken care of is the object hiearchy received, which depends on whether the parameter is set to receive only a single object or the object including children.

Below is an example hierarchy of objects in XSI and the corresponding hierarchy as it appears in mental ray:


Image:Xsi_hrc.png Image:Mr_hrc.png
Blue triangles are miInstance objects, yellow circles are miGroup objects, and the green boxes are geometry representations, the type of which depends on how they're generated.


If the reference parameter is set to receive only the object, the object tag received will point to the miInstance shaded in blue. If it is set to receive the hierarchy, the object tag received will point to the miInstance shaded in red.


Image:Notewriting.png
In all cases is it the miInstance that immediately instantiates geometry in the diagram above that holds the transform and visibility flags. The label can be found on the geometry itself.


Code example

The example doesn't include the main body of the shader, only the _init section.

#include <shader.h>
#include <geoshader.h>

typedef struct
{
    int                 i_object;
    int                 n_object;
    miTag               object[ 1 ];
    int                 i_hierarchy;
    int                 n_hierarchy;
    miTag               hierarchy[ 1 ];
} reference_test_t;

miUint get_instance_label( miTag object_inst )
{
    miTag       object_geo;
    miUint      object_label = 0;

    mi_query( miQ_INST_ITEM, NULL, object_inst, (void *)&object_geo );

    if( mi_db_type( object_geo ) == miSCENE_GROUP )
    {
        // Polymeshes and hair split objects up into a group of instances of
        // geometry.
        mi_query( miQ_GROUP_LABEL, NULL, object_geo, (void *)&object_label );
    }
    else if( mi_db_type( object_geo ) == miSCENE_OBJECT )
    {
        // NURBS don't.
        mi_query( miQ_OBJ_LABEL, NULL, object_geo, (void *)&object_label );
    }
    else
    {
        mi_warning( "Unknown geometry type on object '%s'", mi_api_tag_lookup( object_inst ) );
    }
    
    return( object_label );
}

extern "C" DLLEXPORT void
reference_test_init
(
    miState             *state,
    reference_test_t    *params,
    miBoolean           *inst_init_req
    )
{
    if( params == NULL )
    {
        *inst_init_req = miTRUE;
        return;
    }
    
    int         i;
    
    // Loop over the non-hiearchy object list first.
    mi_info( "Single objects:\n" );
    for( i = 0; i < params->n_object; i++ )
    {
        miTag       object_inst = params->object[ params->i_object + i ];

        mi_info( "  Object %d is '%s' with label %d\n", 
            i + 1, 
            mi_api_tag_lookup( object_inst ), 
            get_instance_label( object_inst ) );
    }

    // Only list object referred to and its immediate children.
    // Recursive enumeration is left as an exercise for the reader.
    mi_info( "Object hierarchy:\n" );
    for( i = 0; i < params->n_hierarchy; i++ )
    {
        miTag       hierarchy_inst = params->hierarchy[ params->i_hierarchy + i ];

        // Get to the group that holds the children and the object itself.
        // The object itself is *always* the first one in the list.
        miTag       group_tag;
        int         group_nkids;

        mi_query( miQ_INST_ITEM, NULL, hierarchy_inst, (void *)&group_tag );
        mi_query( miQ_GROUP_NKIDS, NULL, group_tag, (void *)&group_nkids );

        // Get the first kid of the group. That'll be the object itself.
        // NOTE: The fifth argument is the kid index.
        miTag       object_inst;

        mi_query( miQ_GROUP_KID, NULL, group_tag, (void *)&object_inst, 0 );
        
        mi_info( "  Parent object is '%s' with label %d\n", 
            mi_api_tag_lookup( object_inst ), 
            get_instance_label( object_inst ) );
        
        for( int j = 1; j < group_nkids; j++ )
        {
            miTag       subhrc_inst;

            // To get to the actual child object, we'll have to first grab the
            // miInstance that instantiates its miGroup that holds the child
            // object and all of its (possible) children.
            mi_query( miQ_GROUP_KID, NULL, group_tag, (void *)&subhrc_inst, j );

            miTag       subgroup_tag;
            mi_query( miQ_INST_ITEM, NULL, subhrc_inst, (void *)&subgroup_tag );

            mi_query( miQ_GROUP_KID, NULL, group_tag, (void *)&object_inst, 0 );
            
            mi_info( "  Child object %d is '%s' with label %d\n", 
                j + 1,
                mi_api_tag_lookup( object_inst ), 
                get_instance_label( object_inst ) );

        }
    }
}

The corresponding SPDL is:

SPDL
Version = "2.0.0.0";
Reference = "{2E233074-FE99-495E-B45D-BFA40031D95F}";
PropertySet "reference_test_pset"
{
    Parameter "out" output
    {
        GUID = "{8DB160ED-70C7-4D14-B18E-7271EA4D6901}";
        Type = vector;
    }
    Parameter "object" input
    {
        GUID = "{F2E3C864-B4D5-4FB5-9C39-A8B096F6AE30}";
        Type = reference;
    }
    Parameter "hierarchy" input
    {
        GUID = "{EDF39BFA-E16C-47AD-8CB6-01CFB8154E8A}";
        Type = reference;
        UI "hierarchy" = true;
    }
}

MetaShader "reference_test_meta"
{
    Name = "Reference Test";
    Type = texture;
    Renderer "mental ray"
    {
        Name = "reference_test";
        FileName = "reference_test";
        Options
        {
            "version" = 1;
        }
    }
}

Defaults
{
    object
    {
        UIType = "ReferenceWidget.ReferenceWidget.1";
    }
    hierarchy
    {
        UIType = "ReferenceWidget.ReferenceWidget.1";
    }
}

Layout "Default"
{
    object;
    hierarchy;
}

This page was last modified 04:25, 2 Oct 2010.
This page has been accessed 8885 times.

© Copyright 2009 Autodesk Inc. All Rights Reserved. Privacy Policy | Legal Notices and Trademarks | Report Piracy