TOC PREV NEXT INDEX

The Graphics Display Kit




6 Geometry API User Guide

This chapter discusses the Express Geometry API, a set of language specific APIs that provide C and C++ programmers with a simple mechanism to create standard geometry types such as lines, polygons, and spheres.

6.1 Introduction

Previously in AVS/Express if module writers wish to create such geometry they need to have a good knowledge of the AVS/Express Unstructured Field, a complicated structure, requiring a relative degree of expertise to use. The Geometry API provides module writers with a much simpler way of generating geometry.

The Express Geometry API keeps a state of the geometry that it has created. This will allow full "dynamic editing" of geometry. Users will be able to dynamically update previously created geometry with the minimal amount of effort.

6.2 Fundamentals

The process of creating geometry using the Express Geometry API can be divided into two distinct stages. The first stage involves creating geometric primitives and general object attributes. This has been implemented in Express as a "stand alone" library and maintains its own independent geometric data representation. The two fundamental structures generated are the Edit List (GEOMedit_list) and Geometry Object (GeomObj). These are discussed in more detail in the next section.

The second stage can be described as the conversion stage. The GEOMedit_list and GeomObj, created during stage one, need to be converted to a format recognized by Express. Once converted these structures need to be exposed to Express's Object Manager, allowing the geometry to be fully integrated into Express object environment. This conversion stage is discussed in more detail in section 4.

6.3 Creating Geometry

The Geometry API allows module writer's to construct a scene tree. An scene tree consists of a hierarchy of named objects. Each object in the scene tree has a list of geometry primitives (GeomObjs), a list of child objects, and a set of attributes that can either be defined for this object, or inherited from the object's parent. An object also has a single parent object that defines where it fits into the object hierarchy.

A GEOMedit_list is used to construct and modify scene trees. Each entry in the GEOMedit_list pertains to a particular object in the scene tree. An entry can contain geometry primitives (GeomObj), other object attributes or some other scene graph editing information; for example the entry may declare an object's parent object. Before we describe the GEOMedit_list in any detail we will look at what fundamentally defines each scene object, namely its' geometry primitives, the GeomObjs.

GeomObjs

GeomObj are the building blocks through which you can create geometric scenes in Express. Each scene tree object is composed of one or more GeomObjs. There are five fundamental types of GeomObjs:

Meshes

Polygons

Polytriangles

Spheres

Labels

Each of these primitive types is described below. Following these descriptions, in section 3.1.1, is a listing of the API routines that are used to create and modify GeomObjs. A complete description can be found in Appendix A. Finally a simple example is provided demonstrating how a GeomObj is created.

Mesh Objects

The mesh object type contains a 2D array of vertices ordered such that adjacent vertices in the array are connected. If the dimensions of the 2D vertex array are MxN, a mesh object forms (M-1)*(N-1) quadrilaterals. A single quadrilateral is a simple mesh object with M=N=2.

Polyhedron Objects

A polyhedron object contains a 2D (number of vertices x 3) array specifying the X, Y, and Z coordinates of each vertex and a separate list of connectivity information. The connectivity list is a 1D array of integers. The first integer in the list (call it n) contains the number of vertices in the first polygon of the polyhedron. Following this integer are n consecutive integers (beginning with 1) representing the element in the vertex array that corresponds to the respective vertex data. The last index of the first polygon is followed by an integer representing the number of vertices in the second polygon. This pattern continues until the value of n is zero, which terminates the list. The following example shows the contents of the connectivity list used to describe a polyhedron containing two polygons, one with four vertices and the second with five vertices.

Connectivity list: {4, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 0}

The index values in the connectivity list are "1 based". This makes no difference to the C programmer because AVS interprets the index "1" to indicate the first vertex in the vertex array.

The object types mesh and polyhedron contain an implied surface and wireframe description of the geometry that they represent. For the mesh object, the wireframe description is a 2D array of lines across the rows and columns of the mesh. For the polyhedron object, the wireframe description of the object is formed by the edges of each polygon in the object.

In AVS, the primary object types used to create surface descriptions of geometric objects are the mesh and polyhedron object types. You can easily create a third common description of polygonal data, disjoint polygons, using the "polyhedron" object type. This library provides routines to make this conversion easy.

Polytriangle Objects

Certain rendering platforms can make use of the shared vertices in adjacent polygons to improve the efficiency of rendering. For this reason, we have added a third primitive that represents surface information, the polytriangle strip. In a polytriangle strip, each vertex makes a triangle with the previous two vertices. For a list of N vertices, there are N-2 triangles. If your object is such that each vertex is shared by a number of different triangles and your hardware is most efficient at rendering this type of primitive, the polytriangle strip can be the most efficient description in which to represent your object. The geom library provides routines to convert objects from the mesh and polyhedron primitive types into the polytriangle primitive.

Note that since the polytriangle primitive can only represent triangles, it does not normally contain information necessary for providing an appropriate wireframe description of an object. If we have an object made up entirely of quadrilaterals and used the polytriangle representation as our wireframe description of the object, AVS would naturally draw edges in our object that should not be drawn. For this reason, the polytriangle object type contains both a wireframe and a surface description of the object. If the rendering mode is "lines" the geometry viewer uses the wireframe description, if it is "surface", it uses the surface description.

The surface description is an array of polytriangle strips (where each strip is a single array of connected triangles). The wireframe description contains an array of connected lines and an array of disjoint lines. Each connected line is a single array of vertices such that each vertex draws a line to the previous vertex. If a connected line has N vertices, it contains N-1 lines. The array of disjoint lines contains an even number of vertices such that each successive pair of vertices forms a line. If there are N vertices in a disjoint line, there are N/2 lines.

Usually, the polytriangle strip is not the best choice for representing surface data. It can be efficient for representing objects that have only wireframe information, however. If an object has only wireframe information AVS draws these lines even if the rendering mode is set to surface.

Sphere Objects

The sphere object is used to represent objects that contain a list of spheres or dots. Spheres have a radius as well as a location. Dots are represented as spheres without any radius information.

Label Objects

Label objects are used to represent text that generally annotates or titles other geometric data. There are three classes of labels: annotation labels, titles, and "stroke" labels. Titles have a location in screen coordinates and are not transformed by either the camera or the object's transformation. Annotation labels are transformed with geometry but are always parallel to the screen plane. Stroke text is transformed like geometry, however, it is not supported on all platforms.

Routine Listing

The following list of GEOM routines is organized by functional category, see Appendix A for a complete description.

Object Creation Routines

GEOMadd_disjoint_line(obj, verts, colors, n, alloc)
GEOMadd_disjoint_polygon(obj, verts, normals, colors, nverts, flag, alloc)
GEOMadd_disjoint_prim_data(obj, pdata, n, alloc)
GEOMadd_disjoint_vertex_data(obj, vdata, n, alloc)
GEOMadd_float_colors(obj, colors, n, alloc)
GEOMadd_int_colors(obj, colors, n, alloc)
GEOMadd_label(obj, text, ref_point, offset, height, color, label_flags)
GEOMadd_normals(obj, normals, n, alloc)
GEOMadd_polygon(obj, nverts, indices, flags, alloc)
GEOMadd_polygons(obj, plist, flags, alloc)
GEOMadd_polyline(obj, verts, colors, n, alloc)
GEOMadd_polyline_prim_data(obj, pdata, i, n, alloc)
GEOMadd_polyline_vertex_data(obj, vdata, i, n, alloc)
GEOMadd_polytriangle(obj, verts, normals, colors, n, alloc)
GEOMadd_polytriangle_prim_data(obj, pdata, i, n, alloc)
GEOMadd_polytriangle_vertex_data(obj, vdata, i, n, alloc)
GEOMadd_prim_data(obj, pdata, n, alloc)
GEOMadd_radii(obj, radii, n, alloc)
GEOMadd_vertex_data(obj, pdata, n, alloc)
GEOMadd_vertices(obj, verts, n, alloc)
GEOMadd_vertices_with_data(obj, verts, normals, colors, n, alloc)
GEOMcreate_label(extent, label_flags)
GEOMcreate_label_flags(font_number, title, background, drop, align, stroke)
GEOMcreate_mesh(extent, verts, m, n, alloc)
GEOMcreate_mesh_with_data(extent, verts, normals, colors, m, n, alloc)
GEOMcreate_obj(type, extent)
GEOMcreate_polyh(extent, verts, n, plist, flags, alloc)
GEOMcreate_polyh_with_data(extent, verts, normals, colors, n, plist, flags, alloc)
GEOMcreate_scalar_mesh(xmin, xmax, ymin, ymax, mesh, colors, n, m, alloc)
GEOMcreate_sphere(extent, verts, radii, normals, colors, n, alloc)
GEOMdestroy_obj(obj)
GEOMget_font_number(name, bold, italic)
Object Utility Routines
GEOMauto_transform(obj)
GEOMauto_transform_non_uniform(obj)
GEOMauto_transform_list(objs, n)
GEOMauto_transform_non_uniform_list(objs, n)
GEOMcreate_normal_object(obj,scale)
GEOMctv_mesh_to_polytri(tobj, flags)
GEOMcvt_polyh_to_polytri(tobj, flags)
GEOMflip_normals(obj)
GEOMgen_normals(obj, flags)
GEOMnormalize_normals(obj)
Object Texture-Mapping Routines
GEOMadd_polytriangle_uvs(obj, uvs, i, n, alloc)
GEOMadd_uvs(obj, uvs, n, alloc)
GEOMcreate_mesh_uvs(obj, umin, vmin, umax, vmax)
GEOMdestroy_uvs(obj)
Object File Utilities
GEOMread_obj(fd, flags)
GEOMread_text(fp, flags)
GEOMwrite_obj(obj, fd, flags)
GEOMwrite_text(obj, fp, flags)
Object Debugging Routines
GEOMcheck_obj(name, flags, func)

Example

The code fragment below shows a simple example of creating a polyhedron with 8 points and six faces making a cube:

/*
* 8 vertices of a cube
*/
static float Pts[8][3] = {
-0.75, -0.75, -0.75, 0.75, -0.75, -0.75, 0.75, 0.75, -0.75, -0.75, 0.75, -0.75,
-0.75, -0.75, 0.75, 0.75, -0.75, 0.75, 0.75, 0.75, 0.75, -0.75, 0.75, 0.75,
};
static int numPts = sizeof(Pts)/ (3*sizeof(float));
/*
* indices of the vertices defining the faces of the cube
*/
static int Faces[6][4] = { 4,3,2,1, 6,7,8,5, 2,3,7,6, 3,4,8,7, 5,8,4,1, 2,6,5,1 };
static int numFaces = sizeof(Faces)/ (4*sizeof(int));

GEOMobj *make_cube()
{
GEOMobj *obj;
int index;

/* create and initialize the PolyHedron GeomObj */
obj = GEOMcreate_obj(GEOM_POLYHEDRON,NULL);

/* add the 8 vertices */
GEOMadd_vertices(obj, (float*)Pts, numPts, GEOM_COPY_DATA);

/* add the 6 cube faces */
for (index = 0; index < numFaces; index++) {
GEOMadd_polygon(obj,4, Faces[index], 0,GEOM_COPY_DATA);
}

return obj;
}


GEOMedit_list

During each execution of a module, the module provides a list of changes that it wants made to the scene for that execution. This is accomplished via the GEOMedit_list. Changes are made in the order specified in the edit list. Any object that doesn't already exist is created the first time an attempt to change that particular object is made.

Express has routines that allow a module to change several properties of an object in an edit list:

The geometric data defining the object (geometry will be appended to rather than replacing existing geometry)

Surface or line color

Render mode (Gouraud, Phong, wireframe, etc.)

Parent (the name of the parent object)

Material properties

Transformation

Each time a module is invoked, it should start with an empty edit list. It places into the edit list changes that it wants to be made for this invocation. In creating and using edit lists and geometry objects, a module uses routines in the geom library. A module typically uses the following steps in preparing an edit list for output:

1. Initialize the edit list, using GEOMinit_edit_list. This creates a new list or empties an existing list.
2. Create and modify geometry objects, using routines in the geom library.
3. Modify the edit list, using routines whose names begin with GEOMedit in C (such as GEOMedit_geometry).

A module must deallocate an existing edit list before reusing the list. The module must deallocate this list at the start of each invocation of the module, normally by calling the GEOMinit_edit_list routine before modifying the list.

There is also a GEOMdestroy_edit_list call which destroys the edit list but does not create a new one. Once called, there is no longer a valid edit list to use the various GEOMedit... calls with. Hence, you can not call both GEOMdestroy_edit_list and GEOMinit_edit_list with the same pointer. You should only use GEOMdestroy_edit_list if you know that you will not be doing any more geometry outputs.

