Geometric Objects

Geometric objects can be divided into polygonal, free-form and subdivision surface, and curve geometry. Each object contains one (or more) object groups that define geometry. Multiple object groups are supported for backwards compatibility; new designs should create multiple objects rather than a single object with multiple object groups. Object groups are unrelated to instance groups as described above.

Objects

mi_api_object_begin
miObject *mi_api_object_begin(
    char            *name)     /* object name */

Begin the definition of an object with the given name.

If the name parameter is zero, the object is not registered in the symbol tables, so it cannot be referenced by name. In this case the tag returned by mi_api_object_end can be used to reference the object. All geometrical information is deleted regardless of incremental mode. This is the first call of the object definition sequence. After the object begin, first bases are defined if the object contains free-form surfaces. Next, the object group (or groups) must be defined. The returned miObject pointer can be used to write the visible and other flags into the object. Note, that since the final size of the object is not known at this point, the returned pointer points to a temporary structure that does not contain geometry and will be deleted by mi_api_object_end.

mi_api_object_matrix
miBoolean *mi_api_object_matrix(
    miMatrix        transform)

Deprecated Store the object's texture transformation matrix. It is kept for backwards compatibility only.

mi_api_object_group_begin
miBoolean mi_api_object_group_begin(
    double          merge)     /* merge epsilon */

Begin the definition of a group.

The next step after the begin call is beginning an object group. The merge argument is obsolete and must be set to 0.0.

mi_api_object_group_connection
miBoolean mi_api_object_group_connection(
    char            *surfname1,   /* first surface */
    char            *curvename1,  /* first curve */
    miGeoRange      *range1,      /* of first curve */
    char            *surfname2,   /* second surface */
    char            *curvename2,  /* second curve */
    miGeoRange      *range2)      /* of second curve */

Define connections of free-form surfaces.

After all surfaces in the free-form object have been defined, just before mi_api_object_group_end is called, this function can be used to establish connections between surfaces. Connections can only be defined along the trimming curves on the surfaces, which must exist. Untrimmed surfaces cannot be connected, but a trivial trim curve that follows the parameter boundaries such that no part is actually trimmed off is simple to create. A parameter range must be specified for both curves.

mi_api_object_group_end
miBoolean mi_api_object_group_end(void)

End the definition of a group.

After all geometry in the object group has been defined, this function completes the object group definition. Another group can be started after ending the current one.

mi_api_object_file
miBoolean mi_api_object_file(
    char            *file)

Load an object definition from a file.

Instead of explicitly defining geometry with mi_api_object_group_begin and mi_api_object_group_end, define the object as a placeholder object. This requires that a bounding box and, if applicable, a motion bounding box and a max displacement are defined in the object. mental ray will read the object from the specified .mi scene file file when it needs the geometry during rendering only. The file must define the exact same object, including the name and all flags and options, except that it must contain the actual geometry bracketed with group and end group. Note, that placeholder objects can only contain a single object group.

mi_api_object_callback
typedef miBoolean (*miApi_object_callback)(miTag, void *);

miBoolean mi_api_object_callback(
    miApi_object_callback cb,
    void                  *data)

Create an object definition in a custom callback function.

This is an alternative way to load a placeholder object, but instead of reading a file mental ray will call the callback cb. The callback receives the opaque data pointer data (intended to pass C++ this pointers, for example), and the tag of the object to define. The callback must then look up the name (mi_api_tag_lookup), enter incremental mode (mi_api_incremental), and redefine the object from scratch, this time with complete geometry. It is important that the object has only a single object group. The function may add a user data tag by looking up an existing userdata block and assign it, but it may not create a new one (it would be leaked because nobody is going to delete it later).

mental ray copies the object flags and label automatically, the callback has no control over them. If the callback does not set the bounding boxes, max displace, or ray offset, mental ray will copy them automatically too. Note, that the callback may provide smaller bounding boxes and max displace than originally specified, in case it has better knowledge about the object and can provide tighter bounding boxes, but it may never enlarge them. In previous versions of mental ray, the callback had to specify the same flags, the same label, and the same or smaller bounding box, motion bounding box, max displace, and ray offset values.

This is the recommended method for defining large objects with geometry shaders, and for integrations applications which support multi-threading and asynchronous translation, because no memory or time is spent until the object is actually needed for rendering. If memory runs out (see mi_mem_memory_limit), mental ray can dispose of the object from the cache to make room for more important data. It could not throw out normal geometry shader-generated objects because they cannot be rebuilt on demand. Also, mental ray may run different object callbacks in parallel if necessary.

mi_api_object_placeholder_callback
typedef miBoolean (*miApi_object_placeholder_callback) (miTag, miObject *, void *);

miBoolean mi_api_object_placeholder_callback(
    miApi_object_placeholder_callback cb_create,
    miApi_object_placeholder_callback cb_delete, void *data);

Create and delete an object definition in a custom callback function.

This function may be used instead of mi_api_object_callback(). The syntax is unified with other callbacks in mental ray like those for user data and texture elements: two functions can be specified which are called upon create and delete events, both receiving the same object tag. The separate delete function is optional. The callback gets the object tag being created (which should only be used for name lookups), a miObject pointer (NULL for the create, non-null for delete callback), and always passes the custom data pointer of the application. If the same function is installed for both create and delete callbacks, it can detect the type of the call by checking if the miObject pointer argument is NULL.

mi_api_object_end
miTag mi_api_object_end(void)

Complete the definition of the object.

