Description |
The function will triangulate the given primitive, using the
specified triangulation method.
LiPrimitiveTriangulate is accompanied by an execution
method, LI_EXECUTE_TRIANGULATE, which will
call LiPrimitiveTriangulate for every primitive on the
active primitive list, using the
LI_TRIANGULATE_DEFAULT triangulation method.
LiPrimitiveTriangulate will repeatedly call a simple
"triangulate this polygon" routine, with every polygon of the given
primitive. Only primitives of type LI_PRIM_TYPE_POLY
and LI_PRIM_TYPE_MESH will be processed by this routine.
Passing in a primitive of any other type, will result in a
non-zero return value.
The LtTriangulate parameter specifies the particular triangulation
method that the caller wishes to see employed. The LightWorks ADS
supports 4 different triangulation methods. These are outlined in the
table, below.
All names should be prefixed LI_TRIANGULATE_ |
Name | Comment |
SIMPLE | Keep meshing until all polygons have been triangulated |
MAX_EDGE_LENGTH | Keep meshing until all polygons have been triangulated |
| and no edge in the mesh is longer than some |
| caller-defined maximum edge length. |
POLY_COUNT | Keep meshing until all polygons have been triangulated |
| and the total number of triangles is at least the |
| caller-defined minimum number. |
DEFAULT | One of the above; the user can change what the default |
| triangulation method is for an entire scene, and |
| for a particular primitive, or collection of primitives.
|
|
When a primitive is passed to LiPrimitiveTriangulate,
any primitive-specific meshing requirements (defined by a meshing
refinement, attached to the primitive) will be utilised.
A meshing refinement can also be set as the global default ...
to apply in the absence of any primitive-specific information.
This default refinement is set and read via the control variable
LI_CONTROL_MESHING_REFINEMENT , whose type
is an LtMeshingRefinement , and whose default value is
NULL.
Meshing refinements, and meshing criteria, are vital to any explanation
of how LiPrimitiveTriangulate behaves.
When this documentation refers to a primitive's
`relevant LI_MESH_CRIT_NAME value', the reader
should bear in mind the following 3-step operation, used
whenever a value is being sought for any criterion
- If the primitive being triangulated has a meshing
refinement attached, and the criterion under consideration
has been set for this refinement, then this value will be
used by the triangulation code.
- If there is no refinement attached, or the relevant criterion has
not been set on the refinement that is attached, then the code
will look for a non-NULL global refinement
( LI_CONTROL_MESHING_REFINEMENT).
If such a global refinement is found and it has had the
relevant criterion set, then the value stored with this global
meshing refinement is utilised.
- Otherwise, the system default value will be used.
Having established that it is dealing with a polygon, or polymesh,
primitive, the first action of LiPrimitiveTriangulate is
to establish what triangulation method it is being asked to employ.
When called with any method other than LI_TRIANGULATE_DEFAULT,
this choice is simple; the code will employ the specified method
(the LtTriangulate parameter).
When called with LI_TRIANGULATE_DEFAULT, the code
will use the primitive's relevant LI_MESH_CRIT_METHOD value
Regardless of which triangulation method is decided upon
( SIMPLE, POLY_COUNT, or MAX_EDGE_LENGTH)
the next action of LiPrimitiveTriangulate is to decide
whether it is triangulating the polygons of the primitive as they
stand, or whether extra vertices should first be added.
When the primitive's relevant LI_MESH_CRIT_MAX_EDGE_VERTS
value is TRUE, each (non-bridge) polygon edge has its length
compared to the maximum edge length defined by the primitive's relevant
LI_MESH_CRIT_MAX_EDGE_LENGTH value.
If the polygon edge is longer than the prescribed maximum length, then
the polygon edge is split up into enough equal-sized pieces to ensure
that all the pieces satisfy the length criterion.
Once this process has been repeated for all edges of the primitive,
the resulting polygons are simply triangulated.
If the primitive's relevant LI_MESH_CRIT_MAX_EDGE_VERTS
value is FALSE, then no edge splitting takes place before the
core triangulation operation.
Once the core triangulation has been successfully completed,
LiPrimitiveTriangulate will examine the primitive's relevant
LI_MESH_CRIT_EDGE_SWAPPING value, to see if an
optimal triangulation is being sought by the caller, or
merely an acceptable one.
If the relevant LI_MESH_CRIT_EDGE_SWAPPING value is
equal to LI_EDGE_SWAP_NONE, then no change will be made to
the triangle mesh which has just been generated. However, if this
value is LI_EDGE_SWAP_ALL, then all internal edges
of the primitive are examined, to establish if any of them form
the diagonal of a flat, convex quadrilateral. Those that do are tested to
see if splitting the quadrilateral along its other diagonal might not
produce a better triangulation (i.e., one with a bigger minimum internal angle).
If such a swap appears to improve things, then the edge is swapped. At the
end of such a sweep, the mesh is a Constrained Delaunay Triangulation.
If the relevant LI_MESH_CRIT_EDGE_SWAPPING value is
LI_EDGE_SWAP_NEW, then only those internal edges which
are created during the current call to LiPrimitiveTriangulate
will be considered for swapping. This will preserve the boundaries of
those polygons which were passed into the routine, allowing the caller
to build a hierarchical triangulation, should they so wish, by making
repeated calls with varying meshing parameters.
At the end of an LI_EDGE_SWAP_NEW sweep of all polygon edges,
a Constrained Delaunay Triangulation will again result, but it will
likely have more constraints than the triangulation which would have
resulted from an LI_EDGE_SWAP_ALL sweep of the same polygons.
Having carried out (or not) edge swapping, to the satisfaction of
the relevant LI_MESH_CRIT_EDGE_SWAPPING value,
LiPrimitiveTriangulate will examine the triangulation
method that is being employed, to see if any further work needs to be done:
- If the method being employed is
LI_TRIANGULATE_SIMPLE, then the routine will now quit.
- If the method being employed is LI_TRIANGULATE_POLY_COUNT,
then the code will repeat the following loop, until the number of
triangles in the mesh is at least as large as the relevant
LI_MESH_CRIT_POLY_COUNT value:
- find the primitive's longest polygon edge, and split it into 2 equal-length pieces;
- re-triangulate the 1 or 2 faces which share the recently-split edge;
- ensure that the relevant LI_MESH_CRIT_EDGE_SWAPPING
value is satisfied.
Having raised the polygon count to the requisite level, the routine will quit.
\item If the method being employed is
LI_TRIANGULATE_MAX_EDGE_LENGTH,
then the code will repeat the same 3-step loop, until every polygon
edge is no longer than the primitive's relevant
LI_MESH_CRIT_MAX_EDGE_LENGTH value.
Having succeeded in disposing of all edges which are too long, the routine will quit.
\end{itemize}
Example |
/*
* triangulate. Ensure result is Constrained
* Delaunay Triangulation
*/
data = LiDataCreate();
ref = LiMeshingRefinementCreate();
LiDataSetEnum(data, LI_EDGE_SWAP_ALL);
LiMeshingRefinementSetCriterion(ref,
LI_MESH_CRIT_EDGE_SWAPPING,
data)
LiDataSetGenericPtr(data, ref);
LiControlSet( LI_CONTROL_MESHING_REFINEMENT, data);
LiPrimitiveTriangulate(prim, LI_TRIANGULATE_SIMPLE);
| See Also |
LiPrimitiveHierarchicalTriangulate
LiPrimitiveSetMeshingRefinement
LiMeshingTriProperties
LiMeshingEdgeSwap
LiMeshingEdgeSplit
LiMeshingInsertBridge
|
Copyright © 1990-1998, 1999 LightWork Design Limited. All rights reserved
| |