GEOMinit_edit_list Routines

The following is a list of GEOMedit_list for a full description see Appendix A.

GEOMdestroy_edit_list(list)
GEOMedit_backface(list, name, mode)
GEOMedit_center(list, name, center)
GEOMedit_color(list, name, color)
GEOMedit_concat_matrix(list, name, matrix)
GEOMedit_geometry(list, name, obj)
GEOMedit_parent(list, name, parent)
GEOMedit_position(list, name, position)
GEOMedit_properties(list, name, ambient, diffuse, specular, pec_exp, transparency, spec_col)
GEOMedit_render_mode(list, name, mode)
GEOMedit_selection_mode(list, name, mode, flags)
GEOMedit_set_matrix(list, name, matrix)
GEOMedit_subdivision(list, name, subdiv)
GEOMedit_transform_mode(list, name, redirect, flags)
GEOMedit_visibility(list, name, visibility)
GEOMedit_window(list, name, window)
GEOMinit_edit_list(list)
Example

The code fragment below creates three scene objects: a "cube", a "sphere" and a "diamond". The "sphere" and the "diamond" are both made children of the "cube". The scene tree of this object hierarchy is shown below in Figure 1.

GEOMedit_list create_edit_list()
{
float red[3], green[3], blue[3];
GEOMedit_list list = NULL;
GEOMobj *cube, *sphere, *diamond_big, *diamond_small;
GEOMobj *cube_label, *sphere_label, *diamond_label;

cube = make_cube();
cube_label = make_cube_label();
sphere = make_sphere();
sphere_label = make_sphere_label();
diamond_big = make_big_diamond();
diamond_small = make_small_diamond();
diamond_label = make_diamond_label();

list = GEOMinit_edit_list(list);

/* create scene object "cube" */
GEOMedit_geometry(list, "cube", cube);
GEOMedit_geometry(list, "cube", cube_label);
GEOMedit_color (list, "cube", red);

/* create scene object "sphere" */
GEOMedit_geometry(list, "sphere", sphere);
GEOMedit_geometry(list, "sphere", sphere_label);
GEOMedit_color (list, "sphere", green);

/* create scene object "diamond" */
GEOMedit_geometry(list, "diamond", diamond_big);
GEOMedit_geometry(list, "diamond", diamond_small);
GEOMedit_geometry(list, "diamond", diamond_label);
GEOMedit_color (list, "diamond", blue);

/* sphere is a child of cube */
GEOMedit_parent(list,"sphere","cube");

/* diamond is a child of cube */
GEOMedit_parent(list,"diamond","cube");

return list;
}
6.4 Converting Geometry

The conversion engine of the Express Geometry API is primarily responsible for converting GEOMedit_lists and GeomObjs to a format that can be understood by the Express Object Manager. Basically the Geometry API scene tree is mapped to a similar Object Manager DefaultObject scene tree.

Firstly let us consider the DefaultObjects, its structure will determine the exact nature of the mapping from the Geometry API scene tree and the Object Manager DefaultObject scene tree. Each DefaultObject contains:

Graphics Primitives

Colormap

Transforms

Properties

Children

At the heart of each DefaultObject is either a "Field" or a "LabelField". The "Field" is capable of holding differing multiple primitive sets, i.e. one "Field" can contain multiple sets of meshes, polygons, polytriangle and spheres. A "Field" cannot contain labels. A "LabelField" must be used to represent labels.

The GeomObj contains five graphics primitive types:

Mesh

Polyhedron

Polytriangle

Sphere

Label

For each scene tree object all of the GeomObjs containing Meshes, Polyhedron, Polytriangle and Spheres are converted into one Express "Field", and hence one DefaultObject. If the scene tree object contains any Label primitives these are converted into one separate Express "LabelField", and hence into a separate DefaultObject. Consider how the scene tree in the previous section would be mapped as shown below in Figure 2.

Because full "dynamic editing" is supported, i.e. a module is capable of modifying existing geometry, the conversion engine must maintain a mapping database, to allow previously generated DefaultObject hierarchies to be updated. What happens, for example, if after creating the hierarchy in figure 2, the module is executed again and adds a red sphere and a square to the object named "diamond"? How is this mapped to the DefaultObject hierarchy? Although it would be possible to append the new geometry to the existing DefaultObject containing the small and large diamonds, it is much easier to create a new DefaultObject containing the new sphere and square geometry. The modified scene trees are shown below in Figure 3.

In this section we have discussed how new DefaultObject hierarchies are created from GEOMObjs. How are these "exposed" to the object manager? This is investigated in the next section.

Exposure to the Object Manager

The DefaultObject hierarchy, which is created from the GEOMedit_list, is dynamic; i.e. it is created at runtime. It needs to be attached to some "top level" DefaultObject which is static and known by the object manager, i.e. defined as part of a modules "V" definition. The diagram below shows two typical geometry generating modules:

Example one shows a "macro" based module and example two shows a "group" based module. Both modules define a "top level" DefaultObject as part of its V specification. Express modules using the Geometry API must specify a "top level" DefaultObject as part of its V specification. This will allow the module to be connected to a viewer, saved as part of an application in such a way that when the application is started geometry generated dynamically by the API will immediately be accessible outside the module.

In the next subsection we examine the Geometry API routines which enable GEOMedit_list to be converted to DefaultObject hierarchies and exposed externally to the Object Manager.

6.5 Geometry API conversion routines

As we saw earlier, an important feature of the new Geometry API is its ability to record the state of the geometry it has previously created, allowing module writers to dynamically update the geometry by simply creating a new edit list. This is accomplished by the use of what is called a "convertor". The module writer creates a convertor, identified by a unique id, which keeps track of the geometry that is created. In total five new conversion API calls are provided:

GEOMnew_convertor

GEOMstatus GEOMconvert_edit_list (int id , GEOMedit_list list)

GEOMstatus GEOMconvert_obj (int id , GEOMobj *obj , char *name)

GEOMstatus GEOMclear_convertor (int id)

GEOMstatus GEOMdelete_convertor (int id , int freeOMobjs)

GEOMnew_convertor
int GEOMnew_convertor (OMobj_id module_id , char *top_obj)
module_id

the object identifier of the module calling the routine

top_obj

the OM nameof the "top level" DefaultObject which geometry will be attached to

This routine creates a new convertor. A unique convertor identifier is returned. This identifier is used with all the other convertor routines to identify the convertor instance to use.

GEOMconvert_edit_list
GEOMstatus GEOMconvert_edit_list(int id , GEOMedit_list list)
id

the identifier of the convertor to use

list

the edit list to convert

This routine converts the edit list, using the convertor identified by id. If this is the first time the convertor is being used then a new DefaultObject hierarchy is created. If the convertor has been used previously the edit list will be applied to the existing DefaultObject hierarchy. Any new geometry will be appended to the scene tree.If successful GEOM_STAT_SUCCESS is returned.

GEOMconvert_obj
GEOMstatus GEOMconvert_obj (int id , GEOMobj *obj , char *name)
id

the identifier of the convertor to use

obj

the geometry object to convert

name

the scene tree object name

This routine converts the geometry object, using the convertor identified by id. The geometry object will be appended to the scene tree object identifier by name, if it does not exist it will be created. This is a convience routine, typically GEOMconvert_edit_list should be used. If successful GEOM_STAT_SUCCESS is returned.

GEOMclear_convertor
GEOMstatus GEOMclear_convertor( int id)
id

the identifier of the convertor to use

This routine resets the state of the convertor and destroys all DefaultObjects created. The convertor can subsequently be used to create new DefaultObject hierarchies. If successful GEOM_STAT_SUCCESS is returned.

GEOMdelete_convertor
GEOMstatus GEOMdelete_convertor( int id , int freeOMobjs)
id

the identifier of the convertor to use

freeOMobjs

flag

This routine destroys the convertor freeing up all internal memory. If freeOMobjs is set to zero then the DefaultObject Hierarchy is not destroyed. If freeOMobjs is set to one then the hierarchy is destroyed. If successful GEOM_STAT_SUCCESS is returned.

Header Files

The following include statement should be added to all C/C++ modules using the geometry API:

#include "avs/geomAPI.h"
The V file

When building a new express executable that includes modules that make use of the geomAPI, the following link option must be added to the module's V definition, see section 7.1 The "V" module definition.

<link_files="-lgeomAPI -lgeom">
6.6 Restrictions

There are a number of restrictions to the types of geometry and attribute data values that are actually converted. Section 6.1 looks at restrictions with respect to geometric primitive data. Section 6.2 looks at general edit list attribute restrictions.

Geometry Primitives

There are a number of restrictions regarding the conversion of geometric primitives. These are listed below:

Meshes and Polyhedron

In the current implementation of the Geometry API both the Mesh and Polyhedron will be pre-converted to Polytriangles before being finally converted to a "Field".

Labels

We saw earlier that for each scene object, Label primitives are converted into one separate Express "LabelField". This imposed some restrictions that are listed below:

offsets and heights can only be applied globally not to individual labels in the LabelField. The first labels offset will only be used, the rest will be ignored. This effects GEOMadd_label

label_flags can only be applied globally. Those defined for individual labels in GEOMadd_label are ignored. Only the global label_flags define in GEOMcreate_label are used.

There are several ways to avoid these restrictions. Labels with differing characteristics can be grouped into different named scene objects, creating separate LabelFields. Also if labels are added to the same named objects at different times, i.e. via different edit list, then again separate LabelFields are created.

Primitive data and vertex data

Certain types of geometric data will not be converted. Both primitive data and vertex data will be ignored. This effects the following API routines:

GEOMadd_polyline_prim_data(obj, pdata, i, n, alloc)
GEOMadd_polyline_vertex_data(obj, vdata, i, n, alloc)
GEOMadd_polytriangle_prim_data(obj, pdata, i, n, alloc)
GEOMadd_polytriangle_vertex_data(obj, vdata, i, n, alloc)
GEOMadd_prim_data(obj, pdata, n, alloc)
GEOMadd_vertex_data(obj, pdata, n, alloc)
Extents

Extents are ignored. This effects all geometry types.

Object Attribute

The call to GEOMedit_selection_mode has a restriction regarding the "notify" mode which has not been implemented. Setting the edit section to this mode will default to "normal".

FORTRAN API

This is currently no support for calling the Express Geometry API from FORTRAN.

6.7 Example Express Module

This is an example Express module which uses the Geometry API. It shows many features of the API including:

Creating geometry primitives

Creating edit lists

Using the new conversion routines

Modifying previously created geometry using a new edit list

The module basically creates a cube with two spheres when it is first initialized. If the "AddLabel" button is pressed a new label is added to the scene tree. If "DeleteLabels" is pressed all the labels are removed, leaving the cube and spheres.

The "V" module definition

This V code defines a simple module with two user interface buttons "AddLabel" and "DeleteLabels". Please note the extra option "link_files="-lgeomAPI -lgeom" in the definition below; this is needed to ensure correct linking.

macro GeomAPI_Macro<NEx=286.,NEy=44.,NEwidth=440.,NEheight=418.> {
module GeomAPI_Example<NEx=352.,NEy=209.,NEwidth=407.,NEheight=275.,src_file="createGeom.c",
link_files="-lgeomAPI -lgeom"> {
DefaultObject Top<NEportLevels={0,3}>;
int addLabel_pressed<NEportLevels={2,1}> => <-.AddLabel.do;
int delete_pressed<NEportLevels={2,1}> => <-.DeleteLabels.do;
ptr local_ptr<NEvisible=1>;
omethod+notify_inst+req createGeom<NEx=297.,NEy=275.>() = "createGeom";
omethod addLabel<NEx=88.,NEy=319.>(
addLabel_pressed+read+notify+req) = "addLabel";
omethod deleteLabels(
delete_pressed+read+notify+req) = "deleteLabels";
omethod+notify_deinst+req quitModule() = "quitModule";
};
UIbutton AddLabel<NEx=198.,NEy=88.> {
parent => <-.UImod_panel;
};
UImod_panel UImod_panel<NEx=22.,NEy=22.>;
UIbutton DeleteLabels<NEx=55.,NEy=154.> {
parent => <-.UImod_panel;
};
};
The C source code
#include <stdio.h>
#include <string.h>
#include "avs/geomAPI.h"
#include "express.h"

typedef struct _MODstate {
GEOMedit_list list;
int convertor_id;
int label_no;
} MODstate;