This is the last call of the object definition sequence. If an error occurs, a null tag is returned; otherwise the tag of the new object or group element is returned. API decides whether to create and return an object or an instance group element based on the object complexity: if it has multiple object groups or connections, an instance group is created that has the merge_group flag set, and references one or more instances, each of which references an object element containing a single object group. If there is only one such group and no connections, the object is created and returned directly without creating intermediate instances or connections. This decision is transparent to the caller; the tessellator accepts instance groups in this case as well as objects. The type of the returned element is either miSCENE_OBJECT or miSCENE_GROUP.

Bases

Objects containing free-form surfaces must contain at least one basis. A basis defines the curve type or one of the two surface parameter axis types (e.g., NURBS or Bézier), a rational flag, and the degree. All surfaces in all object groups of an object share the same basis list in the object, and reference bases by name.

mi_api_basis_list_clear
miBoolean mi_api_basis_list_clear(void)

Delete all bases in the current object basis list.

This function is largely obsolete because it is implicitly called when beginning and ending objects.

mi_api_basis_add
miBoolean mi_api_basis_add(
    char              *name,    /* name of basis */
    miBoolean         rational, /* rational surface? */
    enum miBasis_type type,     /* basis type */
    miUshort          degree,   /* degree of basis */
    miUshort          stepsize, /* opt. step size */
    miDlist           *matrix)  /* opt. basis matrix */

Append a basis to the basis list of the current object.

The basis name, a rational flag, the basis type, and the degree must be defined. The matrix stepsize and the basis matrix must be defined only for the basis matrix type. The matrix is passed as a dlist (dynamic list, see above) because its size depends on the degree of the basis; (degree+1)2 floating-point numbers of type miGeoScalar are expected.

mi_api_basis_lookup
miGeoIndex mi_api_basis_lookup(
    char            *name,      /* basis to look up */
    miBoolean       *rational,  /* rational flag */
    miUshort        *degree)    /* returned degree */

Look up a basis by name.

The sequential number of the basis in the object's basis list is returned, as well as the rational flag and the degree if the second and third arguments are non-null pointers. This function is not essential for scene definition.

Polygonal Geometry

Polygonal geometry requires the definition of three blocks of data: vectors, vertices, and polygons. Optionally, an approximation may be given which is used by the tessellator for displacement-mapped polygons.

mi_api_geovector_xyz_add
mi_api_vector_xyz_add
miBoolean mi_api_geovector_xyz_add(
    miGeoVector     *newvec)   /* vector to append */

miBoolean mi_api_vector_xyz_add(
    miVector        *newvec)   /* vector to append */

Add a vector to the current vector list.

After beginning the object group that should contain polygonal geometry, calls to this function for every (x,y,z) vector to be used must be done. Vectors will be referenced by sequential number, beginning with 0 in every object group, to be used as points in space, normals, motion vectors, and various other purposes. There are restrictions of vector sharing; for example, a vector cannot be used as a point in space and a normal at the same time. Also, vectors should be listed in a certain order (points in space first, then normals, and so on) for maximum efficiency. Any other order will be re-sorted automatically.

There are two versions of this call. The first accepts double-precision vectors and the second accepts single-precision vectors. Both store the vectors in double precision. If the vector is available in double precision, always use mi_api_geovector_xyz_add to avoid precision loss. Both versions can be mixed, they are identical except for the argument type.

mi_api_vector_lookup
miBoolean mi_api_vector_lookup(
    miGeoVector     *pos,      /* vertex position */
    int             idx)       /* index of vector */

Look up a vector by index.

This function looks up a vector in the current object by index, and returns its value. This function is not essential for scene definition.

mi_api_vertex_add
mi_api_vertex_deriv_add
mi_api_vertex_deriv2_add
mi_api_vertex_motion_add
mi_api_vertex_normal_add
mi_api_vertex_tex_add
mi_api_vertex_user_add
miBoolean mi_api_vertex_add(
    int             p)         /* point in space */

miBoolean mi_api_vertex_deriv_add(
    int             u,         /* dPdu derivative */
    int             v)         /* dPdv derivative */

miBoolean mi_api_vertex_deriv2_add(
    int             u,         /* d2Pdu2 derivative */
    int             v,         /* d2Pdv2 derivative */
    int             uv)        /* d2Pduv derivative */

miBoolean mi_api_vertex_motion_add(
    int             m)         /* motion vector */

miBoolean mi_api_vertex_normal_add(
    int             n)         /* normal vector */

miBoolean mi_api_vertex_tex_add(
    int             t,         /* texture parameter vector */
    int             x,         /* X basis vec or -1 */
    int             y)         /* Y basis vec or -1 */

miBoolean mi_api_vertex_user_add(
    int             u)         /* user vector */

Add a vertex and optional data to the current vertex list.

After all vectors have been defined, vertices must be defined. Vertices must contain a point in space, defined with mi_api_vertex_add, optionally followed by a normal, first and second surface derivatives, one or more texture vectors with optional bump basis vectors, a motion vector, and one or more user vectors. After the initial point in space, the order of the other calls is fixed. Vectors are referenced by sequential number in the object group, with 0 being the first vector. A vector index -1 means "none," which is useful for defining texture vectors without bump basis vectors. Either no or two bump basis vector indices must be given. All add functions until the next call to mi_api_vertex_add or the end of the vertex list append to the current vertex. The next mi_api_vertex_add begins the next vertex.

mi_api_vertex_lookup
miBoolean mi_api_vertex_lookup(
    miGeoVector     *pos,      /* vertex position */
    int             idx)       /* index of vertex */

Look up a vertex by index.

This functions looks up the point in space of the vertex specified by the index idx. Vertices, like vectors, are sequentially beginning with 0 in every object group. This function is not essential for scene definition.

