home << prev next >> contents  


Geometric Objects

Objects
Bases
Polygonal Geometry
Free-Form Surface Geometry
Curves
Space Curves
Hair
Subdivision Surfaces
Catmull-Clark Meshes
Triangle List Objects
Primitive List Objects

Geometric objects can be divided into polygonal, free-form surface, and space curve objects. Each object contains one or more object groups that group geometry. Object groups are maintained for backwards compatibility with the .mi1 language; newer designs should use multiple objects rather than a single object with multiple object groups. Object groups are unrelated to instance groups as described above.

Objects

    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 must be used for referencing 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 that will be deleted by mi_api_object_end.

    miBoolean *mi_api_object_matrix(
miMatrix transform)

This function is for backwards compatibility with the .mi1 syntax only. It stores the object's texture transformation matrix. It should not be used.

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

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

    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 */

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.

    miBoolean mi_api_object_group_end(void)

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

    miBoolean mi_api_object_file(
char *file)

Instead of 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 3.0 will read the object from the specified .mi scene file file when it needs the geometry. 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 may only contain a single object group...end group block.

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

miBoolean mi_api_object_callback(
miApi_object_callback cb,
void *data)

This is an alternative to mi_api_object_file. It also creates a placeholder object, but instead of reading a file, mental ray 3.x will call the callback cb. The callback receives the opaque data pointer data (intended for passing C++ this pointers), 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, except this time with geometry. It is important that the object has only a single object group because multi-group objects are supported only for backwards compatibility with mental ray 1.x and are automatically converted to instance groups containing separate objects, and mental ray does not support placeholder instance groups because that would defeat the purpose.

In mental ray up to 3.2, the callback must specify the same flags, the same label, and the same or smaller bounding box, motion bounding box, maxdisplace, and ray offset values. It may add a userdata tag by looking up an existing userdata block, but not create a new one (it would be leaked because nobody is going to delete it later). mental ray 3.3 and later copy the flags and label automatically, so the callback no longer has control over them. if the callback does not set the bounding boxes, maxdisplace, or ray offset, mental ray will copy them automatically. Note that the callback may provide smaller bounding boxes and maxdisplace than originally specified, if it has better knowledge about the object and can provide tighter bounding boxes, but it may never enlarge them.

This is the recommended method for defining large objects with geometry shaders because no memory or time is spent until the object is actually needed, and if memory runs out (see mi_job_memory_limit), mental ray can evict the object from the cache to make room for more important data. It could not evict normal geometry shader-generated objects because they cannot be rebuilt on demand. Also, mental ray can run different object callbacks in parallel if necessary.

    miTag mi_api_object_end(void)

Complete the finished 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 object 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.

    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);

The function mi_api_object_placeholder_callback() can be used instead of mi_api_object_callback(). The syntax is unified with userdata and texture callbacks: two functions can be specified (the second one is optional) for create and delete calls, with the same user data block. The callback gets the userdata tag being created, (which should only be used for name lookups), miObject pointer (NULL for the create, non-null for delete callback), and the callback own data. If the same function is used for create and delete callbacks, it can detect the type of the call by checking if the miObject pointer argument is NULL.

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.

    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.

    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.

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

This function allows basis lookups by basis 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

An object group can contain either polygonal or free-form surface 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.

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

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

After beginning the object group that should contain polygonal geometry, one call to this function for every XYZ 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.

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

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

    miBoolean mi_api_vertex_add(
int p) /* point in space */

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

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_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_motion_add(
int m) /* motion vector */

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

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.

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

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.

    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 */

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.

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

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.

    miBoolean mi_api_poly_hole_add(void)

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.

    miBoolean mi_api_poly_end(void)

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 may be begun.

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

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.

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

Begin the definition of a surface with the given name. The name is valid only inside the object group and is used for connections and approximations. The given material is assigned to the surface. The name may not be a null pointer.

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

This function is similar to mi_api_surface_begin, but instead of a name a material tag must be specified. This tag may not be a null tag.

    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 */

A surface has two parameter directions, U and V. After the surface begin call, both must be defined with this call, once with dimen = miU and once 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 with the .mi1 language.

The parameter list is a dlist (dynamic list, see above) containing the parameter vector. The length of this vector depends on the

basis; refer to the .mi2 language specification in the mental ray manual for the exact numbers.

The type of the dlist is miDLIST_GEOSCALAR, containing floating-point numbers of type miGeoScalar.

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

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.

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

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.

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

Attach a special point to a 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.

    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)

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.

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

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

    miBoolean mi_api_surface_end(void)

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 can be started by repeating the sequence beginning with mi_api_surface_begin.

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

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.

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

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 dependent tessellation for the displaced surface to properly approximate the curvature introduced by the displacement. For mental ray 3.1, fine approximation allows resolving extremely detailed displacement maps efficiently.

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

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 as described in the free-form surface section above. In addition, curves can be used in space curves to represent curve objects.

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.

    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.

    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.

    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.

    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.

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

Create a new space curve with the given name.

    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.

    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.

    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. The 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 (for details see page hairobj).

    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.

    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.

    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.

    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.

    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.

    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.

    miBoolean mi_api_hair_hairs_end(void)

This function concludes the definition of indices. The next call is probably 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 also consist of three sections: the vector list, the vertex list, and the subdivision surface list. As before, 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:

    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.

The 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).

    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.

    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.

    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.

    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.

    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.

    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.

    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.

    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.

    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.

    miBoolean mi_api_subdivsurf_crease_edge(
miScalar value)

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

    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.

    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.

    miBoolean mi_api_subdivsurf_end(void)

Complete the definition of the subdivision surface started with mi_api_subdiv_begin.

    miBoolean mi_api_subdivsurf_approx(
char *name,
miApprox *approx)

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

    miBoolean mi_api_subdivsurf_approx_displace(
char *name,
miApprox *approx)

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

    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.

    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).

    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.

    miBoolean mi_api_ccmesh_end()

Complete definition of the current Catmull-Clark mesh object.

    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.

    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.

    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.

    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.

Triangle List Objects

Triangle list objects provide a way of directly specifying the renderable representation of geometry in mental ray, which is boxes of 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, they may change at any major update of mental ray which requires changing the code that uses them. mental ray 3.4 supports a different data structure called primitive lists that replace trilists. Use with care, and expect incompatibilities with new major versions of mental ray.

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

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.

    miBoolean mi_api_trilist_approx(
miApprox *approx)

Attaches a displacement approximation to the current triangle list object.

    miBoolean mi_api_trilist_vectors(
miVector *vectors,
miUint no_vectors)

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

    miBoolean mi_api_trilist_vertices(
miGeoIndex *vertices,
miUint no_vertices)

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

    miBoolean mi_api_trilist_triangle(
char *material,
miGeoIndex *indices)

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.

    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.

    miBoolean mi_api_trilist_end(void)

Completes the definition of a triangle list object.

Primitive List Objects3.4

Primitive list objects replace trilists in mental ray 3.4. Native trilists are no longer supported. 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 primlist functions described below.

    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 mental ray 3.4, 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. In mental ray 3.4 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.

      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 pace user data layout. If set to zero, no such block is allocted in the box, but user per face data can still be defined. primdata_size is the size of user data per primitive in multiples of 32 bit units.

    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.

    miBoolean mi_api_primlist_approx(
miApprox *approx)

Attaches a displacement approximation to the current primlist object.

    miBoolean mi_api_primlist_end(void)

Completes the definition of a primlist object.

home << prev next >> contents  


Copyright © 1986-2007 by mental images GmbH