void gen_label(MODstate *state);
void gen_title(GEOMedit_list edit_list);
void gen_cube(GEOMedit_list edit_list, int vert, int prim, float pt[3]);

int
quitModule(OMobj_id GeomAPI_Example_id, OMevent_mask event_mask, int seq_num)
{
int freeOMobjs = 0;
MODstate *state = (MODstate *)GDget_local(GeomAPI_Example_id, NULL);
GEOMdelete_convertor(state->convertor_id, freeOMobjs);

return (1);
}

int
deleteLabels(OMobj_id GeomAPI_Example_id, OMevent_mask event_mask, int seq_num)
{
int picked_vert = 3 ;
int picked_prim = 4;
float picked_point[3] = { 0.25f, 1.24f, 0.75f};

MODstate *state = (MODstate *)GDget_local(GeomAPI_Example_id, NULL);

state->list = GEOMinit_edit_list(state->list);
state->label_no = 0;

/* Delete the labels */
GEOMedit_visibility(state->list, "label", -1);
GEOMconvert_edit_list(state->convertor_id, state->list);

return(1);
}


/* this routine is called when the "AddLabel" button is pressed */
int
addLabel(OMobj_id GeomAPI_Example_id, OMevent_mask event_mask, int seq_num)
{
MODstate *state = (MODstate *)GDget_local(GeomAPI_Example_id, NULL);
gen_label(state);
return 1;
}


/*
* intialize the module's geometry - this function is called only once when the module
* is first invoked
*/
int
createGeom(OMobj_id GeomAPI_Example_id, OMevent_mask event_mask, int seq_num)
{
int picked_vert = 3 ;
int picked_prim = 4;
float picked_point[3] = { 0.25f, 1.24f, 0.75f};

MODstate *state = (MODstate*) malloc(sizeof(MODstate));
state->list = NULL;
state->convertor_id = GEOMnew_convertor(GeomAPI_Example_id, "Top");
state->list = GEOMinit_edit_list(state->list);
state->label_no = 0;

/* creat the geometry */
gen_cube(state->list , picked_vert, picked_prim, picked_point);
gen_title(state->list);

/* convert the geometry */
GEOMconvert_edit_list(state->convertor_id, state->list);

/* save the state of the module */
GDset_local(GeomAPI_Example_id, state);

return(1);
}


/*
* 8 vertices of a cube
*/
static float Pts[8][3] = {
-0.75, -0.75, -0.75, /* 0 */
0.75, -0.75, -0.75, /* 1 */
0.75, 0.75, -0.75, /* 2 */
-0.75, 0.75, -0.75, /* 3 */
-0.75, -0.75, 0.75, /* 4 */
0.75, -0.75, 0.75, /* 5 */
0.75, 0.75, 0.75, /* 6 */
-0.75, 0.75, 0.75, /* 7 */
};

static int numPts = sizeof(Pts)/ (3*sizeof(float));

/*
* indices of the vertices defining the faces of the cube
*/
static int Faces[6][4] = {
4,3,2,1,
6,7,8,5,
2,3,7,6,
3,4,8,7,
5,8,4,1,
2,6,5,1
};

static int numFaces = sizeof(Faces)/ (4*sizeof(int));


/*
* label colors
*/
static float Colors[10][3] = {
1, 0, 0,
0, 1, 0,
0, 0, 1,
1, 1, 0,
1, 0, 1,
0, 1, 1,
1, 1, 1,
0.5, 1, 0.5,
1, 1, 0.5,
1, 0.5, 0.5
};

static int numColors = sizeof(Colors)/ (3*sizeof(float));

static float *red = Colors[0];
static float *green = Colors[1];
static float *blue = Colors[2];

/*
* font heights
*/
static float Heights[10] = { 0.04f, 0.06f, 0.08f, 0.1f, 0.12f, 0.14f, 0.16f, 0.18f, 0.2f, 0.24f};

static int numHeights = sizeof(Heights)/ sizeof(float);

static char *Labels[] = {
"London", "Brighton", "Oxford",
"Cambridge", "Nottingham", "Derby",
"Manchester", "Preston", "Banbury",
"Chipping Norton"
};

static int numLabels = sizeof(Labels)/sizeof(char*);

static char *Fonts[] = { "Charter", "Helvetica", "New Century", "Times",
"Courier", "Symbol", "Roman", "Script",
"Mathematics"
};
static int numFonts = sizeof(Fonts)/sizeof(char*);


/*
* generate a new label, add it to the existing geometry
*/
void gen_label(MODstate *state)
{
GEOMedit_list edit_list;
GEOMobj *obj;

int label_no;
int label_flag;
int font_num;
int loop;
float Offset[3] = { 0.0f,0.0f,0.00f};
float Pos[3];
float scale;

edit_list = state->list;
label_no = state->label_no;

/* clear out old edit list */
GEOMinit_edit_list(edit_list);

/* calculate position to place label */
scale = 1.0f + (label_no / numPts);
for (loop = 0; loop < 3; loop++)
Pos[loop] = scale * Pts[label_no % numPts][loop];

/* choose a font */
font_num = GEOMget_font_number(Fonts[label_no % numFonts], 0, 0);
/* create label using stroke font */
label_flag = GEOMcreate_label_flags(font_num, 0, 0, 1, GEOM_LABEL_CENTER ,1);

/* create GeomObj */
obj = GEOMcreate_label(NULL, label_flag);

/* one the label to the GeomObj */
GEOMadd_label(obj, Labels[label_no % numLabels], Pos, Offset,
Heights[label_no % numHeights] , Colors[label_no % numColors], 0);

/* if it's the first label, we are creating the object, make it a child of the "cube" */
if (label_no == 0) {
GEOMedit_geometry(edit_list,"label",obj);
GEOMedit_parent(edit_list,"label","cube");
GEOMconvert_edit_list(state->convertor_id, state->list);
} else
/* append the new label geometry to the "label" object */
GEOMconvert_obj(state->convertor_id, obj, "label");

GEOMdestroy_obj(obj);

state->label_no++;
}


/*
* gen_title
*/

void gen_title(GEOMedit_list edit_list)
{
GEOMobj *obj;

int label_flag;
int font_num;

float title_pos[3] = { 0.0f,0.85f, 0.0f};
float offset[3] = { 0.0f,0.0f,0.00f};

/* create a label using "standard" non-stroke font */
font_num = GEOMget_font_number("Times", 1, 0);

/* make the label a "title" */
label_flag = GEOMcreate_label_flags( font_num,1,0,0, GEOM_LABEL_CENTER ,0);


obj = GEOMcreate_label(NULL, label_flag);
GEOMadd_label(obj, "Geometry API", title_pos, NULL, 0.1f, NULL, 0);
GEOMedit_geometry(edit_list,"title",obj);

/* color it green */
GEOMedit_color(edit_list,"title", green );

GEOMdestroy_obj(obj);
}


GEOMobj *make_cube();

/*
* gen_cube
*
* This function generates a cube, a red polygon marking one face of
* the cube, a green sphere marking the selected vertex, and a blue sphere
* marking the selected point.
*
*/
void gen_cube(GEOMedit_list edit_list, int vert, int prim, float pt[3])
{

GEOMobj *obj;
int i;
float radii = 0.05f;


/* creat a polyhedron */
obj = GEOMcreate_obj(GEOM_POLYHEDRON,NULL);

/* add the six faces of the cube */
for (i = 0; i < numFaces; i++) {
if (prim != i) {
GEOMadd_polygon(obj,4, Faces[i], 0,GEOM_COPY_DATA);
GEOMadd_prim_data(obj,&i,1,GEOM_COPY_DATA);
}
}

/* add the cubes vertices */
GEOMadd_vertices(obj, (float*)Pts, numPts, GEOM_COPY_DATA);

GEOMgen_normals(obj,GEOM_FACET_NORMALS);

GEOMedit_geometry(edit_list,"cube",obj);

GEOMdestroy_obj(obj);


if (prim != -1) {
obj = GEOMcreate_obj(GEOM_POLYHEDRON,NULL);
GEOMadd_polygon(obj,4, Faces[prim], 0, GEOM_COPY_DATA);

GEOMadd_vertices(obj, (float*)Pts, numPts, GEOM_COPY_DATA);

GEOMadd_prim_data(obj,&prim,1,GEOM_COPY_DATA);
GEOMedit_geometry(edit_list,"cube_prim",obj);
GEOMedit_color(edit_list,"cube_prim",red);
GEOMedit_parent(edit_list,"cube_prim","cube");
GEOMedit_render_mode(edit_list, "cube_prim", "outline_nolight");

GEOMdestroy_obj(obj);
}

/* Create a sphere, make it a child of the cube and make it green */
if (vert != -1) {
obj = GEOMcreate_sphere(NULL,&Pts[vert][0],&radii,NULL,NULL,1,
GEOM_COPY_DATA);
GEOMedit_geometry(edit_list,"cube_vert",obj);
GEOMedit_parent(edit_list,"cube_vert","cube");
GEOMedit_color(edit_list,"cube_vert",green);
GEOMdestroy_obj(obj);
}

/* Now highlight the selected point */
if (pt != NULL) {
obj = GEOMcreate_sphere(NULL,pt,&radii,NULL,NULL,1,
GEOM_COPY_DATA);
GEOMedit_geometry(edit_list,"cube_point",obj);
GEOMedit_parent(edit_list,"cube_point","cube");
GEOMedit_color(edit_list,"cube_point",blue);
GEOMedit_selection_mode(edit_list,"cube_point","ignore",0);
GEOMdestroy_obj(obj);
}
}

6.8 The Geometry API Reference

This appendix describes in detail the API routines available in the AVS5 Geometry API. The appendix is divided into two sections. The first section considers API routines used to create geometry objects. The second section looks at API routines used to maintain edit lists.

IMPORTANT: This appendix contains the full listing of all the AVS5 Geometry API calls. Not all of these routines are supported in the Express Geometry API. Only those listed in sections Section 6.3 are supported. Furthermore the reader should note the restrictions listed above in Section 6.6 of this guide.
Geometry Object Library
Description

The geom library provides functions for reading and writing objects, creating objects from a variety of different data formats, processing objects (such as generating normals), and "compiling" databases into a format that is most efficient for the hardware to render.

The geom library contains both a C and a FORTRAN version of each routine. The main routine descriptions in this manual page discuss the C versions. For a discussion of the FORTRAN calling sequences, see the "Fortran Binding" section near the end of this chapter.

Many routines allow a NULL value for some arguments. In all such cases, the constant GEOM_NULL should be used to represent a NULL value.

The basic entity in the geom package is the geom object. Several types of objects are supported:

GEOM_LABEL
GEOM_MESH
GEOM_POLYHEDRON
GEOM_POLYTRI
GEOM_SPHERE

Each object can have colors or normals associated with each vertex in the object, but it need not have either.

Label

A label contains one or more text strings normally used to label an AVS object or view. The label is presented as annotation text: its position can be transformed, but the text always appears upright in a plane parallel to the display surface.

Mesh

A mesh object contains one two-dimensional array of vertices.

Polyhedron

A polyhedron contains a list of vertices and a list of polygons, which are defined by indirectly referencing the vertices that the polygon contains.

Polytriangle

A polytriangle object contains a list of polytriangle strips, a list of polylines, or a list of disjoint lines. When a single object has both line and surface data, the line data is assumed to be an alternate wireframe description for the same geometry (only one should be displayed at a given time).

Sphere

A sphere object contains a list of points and a corresponding list of radii.

Object Creation Routines

Many routines can be used to create an object. The goal is to provide entry points that allow many different data formats to be simply converted to the internal data base format. Different routines are used by different filters.

The creation routines for the geom library define some simple data formats:

A list of vertices is a 2D array of floats of X, Y, and Z.

A list of normals is a 2D array of floats of NX, NY, and NZ.

A list of float colors is a 2D array of floats of R, G, B (in the range of 0.0 to 1.0).

A list of integer colors is also defined where R, G, and B are bytes packed into an integer using the shifts AVS_RED_SHIFT, AVS_GREEN_SHIFT, and AVS_BLUE_SHIFT, defined in /usr/avs/include/port.h. All colors are stored internally as arrays of floats with values between 0 and 1.

A list of floating point transparency values that are associated with each vertex. The values should be in the range of 0.0-1.0 with 0.0 being opaque and 1.0 being transparent. The transparency value is meant to be interpolated across the surface and then used as the transparency attribute for each individual rendered point. Many renderers ignore this type of data.

A list of extents is a 1D array of 6 floats in the order: MIN X, MAX X, MIN Y, MAX Y, MIN Z, MAX Z.