mi_api_poly_begin
miBoolean mi_api_poly_begin(
    int             type,      /* 0=concave, 1=convex */
    char            *material) /* material name */

miBoolean mi_api_poly_begin_tag(
    int             type,       /* 0=concave, 1=convex */
    miTag           material)   /* material tag */

Begin a polygon definition.

After all vectors and vertices have been defined, polygons are defined. Each polygon requires a begin call followed by at least three index add calls followed by an end call. Optionally, holes may be defined. At this time, type must be either 0 (concave or unknown) or 1 (convex). Specifying type 1 improves performance because the tessellator does not need to test the convexity of the polygon. The first polygon in an object group must always specify a material by either a name or a tag, therefore the two begin functions are provided. For all following polygons, a null pointer or a null tag may be passed to specify "same material as before in the same object group." This improves API performance. In the case of tagged objects, the material pointer or tag must be null; the label is passed as an extra index (using mi_api_poly_index_add) before the regular vertex indices.

mi_api_poly_index_add
miBoolean mi_api_poly_index_add(
    int             idx)         /* new index to append */

Add a vertex reference to the current polygon.

After the polygon begin call, at least three vertices must be specified by index. The first vertex in the current object group has index 0. The order is significant; polygon vertices must be defined in counter-clockwise order. Polygons (and their holes) should be planar. Small deviations are handled gracefully but very large deviations may lead to unpredictable behavior. This function is also used to store the polygon label directly after mi_api_poly_begin if the object is tagged.

mi_api_poly_hole_add
miBoolean mi_api_poly_hole_add(void)

Add a hole vertex reference to the current polygon.

After the boundary loop of the polygon has been specified using index add calls, this call may be used to indicate the end of the current loop and the beginning of a hole loop. Hole loops, like boundary loops, consist of a sequence of at least three index add calls. No two loops may intersect, and a hole loop must be fully contained in the boundary loop in the plane of the polygon.

mi_api_poly_end
miBoolean mi_api_poly_end(void)

End a polygon definition.

After all boundary and optional hole loops have been added, the polygon must be completed with this call. After the end call, a new polygon definition may be started.

mi_api_poly_approx
miBoolean mi_api_poly_approx(
    miApprox        *approx)      /* approx technique */

Attach a displacement approximation.

After the last polygon an approximation statement may be specified. It is used by the tessellator for displacement-mapped polygons only. Displacement mapping is a feature of the material assigned to polygons.

Free-Form Surface Geometry

Object groups containing free-form surfaces also consist of three sections: the vector list, the vertex list (more accurately called the control point list), and the curve and surface lists. The vector list is defined using one call to mi_api_vector_xyz_add for every vector. All vectors have three components x, y, z; weights for rational curves and surfaces are specified as part of the vertex references later.

The vertex list is defined with calls to mi_api_vertex_add, exactly like in the polygonal case, except that all normals, textures, and other optional vertex information except motion vectors is ignored and should not be specified. Surfaces always compute their own normals, and there are special constructs for textures and bump maps.

The curve and surface list uses the vertices defined in the first section as control points. Curves can be used as trimming curves, hole curves, and special curves. Vertices can also be used as special points on surfaces. Special points and special curves are always included in the tessellated surface.

mi_api_surface_begin
miBoolean mi_api_surface_begin(
    char            *name,     /* surface name */
    char            *mtlname)  /* material name */

Begin the definition of a free-form surface.

The name is valid only inside the object group to be refernced in connections and approximations. The given material is assigned to the surface. The name may not be a null pointer.

mi_api_surface_begin_tag
miBoolean mi_api_surface_begin_tag(
    char            *name,     /* surface name */
    miTag           mtltag)    /* material name */

Begin the definition of a free-form surface.

This function is similar to mi_api_surface_begin but the material is given by a tag instead of by name. This tag may not be a null tag.

mi_api_surface_params
miBoolean mi_api_surface_params(
    int             dimen,       /* miU or muV */
    char            *basis_name, /* basis for U or V */
    miGeoScalar     range_min,   /* minimum range */
    miGeoScalar     range_max,   /* maximum range */
    miDlist         *params,     /* params for U or V */
    miBoolean       rational)    /* rational flag */

Set free-form surface parameters.

A free-form surface has two parameter directions, u and v. After the surface begin call, both must be defined with this call, first time with dimen = miU and second time with dimen = miV. Both times, the basis name as defined at the beginning of the object definition must be given, as well as the parameter range, the surface parameter list, and the rational flag. The rational flag can either be set here or in the basis; the latter is recommended. The rational flag can be specified here for backwards compatibility.

The parameter list is a dynamic list (see dlist) containing the parameter vector. The length of this vector depends on the basis, see surface parameter list for the exact numbers. The type of the dlist is miDLIST_GEOSCALAR, containing floating-point numbers of type miGeoScalar.

mi_api_vertex_ref_add
miBoolean mi_api_vertex_ref_add(
    int             ref,         /* vertex reference */
    double          w)           /* homogeneous coordinate */

Add a control point reference to the current free-form surface.

After both surface parameter vectors have been specified, the control points must be listed. The number of control points depends on both bases and the length of their parameter vectors; again refer to the mental ray manual for details. For every control point one call to mi_api_vertex_ref_add is required. If both bases are non-rational, it is sufficient to specify a vertex index ref. As with polygons, 0 selects the first vertex in the current object group. For rational bases, a weight w must be given for every control point reference.

