Function Definitions

Functions, also called function calls, are references to a particular C function bundled with a set of parameter values. A function definition begins with naming the desired C function, which must have been declared (see above), followed by assignments of numerical or other values to individual parameters. The order of assignments is irrelevant; it is done by parameter name. Parameters that remain unassigned have a numerical value 0 or the empty string.

miBoolean mi_api_function_call(
    char            *name)     /* called function */

Every function definition begins with this call, which references the C function by name. An error occurs if the name is not declared. This function is special in that it does not insist on name to be declared in the current scope (see Scopes below). Instead, it searches for the function beginning in the innermost scope and works back towards the outermost scope. This is useful because shader declarations usually appear in the form of a $include statement at the beginning of the scene file, it would be inconvenient to force a redeclaration in every scope (such as phenomenon definitions) just to have the correctly scoped names handy.

miBoolean mi_api_parameter_name(
    char            *name)     /* new parameter */

After mi_api_function_call, the parameter values are assigned. The first step for an assignment is this call, which specifies the name o the parameter to be assigned to. The name must be one of those specified when the function was declared. name is always a simple name; to access the subtrees of arrays and structs special functions (push, pop, array element) are provided, see below. Parameter names may not contain dots (".").

miBoolean mi_api_parameter_default(
    miParam_type    type,           /* one of miTYPE_* above */
    void            *value)         /* ptr to int, float, bool */

Store a parameter default value for the parameter declared with the preceding mi_api_parameter_decl call. The value must point to a miBoolean, miInteger, or miScalar, depending on the parameter type. Correspondingly, the type argument must be one of miSCENE_BOOLEAN, miSCENE_INTEGER, and miSCENE_SCALAR. Integers are automatically converted to scalars if the declared parameter type requires it. To declare all three components of a vector, or all four components of a color, or all sixteen components of a transformation, it must be called three, four, or sixteen times. Non-numeric types and array members may not have defaults.

miBoolean mi_api_parameter_value(
    miParam_type    type,      /* parameter type */
    void            *value,    /* pointer to value */
    int             *null,     /* null pointer */
    int             *size)     /* size in parm block */

Assign a value to the parameter named with the previous call. The type of the value being assigned and a pointer to the value must be passed. The type must agree with the declared type of the parameter, following these rules:

These rules are all consequences of the fact that a .mi2 language parser, when it sees a value, does not have access to the declaration.

The passed null pointer must be a null pointer. It exists only for backwards compatibility of the function prototype. The size pointer must be either a null pointer or a pointer to an integer that will be set to the size in bytes of the parameter. For example, if type is miTYPE_VECTOR, mi_api_parameter_value will set it to 12 (sizeof(miVector)).

miBoolean mi_api_parameter_shader(
    char            *name)     /* shader name */

Instead of providing a value to a parameter, register another function by name that is called at runtime to calculate the value. This is used to build dynamic shader trees.

miBoolean mi_api_parameter_interface(
    char            *name)     /* interface parm name */

Instead of providing a value to a parameter, register a link to an interface parameter that provides the value at runtime.

miBoolean mi_api_parameter_push(
    miBoolean       is_array)  /* pushing array? */

After the call to mi_api_parameter_name for a structure or array, before values can be stored, the context must be pushed one level down into the structure's or array's parameter subtree. The is_array argument is miFALSE for structures and miTRUE for arrays. After the push, structure members and array elements can be assigned with regular mi_api_parameter_value calls. Every new array member must be preceded with a call to the following function.

miBoolean mi_api_new_array_element(void)

After the push operation, before a new array value can be assigned, this function must be used to make room for another array element. After the first call to this function, mi_api_parameter_value assigns to array element [0], after the next [1] is assigned, and so on. Array elements can only be assigned sequentially. If no values or not enough values are assigned to a parameter, its remaining scalars remain zero.

miBoolean mi_api_parameter_pop(void)

After a structure or array has been assigned its component values, the parameter subtree of the structure or array must be exited with a pop operation. For example, to assign the scalars 1 and 2 to members a and b of structure s, the call sequence is name(s), push, name(a), value(1), name(b), value(2), pop. The order of assignment to a and b is not significant. To assign 3 and 4 to an array a of length 2, the call sequence is name(a), push, new_element, value(3), new_element, value(4), pop. Push/pop pairs can be nested.

miTag mi_api_function_call_end(
    miTag           oldtag)    /* for incr change */

After all parameter values have been assigned, the function definition is completed with this call. The tag of the new function is returned and can now be used where a function is expected during scene definition. Since functions (as opposed to declarations) are not generally named, the standard incremental method cannot be applied; therefore a tag argument can be supplied. If tag is not the null tag, the existing function identified by tag is replaced with the new one such that all references in the scene that referred to the old function now refer to the new one. In this case tag is also returned.

miTag mi_api_function_append(
    miTag           list,      /* append to this list */
    miTag           func)      /* function to append */

Most regular shaders (not output shaders and inheritance functions) can be given as a list of shaders. In this case mental ray will call all shaders in the list in sequence, with each successive shader operating on the result of the previous. The main application are lens shaders, which are often lists of lens shaders. To append a function func to another function or function list list this call is used. The first function in the list is the anchor of the list; it can be passed as list when appending to the list but it is more efficient to pass the last function added to the list.

miBoolean mi_api_function_delete(
    miTag           *list)     /* func list to delete */

When a scene element referencing functions is changed incrementally, it is usually desired to delete the old function list before a new one is built with calls to mi_api_function_append. This call deletes all functions of the function list, and stores a null tag in the list anchor. The list argument is a pointer to the function list tag to permit this call to clear the function list tag itself.

miBoolean mi_api_shader_add(
    char            *name,     /* shader name */
    miTag           func_tag)  /* shader function */

Normally functions are unnamed. This call can be used to assign a name to a function. The main application are procedural textures, which are nothing but a texture shading function accessible by name (the name can be provided as parameter value to texture parameters of other functions). Named shaders also appear in the .mi2 language as shader statements. Note that lights, materials, and other scene elements are more than just shading functions, a named shader cannot be used where a material or light is expected.

miTag mi_api_function_assign(
    char            *name)     /* name of shader */

This call can be used to look up a named shader (was given a name by the preceding call) to obtain its tag. The returned tag can be used like a tag returned by mi_api_function_call_end. This is called an "assignment" because the .mi2 language allows assigning an existing named shader wherever a shading definition is called; such assignments are introduced with an equals sign.

miBoolean mi_api_shader_call(
    miTag           func_tag,     /* function to call */
    char            *c_inst_name, /* camera instance */
    char            *option_name) /* options element */

This function can be used to call a shading function immediately. This call returns after the called function returns. If func_tag is a function list, all functions in the list are called in sequence. The functions are provided with a dummy state containing mostly nulls; if a camera instance or options element are passed by name, appropriate camera and options substructures are placed in the state. Either c_inst_name or option_name may be null pointers.

miBoolean mi_api_shader_call_x(
    miColor         *result,      /* returned color */
    miTag           func_tag,     /* function to call */
    char            *c_inst_name, /* camera instance */
    char            *option_name, /* options element */
    void            *data)        /* extra user data */

This is a variant of mi_api_shader_call that can be used to call a shader, and retrieve a result from it. It is the caller's responsibility to pass a result pointer to memory that is large enough to hold all the data that the shader returns, if it returns data other than a miColor. The data pointer is passed to the shader as its fourth argument, and is not otherwise touched or dereferenced by mental ray.

Copyright © 1986, 2013 NVIDIA Corporation