Compute_Optimized_Shell

Functions

void Compute_Optimized_Shell (int pcount, const HC_POINT *points, const HC_VECTOR *normals, int flist_length, const int *face_list, const char *options, int *new_pcount, HC_POINT *new_points, int *new_flist_length, int *new_face_list, int *point_mapping_list, int *face_mapping_list)
 Performs one of several computations to prepare shell data for improved rendering performance. The default computation is to remove redundant vertices and degenerate faces. More...
 
void DCompute_Optimized_Shell (int pcount, const HCD_POINT *points, const HC_POINT *normals, int flist_length, const int *face_list, const char *options, int *new_pcount, HCD_POINT *new_points, int *new_flist_length, int *new_face_list, int *point_mapping_list, int *face_mapping_list)
 Similar to Compute_Optimized_Shell(), but computes and returns double-precision values. More...
 

Detailed Description

Function Documentation

◆ Compute_Optimized_Shell()

void Compute_Optimized_Shell ( int  pcount,
const HC_POINT *  points,
const HC_VECTOR *  normals,
int  flist_length,
const int *  face_list,
const char *  options,
int *  new_pcount,
HC_POINT *  new_points,
int *  new_flist_length,
int *  new_face_list,
int *  point_mapping_list,
int *  face_mapping_list 
)

Performs one of several computations to prepare shell data for improved rendering performance. The default computation is to remove redundant vertices and degenerate faces.

Parameters
pcount- Number of valid points in points.
points- Vector of x-y-z triplets for the coordinates of the vertices that could be used to build the shell. (A simple N = 3 array can also be used.) Passed by reference always.
normals- Sequential list of vertex normals, x-y-z triplets. It is legal to pass NULL for this parameter, in which case normal information will be ignored. If non-NULL, however, the normals are assumed to be normalized to length 1. Passed by reference always.
flist_length- Total number of integers in face_list.
face_list- Encoded description of how to connect the points to build the faces of the shell. Passed by reference always.
options- A quoted string or a string variable containing a list of desired options. Passed by reference always.
new_pcount- Number of valid points in new_points after computation. Returned to caller. Passed by reference always.
new_points- Vector of x-y-z triplets for the coordinates of the non-redundant vertices that could be used to build the shell. (A simple N = 3 array can also be used.) Returned to caller. Passed by reference always.
new_flist_length- Total number of integers in computed new_face_list. Returned to caller. Passed by reference always.
new_face_list- Encoded description of how to connect the points to build the faces of the computed shell. Returned to caller. Passed by reference always.
point_mapping_list- Mapping of vertices from the original point list to the vertices in the new (computed) point list. In other words, for each old vertex i, point_mapping_list[i] represents the vertex in the new shell to which it has moved. Eliminated points are mapped to -1. Returned to caller. Passed by reference always.
face_mapping_list- Mapping of faces from the original face list to the new (computed) face list. In other words, for each old face j, face_mapping_list[j] represents the vertex in the new shell to which it has moved. Eliminated faces are mapped to -1. Returned to caller. Passed by reference always.

DETAILS

The HOOPS routine Insert_Shell() accepts a set of points, an encoded description of how to connect the points to form the faces of a shell. Insert_Shell() performs no interrogation of the data received. It has no provision for eliminating redundant points nor for ignoring disconnected points. Compute_Optimized_Shell() accepts data normally used to insert a shell and returns a new set of data with redundancies and discontinuities removed. This new data can then be used to insert a shell. The arrays point_mapping_list and face_mapping_list are available to help you refer to the new data, if given indices to the original data.

Programs designed to work with geometric modelers often receive geometry in a stream. This means they cannot ascertain the overall connectedness of a shell's faces. For instance, to define a diagonally-split quadrilateral using two faces, one needs only four vertices, with two of them referenced twice. While it is geometrically correct to redefine the "re-used" vertices, for a total of six, face-connectivity information is lost. This is because duplicated points, though equivalent, are still distinct—each face has its "own" vertices. Compute_Optimized_Shell() recaptures the connectivity by eliminating the duplicated vertices and forcing faces to share the remaining unique vertices.

Faces that refer to fewer than three unique vertices are eliminated.

Since shells are arbitrary collections of faces, Compute_Optimized_Shell() can be used to convert a group of polygons into a coherent shell. The advantage is less data must be sent to HOOPS. Performance is improved since fewer points must be transformed and clipped.

Compute_Optimized_Shell() does not allocate memory for you. All arrays passed to it must contain adequate storage.

The following choices are recognized for options:
fix handedness

This option is a convenience for converting a minority of faces to the handedness comprising the majority.
Determines the handedness of the majority of faces, and reverses the winding of the minority faces. Returns facelist data to the caller. Shell data is modified in no other way. Mutually exclusive to options "fix handedness", "skin", and "lod".