mi_api_surface_curveseg
miBoolean mi_api_surface_curveseg(
    miBoolean         newloop,   /* new loop? */
    enum miCurve_type type,      /* type of curve */
    char              *name,     /* existing curve */
    miGeoRange        *range)    /* curve range */

Add a curve or curve segment to a freeform surface.

After the surface parameters have been defined, this call can be used to attach curves to the surface. The curve must have been defined in the same object group (see below) and is referenced by name. The type of the curve is one of miCURVE_TRIM, miCURVE_HOLE, and miCURVE_SPECIAL. The parameter range specifies the piece of the curve to be used. Multiple curves or pieces of curves can be concatenated to form the final loop; curves specified by consecutive mi_api_surface_curveseg are concatenated to a single loop by setting newloop to miTRUE for the first call and to miFALSE for all following curves to be appended.

mi_api_surface_specpnt
miBoolean mi_api_surface_specpnt(
    int             uv_index,    /* 2D point reference */
    int             v_index)     /* optional 3D point */

Attach a special point to a free-form surface.

A vertex index uv_index must be given that contains the coordinate in the surface's UV space. The tessellated surface will contain a triangle vertex at that UV coordinate. If v_index is not -1, the special point is assigned the XYZ coordinate contained in the indexed vertex.

mi_api_surface_texture_begin
miBoolean mi_api_surface_texture_begin(
    miBoolean       is_volume,
    miBoolean       is_bump,
    char            *ubasis_name,
    miDlist         *uparams,
    miBoolean       u_rational,
    char            *vbasis_name,
    miDlist         *vparams,
    miBoolean       v_rational)

Attach a texture surface to a free-form surface.

This call attaches a texture surface to the most recently defined surface. A texture surface is a simplified type of surface that causes texture vectors to appear in the vertices of the triangles that result from tessellation. Whenever the tessellator creates a triangle vertex at a certain UV coordinate of the main surface, it looks up this UV coordinate in the texture surface and computes the location of the texture surface at that point, and stores that as texture vector. If is_volume is miFALSE, wrap compensation is applied before storing the texture vector; this ensures that texture lookups near the surface seam do not "rewind." Generally it should be miFALSE for 2D textures and miTRUE for 3D (volume) textures. If is_bump is miTRUE, a pair of basis vectors is created in the tessellated surface instead of a texture vector. The bases and parameters in both the U and V directions are specified in the same call; they must use the same parameter ranges as the base surface.

Note that whenever the texture on a surface looks strangely shifted, or if texture coordinates are too large by a constant of 1, the reason is usually that is_volume had not been set to miTRUE on a 3D texture.

mi_api_surface_derivative
miBoolean mi_api_surface_derivative(
    int             degree)     /* 1=1st, 2=2nd deriv */

Request computation of surface derivatives.

Specify that during tessellation, first or second order derivatives should be computed and stored with the vertices of the tessellated surface that was most recently started with mi_api_surface_begin. If both first and second order derivatives should be stored, this function must be called twice.

mi_api_surface_end
miBoolean mi_api_surface_end(void)

End a free-form surface definition.

After the surface, both of its parameter directions, all its texture surfaces and its derivatives have been specified, this call must be used to complete the surface definition. After this call, the next surface may be started by repeating the sequence beginning with mi_api_surface_begin.

mi_api_surface_approx
miBoolean mi_api_surface_approx(
    char            *name,      /* name of surface */
    miApprox        *approx)    /* approx technique */

Attach a surface approximation to a free-form surface.

After the definition of a surface is complete, an approximation can be attached to it. The default is parametric approximation. This call can be used to change the default to regular parametric, curvature-dependent or spatial approximations. This call must be used before the object group ends because at that point the surface names go out of scope.

mi_api_surface_approx_displace
miBoolean mi_api_surface_approx_displace(
    char            *name,     /* name of surface */
    miApprox        *approx)   /* approx technique */

Attach a displacement approximation to a free-form surface.

In addition to mi_api_surface_approx, which control the approximation of the base surface, this function stores an approximation for the displaced surface. The default is parametric. This is often useful to provide a high-resolution parametric approximation for the base surface to catch small displacement map features, and a curvature or view dependent tessellation like fine approximation for the displaced surface to properly approximate the details introduced by the displacement.

mi_api_surface_approx_trim
miBoolean mi_api_surface_approx_trim(
    char            *name,     /* name of surface */
    miApprox        *approx)   /* approx technique */

Attach a curve approximation to a surface.

This function assigns an approximation to the trimming, hole, and special curves attached to the named surface, just like the previous function assigns an approximation to the surface itself.

Curves

Curves can be used as trimming curves, hole curves, and special curves for free-form surfaces as described in the previous section. In addition, space curves can be used to desribe 3D curve objects. A special variant of curves is used to represent hair.

This section lists the API functions to create curves. This can be done inside any object group, after the vectors and vertices are defined, in any place where a surface definition would be legal. Like surface names, curve names are in object group scope and can only be referenced in the object group they are defined in.

mi_api_curve_begin
miBoolean mi_api_curve_begin(
    char            *name,       /* name of the curve */
    char            *basis,      /* name of the basis */
    miBoolean       rational)

Create a new curve with the given name, using the specified basis. Like surfaces, a rational flag can be set for backwards compatibility reasons. The recommended method is setting the rational flag in the basis. Curves and surfaces can share the same bases.

mi_api_curve_specpnt
miBoolean mi_api_curve_specpnt(
    int             t_index,     /* 1D point reference */
    int             v_index)

Attach a special point to a curve at the parameter point v_index of the curve. v_index references the vertex to use; only the X value is used.

mi_api_curve_end
miBoolean mi_api_curve_end(
    miDlist         *dlp)        /* parameter list */

