|
||||||
|
AVS TechnoteInterpreting GEOM Edit ListsThis note is intended to be used by programmers that want to input geometric data. The current interface is both cumbersome and poorly defined. We hope to refine this interface in a future version of AVS will retain compatibility with old modules. As documented in the developers guide, the data type that is passed around for geometry is called an edit list. This data structure is a linked list of changes that should be made to the current object description. Note that this differs from most data types in that it generally requires that the downstream module maintain some state about previous changes that have been made. An edit list can contain changes to both geometry (lines, polygons etc.) and attributes (colors, matrices etc). The basic structure of an edit list is found in geom.h: typedef struct _GEOMedit_list {
GEOMedit *l;
} *GEOMedit_list;
It is simply a pointer to a linked list of edit structures. An edit structure is found below: typedef struct _GEOMedit {
int type;
char *data;
char *name;
int size; /* If it is a generic value, this is valid */
struct _GEOMedit *next;
} GEOMedit;
The type field is an integer that defines the type of the change. Since this structure is generally not accessed by programmers, the values for this type are not found in any include files that are supplied. A list of all of the valid types is: #define GEOM_EDIT_GEOMETRY 0 #define GEOM_EDIT_SET_MATRIX 1 #define GEOM_EDIT_CONCAT_MATRIX 2 #define GEOM_EDIT_COLOR 3 #define GEOM_EDIT_RENDER_MODE 4 #define GEOM_EDIT_VISIBILITY 5 #define GEOM_EDIT_LIGHT 6 #define GEOM_EDIT_PROPERTIES 7 #define GEOM_EDIT_PARENT 8 #define GEOM_EDIT_TRANSFORM_MODE 9 #define GEOM_EDIT_SELECTION_MODE 10 #define GEOM_EDIT_CENTER 11 #define GEOM_EDIT_POSITION 12 #define GEOM_EDIT_WINDOW 13 #define GEOM_EDIT_TEXTURE 14 #define GEOM_EDIT_PROJECTION 15 There is a one-to-one correspondance between these names and the GEOMedit... routines described in the documentation. The data field of an edit structure is a pointer to an edit-specific piece of information. For the routine: GEOMedit_geometry, the data is a pointer to a GEOMobj structure. (see documentation note below for accessing GEOMobj structures). For a matrix edit routine, it is a pointer to a 4x4 array of floats. The name field is the name of object, camera or light that is being changed. For all edit's except for edit geometry, the size field contains a value indicating the number of bytes pointed to by the data pointer. Instead of traversing the edit list manually, programs normally use the routine: GEOMprocess_edit_list(edit_list) GEOMedit_list edit_list; It takes a pointer to an edit_list structure and traverses it. For each edit list entry, a user-supplied routine is called with: (*function)(name,data) char *name; char *data; Where function is your function, name is the name of the value of the name field of the edit structure, and data is the value of the data field for the structure. A different function will be called for each type of edit that you have. This function is set by calling a routine of the form: GEOMset_new_XXX_func where "XXX" is the name of the type of edit. For example, the routine: GEOMset_new_geometry_func(foobar) would set foobar as the function to call when we encounter a geometry edit in the list. This call needs to be made only once for a particular process using the GEOM library. The other GEOMset_new... functions are: GEOMset_new_geometry_func(func) GEOMset_new_matrix_func(func) GEOMset_new_light_func(func) GEOMset_new_properties_func(func) GEOMset_concat_matrix_func(func) GEOMset_new_color_func(func) GEOMset_new_render_mode_func(func) GEOMset_new_visibility_func(func) GEOMset_new_parent_func(func) GEOMset_new_transform_mode_func(func) GEOMset_new_selection_mode_func(func) GEOMset_new_center_func(func) GEOMset_new_position_func(func) GEOMset_new_projection_func(func) GEOMset_new_window_func(func) GEOMset_new_texture_func(func) Often a module will want to simply process the values of geometries and ignore the other values. This can be done by calling first GEOMset_new_geometry_func and then calling: GEOMprocess_edit_list. The function argument to GEOMset_new_geometry_func will be called once for each geometry in the list. The difficult part comes when you try and interpret the GEOMobj object that is an argument to this function. The GEOMobj structure is defined in geom.h. The GEOM package defines the raw geometric information that is displayed. It defines 5 types of geometric objects: GEOM_POLYTRI (polytriangle, disjoint lines and polylines), GEOM_MESH (2D arrays of vertices), GEOM_POLYHEDRON (list of vertices with another list of indices into those vertices), GEOM_SPHERE (list of sphere centers, radii), GEOM_LABEL (list of annotation text objects with attributes such as font). You can make your life somewhat easier off the bat by converting the GEOM_MESH and GEOM_POLYHEDRON objects into GEOM_POLYTRI objects. This is done with the GEOM routines: GEOMcvt_mesh_to_polytri and GEOMcvt_mesh_to_polyh. See the GEOM documentation for details. It is necessary to know a little about the GEOM data structures. The basic data structure that you need to deal with is the GEOMobject. It's type definition is: typedef struct _GEOMobj {
int type; /* Object type */
int data; /* Vertex data that this object has (normals and vertices) */
float extent[6];
int has_extent;
char *name, *filename;
char *groupname;
GEOMval *vals; /* Pointer to a list of name/value pairs */
int nvals;
union { /* An objects internal bits */
GEOMmesh m;
GEOMpolyh ph;
GEOMpolytri pt;
GEOMsphere sp;
GEOMlabel la;
} d;
int refcnt;
} GEOMobj;
The type field can be one of: GEOM_POLYTRI, etc. indicating the object type. The data field can have the bit values: #define GEOM_NORMALS 1 #define GEOM_VCOLORS 2 #define GEOM_UVS 4 #define GEOM_UVWS 8 If data has the bit GEOM_NORMALS, then all vertices in the object (that aren't lines) will have normals associated with them. If data has the bit GEOM_VCOLORS, then all vertices have colors associated with them. All vertex lists in GEOM are set up to have an optional associated color list. When this list is defined, these colors should override the surface color attribute in defining the color for the object. There currently is no facet data in GEOM. The flags GEOM_UVS and GEOM_UVWS only are used for texture mapping and whether the object has texture mapping information for 2D and 3D texture maps. The particular member of the union for the type of object that you have contains the geometric data for the object. The polytriangle object is as follows: typedef struct _GEOMpolytri {
int npts; /* Number of polytris */
GEOMvert_list *ptverts; /* Polytriangle data */
GEOMvert_list *ptcolors;
GEOMvert_list *ptnormals;
GEOMscalar_list *ptuvs;
int npls; /* Number of polylines */
GEOMvert_list *plverts; /* Polyline data */
GEOMvert_list *plcolors;
GEOMvert_list dlverts; /* Disjoint line data */
GEOMvert_list dlcolors;
} GEOMpolytri;
npts indicates the number of polytriangle strips in the object. Each strip is a list of vertices where vertices 0, 1, 2 form the first triangle, vertices 1, 2, 3 form the second triangle etc. The array: ptverts contains the vertex information for all of the strips. It is an array of GEOMvert_list which is defined as: . typedef struct _GEOMvert_list {
int alloced_size;
int n;
float *l;
} GEOMvert_list, GEOMscalar_list;
The value n is the number of vertices in the polytriangle strip, the pointer l points to the first vertex. l points to a list of vertices in the form: XYZ. The following code fragment demonstrates how to get at the vertices in a polytriangle object: GEOMobj *gobj;
int i;
/* For each polytriangle strip */
for (k = 0; k < PT(gobj).npts; k++) {
/* For each vertex in a polytriangle */
for (i = 0; i < PT(gobj).ptverts[k].n; i++) {
printf("X is: %f, Y is %f, Z is %f\n",
PT(gobj).ptverts[k].l[3*i],PT(gobj).ptverts[k].l[3*i+1],
PT(gobj).ptverts[k].l[3*i+2]);
}
}
Normals and colors are accessed in a similar way. The GEOM_POLYTRI geom object contains an array of polytriangle strips an array of polylines, and a set of disjoint lines. The value npls is the number of poly or connected lines. Each connected line consists of a list of vertices where the first line is formed by vertices 0 and 1, the second line by vertices 1 and 2 etc. The fields plverts is an array of the vertex lists for each of the polylines. The dlverts field contains a list of vertices that form a set of disjoint lines. A disjoint line is a list of vertices where the first line is formed by vertices 0 and 1, the second by 2 and 3. Unlike the polylines and polytriangles, there is only a single list of disjoint line vertices in a poltriangle object. The polytriangle object can contain both surface and wireframe information. The polytriangle object is unique in this respect. Other objects are defined such that their surface description implies an accurate wireframe description -- the wireframe description implied by the polytriangle strip represents the outlines of the object as triangles where the original database could have been quadrilaterals for example. There is also an opportunity for eliminating edges that are shared by two polygons if you create a separate wireframe represetation for an object resulting in a much more efficient data base. As a result, when a polytriangle object has both a wireframe and a surface description, it is assumed that the wireframe description is an alternate representation for the same object as the surface description. If the rendering mode of the object is wireframe, we draw the polylines and disjoint lines, if the rendering mode is surface, we draw the polytri strip representation. If the object has only a wireframe description, you should draw the wireframe description regardless of what the mode is. If the object has only a surface description, you should draw the surface description for surface modes and use the implied description for the wireframe case (treat the polytriangle strips as lines). Of the GEOM objects, the GEOM_POLYTRI is the most confusing. If you understand this type, the others will probably be easier to understand. The mesh object contains a single list of vertices which is a 2 dimensional array of vertices. The two dimensions are indicated as fields m and n in the structure. The polyhedron objects are implemented as a single list of vertices and a polygon index list. The polygon index list is a single array of integers that define an array of polygons. The first value, n, in this array is the number of vertices in the first polygon. The next n integers are indices into the vertex list selecting the vertices in the polygon. Note that the indices are "1" based, not zero based (i.e. 1 refers to the first vertex in the list). The GEOM_LABEL objects basically consist of three main components: a list of NULL terminated character strings (serving as the labels), a corresponding list of base points for those character strings, label attributes indicating the method for drawing the labels. The label attributes can either be defined for the entire GEOMobj or can be per-label. The routine: GEOMget_label_flags(obj,vert) GEOMobj *obj; int vert; can be used to hide the distinction between the two. Given the GEOMobj obj the value n, it returns the label flags for the "n"th label. The label flags for a particular label is a single integer that is a bitmask indicating the properties of the label. The values for this bitmask are: #define GEOM_LABEL_STROKE 0x100 If this flag is set, the font should be drawn in stroke mode (where the label is essentially treated as a line object that is rotated and scaled with the transformation matrix). This mode is not required and tends only to be implemented when the underlying graphics library makes it easy. #define GEOM_LABEL_DROPSHADOW 0x400 This is another (very) optional label attribute. If this flag is set, a black label is drawn down and to the right one pixel before the real label is drawn. This helps labels stand out from a background that is the same color as the label. #define GEOM_LABEL_ABSOLUTE 0x800 If this value is defined, the basepoint should not be transformed by the transformation matrix of the object. It should be drawn in a screen coordinate system where -1,-1 is the lower right hand cornder and 1,1 is the upper left hand corner. This mode corresponds to the Title label attribute. #define GEOM_LABEL_CENTER 0x1000 #define GEOM_LABEL_RIGHT 0x2000 #define GEOM_LABEL_LEFT 0x4000 These flags are used to indicate the position of the base point relative to the text string. GEOM_LABEL_LEFT means that the base point should be located at the left hand edge of the text string. #define GEOM_LABEL_HIGHLIGHT 0x10000 This value is used to highlight the current label. This can vary from implementation to implementation. Some systems put "[ ]" around the text string, some draw a red box around it. #define GEOM_FONT_NUMBER(A) This macro can be used where A is the label flags. It returns a device specific number that determines the font to use. The mapping of numbers to font names is handled in the device specific porting layer routine that you write called: OBJ_lib_inq_fonts.
| |||||