This option will also fix the special winding of holes (and nested holes) in shell faces also. A limitation of fixing face handedness is that we cannot do better than the "majority wins" method for the general case.

reverse handedness

This option is a convenience for reversing the winding of shell faces if the option "fix handedness" gives you an inside-out shell and you prefer not to change the appearance with the Heuristic "polygon handedness".

Reverses the winding of each face in the facelist provided. Returns facelist data to the caller. Shell data is modified in no other way. Mutually exclusive to options "fix handedness", "skin", and "lod".

It should not be necessary to pass in point data.
[no] [level of detail | lod] [ = xx% ]

Causes Compute_Optimized_Shell to abandon the normal redundant-vertices calculation in favor of calculating a Level of Detail (LOD). Any other choice will cause the shell to be reduced using shell simplification instead of the standard code path. The default reduction when LOD is turned on is 50%. If a percentage is specified in the form of xx%, the number of triangles in the model will be reduced to to the given percentage of the original model. The options "skin" and "lod" are mutually exclusive.

The new point count is guaranteed not to be larger than the original, so the original length can be used as upper bounds for allocation. The same goes for the facelist if the input is triangles. If quads (or polygons of higher order) are provided, then the output facelist may be larger. This is because our LOD algorithm outputs triangles only.

With quad input and level of detail = 100%, we will output double the faces. Triangle faces have 4/5 the number of integers that quad faces do, so we don't need to double the facelist alloc size, rather multiply it by 1.6. This factor shrinks by user-provided level of detail. For example, with quad face input and level of detail = 75%, the new facelist alloc size becomes 1.6*0.75 = 1.2x original.

Generally, for turning n-gon data into a LOD shell with level of detail x, you are safe if you alloc an array of size (Original_FaceList_Length * 4*(n-2)/(n+1) * x).

Alternatively, you can safely run Optimize twice – first just to generate the facelist length (no array passed in), next with the array after your accurately sized alloc. This, however will take more cpu time.

Not set by default.
lod algorithm = [fast | nice]

Use the fast-LOD algorithm, with some visual quality degradation, or the "nice" LOD algorithm, with extra generation time but a better representation. Default is "fast". Default is "fast", but only applies if the "lod" option is used.
[no] orphan elimination

If this option is set, points that are not referenced by any face are removed. The default is "orphan elimination".
[no] skin