Complete the definition of the curve, and pass the parameter vector. The type of the dlist is either miScalar for the non-rational case or miVref for the rational case.

mi_api_curve_approx
miBoolean mi_api_curve_approx(
    char            *name,       /* name of curve */
    miApprox        *approx)     /* approx technique */

This function assigns an approximation to the curve. Alternatively, an approximation can be assigned to all curves used in a surface at once using mi_api_surface_approx_trim, which overrides the approximation set with mi_api_curve_approx.

Space Curves

This section lists the API functions to create space curves. Space curve objects are primarily useful in geometry shaders, they are not used for rendering. Geometry shaders can build renderable surfaces with space curve objects or use them for dynamic trimming operations on surfaces. The definition can be done inside any object group, after the vectors and vertices are specified. Like curve or surface names, space curve names are in object group scope and can only be referenced in the object group they are defined in.

mi_api_spacecurve_begin
miBoolean mi_api_spacecurve_begin(
    char            *name)     /* space curve */

Create a new space curve with the given name.

mi_api_spacecurve_curveseg
miBoolean mi_api_spacecurve_curveseg(
    miBoolean       newloop,   /* is this a new loop */
    char            *name,     /* curve name */
    miGeoRange      *range)    /* range of the curve */

This call can be used to attach curve segments to the space curve. The curve must have been defined in the same object group (see below) and is referenced by name. The parameter range specifies the piece of the curve to be used. Multiple curves or pieces of curves can be concatenated to form the final space curve; curves specified by consecutive mi_api_spacecurve_curveseg are concatenated to a single curve by setting newloop to miTRUE for the first call and to miFALSE for all following curves to be appended.

mi_api_spacecurve_approx
miBoolean mi_api_spacecurve_approx(
    char            *name,     /* name of surface */
    miApprox        *approx)   /* approx technique */

After the definition of a space curve is complete, an approximation can be attached to it. The default is parametric approximation. This call can be used to change the default to regular parametric, curvature-dependent or spatial approximations. This call must be used before the object group ends because at that point the space curve names go out of scope.

mi_api_spacecurve_end
miBoolean mi_api_spacecurve_end(void)

This function must be called to finalize the definition of a space curve. After this call, the next space curve can be started by repeating the sequence beginning with mi_api_spacecurve_begin.

Hair

Hair geometry shares the same object begin and end calls with all other geometry types, but the actual geometry uses special mi_api_hair_* calls instead of mi_api_object_group_begin and mi_api_object_group_end. A typical sequence is:

mi_api_hair_begin
    mi_api_hair_info                    (zero or more calls)
    mi_api_hair_scalars_begin
    mi_api_hair_scalars_end             (followed by array write)
    mi_api_hair_hairs_begin
        mi_api_hair_hairs_add           (once per hair plus 1)
    mi_api_hair_hairs_end
mi_api_hair_end

The mi_api_hair_info calls are optional; they describe the information attached to hairs and vertices (see hair geometry for details).

mi_api_hair_begin
miHair_list *mi_api_hair_begin(void)

Begin a hair block in an object. The returned hair list may be used to specify the global fields material, radius, degree, approx, space_max_size, and space_max_depth.

mi_api_hair_info
miBoolean mi_api_hair_info(
    int             where,     /* 0=per hair, 1=per vertex */
    char            what,      /* n=norm,m=mot,t=tex,u=user,r=radius*/
    int             num)       /* how many? */

Specify that each hair (if where == 0) or each vertex (if where == 1) has the specified number of normal scalars (what == 'n', num must be 0 or 3), number of motion scalars (what == 'm', num must be 0 or a multiple of 3), number of texture scalars ( what == 't'), number of user scalars (what == 'u'), or whether it has a radius ( what == 'r', either 0 or 1). If there are vertex normals, vertex motion vectors, or a vertex radius, the hair normals, hair motion vectors, or hair radius, respectively, are ignored.

mi_api_hair_scalars_begin
miScalar *mi_api_hair_scalars_begin(
    int             num)       /* expected number of scalars */

After the hair info, the scalar list follows in the hair object definition. The num argument specifies the number of scalars in the hair object. This function returns a scalar array with room for num scalars, which the caller must fill. See page hairlayout for the scalar layout. There is no add-scalar function for performance reasons.

mi_api_hair_scalars_end
miBoolean mi_api_hair_scalars_end(
    int             num)       /* received number of scalars */

After all scalars have been defined, this function must be called. It performs some consistency checks.

mi_api_hair_hairs_begin
miGeoIndex *mi_api_hair_hairs_begin(
    int             num)       /* expected number of hairs + 1 */

After the scalar definition, the hair indices must be defined with this function. The number num is the number of indices that follow, which is the number of hairs plus 1. Again, see page hairlayout. A pointer to an index array with num indices is returned, which the caller must fill by calling mi_api_hair_hairs_add repeatedly, or manually.

mi_api_hair_hairs_add
miBoolean mi_api_hair_hairs_add(
    int             si)        /* index into scalar list */

Add a hair index si. This ends the definition of the previous hair, if any, and begins a new hair (unless this is the last index). Each hair needs a fixed number of scalars: the number required by the hair info (data shared by all vertices of the hair), followed by one or more vertex info blocks (data separate for each hair), as defined with mi_api_hair_info. Note that there need to be as many calls to this function as have been specified by the num argument of the mi_api_hair_hairs_add call, which is one more than the number of hairs (to terminate the last hair). The first hair index is normally 0, and the last hair index normally equals the number of scalars num passed to mi_api_hair_scalars_begin.