User-supplied primitive data. The user may associate a single integer with each primitive where a primitive is defined as a line or polygon.

User-supplied vertex data. This is similar to user-supplied primitive data but is associated with a vertex instead of a primitive.

Creating an Object

A geom object is initially created without any data at all. Data is then added to the object incrementally. A typical sequence would be to create an object of type polyhedron, add a polygon list, add vertices, then add normals. Notice that an object can be in an intermediate state where it doesn't make sense - it can have a polygon list without vertices, for example.

To reduce the number of procedure calls required to create an object, the geom library also provides macro functions that create and add various pieces of data. When one of these calls has a parameter for an optional piece of data (normals and colors, for example), GEOM_NULL can be used to indicate that this object does not have this type of data.

Extents

Each object can have extent information associated with it. The extent of an object is determined by the minimum and maximum values of the coordinates of the object's vertices. Routines that create objects take optional extent information. Passing GEOM_NULL for this parameter indicates no extent is being specified. This is usually the best way to specify the extents unless you have explicit knowledge of what the extents should be for the object.

If you do not supply extent information during the creation of your object, it is generated for you when and if it is needed by some other part of the system. It is generated by finding the minimum and maximum values of X, Y, and Z in your vertex list. For spheres, the radii is used to determine the extents.

In some situations, you might want to provide extent information that is not the same as the object's actual extents. For example, if you have a time series of data where the object's extents are expanding (an explosion, for example) you may want to set the extent for the whole series to be large enough to avoid clipping the scene as the extents required increase in dimension. This way you can normalize the object (center it in the view) and not loose portions of it as the time series progresses

You should not set the extent so that it is smaller than the geometry of your object, as the system relies on the extent to display all of the geometry.

Flags

Many routines have an alloc flag as a parameter. If this flag is set to GEOM_COPY_DATA, the geom routine allocates its own space and copies the data of the object. If this flag is set to GEOM_DONT_COPY_DATA, the geom routine does not copy the data. In this case, you must allocate space for the data using the C entry library routine malloc(3C). It is usually easier to allow the routine to allocate the required space.

User Supplied Primitive Data

You may associate a single integer with each line or polygon primitive within an object. This integer should contain no more than 4 bytes of significant information. Unlike other data values that are associated with the object, this data is not interpreted by the geometry viewer. It is returned to the user for pick correlation purposes using upstream data. See the section on upstream data in Chapter 4 for more information on how to use this within a module.

For polyhedrons, there can be a single value for each polygon in the object. For meshes, there can be "m-1" * "n-1" values (this is the number of quadrilaterals in the mesh). For triangle strips, there can be "n-2" values. For disjoint lines, there can be "n/2" and for polylines there can be "n-1".

User Supplied Vertex Data

This is similar to user-supplied primitive data but is associated with a vertex instead of a primitive. During any particular pick, the user picks a primitive, but AVS returns the information corresponding to the closest selected vertex as well. For a particular object, there can be a single piece of user-supplied data for each vertex in the object.

Vertex and primitive data are not applicable to all object types. The following chart shows what object types can use each type of data:

Object Vertex and Primitive Data Applicability

Type

Primitive

Vertex

GEOM_POLYHEDRON
yes

Yes

GEOM_POLYTRI

yes

Yes

GEOM_SPHERE

no

Yes

GEOM_LABEL

no

No

GEOM_MESH

yes

Yes

GEOMadd_disjoint_line
GEOMadd_disjoint_line(obj, verts, colors, n, alloc)
GEOMobj
*obj;
float *verts;
float *colors;
int n;
int alloc;

Adds an array of lines to an object of type GEOM_POLYTRI. It adds the vertices of this disjoint line to any existing disjoint lines in the object.

GEOMadd_disjoint_polygon
GEOMadd_disjoint_polygon(obj, verts, normals, colors, nverts, flag, alloc)
GEOMobj
*obj;
float *verts, *normals, *colors;
int nverts;
int alloc;
int flag;

Adds a disjoint polygon to a polyhedron object. The polygon has nverts vertices which are specified in the array verts. The normals and colors arguments can contain the normals and colors for the object, or they can be GEOM_NULL. The flag argument contains two pieces of information: the nature of the polygon (whether it is convex, concave, or complex), and whether the vertices of the polygon should be shared with the other vertices in the object. Shared vertices create an object whose vertices approximate a smooth object (such as a sphere); unshared vertices create an object that is faceted. The flags GEOM_SHARED and GEOM_NOT_SHARED are used to determine whether the vertices are shared or not. The values GEOM_CONCAVE, GEOM_CONVEX, and GEOM_COMPLEX can be OR'd with the other value to produce the flag argument.

Specifying shared vertices causes this routine to try to determine whether any vertices in the object are already represented. Instead of adding a new vertex when an old identical vertex is found, it uses a reference to this vertex. This process can take considerable time when the number of vertices in the object is large, but it produces an object that is significantly more efficient to render, because the resulting object contains fewer vertices to transform, light, and shade.

GEOMadd_disjoint_prim_data
GEOMadd_disjoint_prim_data(obj, pdata, n, alloc)
GEOMobj
*obj;
float *pdata;
int n;
int alloc;

This routine should only be used for objects of type GEOM_POLYTRI that have disjoint line primitives in them. It allows the user to associate primitive data with the disjoint lines in a polytriangle type object. The number "n" should be the number of disjoint lines in the object- note that this is one-half the number of vertices that the object contains.

GEOMadd_disjoint_vertex_data
GEOMadd_disjoint_vertex_data(obj, vdata, n, alloc)
GEOMobj
*obj;
int *vdata;
int n;
int alloc;

This routine should only be used for objects of type GEOM_POLYTRI that have disjoint line primitives in them. It allows the user to associate vertex data with the disjoint lines in a polytriangle type object. The number "n" should be the number of vertices in the disjoint line object. Note that this is twice the number of disjoint lines.

GEOMadd_float_colors
GEOMadd_float_colors(obj, colors, n, alloc)
GEOMobj
*obj;
float *colors;
int n;
int alloc;

Adds a list of float colors to an object. The Red, Green, and Blue values are stored separately (i.e., it takes three floats to specify an RGB), and should range between 0 and 1. This routine cannot be used with objects of type GEOM_POLYTRI.

GEOMadd_int_colors
GEOMadd_int_colors(obj, colors, n, alloc)
GEOMobj
*obj;
unsigned long *colors;
int n;
int alloc;

Adds a list of integer colors to an object. The RGB values are packed into a single integer using the shifts AVS_RED_SHIFT, AVS_GREEN_SHIFT, and AVS_BLUE_SHIFT, defined in /usr/avs/include/port.hi. This routine cannot be used with an object of type GEOM_POLYTRI.

GEOMadd_label
GEOMadd_label(obj, text, ref_point, offset, height, color, label_flags)
GEOMobj
*obj;
char *text;
float ref_point[3];
float offset[3];
float height;
float color[3];
int label_flags;

This routine adds a text string and related characteristics to an existing label object. Each label object can have more than one text string, along with related characteristics for each string. Each such string is added by a separate call to GEOMadd_label for the same label object. All data is copied (GEOM_COPY_DATA is assumed). The arguments are as follows:

text

The text string for the label.

ref_point, offset

These arguments determine the positioning of the label. The reference point is an array of X, Y, and Z coordinates. For a label used as a window title, these are in screen space, with (-1, -1, -1) at the lower left rear corner and (1, 1, 1) at the upper right front corner, and are not transformed. For other labels the coordinates of the reference point are transformed. The offset is an array of X, Y, and Z values in screen space. After the reference point is transformed (if necessary), the offset is applied to determine the final position of the reference point in screen space. The label always appears upright and in a plane parallel to the display surface.

height

The height of the label in screen space.

color

An RGB triple specifying the text color, or GEOM_NULL to indicate that the foreground color (usually white) should be used. (When the text background rectangle is drawn, the window background color is used for the rectangle.)

label_flags

An integer returned by a call to GEOMcreate_label_flags, or a value of -1 to indicate that the default label flags in the label object, added by the call to GEOMcreate_label, should be used. For a given label object, either all text strings must use the default label flags, or no text strings can use the default label flags. That is, either all calls to GEOMadd_label must pass - 1 for the label_flags argument, or no calls to GEOMadd_label can pass -1 for the label_flags argument.

GEOMadd_normals
GEOMadd_normals(obj, normals, n, alloc)
GEOMobj
*obj;
float *normals;
int n;
int alloc;

Adds a list of normals to an object. This routine cannot be used with objects of type GEOM_POLYTRI or GEOM_SPHERE.

GEOMadd_polygon
GEOMadd_polygon(obj, nverts, indices, flags, alloc)
GEOMobj
*obj;
int nverts;
int *indices;
int flags;
int alloc;

Adds a polygon to a polyhedron object. The indices argument specifies an array of nverts integers, where each integer is an index into a vertex array that is added with the GEOMadd_vertices call either before or after this call is made. If multiple calls to GEOMadd_vertices are made, the first vertex added always remains the first vertex in the list. The indices in this array are "1 based". The first vertex in the list is 1, not 0. The flags argument can be either GEOM_CONCAVE or GEOM_CONVEX.

GEOMadd_polygons
GEOMadd_polygons(obj, plist, flags, alloc)
register GEOMobj
*obj;
register int *plist;
int flags;
int alloc;

Adds a polygon list to a polyhedron object. The polygon list is an array of ints where the first int (plist[0]) indicates the number of vertices in the first polygon. The number of vertices (plist[0]) is followed by that number of indices into the vertex list. The second polygon's vertex list immediately follows the first. The list is terminated with a 0 number of vertices after the last polygon's vertex list. As with the GEOMadd_polygon routine, the vertex indices are "1 based". The first vertex in the list is 1, not 0. The flags argument can be either GEOM_CONCAVE or GEOM_CONVEX.

GEOMadd_polyline
GEOMadd_polyline(obj, verts, colors, n, alloc)
GEOMobj
*obj;
float *verts;
float *colors;
int n;
int alloc;

Adds a polyline to an object of type GEOM_POLYTRI. The colors argument can be GEOM_NULL.

GEOMadd_polyline_prim_data
GEOMadd_polyline_prim_data(obj, pdata, i, n, alloc)
GEOMobj
*obj;
int *pdata;
int i;
int n;
int alloc;

This routine should be used only for objects of type GEOM_POLYTRI that contain polyline primitives. It allows the user to associate vertex data with the polylines in a polytriangle type object. The number n is the number of vertices in the polyline object. Note that this is the number of disjoint lines - 1. The value of i specifies the particular primitive within the object, with which you want to associate the data. The first primitive is 0, the second is 1, etc.

GEOMadd_polyline_vertex_data
GEOMadd_polyline_vertex_data(obj, vdata, i, n, alloc)
GEOMobj
*obj;
int *vdata;
int i;
int n;
int alloc;

This routine should be used only for objects of type GEOM_POLYTRI that contain polyline primitives. It allows the user to associate vertex data with the polylines in a polytriangle type object. The number n is the number of vertices in the polyline object. Note that there are n vertices, but the number of lines is n-1. The value of i specifies the particular primitive within the object, with which you want to associate the data. The first primitive is 0, the second is 1, etc.

GEOMadd_polytriangle
GEOMadd_polytriangle(obj, verts, normals, colors, n, alloc)
GEOMobj
*obj;
float *verts;
float *normals;
float *colors;
int n;
int alloc;

Adds a polytriangle to the object. Note that colors is an array of float colors, not int colors. An object can contain more than one polytriangle strip.

GEOMadd_polytriangle_prim_data
GEOMadd_polytriangle_prim_data(obj, pdata, i, n, alloc)
GEOMobj
*obj;
int *pdata;
int i;
int n;
int alloc;

This routine should be used only for objects of type GEOM_POLYTRI that contain polytriangle strip primitives. It allows the user to associate vertex data with the polytriangle strips in a polytriangle type object. The number n is the number of triangles in the polytriangle object. Note that this is the number of vertices - 2. The value of i specifies the particular primitive within the object, with which you want to associate the data. The first primitive is 0, the second is 1, etc.

GEOMadd_polytriangle_vertex_data
GEOMadd_polytriangle_vertex_data(obj, vdata, i, n, alloc)
GEOMobj
*obj;
int *vdata;
int i;
int n;
int alloc;

This routine should be used only for objects of type GEOM_POLYTRI that contain polytriangle strip primitives. It allows the user to associate vertex data with the polytriangle strips in a polytriangle type object. The number n is the number of triangles in the polytriangle object. Note that this is the number of vertices - 2. The value of i specifies the particular primitive within the object, with which you want to associate the data. The first primitive is 0, the second is 1, etc.