Particularly geared towards the needs of the finite element analysis community, this option causes Compute_Optimized_Shell() to abandon its normal goal of merging nearby vertices in favor of extracting the exterior surface from shells that also have interior vertices and faces. This special computation mode works its magic by looking for pairs of faces that reference 3 or more of the same vertex indices. If coincident vertices are not shared for adjacent faces, this computation will not do anything (though running the standard form of Compute_Optimized_Shell() on the data first would solve that problem. The options, "skin" and "lod" are mutually exclusive. When "skin" mode is used only "orphan elimination" has any meaning – the rest are ignored. As usual, the new face list length and new point count are guaranteed not to be larger than the original, so the original lengths can be used as upper bounds for allocation. Not set by default.
[no] tolerance [= nnn oru / nnn % fru]

"Tolerance" controls the identification of duplicate points. If a specification is given in object-relative units (oru), then the points that are separated by a distance less than this value are considered equal.

Often, one cannot ascertain a "good" value for an object-relative tolerance. In this case, specify the tolerance using "feature-relative units (fru)". Feature size is defined to be the smallest non-zero distance between any two adjacent vertices on any face. It is calculated internally by Compute_Optimized_Shell() , and is constant for the entire collection of faces. The feature-relative tolerance is expressed as a percentage of this minimum distance. A setting less than "tolerance = 100% fru" guarantees that unequal vertices on a single face won't be eliminated.

"No tolerance" is the same as "tolerance = 0 oru".

The default is "no tolerance".
[no] normal tolerance [= nnn deg / nnn rad / nnn]

"Normal Tolerance" also controls the identification of duplicate points. Points which have an angular difference greater than the specified normal tolerance are assumed to be unique.

"no normal tolerance" is the same as "normal tolerance = 0 deg".

The default is "no normal tolerance".

[no] collapsible [= <defined callbackname>]

This option enables the user to replace the default distance measure, euclidian distance, with their own function to determine whether any given two nearby points should be merged or not. While it was originally designed to accept normals as its primary information, any sort of pointer that is passed as normals in the call to Compute_Optimized_Shell will be passed through to the callback.

NOTES

If you are not interested in the mapping lists, pass a null pointer for either the point_mapping_list or the face_mapping_list. If you are not interested in using normal information as a criterion for collapsing points, pass a null pointer for normals.
This function replaces Compute_Minimized_Shell() , which is now obsolete.
It is not legal to pass the same pointer for both input and output.
EXAMPLES
The following example demonstrates passing a struct pointer in place of normals.


    typedef struct {
        /* contents of this structure are unrestricted */
        float   myparam1,  myparam2;
    } optimized_shell_passthru;

    /* returns 1 if points a and b are collapsible -- 
       0 if points a and b are not collapsible */
    int are_collapsible_callback ( 
    void *pts_in, 
    void *norms_in, 
    int a, 
    int b,  
    double tolerance_squared,  
    double  normal_distance_squared )
    {
        optimized_shell_passthru *info= (optimized_shell_passthru *) norms_in;
        /* use info to do any test here, and return the result */
    }

    /* and this is how the function is called */
    optimized_shell_passthru info = { a, b, etc. };
    HC_Define_Callback_Name( "are_collapsible_callback", are_collapsible_callback );
    HC_Compute_Optimized_Shell(
        in_point_count, in_points,
    (void *)(&info),
        in_face_list_length, in_face_list,
        "collapsible = are_collapsible_callback",
        &out_point_count, out_points,
        &out_face_list_length, out_face_list,
        vertex_mapping, face_mapping
    );

The following example demonstrates using the vertex_mapping array to copy attributes from the old shell to the new one. Two things to note from this example:

  • a) that the check for "vertex_mapping >= 0" really is necessary, since unreferenced vertices from the original shell have vertex_mapping entries set to "-1"; and
  • b) that performance could be improved if the normals from the original shell were available a priori in an array so that the vertices did not have to be individually opened.
  • c) vertices in the new shell can potentially be touched more than once.


    HC_Show_Shell( old_key, &point_count, points, &face_list_length, face_list );
    HC_Compute_Optimized_Shell(
        &point_count, points, NULL,
        &face_list_length, face_list,
        "",
        &new_point_count, new_points, 
        &new_face_list_length, new_face_list,
        vertex_mapping, face_mapping
    );
    new_key = HC_Insert_Shell( new_point_count, new_points, new_face_list_length, new_face_list );
    for( i = 0 ; i < point_count ; i++ ) {
        HC_Open_Geometry( old_key );
            HC_Open_Vertex( i );
                HC_Show_Normal( &x, &y, &z );
            HC_Close_Vertex();
        HC_Close_Geometry( );
        if( vertex_mapping[i] >= 0 ) {
            HC_Open_Geometry( new_key );
                HC_Open_Vertex( vertex_mapping[i] );
                    HC_Set_Normal( x, y, z );
                HC_Close_Vertex();
            HC_Close_Geometry( );
        }
    }



RESTRICTIONS

See also
Insert_Shell, Show_Shell, Show_Shell_Size.

◆ DCompute_Optimized_Shell()

void DCompute_Optimized_Shell ( int  pcount,
const HCD_POINT *  points,
const HC_POINT *  normals,
int  flist_length,
const int *  face_list,
const char *  options,
int *  new_pcount,
HCD_POINT *  new_points,
int *  new_flist_length,
int *  new_face_list,
int *  point_mapping_list,
int *  face_mapping_list 
)

Similar to Compute_Optimized_Shell(), but computes and returns double-precision values.

Parameters
pcount- Number of valid points in points.
points- Vector of x-y-z triplets for the coordinates of the vertices that could be used to build the shell. (A simple N = 3 array can also be used.) Passed by reference always.
normals- Sequential list of vertex normals, x-y-z triplets. It is legal to pass NULL for this parameter, in which case normal information will be ignored. If non-NULL, however, the normals are assumed to be normalized to length 1. Passed by reference always.
flist_length- Total number of integers in face_list.
face_list- Encoded description of how to connect the points to build the faces of the shell. Passed by reference always.
options- A quoted string or a string variable containing a list of desired options. Passed by reference always.
new_pcount- Number of valid points in new_points after computation. Returned to caller. Passed by reference always.
new_points- Vector of x-y-z triplets for the coordinates of the non-redundant vertices that could be used to build the shell. (A simple N = 3 array can also be used.) Returned to caller. Passed by reference always.
new_flist_length- Total number of integers in computed new_face_list. Returned to caller. Passed by reference always.
new_face_list- Encoded description of how to connect the points to build the faces of the computed shell. Returned to caller. Passed by reference always.
point_mapping_list- Mapping of vertices from the original point list to the vertices in the new (computed) point list. In other words, for each old vertex i, point_mapping_list[i] represents the vertex in the new shell to which it has moved. Eliminated points are mapped to -1. Returned to caller. Passed by reference always.
face_mapping_list- Mapping of faces from the original face list to the new (computed) face list. In other words, for each old face j, face_mapping_list[j] represents the vertex in the new shell to which it has moved. Eliminated faces are mapped to -1. Returned to caller. Passed by reference always.

DETAILS

No additional details. See Compute_Optimized_Shell().