mi_api_hair_hairs_end
miBoolean mi_api_hair_hairs_end(void)

This function concludes the definition of indices. The next call is probably mi_api_hair_end.

mi_api_hair_end
void mi_api_hair_end(void)

Finish the definition of the hair geometry. The next call is probably mi_api_object_end.

Subdivision Surfaces

Object groups containing subdivision surfaces consist of three sections: the vector list, the vertex list, and the subdivision surface list. As common, the vector list is defined using one call to mi_api_vector_xyz_add for every vector, and the vertex list is defined with calls to mi_api_vertex_add like in the polygon case. The subdivision surface list uses the vertices for both position and detail vertices. Subdivision surface vertices can have flags attached, they can be added by calling:

mi_api_vertex_flags_add
typedef enum {
    miAPI_V_SMOOTH=0,
    miAPI_V_CORNER,
    miAPI_V_CONIC,
    miAPI_V_CUSP,
    miAPI_V_DART
} miApi_vertexflags;

miBoolean mi_api_vertex_flags_add(
    miApi_vertexflags flags,
    miScalar          value)

This function adds a sharpness feature to the current vertex beginning with a specified level. It should be called only once for each vertex, and may be called for individual vertices. If not called for a vertex, default flags are used (miAPI_V_SMOOTH), which will lead to smooth vertex processing. value specifies the sharpness for conic and cusp vertices. For corner vertices zero sharpness should be passed. It is redundant to mark a vertex smooth with this call.

A typical call order for subdivision surface construction is:

mi_api_subdivsurf_begin
   mi_api_subdivsurf_index                 (n times)
   mi_api_subdivsurf_baseface
   [mi_api_subdivsurf_crease_edge          (optional)
    mi_api_subdivsurf_crease]              (optional)
   mi_api_subdivsurf_trim                  (optional)
   mi_api_subdivsurf_mtl                   (optional)
      [mi_api_subdivsurf_push              (block optional)
         mi_api_subdivsurf_subdivide
            mi_api_subdivsurf_mtl          (optional)
            [mi_api_subdivsurf_index       (up to 6/9 times)
             mi_api_subdivsurf_detail]     (optional)
            [mi_api_subdivsurf_crease_edge (optional)
             mi_api_subdivsurf_crease]     (optional)
            mi_api_subdivsurf_trim         (optional)
            [mi_api_subdivsurf_push        (optional)
               mi_api_subdivsurf_subdivide
               ...
             mi_api_subdivsurf_pop]
       mi_api_subdivsurf_pop]
mi_api_subdivsurf_end

n is 3 or 4 for triangles or quads, respectively, plus either 1 (base polygon) or 4 (polygon kit) if the object is tagged, in which case the triangle/quad labels must be passed first. A "kit" consists of 3 or 4 indices that subdivide the edge of the parent polygon into four sub-polygons, each of which may have its own material (part of the kit) and each may in turn be subdivided (using up to four separate push/pop blocks).

mi_api_subdivsurf_begin
miBoolean mi_api_subdivsurf_begin(
    char            *name)          /* name of the surface */

Begin the definition of a subdivision surface with the given name. The name is valid only inside the object group.

mi_api_subdivsurf_baseface
miBoolean mi_api_subdivsurf_baseface(void)

Define a base triangle or quad. Before calling this function there must be either 3 or 4 vertices specified with mi_api_subdivsurf_index. If the object is tagged, one additional index must be specified, for a total of either 4 or 5.

mi_api_subdivsurf_mtl
miBoolean mi_api_subdivsurf_mtl(
    int             child,          /* 0-3 */
    char            *mtlname)       /* material name or 0 */

Add a material to the current face. A face may have only one material. child specifies to which child of the current kit the material is assigned. If the current face is a base polygon, -1 must be passed for child.

mi_api_subdivsurf_mtl_tag
miBoolean mi_api_subdivsurf_mtl_tag(
    int             child,
    miTag           mtltag)         /* material tag or 0 */

This function is equivalent to the previous but specifies the material as a tag.

mi_api_subdivsurf_index
miBoolean mi_api_subdivsurf_index(
    int             idx)            /* another base face vertex index */

If the object is tagged, the first index specified by this function is interpreted as a face material, subsequent indices specify base face vertices. If the object is not tagged, only the three or four vertex indices may be specified. When using this function for detail vector specification, object tagging is not admissible since materials are specified in other ways for kits. The first index specified will directly correspond to the first detail vector, even if tagging is enabled.

mi_api_subdivsurf_push
miBoolean mi_api_subdivsurf_push(void)

This function prepares a face subdivision. It must be called immediately before mi_api_subdivsurf_subdivide. The purpose of this function is to save the current face context, i.e. current face and level.

mi_api_subdivsurf_pop
miBoolean mi_api_subdivsurf_pop(void)

When a face subdivision is completed, this function must be called to restore the state as it was before face subdivision.

mi_api_subdivsurf_subdivide
miBoolean mi_api_subdivsurf_subdivide(
    int             child)

This function subdivides the specified child of the current kit. It must be called after mi_api_subdivsurf_push. Initially no detail vectors are assigned to the vertices. If the current face is a base polygon, -1 must be passed for child.

mi_api_subdivsurf_detail
miBoolean mi_api_subdivsurf_detail(
    int             mask)

This function sets detail vectors for the current face and for the current level. A vertex may have details beginning with the vertex definition level, and also on higher levels. mask specifies which vertices of the current kit will have details. This parameter is a bitmap. Bit 0-2 for triangles and 0-3 for quads specify whether the even vertices of the kit have details, bits 3-5 for triangles and 4-6 for quads specify whether the odd vertices of the kit have details. Detail vectors must be specified before calling this function with enough calls to mi_api_subdivsurf_index. These detail vectors are associated to the kit vertices using the mask bitmap. The current face must be a kit.