GEOMadd_prim_data
GEOMadd_prim_data(obj, pdata, n, alloc)
GEOMobj
*obj;
int *pdata;
int n;
int alloc;

Associate the array of primitive data with the object specified. This routine can be used only for objects of type GEOM_POLYHEDRON and GEOM_MESH. For objects of type GEOM_MESH, there value n should be equal to: (m-1) * (n-1). Where "m" and "n" are the dimensions of the mesh.

GEOMadd_radii
GEOMadd_radii(obj, radii, n, alloc)
GEOMobj
*obj;
float *radii;
int n;
int alloc;

This routine adds the radii supplied to an object of type GEOM_SPHERE. The number n contains the number of spheres in the object. The alloc parameter is GEOM_DONT_COPY_DATA if the data has been allocated using the malloc(3C) routine, and has not been freed by the application. It should be GEOM_COPY_DATA otherwise.

GEOMadd_vertex_data
GEOMadd_vertex_data(obj, vdata, n, alloc)
GEOMobj
*obj;
int *vdata;
int n;
int alloc;

Associates the array of vertex data with the object specified. This routine can be used only with objects of type: GEOM_MESH, GEOM_POLYHEDRON, and GEOM_SPHERE. The number of data elements n, should be equal to the number of vertices in the object.

GEOMadd_vertices
GEOMadd_vertices(obj, verts, n, alloc)
GEOMobj
*obj;
float *verts;
int n;
int alloc;

Adds a list of vertices to an object. This routine should not be used for objects of type polytriangle (use GEOMadd_polytriangle instead).

GEOMadd_vertices_with_data
GEOMadd_vertices_with_data(obj, verts, normals, colors, n, alloc)
GEOMobj
*obj;
float *verts;
float *normals;
unsigned int colors;
int n;
int alloc;

Adds vertices, colors, and normals to the object. It assumes integer colors. Both the normals and colors parameters can be GEOM_NULL. This is a macro function combining the GEOMadd_vertices, GEOMadd_normals, and GEOMadd_int_colors routines.

GEOMcreate_label
GEOMobj * GEOMcreate_label(extent, label_flags)
float
*extent;
int label_flags;

This routine creates a label object. Each label object can have more than one text string, along with related characteristics for each string. Each such string is added by a separate call to GEOMadd_label for the same label object. The label_flags argument to GEOMcreate_label is normally an integer returned by a call to GEOMcreate_label_flags. It specifies default characteristics for all text strings in the label object. Either all text strings must use the default label flags, or no text strings can use them; see GEOMadd_label for more information. The extent argument can be GEOM_NULL if no extent is known.

GEOMcreate_label_flags
int
GEOMcreate_label_flags(font_number, title, background, drop, align, stroke)
int font_number, title, background, drop, align, stroke;

This routine creates and returns a bit mask that is used to represent some characteristics of a label. The label flags are added by a call to GEOMcreate_label or to GEOMadd_label. To add a text string and related characteristics to the label, use the GEOMadd_label routine. The arguments are as follows:

font_number

An integer from 0 through 21 that specifies the font for the label's text string. The GEOMget_font_number call will generate a number to use here (which may differ from platform to platform) based upon a text string font name such as "Helvetica" or "Times", together with two booleans that flag bold or italic.

title

A value of 1 means that the label is to be used as a title for the window. The label is drawn in an absolute position with respect to screen space, which is defined so that (-1, -1, -1) is the lower left rear corner and (1, 1, 1) is the upper right front corner. A value of 0 means that the reference point of the label is transformed before the label is drawn. See the documentation for the GEOMadd_label routine for more information.

background

A value of 1 means that both the foreground text and the background rectangle that encloses the text are drawn. A value of 0 means that only the foreground text is drawn.

drop

A value of 1 means that a one-pixel drop-shadow highlight is added to the text. This makes the text stand out against a background of similar color. A value of 0 means that no highlight is added.

align

Specifies the position of the reference point within the label and therefore the alignment of the label. A value of GEOM_LABEL_LEFT places the reference point at the lower left corner of the label. A value of GEOM_LABEL_CENTER places the reference point at the bottom center of the label. A value of GEOM_LABEL_RIGHT places the reference point at the lower right corner of the label.

stroke

Not implemented; the value should be 0.

GEOMcreate_mesh
GEOMobj *
GEOMcreate_mesh(extent, verts, m, n, alloc)
float
*extent;
float *verts;
int m, n;
int alloc;

Creates a mesh from a 2D array of vertices. The dimensions of the array are specified by the m and n parameters. The first n vertices constitute the first row of the mesh. There are m rows of vertices. The extent parameter can be GEOM_NULL if no extent is known.

GEOMcreate_mesh_with_data
GEOMobj *
GEOMcreate_mesh_with_data(extent, verts, normals, colors, m, n, alloc)
float
*extent;
float *verts;
float *normals;
unsigned long *colors;
int m, n;
int alloc;

This routine is a macro function combining the GEOMcreate_mesh, GEOMadd_int_colors, and GEOMadd_normals routines.

GEOMcreate_obj
GEOMobj *
GEOMcreate_obj(type, extent)
int
type;
float *extent;

Type should be one of GEOM_LABEL, GEOM_MESH, GEOM_POLYHEDRON, GEOM_POLYTRI or GEOM_SPHERE. Extent can be either the extent of the object or GEOM_NULL if no extent is known. This routine creates an object of the specified type. Initially the object has no data.

GEOMcreate_polyh
GEOMobj *
GEOMcreate_polyh(extent, verts, n, plist, flags, alloc)
float
*extent;
float *verts;
int n;
int *plist;
int flags;
int alloc;

This routine is a macro function combining the GEOMcreate_obj, GEOMadd_vertices, and GEOMadd_polygons routines. The flags argument can be either GEOM_CONCAVE or GEOM_CONVEX.

GEOMcreate_polyh_with_data
GEOMobj *
GEOMcreate_polyh_with_data(extent, verts, normals, colors, n, plist, flags, alloc)
float
*extent;
float *verts;
float *normals;
unsigned long *colors;
int n;
int *plist;
int flags;
int alloc;

This routine is a macro function combining the GEOMcreate_polyh, GEOMadd_int_colors, and GEOMadd_normals routines. The flags argument can be either GEOM_CONCAVE or GEOM_CONVEX

GEOMcreate_scalar_mesh
GEOMobj *
GEOMcreate_scalar_mesh(xmin, xmax, ymin, ymax, mesh, colors, n, m, alloc)
float
xmin, xmax, ymin, ymax
float *mesh, *colors; /* Colors is R,G,B */
int n, m;

Creates a mesh from a single array of scalar values (a height field). The scalars are taken to be the Z component of the object. X will be evenly spaced between xmin and xmax, and Y will be evenly spaced between ymin and ymax. The colors parameter can be GEOM_NULL.

GEOMcreate_sphere
GEOMobj *
GEOMcreate_sphere(extent, verts, radii, normals, colors, n, alloc)
float
*extent;
float *verts;
float *radii;
float *normals;
unsigned long *colors;
int n, alloc;

Creates a sphere object. The vertices (vert) argument specifies the sphere centers. The normals and colors arguments can be GEOM_NULL. When the value of radii is GEOM_NULL, the spheres will be rendered as dots. The normals are generally not used. To create a sphere with float colors, use the GEOMadd_float_colors routine after the sphere is created.

GEOMdestroy_obj
GEOMdestroy_obj(obj)
GEOMobj *obj;

Frees all memory associated with the object, including memory given to a "create" call with the flag GEOM_DONT_COPY_DATA.

GEOMget_font_number
int
GEOMget_font_number(
name, bold, italic)
char
*name;
int bold, italic;

This routine is used to convert a font name, bold and italic values, and produce a font number that is used as the first argument to the routine GEOMcreate_label_flags. The label flags are then used to define the font, alignment, and other drawing attributes for the label primitive.

This routine is given a font name which can be one of: "Courier", "Helvetica", "New Century", "Times", "Charter", "Symbol", "Roman", "Script", or "Mathematics". It also takes two boolean values to indicate whether the font should be drawn with bold or italic style. The return of this routine is the font number to use in the routine GEOMcreate_label_flags.

Not all fonts and styles are implemented on all renderers. If a font is not implemented by a particular renderer, it will be simulated with the closest approximating font that is available.

Object Utility Routines

Once a geom object has been created, the utility routines can be used. These routines control: object normals (the generation of proper normals is critical to an accurate and illustrative description of geometry); object autotransformations (the transformation of individual objects and groups of objects to fit within a unit cube (-1 to 1 in X, Y, and Z)-this is distinct from the general transfomation of objects within world space using edit list calls; and object format conversions).

This last is necessary because on some architectures, the most efficient object format is the polytriangle for nonsphere surface descriptions and the polyline for wireframe descriptions. Two utility routines convert data to the proper type. The conversion routines convert to either polytriangles, polylines, or both, depending on the setting of the flags. Sphere primitives should not be converted. This conversion should be performed after normals have been generated for the object (if normals are desired) as the conversion results in a loss of vertex coherence information.

GEOMauto_transform
GEOMauto_transform(obj)
register GEOMobj
*obj;
GEOMauto_transform_non_uniform
GEOMauto_transform_non_uniform(obj)
register GEOMobj
*obj;

Transforms the object specified to lie within the cube from -1 to 1 in X, Y, and Z. The scaling and translation factors are uniform for GEOMauto_transform and nonuniform for GEOMauto_transform_non_uniform.

GEOMauto_transform_list
GEOMauto_transform_list(objs, n)
register GEOMobj
**objs;
register int n;
GEOMauto_transform_non_uniform_list
GEOMauto_transform_non_uniform_list(objs, n)
register GEOMobj
**objs;
register int n;

Transforms the list of objects specified to lie within the cube from -1 to 1 in X, Y, and Z. First the bounding box of all objects in the list is generated, then scaling and translation factors are computed to transform this box to lie inside the cube from -1 to 1 in X, Y, and Z. The scaling and translation factors are uniform for GEOMauto_transform_list and nonuniform for GEOMauto_transform_non_uniform_list. The relative sizes of objects in the list are not affected.

GEOMcreate_normal_object
GEOMobj *
GEOMcreate_normal_object(obj,scale)
GEOMobj
*obj;
float scale;

This routine takes an object that has normal data and returns an object that consists of disjoint lines that represent the normals of that object. The normals will be of length scale times their current length.

GEOMcvt_mesh_to_polytri
GEOMcvt_mesh_to_polytri(tobj, flags)
GEOMobj
*tobj;
int flags;

Creates a polytriangle or polyline description of the mesh object given. The resulting object contains one large polytriangle strip (if the flags argument is GEOM_SURFACE) and n * m polylines (if the flags argument is GEOM_WIREFRAME).

GEOMcvt_polyh_to_polytri
GEOMcvt_polyh_to_polytri(tobj, flags)
GEOMobj
*tobj;
int flags;

Uses a graph traversing algorithm to generate either a surface or a wireframe description of a polyhedron object, depending on the flags argument. It attempts to share as many vertices as possible. The surface algorithm can take a reasonably long time to complete for very large objects. The wireframe algorithm creates polylines for large connected strips and disjoint lines for smaller ones. The flags argument can be GEOM_SURFACE, GEOM_WIREFRAME, or GEOM_EXHAUSTIVE. The GEOM_EXHAUSTIVE flag should be used only in dire circumstances.

GEOMflip_normals
GEOMflip_normals(obj)
GEOMobj
*obj;

This routine inverts the direction of the normals in the object given.

GEOMgen_normals
GEOMgen_normals(obj, flags)
GEOMobj
*obj;
int flags; /* 0 or GEOM_FACET_NORMALS */

Generates surface normals for GEOM_MESH or GEOM_POLYHEDRON objects. By default, it assumes that the object is an approximation of a smooth surface. If the flags field is GEOM_FACET_NORMALS and the object is a polyhedron, a separate normal is generated for each facet (polygon). A copy of the facet normal is associated with each of the facet verticies. A vertex that is shared by multiple facets is replicated for each facet. This replication decreases the rendering performance of the object. Normals generated by this routine are guaranteed to be of unit length.

GEOMnormalize_normals
GEOMnormalize_normals(obj)
GEOMobj
*obj;

Normalizes (converts to unit length) the normals of the object specified. Normals are normalized automatically by the GEOMgen_normals routine.

GEOMset_computed_extent
GEOMset_computed_extent(obj, extent)
GEOMobj
*obj;
float extent[6];