mi_api_subdivsurf_crease_edge
miBoolean mi_api_subdivsurf_crease_edge(
    miScalar        value)

Specifies the sharpness for a crease edge, in the range 0...1.

mi_api_subdivsurf_crease
miBoolean mi_api_subdivsurf_crease(
    int             child,
    int             mask)

This function defines a crease edge for the current face. The face is specified with child, for base polygons -1 must be given for child. The crease edges are specified with the bitmap mask. Bits 0..2 for triangles and 0..3 for quads specify the edges to be used for the crease. It is sufficient to mark a crease edge only in one direction, the other direction is marked automatically. Before calling this function enough crease sharpness values must be specified with calls to mi_api_subdivsurf_crease_edge. The bitmap mask is used to associate the sharpness values to the selected crease edges.

mi_api_subdivsurf_trim
miBoolean mi_api_subdivsurf_trim(
    int             child,
    int             mask)

This function defines a trim edge for the current face. The face is specified with child, for base polygons -1 must be given for child. The trim edges are specified with the bitmap mask. Bits 0-2 for triangles and 0-3 for quads specify the edges to be used for the trim edge. The current face will be located inside the trimmed region, i.e. it is cut out of the surface.

Trim edges must form a connected loop on the same level. Connected trim edges must be defined on the same level in the hierarchy. A trim edge may not be defined on the outer boundary loop of the subdivision surface. Nested trimming regions are not supported, i.e. it is only possible to define a single level of trim regions, not trim regions within trim regions. Edges of two different trim regions may not share the same edge or vertex. Trim regions may not overlap, intersect or touch.

mi_api_subdivsurf_end
miBoolean mi_api_subdivsurf_end(void)

Complete the definition of the subdivision surface started with mi_api_subdiv_begin.

mi_api_subdivsurf_approx
miBoolean mi_api_subdivsurf_approx(
    char            *name,
    miApprox        *approx)

Change the default approximation of a subdivision surface with name name to approx.

mi_api_subdivsurf_approx_displace
miBoolean mi_api_subdivsurf_approx_displace(
    char            *name,
    miApprox        *approx)

Change the default displacement approximation of a subdivision surface with name name to approx.

mi_api_subdivsurf_derivative
miBoolean mi_api_subdivsurf_derivative(
    int             degree,
    int             space)

Enable computation of derivatives for the current subdivision surface. degree must be 1. space selects which texture space should be used for the parameterization of the subdivision surface.

mi_api_subdivsurf_texspace
typedef struct miApi_texspace_options {
    miBoolean              face;
} miApi_texspace_options;

miBoolean mi_api_subdivsurf_texspace(
    miApi_texspace_options *opt,
    miUint                 no_opt)

This function sets the interpolation methods used for the defined texture spaces: if face is miTRUE, textures are evaluated per face (faceted) instead of being interpolated between vertices, which is the default. The method must be selected in the options array passed to this function. The array has one member for each texture space; no_opt is the number of array members.

Catmull-Clark Meshes

Catmull-Clark meshes are defined in a similar way as polygonal objects, however the mesh is subdivided using certain rules to get a smoother surface. The individual polygons in the input mesh can have an arbitrary number of edges. A fractional sharpness value can be assigned to the polygon edges, resulting in a local crease on the surface. Each polygon vertex may be tagged with a corner feature (see the Subdivision Surface section above for more details on vertex features).

mi_api_ccmesh_begin
struct miApi_ccmesh_options {
    miUint                 no_polygons;
    miUint                 no_vertices;
}
miBoolean mi_api_ccmesh_begin(
    char                   *name,
    miApi_ccmesh_options   *opt)

Begin a Catmull-Clark mesh object with the given name and options. no_polygons specifies the total number of polygons which will be defined, no_vertices the total number of polygon vertices.

mi_api_ccmesh_polygon
miBoolean mi_api_ccmesh_polygon(
    miUint                 no_vertices,
    miUint                 *vertices,
    miUint                 mtl_tag)

Adds a single polygon to the current Catmull-Clark mesh object. The polygon has no_vertices vertices, the vertex indices are given in vertices. An optional material can be given in mtl_tag. If the object is created in tagged material mode, mtl_tag is the material label, otherwise it is either a material tag or null.

mi_api_ccmesh_crease
miBoolean mi_api_ccmesh_crease(
    miScalar               *sharpness)

Assigns crease values to the current polygon, so this function must be called after mi_api_ccmesh_polygon. For each polygon edge a sharpness value must be given in the sharpness array. A smooth edge has a value 0, an infinitely sharp edge a value 1. If some edges do not have creases, 0 must be given in the corresponding array entries.

mi_api_ccmesh_approx
miBoolean mi_api_ccmesh_approx(
    char                   *name,
    miApprox               *approx)

Assign an approximation to the current Catmull-Clark mesh object. In the current implementation, a single subdivision step is always done. Any further subdivision is applied to this resulting quad mesh using the given approximation.

mi_api_ccmesh_derivative
miBoolean mi_api_ccmesh_derivative(
    miUint                 degree,
    miUint                 space)

Request generation of first or second derivatives for the current Catmull-Clark mesh object. For the first derivatives, a corresponding texture space index must be given, used for alignment of the tangent vectors.

mi_api_ccmesh_end
miBoolean mi_api_ccmesh_end()

Complete definition of the current Catmull-Clark mesh object.

Primitive List Objects

Primitive list objects provide a way to directly specify the renderable representation of geometry in mental ray, as boxes of final triangles. Displacement mapping is fully supported. Primitive list objects are way more efficient in terms of storage and runtime compared to polygon objects because no further face tessellation needs to be performed, and no copies of mostly big data blocks need to be made. However, primitive lists expose internal data structures used for rendering which may change with any major update of mental ray. That may require to re-compile and potentially adjust the code which utilize them. Primitive list objects replace triangle lists.

mi_api_primlist_begin
miBox *mi_api_primlist_begin(
    miVertex_info   *info,
    miUint          no_lines,
    miUint          no_prim_lists,
    miUint          no_indices,
    miUint          no_materials,
    miUint          pd_size,
    miUint          no_prims)

The current object being created is set to type miOBJECT_BOXES and a scene element of type miSCENE_NBOX is created. no_lines specifies the number of vertex lines containing floating point vertex data, no_prim_lists is the number of primitive lists requested. Each primitive list contains multiple primitives of the same type. In current mental ray, no_prim_lists must be 1 and only primitives of type miSCENE_PRIM_TRI are supported. The number of primitive indices ( references to the vertex lines) is given with no_indices, the number of materials with no_materials. There must be a corresponding material entry defined for each primitive (triangle). The total number of primitives in all primitive lists is given with no_prims. Each primitive may have user data attached to it, pd_size specifies the total size reserved in the miBox in multiples of 32 bit units.

mi_api_primlist_begin_2
miBox *mi_api_primlist_begin_2(
    miVertex_info   *info,
    miUint          no_lines,
    miUint          no_prim_lists,
    miUint          no_indices,
    miUint          no_materials,
    miUint          primdata_size,
    miUint          pd_info_size,
    miUint          no_prims)

The second primlist object constructor has one additional argument pd_info_size. It allows attaching an information block to the box, describing the per face user data layout. If set to zero, no such block is allocated in the box, but per face user data can still be defined. The primdata_size is the size of user data per primitive in multiples of 32 bit units.

mi_api_primlist_dimensions
miBoolean mi_api_primlist_dimensions(
    miUint          *tex_dims,
    miUint          *user_dims)

This function helps initializing the texture and user offset section in a miBox. Both tex_dims and user_dims specify the dimension for each texture/user space defined in the box. Memory for both arrays is not released by this function.

mi_api_primlist_approx
miBoolean mi_api_primlist_approx(
    miApprox        *approx)

Attaches a displacement approximation to the current primlist object.

mi_api_primlist_end
miBoolean mi_api_primlist_end(void)

Completes the definition of a primlist object.

Triangle List Objects

Deprecated Triangle list objects provide a way to directly specify the renderable representation of geometry in mental ray, as boxes of final triangles. Displacement mapping may still be applied. Triangle list objects are more efficient in terms of storage and runtime than polygon objects because no tessellation or other operation are performed that copy data. However, since triangle lists expose data structures used for rendering which may change at any major update of mental ray may require to change the code that uses them. mental ray now supports a different data structure called primitive lists which replace trilists. The miGeoBox data structure has been replaced by the new type miBox. The trilist family of API functions can still be used for defining triangle objects, however maximum performance is achieved by using the primlistfunctions.

mi_api_trilist_begin
miGeoBox * mi_api_trilist_begin(
    miVertex_content       *vc,
    miUint                 no_vectors,
    miUint                 no_vertices,
    miUint                 no_triangles)

Deprecated Begin definition of a triangle list object. The vertex layout is specified in vc, the other parameters specify the number of vectors, vertices and triangles for the object.

Returns a pointer to the low level result structure of a triangle list object, which is a miGeoBox. Instead of using mi_api_trilist_vectors, mi_api_trilist_vertices, mi_api_trilist_triangle or mi_api_trilist_triangles for geometry specification, the returned box may be initialized directly with help of the miBOX_GET_VERTICES and miBOX_GET_PRIMITIVES macros.

mi_api_trilist_approx
miBoolean mi_api_trilist_approx(
    miApprox               *approx)

Deprecated Attaches a displacement approximation to the current triangle list object.

mi_api_trilist_vectors
miBoolean mi_api_trilist_vectors(
    miVector               *vectors,
    miUint                 no_vectors)

Deprecated Appends no_vectors vectors to the triangle list. The vectors array is not released by this function.

mi_api_trilist_vertices
miBoolean mi_api_trilist_vertices(
    miGeoIndex             *vertices,
    miUint                 no_vertices)

Deprecated Appends no_vertices vertices to the triangle list. Each vertex requires corresponding vc→sizeof_vertex integers in the vertices array. The vertices array is not released by this function.

mi_api_trilist_triangle
miBoolean mi_api_trilist_triangle(
    char                   *material,
    miGeoIndex             *indices)

Deprecated Defines a single triangle with a named material. The indices array contains exactly three triangle indices referencing the vertex section of the box. The material string must be allocated and is released by this function, but the indices array is not released.

mi_api_trilist_triangles
miBoolean mi_api_trilist_triangles(
    miGeoIndex             *indices,
    miUint                 no_triangles)

Defines multiple triangles. The number of trinagles is specified in no_triangles. The triangle vertices are specified in the indices array. If the triangle list object has been created with the tagged flag, the material index must be given first in the index array, followed by the three triangle vertices. These three or four index groups must be repeated no_triangles times. The indices array is not released by this function.

mi_api_trilist_end
miBoolean mi_api_trilist_end(void)

Deprecated Completes the definition of a triangle list object.


Copyright © 1986, 2013 NVIDIA Corporation