Sets the extent of the object to the extent passed in. The extent passed in should contain in order: xmin, xmax, ymin, ymax, zmin, zmax. This can be used in conjunction with either auto_transform routine to perform arbitrary scaling and translation of objects.

GEOMset_extent
GEOMset_extent(obj)
GEOMobj
*obj;

Sets the extent of the object given. Currently, it is not implemented properly for objects of type GEOM_SPHERE.

GEOMset_object_group
GEOMset_object_group(obj, name)
GEOMobj
*obj;
char *name;

This routine is used when storing multiple AVS objects (groups of geom objects) in a single geom file. By default, when AVS reads a geom file it places all geom objects in that file into a single AVS object. The read_subset script language command can read a subset of the geom objects in a geom file and place only those geom objects into an AVS object. Each geom object to be placed into the same AVS object must have the same group name, which is added by the GEOMset_object_group routine. The read_subset command takes a group name as an argument and places all geom objects in the geom file that have that group name into a single AVS object. The read_subset command ignores all geom objects in the geom file that do not have that group name.

GEOMset_pickable
GEOMset_pickable(obj, pickable)
GEOMobj
*obj;
unsigned long pickable;

This routine sets the pickable state of an object. If multiple objects are placed in a geom file, by default they are not pickable individually. If this attribute is set to "1", they can be picked individually when running the AVS viewing application.

GEOMunion_extents
GEOMunion_extents(obj1, obj2)
GEOMobj
*obj1, *obj2;

Sets the extent of obj1 to include the extent of obj2. It generates the extents of both objects if they aren't set already.

Object Property Routines

A feature of the geom library allows arbitrary value lists to be associated with each object. These value lists can then be interpreted by packages reading in the objects. The object format supports values that are arbitrarily long. Currently only integer values are supported by the subroutine interface.

GEOMadd_int_value
GEOMadd_int_value(obj, type, value)
GEOMobj
*obj;
int type;
int value;

Adds an integer property to an object. Currently the only fully supported property of an object is the color (type GEOM_COLOR).

GEOMquery_int_value
int
GEOMquery_int_value(
obj, type, value)
GEOMobj
*obj;
int type;
int *value;

An integer value can be queried with this routine. The type is an integer value. The only fully supported property type is GEOM_COLOR. Its value can be queried with:

GEOMquery_int_value(obj, GEOM_COLOR, &color);

This routine returns 0 if no color was associated with the object.

GEOMset_color
GEOMset_color(obj, color)
GEOMobj
*obj;
unsigned long color;

Sets the color property of an object (by calling the GEOMadd_int_value routine).

Object Texture Mapping Routines

Each surface object can have uv data associated with each vertex. The uv data consists of two floating point values per vertex, which specify a mapping into a texture map. The value of u=0, v=0 is the index into the upper left hand corner of the texture map; u=1, v=1 is the lower right hand corner. These values are stored in memory as an array of floating point values.

GEOMadd_polytriangle_uvs
GEOMadd_polytriangle_uvs(obj, uvs, i, n, alloc)
GEOMobj
*obj;
float *uvs;
int i;
int n;
int alloc;

Each polytriangle object has an array of polytriangle strips. This routine is used to add uv data to a polytriangle object. These polytriangle strips are kept in an array in the order in which they were added: the first polytriangle is index 0, the second is index 1, etc. This routine adds uv data for a single polytriangle strip. The index of the polytriangle strip is the variable i. This polytriangle strip should have n vertices. The alloc parameter is GEOM_DONT_COPY_DATA if the data has been allocated using the malloc(3C) routine, and has not been freed by the application. It should be GEOM_COPY_DATA otherwise.

GEOMadd_uvs
GEOMadd_uvs(obj, uvs, n, alloc)
GEOMobj
*obj;
float *uvs;
int n;
int alloc;

This routine adds the uv data to an object of type GEOM_POLYHEDRON, or GEOM_MESH. n should specify the number of vertices in the object. The alloc parameter is GEOM_DONT_COPY_DATA if the data has been allocated using the malloc(3C) routine, and has not been freed by the application. It should be GEOM_COPY_DATA otherwise.

GEOMcreate_mesh_uvs
GEOMcreate_mesh_uvs(obj, umin, vmin, umax, vmax)
GEOMobj
*obj;
double umin, vmin, umax, vmax;

This routine creates uv data for a mesh object such that the 0,0 vertex in the mesh will have u=0, v=0, and the n,m vertex in the mesh will have u=1, v=1. It is an error to use this routine with an object that is not of type GEOM_MESH.

GEOMdestroy_uvs
GEOMdestroy_uvs(obj)
GEOMobj
*obj;

This routine takes an object that has uv data for each vertex and turns it into an object that doesn't have uv data for each vertex.

Object Vertex Transparency Routines
GEOMadd_vertex_trans
GEOMadd_vertex_trans(name, vtrans, n, alloc)
GEOMobj *name;
float *vtrans;
int n, alloc;

This routine adds vertex transparency values to a geometry object of type GEOM_MESH and GEOM_POLYHEDRON. This routine should not be used with objects of type: GEOM_SPHERE, GEOM_LABEL and GEOM_POLYTRI. Vertex transparency values, specified by the argument vtrans should be floating point values in the range 0.0-1.0. The value 0.0 will produce a completely opaque surface and the value 1.0 will produce an transparent object. The parameter n corresponds to the number of floating point values supplied with this call. This number should correspond to the number of vertices in the object. The alloc flag can be either the value GEOM_COPY_DATA, or the value GEOM_DONT_COPY_DATA. The flag GEOM_DONT_COPY_DATA should only be used by C applications that have allocated the data using the malloc utility. If GEOM_DONT_COPY_DATA is used, the user should not free the data This will be taken care of by GEOM when the object itself is destroyed. If this is not the case, the user should use the flag GEOM_COPY_DATA and is then responsible for the maintenance of this storage.

GEOMadd_polytriangle_vertex_trans
GEOMadd_polytriangle_vertex_trans(name, vtrans, i, n, alloc)
GEOMobj *name;
float *vtrans;
int i, n, alloc;

This routine adds vertex transparency values to a geometry object of type GEOM_POLYTRI. This routine should not be used with objects of type: GEOM_MESH, GEOM_POLYHEDRON, GEOM_SPHERE, and GEOM_LABEL.

Vertex transparency values, specified by the argument vtrans should be floating point values in the range 0.0-1.0. The value 0.0 will produce a completely opaque surface and the range 1.0 will produce an transparent object. The parameter n corresponds to the number of floating point values supplied with this call which should equal the number of vertices contained in the individual polytriangle strip.

The parameter i specifies which polytriangle these vertex colors should be associated with. Polytriangles are numbered in the order in which they are added to the polytriangle object with 0 being the first triangle strip. The alloc flag can be either the value GEOM_COPY_DATA, or the value GEOM_DONT_COPY_DATA. The flag GEOM_DONT_COPY_DATA should only be used by C applications that have allocated the data using the malloc utility. If GEOM_DONT_COPY_DATA is used, the user should not free the data. This will be taken care of by GEOM when the object itself is destroyed. If this is not the case, the user should use the flag GEOM_COPY_DATA and is then responsible for the maintenance of this storage.

Object File Utilities

Prior to writing data to files in most implementations, each platform determines which format (e.g., GEOM_POLYTRI or GEOM_POLYHEDRON) is most efficient for that platform and automatically converts the data to this format.

GEOMread_obj
GEOMobj *
GEOMread_obj(fd, flags)
int
fd;
int flags;

Performs a read operation on the file descriptor given and interprets the data it finds as a geom object. Data can be stripped off by specifying the GEOM_NORMALS flag (to strip off the normals), the GEOM_VCOLORS flag (to strip of the colors), or the OR of these values (to strip off normals and colors). A flags value of 0 means leave the data intact.

GEOMread_text
GEOMobj *
GEOMread_text(fp, flags)
FILE *fp;
int flags;

This routine reads the text GEOM file from the file pointer fp. Normally this routine is used on a file that was previously output from the routine GEOMwrite_text. The flags argument can be used to strip off the normals or colors in the object by supplying the GEOM_NORMALS or GEOM_VCOLORS arguments. Normally this parameter is 0.

GEOMwrite_obj
GEOMwrite_obj(obj, fd, flags)
GEOMobj
*obj;
int fd;
int flags;

Writes a geom object to a file. The fd parameter is a file descriptor representing the file or device to write to. Data can be stripped off by specifying the GEOM_NORMALS flag (to strip off the normals), the GEOM_VCOLORS flag (to strip of the colors), or the OR of these values (to strip off normals and colors). A flags value of 0 means leave the data intact.

GEOMwrite_text
GEOMwrite_text(obj, fp, flags)
GEOMobj
*obj;
FILE *fp;
int flags;

This routine writes an ASCII version of the geom object specified to the stream fp. This routine is implemented for all geom object types and is useful for debugging or transporting geom data to different architectures.

Object Debugging Facilities
GEOMcheck_obj
GEOMcheck_obj(name, flags, func)
GEOMobj *name;
int flags;
int (*func)();

This routine verifies that the geom object that you supply is a valid geometry object. It ensures that your object contains:

zero or a positive number of vertices.

the same number of vertices, normals, colors etc.

no "not-a-number" floating point values as produced in some undefined floating point operations.

color values that are within the 0.0-1.0 range.

extent minimum is less than extent maximum.

polyhedron objects have no indices that are out of range of the number of vertices.

When this routine encounters an error, it will supply a reasonably detailed message indicating the nature of the error. If the func argument is passed in with a NULL value, this message will be sent to "standard error" of the calling process. Otherwise, the function pointer func will be called with a NULL terminated error message as the first argument:

(*func)(error_message)
char *error_message;

The flags argument is currently not used and should be set to 0.

This routine will be called automatically every time that each geometry object is either read from or written to a file, or passed as an input or output from a module when the environment variable AVS_GEOM_VERIFY is set in the shell before either AVS or the geometry filter is executed. You can do this as follows in the C-shell:

setenv AVS_GEOM_VERIFY
./avs

Or in the Bourne shell:

AVS_GEOM_VERIFY=1
export AVS_GEOM_VERIFY
AVS Module Interface Routines

Module interface routines allow you to create, modify, and destroy edit lists.

Edit Lists

The data type used by AVS modules that handle geometries is an edit list. The AVS data type for an edit list is GEOMedit_list. An edit list is an arbitrarily long list of changes to be applied to a scene. Each change pertains to a particular object of type GEOMobj or to a light source. Changes are made in the order specified in the edit list.

AVS allows a user module to create edit lists as outputs; AVS does not support using them as inputs. A C language module computation routine declares an argument representing an input port or parameter as GEOMedit_list and an argument representing an output port as GEOMedit_list * (note the single asterisk).

Geometry output is typically used as input to a geometry renderer module such as the Geometry Viewer.

Each object or light is referred to by a name which is an ASCII string. Any object that doesn't already exist is created the first time an attempt to change that particular object is made. By default, an object name is modified by the port through which it is communicated. This prevents two different modules from modifying each other's objects. For example, two "plate" modules would each try to modify the data for the object named "plate". Since the name is modified by the port, the first plate module modifies plate.0, and the second modifies plate.1. When it is desirable for a module to use the absolute name of an object, it can precede the object name by a % character (e.g., "%plate").

AVS has routines that allow a module to change several properties of an object in an edit list:

The geometric data defining the object

Surface or line color

Render mode (Gouraud, Phong, wireframe, etc.)

Parent (the name of the parent object)

Texture mapping

Material properties

Transformation

The name of each light source in an edit list is a string of the form "lightn", where n is an integer from 1 through 16.

Certain edit list commands take the name of an object or camera/view as an argument. This camera name can be one of two forms either: "cameran" where n is an integer ranging between 1 and the number of cameras defined for the current scene, or the camera name can refer to the title of the particular camera.

The value n in the "cameran" scheme is defined by the order in which the cameras are created. Using n = 1 refers to first camera created for the scene. Note how this way of naming cameras changes when a camera is deleted from the scene.

The camera title refers to a particular camera. The name of a particular camera will not change when another camera is deleted. The title of a camera can be specified using the Geometry Viewer CLI when the camera is created. Otherwise, the camera name follows the scheme: "Camera m" where m is an integer, starting at 0, that increases each time that a new camera is created. The title index m is different from the previous naming index n only when a camera is deleted.

Each time a module is invoked, it should start with an empty edit list. It places into the edit list changes that it wants to be made for this invocation. In creating and using edit lists, geometry objects, and light sources, a module uses routines in the geom library. A module typically uses the following steps in preparing an edit list for output:

Initialize the edit list, using GEOMinit_edit_list. This creates a new list or empties an existing list.

Create and modify geometry objects or lights sources, using routines in the geom library.

Modify the edit list, using routines whose names begin with GEOMedit in C (such as GEOMedit_geometry).

Coroutine module should use AVScorout_output to output the list.

A module must deallocate an existing edit list before reusing the list. For a subroutine module, the edit list passed to the module as an output argument is the edit list the module created on its last execution. The module must deallocate this list at the start of each invocation of the module, normally by calling the GEOMinit_edit_list routine before modifying the list. Coroutine modules can use GEOMinit_edit_list to deallocate/initialize a list after calling AVScorout_output.

There is also a GEOMdestroy_edit_list call. GEOMdestroy_edit_list destroys the edit list but does not create a new one. Once called, there is no longer a valid edit list to use the various GEOMedit... calls with. Hence, you can not call both GEOMdestroy_edit_list and GEOMinit_edit_list with the same pointer. You should only use GEOMdestroy_edit_list from within a coroutine if you know that you will not be doing any more geometry outputs.

Object Transformations

Some modules writers require detailed knowledge of how the transformation matrices of objects is maintained. This section describes this in detail and assumes significant knowledge of how computer graphics transformations are traditionally done.

Each object as a 4x4 homogenous transformation matrix and a 3x1 position vector that describes the current position and orientation of the object. The 4x4 matrix is treated in C as a 4x4 array of floats: e.g. float matrix[4][4]; and in FORTRAN as: REAL*4 matrix(4,4). In C, the translation component of this matrix is: X = matrix[3][0], Y = matrix[3][1], Z = matrix[3][2] and in FORTRAN it is: X = matrix(1,4), Y = matrix(2,4), Z = matrix(3,4).

At the point at which the matrix is applied to the object, the 3x1 position vector is added onto the matrix. It is kept separate so that we can define a fixed object center. The first transformation that we apply to the 4x4 matrix is a translate of the center of the object to the origin. After all of the rotations and scales we then apply a translation from the object center back to the origin. Then we tack on to the end the translation to the position of the object.

The vertex transformation can be depicted as follows:

Verts * [ Trans(-center) ] * [ Rotates + Scales ] * [ Trans(center) ] + Position

In general, the module writer does not have to be aware of this level detail. Note that if you use the routine GEOMedit_set_matrix for an object, though, that you are replacing the transformations that define the object center and therefore negate any center that you might have set.

Each child object is transformed by the complete matrix of its parent object. This occurs for each object all the way up to the top-level object. After its transformation has been applied, we are now in the "world coordinate" system. The world coordinate system is where light sources are defined.

Light Transformations

Light sources have a simpler transformation scheme than objects. They currently do not have a center of rotation, just a 4x4 transformation matrix and a position. The resulting position of light sources is determined by applying the resulting complete transformation of the light by the default location of the light source.

This is handled slightly differently for each different type of light source:

ambient lights are not transformed at all

directional lights are transformed as a direction vector with a homogenous coordinate of zero. Effectively this means that translations are ignored. The default direction vector is pointing into the scene: (0, 0, -1)

point light sources are by default placed at: (0, 0, 1). This point is transformed regularly by the transformation matrix of the light.

spot light sources are by default such that the position of the light source is at (0, 0, 0). This position is transformed regularly by the transformation matrix. The spot light also has a direction vector which has a default of (0, 0, -1) and this is transformed as directional light sources are.

Camera Transformations

The camera position is defined by a single 4x4 matrix and a 3x1 position vector that defines the cameras orientation and position and a separate 4x4 matrix that defines the projection for the camera matrix.

The resulting viewing pipeline is depicted as follows:

( Verts * [ Obj Matrices] * [ View Orientation ] + Position ) * [ Projection ]

The main utility for keeping the projection in a separate matrix is because it prevents us from applying any transformations after the perspective transformation.

In the Geometry Viewer, when you turn on and off the Perspective and Front/ Back Clipping buttons, you are modifying the default projection matrix. When you scale or rotate the camera, you are post-concatenating onto the "View Orientation" matrix. Using the GEOM routine GEOMedit_set_matrix with a camera sets the "View Orientation" matrix. Using the GEOM routine edit list Routines

GEOMdestroy_edit_list
GEOMdestroy_edit_list(list)
GEOMedit_list
list;

Destroys an existing edit list.

GEOMedit_backface
GEOMedit_backface(list, name, mode)
GEOMedit_list list;
char *name;
int mode;

This routine can be used to change the named object's backface properties. Backface properties determine how polygons that are facing away from the viewer are drawn. Vertices that are oriented in a clockwise fashion are backfacing. This is equivalent to the "right-hand" rule of orienting polygons.

Possible values for the mode argument are: GEOM_BACKFACE_NORMAL, GEOM_BACKFACE_CULL_BACK, GEOM_BACKFACE_CULL_FRONT, GEOM_BACKFACE_FLIP, GEOM_BACKFACE_INHERIT.

GEOM_BACKFACE_NORMAL

This mode causes the object's backfaces to be drawn in the normal backface mode for the specific renderer. Some renderers "flip the normals" when a polygon is backfacing so that the backside of the polygon is lit in the same way as the front face. Other renderers light the backface of the polygon with the ambient intensity as the normal rendering mode.

GEOM_BACKFACE_FLIP

Some renderers support both the mode where backfaces are lit and the mode where backfaces are colored with only the ambient intensity. If this is the case, the normal mode will be where backfaces are lit with ambient intensity. In this case, the GEOM_BACKFACE_FLIP mode can be used to cause the normals to be flipped and the backfaces to lit like front faces. Using bi-directional light sources is a partial work around for systems that do not support the GEOM_BACKFACE_FLIP rendering attribute.

GEOM_BACKFACE_CULL_BACK

This backface mode causes the renderer to not draw polygons that are backfacing.

GEOM_BACKFACE_CULL_FRONT

Some renderers support this rendering mode in which front faces are not drawn. This mode is of limited utility and is only useful when the renderer does not accurately determine front versus backfaces.

GEOM_BACKFACE_INHERIT

This mode causes the specified object to inherit the backface property of its parent object. This is the default backface property for a newly created object.

GEOMedit_camera_orient
GEOMedit_camera_orient(list, name, flags, scale, at, up, from)
GEOMedit_list list;
char *name;
int flags;
float scale, at[3], up[3], from[3];

This routine sets the camera orientation of the camera specified by name. See the section "Edit Lists" for information on how to specify camera names. The flags argument contains the or'd combination of the values: GEOM_CAMERA_SCALE, GEOM_CAMERA_AT, GEOM_CAMERA_UP, GEOM_CAMERA_FROM. If you use one of the above flags, the corresponding argument will be used to set the camera orientation. If a flag is not specified, then the corresponding argument you supply will be ignored by the routine. You must, however, supply a valid floating point number or array of floating point numbers in its place. Normally, you can use the value GEOM_CAMERA_ALL to indicate that all of the values should be applied to the camera.

See the section in the "Geometry Viewer Subsystem" chapter of the User's Guide on "Camera Options" to determine the precise interpretation of the values: scale, at, up, and from.

GEOMedit_camera_orient modifies the same transformation as the routine GEOMedit_set_matrix when GEOMedit_set_matrix is used with a camera name argument.

GEOMedit_camera_params
GEOMedit_camera_params(list, name, options, val)
GEOMedit_list list;
char *name;
int options, val;

This routine modifies camera parameters for the camera specified by the name parameter. (See the section on "Edit Lists" for more indicates which parameters values are to be modified. The val parameter indicates whether to turn the parameters on or off. Possible values for the options parameter are:

GEOM_CAMERA_DEPTH_CUE
GEOM_CAMERA_ZBUFFER
GEOM_CAMERA_SORT_TRANSPARENCY
GEOM_CAMERA_GLOBAL_ANTIALIAS
GEOM_CAMERA_PERSPECTIVE
GEOM_CAMERA_AXES
GEOM_CAMERA_FREEZE
GEOM_CAMERA_SHOW
GEOM_CAMERA_DOUBLE_BUFFER
GEOM_CAMERA_SHADOWS

The val parameter is a 1 to turn the specified parameters on, and a 0 to turn the specified parameters off.

GEOMedit_camera_project
GEOMedit_camera_project(list, name, flags, front, back, fov, wsize)
GEOMedit_list list;
char *name;
int flags;
float front, back, fov, wsize;

This routine sets the camera projection matrix of the camera specified by name. See the section "Edit Lists" for information on how to specify camera names. The flags argument can contain the or'd combination of the values: GEOM_CAMERA_FRONT, GEOM_CAMERA_BACK, GEOM_CAMERA_WSIZE, GEOM_CAMERA_FOV. If you use one of the above flags, the corresponding argument will be used to set the camera orientations. If a flag is not specified, then the corresponding argument you supply will be ignored. You must, however, pass a valid floating point number in its place. Normally you can use the value: GEOM_CAMERA_ALL to indicate that all of the values should be applied to the camera.

See the "Camera Options" section in the "Geometry Viewer Subsystem" chapter of the User's Guide for an explanation of the precise interpretation of the values: front, back, fov, and wsize.

This routine modifies the same transformation as the routine: GEOMedit_projection.

GEOMedit_center
GEOMedit_center(list, name, center)
GEOMedit_list
list;
char *name;
float center[3];

Sets the center of rotation of the object specified. This does not currently work for lights. The center of rotation is defined before the object's transformation matrix is applied. It should, therefore, be defined in the same coordinate system as the vertices of the object.

GEOMedit_clip_plane
GEOMedit_clip_plane(edit_list, name, clip, state)
GEOMedit_list list;
char *name;
char *clip;
int state;

This routine can be used to specify arbitrary clip planes from a module. Arbitrary clip planes cause geometric objects to be clipped by a plane that has an arbitrary position and orientation. This is implemented using a geometric object to represent the clip plane. We call this the "clip object." The clip object's transformation is then used to specify the position and orientation of the clip plane. The default position of the clip plane is (0,0,0) and the initial normal to the clip plane is the Y axis. Objects are "inside" the clip plane if they are in the positive direction of the Y axis. The position and orientation are transformed by the clip object's current transformation matrix.

An object can be clipped either to the "inside" or "outside" of the clip object. If an object is clipped to the "inside" and the clip object has an identity transformation, only the geometry that has a positive Y component will be drawn. If an object is clipped to the "outside", only geometry with a negative Y component will be drawn.

The GEOMedit_clip_plane defines the object with name clip to be a clip object for the object named name. If the object named clip does not exist, a new object is created as an immediate child of the top object. clip can be any existing object. All that is used from the clip object is its transformation matrix to define a clip plane that will clip name.

The clip state of an object, defined by the state parameter, can be set to one of the following values:

GEOM_CLIP_INSIDE
GEOM_CLIP_OUTSIDE
GEOM_CLIP_IGNORE
GEOM_CLIP_INHERIT

The default clip state for a given clip plane object and object to be clipped is GEOM_CLIP_INHERIT. Here the clip state is inherited by all descendants of name that do not specify a different state for the same clip object. For example, if you specify that the object "bar" should clip the "top" object to the inside (with state GEOM_CLIP_INSIDE), all descendants of "top" (including "bar" itself) will be clipped by the clip plane defined by the current transformation of "bar". If you then specify that "bar" should not be clipped by "bar" (with state GEOM_CLIP_IGNORE), all descendants of "top" except for "bar" and its descendants will be clipped.

An arbitrary number of clip planes may be defined, but different rendering implementations may provide a different number of actual clip planes.

This feature is only supported on some renderers. It can always be accessed through the software renderer if your particular hardware renderer does not support it.

GEOMedit_color
GEOMedit_color(list, name, color)
GEOMedit_list
list;
char *name;
float color[3];

Sets the color of the object named name. The color argument is an RGB triple, each float in the range 0.0 to 1.0. If the name argument is "cameran", where n is an integer ranging from 1 to the number of views, this routine sets the background color for the view specified by the index n. If the name argument is "lightn", where n is an integer ranging from 1 to the number of light sources, this routine sets the light source color for the light source specified by the index n.

GEOMedit_concat_matrix
GEOMedit_concat_matrix(list, name, matrix)
GEOMedit_list
list;
char *name;
float matrix[4][4];

Post-concatenates matrix to the matrix of the object named name. If the name argument is "cameran", where n is an integer ranging from 1 to the number of views, this routine post-concatenates matrix to the camera matrix for the view specified by the index n. If the name argument is "lightn", where n is an integer ranging from 1 to the number of light sources, this routine post-concatenates matrix to the light matrix for the light source specified by the index n.

GEOMedit_depth_cue_params
GEOMedit_depth_cue_params(list, name, flags, depth_front, depth_back, depth_scale)
GEOMedit_list list;
char *name;
int flags;
float depth_front, depth_back, depth_scale;

This routine modifies the depth cueing attributes for the camera defined by name. See the "Edit Lists" section for more information on how to specfiy camera names. The flags argument is an or'd combination of the following constants: GEOM_DEPTH_CUE_FRONT, GEOM_DEPTH_CUE_BACK, and GEOM_DEPTH_CUE_SCALE. If you use one of the above constants, the corresponding attribute will be modified. Alternatively, you can specify the constant GEOM_DEPTH_CUE_ALL to modify depth_front, depth_back, and depth_scale parameters.

See the "Camera Options" section of the "Geometry Viewer Subsystem" chapter in the User's Guide for the precise interpretation of the depth cue parameters: depth_front, depth_back, and depth_scale,

GEOMedit_geometry
GEOMedit_geometry(list, name, obj)
GEOMedit_list
list;
char *name;
GEOMobj *obj;

Specifies a change in the geometry for an object named name in the edit list list. The first edit geometry entry in an edit list for a specific object replaces all existing geometry for this object with the geometry specified by obj. All other edit geometry entries for the object named name simply add additional geometry to that object.

Entering geometry into an edit list does not copy the geometric description of the object. Instead, it creates a reference to the GEOMobj specified in the call to GEOMedit_geometry. This means that a module must take care not to modify the GEOMobj until the edit list has been destroyed. The module must also destroy its own reference to the GEOMobj, using GEOMdestroy_obj, when it is finished with the geometry. For most purposes, a call to GEOMdestroy_obj should be made after every call to GEOMedit_geometry.

GEOMedit_parent
GEOMedit_parent(list, name, parent)
GEOMedit_list
list;
char *name;
char *parent;

Sets the parent of the object named name to be the object named parent. The top level object is referred to by a "NULL" name entry.

GEOMedit_light
GEOMedit_light(list, name, type, status)
GEOMedit_list
list;
char *name, *type;
int status;

Changes the light source representation for a light source. The light source name is "lightn", where n is an integer from 1 through 16. The type argument is one of "spot", "directional", "point", or "bi-directional". If the status argument is 1, the light source is on; if the status argument is 0, the light source is off.

GEOMedit_position
GEOMedit_position(list, name, position)
GEOMedit_list
list;
char *name;
float position[3];

Sets the position vector for the object specified. Positions are always applied after the matrix that you can set with GEOMedit_set_matrix. See the section on Geometry Viewer transformations for more information on the position.

GEOMedit_properties
GEOMedit_properties(list, name, ambient, diffuse, specular, spec_exp,
transparency, spec_col
)
GEOMedit_list
list;
char *name;
float ambient, diffuse, specular, spec_exp;
float transparency, spec_col[3];

Changes the material properties of the object named name. The properties are ambient, diffuse, and specular reflection coefficients; specular exponent; transparency; and specular color (as an RGB triple). Values to be changed are in the range 0.0 to 1.0 except for the specular exponent, which is greater than or equal to 1.0. If any value is -1.0, that property is not changed.

GEOMedit_projection
GEOMedit_projection(list, name, projection)
GEOMedit_list
list;
char *name;
float projection[4][4];

Sets the projection matrix for a particular camera. The argument "name" is as described above under "Edit Lists". See the section on Geometry Viewer transformations in this chapter for more information on how the projection is applied.

GEOMedit_render_mode
GEOMedit_render_mode(list, name, mode)
GEOMedit_list
list;
char *name;
char *mode;

Sets the render mode of the object named name to one of "gouraud", "phong", "lines", "smooth_lines", "no_light", "inherit", or "flat".

GEOMedit_selection_mode
GEOMedit_selection_mode(list,name,mode,flags)
GEOMedit_list
list;
char *name;
char *mode;
int flags;

This routine sets the selection mode of the object given. It can be used for two major purposes: 1) to make an object "unpickable" by the user, 2) to allow an upstream module to receive pick information when this object is selected.

Values for the "mode" argument are:

notify

Notify the calling module when the object "name" is selected by the user. If the object is subsequently selected, and the module has an input port connected to the render geometry output port named: "Geom Info", the module will be executed with some information pertaining to the specifics of the selection.

normal

Restore the selection mode of the object to normal. No module will receive selection information from the object.

ignore

Do not allow the user to pick the object specified. Any attempt to pick the object will result in a pick of the parent object instead.

The flags argument is only relevant when the notify mode is set. It should contain one or more of the following flags: BUTTON_DOWN, BUTTON_UP, BUTTON_MOVING. The definition for these flags is contained in the include file <avs/udata.h>.

The flags field indicates for what button states information should be redirected to the module.

GEOMedit_set_matrix
GEOMedit_set_matrix(list, name, matrix)
GEOMedit_list
list;
char *name;
float matrix[4][4];

Sets the transformation matrix for the object named name to the matrix matrix. If the name argument is "cameran", where n is an integer ranging from 1 to the number of views, this routine sets the camera matrix for the view specified by the index n. If the name argument is "lightn", where n is an integer ranging from 1 to the number of light sources, this routine sets the light matrix for the light source specified by the index n.

GEOMedit_subdivision
GEOMedit_subdivision(list, name, subdiv)
GEOMedit_list list;
char *name;
int subdiv;

This routine sets the sphere subdivision object attribute of the object specified by name to the value subdiv. The subdiv parameter determines the number of polygons used to tesselate a sphere on systems that cannot render spheres directly. A subdivision parameter of 1 draws spheres as tetrahedra. A parameter of 2 subdivides each triangle in the tetrahedra into three triangles. This process occurs so that with each increment in the subdivision parameter, each triangle in the previous subdivision level is subdivided into three new triangles.

GEOMedit_texture
GEOMedit_texture(list, name, texture)
GEOMedit_list
list;
char *name;
char *texture;

This routine sets the texture of a particular object. The texture argument can be the keyword "dynamic" or a filename containing the path name of a texture file. The keyword "dynamic" tells the module to set the texture that is present on the "Texture Input" port of the geometry viewer module. If there is currently no data present on that port, setting the texture to "dynamic" will be ignored.

If a filename is specified, the Geometry Viewer will read in this file and apply the texture contained in this file to the object specified. The filename must be accessible from the host that the geometry viewer module is running on. The format of the file is the same as the file format for reading in textures from the Geometry Viewer. See the User's Guide documentation on texture mapping in the "Geometry Viewer Subsystem" chapter for more details.

On systems that do not supported texture mapping, this attribute will be ignored.

GEOMedit_texture_options
GEOMedit_texture_options(list, name, options, val)
GEOMedit_list list;
char *name;
int options, val;

This routine is used to change the method by which a particular named object is texture mapped by turning on and off particular texture mapping options. The object whose texture options are to be modified is referred to by the name argument. The options argument specifies which options are to be changed. Possible values are: GEOM_TEXTURE_FILTER, GEOM_TEXTURE_ALPHA, and GEOM_TEXTURE_VOLUME. The val argument specifies whether or not the particular flag is to be turned on or off. A value of 1 specifies that the flag is to be turned on, a 0 specifies that the value is to be turned off. The GEOM_TEXTURE_FILTER argument, when turned on, indicates that the object, when texture mapped, should be rendered with filtered (i.e., antialiased) textures. The GEOM_TEXTURE_ALPHA argument when enabled specifies that the alpha channel of the texture map should be used for opacity values when rendering the texture mapped object. An opacity of 0 means that the object is totally transparent, an opacity of 255 means that pixel is totally opaque. The GEOM_TEXTURE_VOLUME specifies that a 3D texture should be treated as a volume primitive for the object. In the case of volume rendering, the extents of the object to be volume renderered are defined by the "window" of the object as defined by the GEOMedit_window routine.

GEOMedit_transform_mode
GEOMedit_transform_mode(list,name,mode,flags)
GEOMedit_list
list;
char *name;
char *mode;
int flags;

This routine sets the transformation mode of the object with the given name. It can be used for two purposes: 1) to prevent the user from accidentally transforming an object which should always be defined in the coordinate system of its parent and 2) to allow an upstream module to receive notification when the object is transformed by the user.

Values for the "mode" argument are:

normal

Restore the transform mode to the default or normal mode. In this case, the "flags" argument is ignored.

parent

Any transformations that are applied to this object are redirected to the parent object. This mode can be used to prevent the user from transforming this object relative to its parent object. In this case, the "flags" argument is ignored.

notify

Notify the calling module when the object "name" is transformed by the user. If the object is subsequently transformed, and the module has an input port connected to the render geometry output port named: "Transform Info", the module will be executed with a variety of information including the transformation matrix of the object.

redirect

This mode is similar to the "notify" mode above. There are only two differences: 1) the transformation matrix that is accumulated for the object and passed to the module is not used in transforming the geometry of the object, 2) since the Geometry Viewer is not going to directly transform the object when the transformation matrix changes, it does not refresh the display. This mode is useful when the module is always going to regenerate the geometry of the object each time that the transformation matrix changes. Note that since the identity matrix will be used when rendering the object always, that the module will have to transform any vertices generated itself.

The flags argument is only relevant when the "notify" or "redirect" transform mode is set. It should contain one or more of the following flags: BUTTON_DOWN, BUTTON_UP, BUTTON_MOVING. The definition for these flags is contained in the include file <avs/udata.h>.

The flags field indicates for what button states information should be redirected to the module. Transformations that are not caused by mouse movement use the state BUTTON_UP.

See the "Upstream Data" section of the "Advanced Topics" chapter for more information on using the transform mode from a module.

GEOMedit_visibility
GEOMedit_visibility(list, name, visibility)
GEOMedit_list
list;
char *name;
int visibility;

Sets the visibility of the object named name. If the visibility argument is 1, the visibility is set to on; if the visibility argument is 0, the visibility is set to off; if the visibility argument is -1, the object is deleted.

GEOMedit_window
GEOMedit_window(list,name,window)
GEOMedit_list
list;
char *name;
float window[6];

This routine allows the user to specify the "window" of interested for an object. It allows a module to cause the Geometry Viewer to "auto-normalize" and "auto-center" the top level object when the window changes. By default, the Geometry Viewer will only display geometry that is in the range -5 to 5 in X and Y. Either you must scale and translate your data to lie in this range or you must change the transformation matrix of either the object, a parent of the object or the camera so that your geometry will become viewable.

The GEOMedit_window routine implements a mechanism whereby the geometry viewer will handle this scale and translate automatically. It does so in a way that allows multiple geometry producing modules to cooperatively decide on a global scale/translate that displays all geometries that are produced. It also keeps that data in the natural coordinate system in which the data is defined. This allows the Geometry Viewer to display data sets that are defined in the same physical coordinate system simultaneously without distorting their interrelationships.

The window that is specified by the module contains an array of 6 floating point numbers in the order: minimum X, maximum X, minimum Y, maximum Y, minimum Z, maximum Z. These values define a bounding box relative to the top level object (i.e. not transformed by the object's own transformation). This box should contain the range of the coordinate system of interest. For example, if your vertices lie within 0-100 in X, Y and Z, your window should be: 0, 100, 0, 100, 0, 100. The window should include any transformations that are going to be applied to the object (not including the top level object). For example, if your vertices are defined as above, but you are going to scale your object down by a factor of 2, the window should be set to : 0, 50, 0, 50, 0, 50.

The window is associated with a particular object. While that object still exists in the scene and it still has a window defined for it, it will continue to be used to determine the scale and position of the top level object.

The Geometry Viewer maintains a global "window" that includes the extent of all windows currently defined in the scene. Whenever an "edit window" request is received, the Geometry Viewer recomputes the new window by com

puting a box that surrounds all of the windows currently defined. If the new global window is different from the old global window, the scene is scaled and translated so that the new global window will lie inside of the viewable region of the screen. The rotation/scale center of the top level object is also set to be the center point of the global window.

If the window does not change between subsequent "edit window" requests, the top level object's transformation is left unchanged.

GEOMinit_edit_list
GEOMedit_list
GEOMinit_edit_list(
list)
GEOMedit_list
list;

Initializes an existing edit list (removes all existing entries). If list is GEOM_NULL, it returns a new empty edit list.


TOC PREV NEXT INDEX

Copyright © 2001 Advanced Visual Systems Inc.
All rights reserved.