HOOPS is a retained graphics database system. You create a scene by inserting geometry and setting attributes in a segment tree maintained by HOOPS. When you call ::Update_Display (or you request input), the system traverses the segment tree and draws the picture on the display device. With the classic HOOPS library, additions and modifications to the segment tree cannot be made while HOOPS is traversing the tree.
HOOPS I.M. routines complement the classic HOOPS library and provide for traversal-time modifications of the segment tree walk. The I.M. library provides a means for the application to trap the HOOPS update cycle at certain points in the rendering pipeline, by means of a callback mechanism. When you trap the traversal at a callback point, you can make decisions about what and how something is drawn, or even abort the traversal process itself. In addition to the callback mechanism, the HOOPS I.M. library provides a set of functions you can call from your callback functions to draw to the display in an "immediate mode" style and to query the graphics database and the device characteristics.
The HOOPS selection feature also involves a traversal of the graphics database contained in the segment tree. However, the selection traversal does not draw on the display. Rather, it computes the screen positions of objects in the database to determine which objects have been hit by selection events. HOOPS I.M. provides callback points at which you can trap the selection traversal as well as the update traversal.
You would use HOOPS I.M. when you want your application to be able to make traversal-time decisions about the rendering or selection process, or to accomplish special processing that is not provided by the built-in HOOPS traversal process. Here are some examples of situations for I.M. use:
- You may want the graphical representation of your data, i.e. the actual primitives and attribute values used, to depend on the viewing parameters or the screen transformation. In particular, if your model has a hierarchy of scale and the view is zoomed out sufficiently far, then you may want to skip the rendering of entire subtrees that would appear very small on the display.
- You may want to define your own version of a HOOPS primitive. For example, you could implement a spline drawing algorithm through the HOOPS polyline primitive, using the polyline vertices as spline control points. In this case, you would intercept at one of the callback points in the polyline drawing pipeline, and substitute your own spline drawing routine for the HOOPS polyline drawing routine.
- If your graphics database is voluminous, you may want to avoid spending the memory needed for HOOPS to duplicate in its database some of the same information already contained in your application's private data structures. Using HOOPS I.M. in an "immediate mode" style allows you to pass some of your primitives to HOOPS one at a time in I.M. callbacks, rather than storing them in HOOPS segments.
- In a real-time application, you may want to be able to modify the picture being displayed according to input received during traversal.
To perform a display update, HOOPS clears the screen, then traverses the segment tree. Each segment can contain a list of inserted geometry elements, some attribute settings, and possibly a list of pointers to owned segments. Attributes are inherited down the tree while some are inherited upwards. Some attributes, such as the net modelling matrix, are accumulated down the tree. The traversal process keeps track of the current values of the attributes as it walks the tree. A rendition is a structure that contains a value for each of the defined HOOPS attributes. The net rendition is the set of attribute values that apply to a particular segment when it is processed by the traversal. Geometry stored in the segment is specified in terms of the 3D object coordinates that the application uses in inserting primitives.
At each segment, the HOOPS system processes the list of geometry elements, and passes each geometry element through a rendering pipeline to produce the pixels that are written to the screen (possibly subject to a Z-buffer test). These rendering computations include a transformation pipeline that applies the net modelling transformation to map the geometry to world coordinates, and then applies the viewing transformations and screen transformations, which are defined by the camera attributes, to map the geometry to the device coordinates that place objects on the display surface. More details on the definition of device coordinates are given below.
We can describe the traversal process and rendering pipeline in terms of a hierarchy of methods. At the top level is the method that walks the tree. A submethod of the tree walk is "draw segment", which processes all the geometry in a segment, and recursively processes its subsegments. "draw segment" is the highest level method that you can trap within the HOOPS I.M. library. HOOPS geometry elements are of several types–polygon, polyline, circle, circular arc, text, marker, mesh, shell, etc. See the discussion of ::HIC_Show_Geometry_Type in the reference section for the complete list of geometry types. The "draw segments" method traverses a segment's list of geometry elements and applies a method "draw 3d ..." to each geometry element according to its type "...". Each "draw 3d ..." method must perform the necessary modelling and viewing transformations and eventually call on lower-level "draw dc ..." drawing methods, which draw primitives specified in device coordinates. For some of the geometry types, the "draw 3d ..." method must decompose the object into smaller objects of one or more types. Thus, a mesh or shell will be decomposed into multiple faces and edges and so give rise to a number of "draw dc ..." calls.
For the text primitives, HOOPS I.M. offers the ability to trap the pipeline at an intermediate level, "draw text", between the "draw 3d text" and "draw dc text" levels of the method hierarchy. In addition, there is a provision for trapping the method "draw windows", which paints a window background and the method "draw window frame", which draws a frame around a window. The next section presents in detail the set of methods that you can trap with HOOPS I.M. callbacks.
High Level View of Drawing Pipeline
HOOPS I.M. provides the following set of callback points at which you can trap the traversal process. These are entry points to methods in the rendering pipeline for which you can define callbacks. Here they are listed in order of higher to lower levels (with respect to their level in the rendering pipeline), along with a brief description of the standard default behavior of the method.
The "draw segment" callback is called at the beginning of processing each segment for which it is in effect. As for all but the callback points, a "draw segment" callback is inherited by all the subsegments of the segment on which it is set.
The "draw segment tree" callback is like "draw segment", except that the callback is not inherited by subsegments of the segment on which it is set. This is the one exception to the rule that callbacks are inherited by subsegments. It is provided because it is frequently the case that a callback function can make a decision about the processing of the subsegment hierarchy below a given segment when the given segment is first encountered in the traversal and so does not need to be called back for every descendent segment.
The "draw window" callback is called to fill in the segment's window with the background pattern, subject to the current hard clip limits
The "draw window frame" callback is called to draw a frame around a segment's window.
The "draw 3d geometry" callback point allows you to trap the "draw 3d ..." method for all of the HOOPS 3D geometry types(ellipses, circles, arcs, etc).
The 3D Geometry Drawing Pipeline
There are callback points in HOOPS that allow you to trap specifically the "draw 3d ..." methods for each of the geometry types: marker, polyline, polygon, text, tristrip, polyedge, polymarker, ellipses, circles, arcs, etc. The first three of these essentially apply the transformations needed to map object coordinates to device coordinates, then call on the corresponding "draw dc ..." method. Text processing is somewhat more complex. See the discussion of "draw text" below for more information on the work of the "draw 3d text" method. Tristrip, polyedge, and polymarkers are associated with HOOPS shells.
The Callback Flow for Shells, Meshes and Grids
If you set a callback both at "draw 3d geometry" and at one of the type-specific callback points like "draw 3d marker", "draw 3d polyline", "draw 3d polygon", or "draw 3d text", then the latter prevails and your "draw 3d geometry" callback will not be called for geometry elements of that type.
Callbacks: draw 3d geometry, draw 3d marker, draw 3d polyline, draw 3d polygon, draw 3d text, draw 3d tristrip, draw 3d polyedge, draw 3d polymarker, draw 3d image, draw 3d grid, draw 3d mesh, draw 3d shell, draw 3d sphere, draw 3d cylinder, draw 3d polycylinder, draw 3d nurbs curve, draw 3d nurbs surface, draw 3d isoline
The "draw text" callback is at an intermediate level of the text processing, below the level of "draw 3d text". Like "draw 3d text", the "draw text" method is called once for each inserted text string. The higher level passes to "draw text" an intermediate text information structure, which contains the results of certain computations that apply to the string as a whole. The computations performed by the "draw 3d text" level include the effects on the text reference point of modelling transformation, camera, text font size, text spacing, extra space, text alignment, text path, text rotation, and text slant attributes. Finally, the intermediate text information structure will contain some intermediate results, which depend on the coordinate transformations and the text attributes, and which might be needed to apply the per-character transformations as required by the text font transformability attribute. The work of the standard "draw text" method is to reconcile the text attributes called for by the application with the capabilities of the requested font, and to complete the computations needed to draw the text. In particular, the "draw text" method is responsible for applying the per character transformations when appropriate and for applying atmospheric attenuation (fog) to text when it is called for. If the text is finally to be drawn in a font provided by the hardware, the window system, or the driver, then "draw text" eventually calls on a driver-level "draw dc text" method, which does not have an I.M callback point. Otherwise, "draw text" causes the text to be stroked out, using the ordinary geometry drawing provisions, through "draw 3d text stroke" and "draw 3d text area" when per-character transformations are in effect, or directly through "draw dc text stroke" and "draw dc text area" otherwise.
The Draw Text Drawing Pipeline
These "draw 3d text area" and "draw 3d text stroke" are effectively entry points to the "draw 3d polygon" and "draw 3d polyline" methods respectively, when the latter are called from the "draw text" level in the process of drawing characters of transformable stroked text. This includes text drawn from the built-in stroked font or user defined fonts.
These are used to draw the respective objects, specified in device coordinates, subject to the relevant attribute values in the net rendition. Device coordinates are 3D floating-point coordinates. The x and y device coordinates are in pixel units, with origin at the lower left. When the graphics platform has a windowing system, the xy origin of the device coordinates may be at the lower left of the screen or at the lower left of the outer window, which is the window-system window that contains the HOOPS picture. The device driver determines which origin is used. In any case, at traversal time, you can determine the location of the device coordinate origin with respect to your HOOPS window by calling
::HIC_Show_Window_Extent . The device z coordinate is relevant only when Z-buffering is in effect. The standard method for "draw dc edge" is exactly the same as "draw dc polyline", except that it uses the edge attributes in the net rendition rather than the line attributes. "draw dc line" is a special case of "draw dc polyline", specialized to the two-vertex polyline (line segment). It is called only from "draw dc colorized line", after the latter has changed the line color attribute according to its argument.
The Drawing Pipeline for Polygons
Note on cutting planes:
When cutting planes are present, some callbacks such as "draw dc face" will not be called. When cutting planes are involved, faces are triangulated, and they need a "draw dc triangle" callback instead.
These are used to draw the respective objects with an RGB color passed as an argument to the method, rather than with the color specified by the rendition. These are called typically in the processing of geometry elements of a constant color, when the color has been computed by HOOPS, as in the case of lighting or fog. Each of the standard "draw dc colorized ..." methods changes the relevant color attributes in the rendition and then calls on the corresponding "draw dc ..." method.
The Drawing Pipeline for Markers
Callbacks: draw dc colorized marker, draw dc colorized polymarker, draw dc colorized line, draw dc colorized polyline, draw dc colorized face, draw dc colorized triangle, draw dc colorized polytriangle
The software path for drawing cut lines from cutting planes adds a lot of overhead, resulting in poor performance. To offset this, a "draw dc cut line" callback has been added. Using this, a program can "compute" the cutting lines by drawing the scene with them visible, storing the cut lines, turning the visibility of cut lines back off (restoring the fast path drawing), and inserting the stored lines as real geometry.
Callbacks: draw dc cut line
The "draw dc gourad ..." and "draw dc phong ..." callbacks are used to draw the respective objects with color interpolated from vertex colors passed as arguments.
The driver startup and driver shutdown callbacks are called when the HOOPS driver instances are created and destroyed. As callback points they provide hooks in case the application needs to do something special. However, these points DO NOT CORRESPOND to any existing HIC functions. Therefore developers must make sure that their callback functions return, so that HOOPS can continue startup or shutdown normally.
The "finish picture" callback is called when the HOOPS driver finishes drawing to a device. Can be used to access device-specific data using device-native functions. An example would be a frame buffer grab from OpenGL using glReadPixels.
These callback points will be executed when hidden line is the active hidden surface removal algorithm. In this case the visible lines and markers will be accessible through the "hlr polyline" and "hlr marker" callbacks, while the hidden geometry can be accessed through the "hlr hidden polyline" and "hlr hidden marker" callbacks.
These are called for processing the respective database elements in the course of a selection traversal. Setting a callback for "select 3d geometry" causes the callback function to be called for all the other geometry elements for which a specific "select ..." callback has not been set. "select segment tree" behaves for selection just as "draw segment tree" does for drawing, that is, it is only called on the segment that specifies it, not inherited and called on every subsegment the way "select segment" (and "draw segment") are. Selection traversal is initiated by a ::Get_Selection, ::Show_Selection, or ::Compute_Selection call. Given the locator screen coordinates for a selection event (or in the arguments of a ::Compute_Selection call), the system traverses the database and performs essentially the same computations as when updating the display, but draws nothing on the screen. Rather, the screen locations covered by each selectable geometry item are tested against the specified locator coordinates for hits. Hit criteria include proximity, area intersection, or volume intersection. During selection traversal the system keeps a list of selected elements, i.e. those encountered elements that are selectable according to the selectability attribute, and which are hit according to the hit criteria. The list of selected elements is ordered by proximity and by z coordinate. Its length is limited by the related selection limit heuristic. At the end of the selection traversal, the application can examine the selected elements with the various Show_Selection_ functions and ::Find_Related_Selection.
These callback points will be activated when there is a modification to the segment tree under the point where the callback is set. The callback returns both the old and the new activity flags as well as the segment on which the change initially occurred. This callback is called when the actual database edit occurs, and is independent of a call to ::Update_Display.
Callbacks: segment activity change
Now that we have discussed the various callback points available through HOOPS I.M., you can implement your own callback functions. First, determine at which point you want to intercept HOOPS in the update cycle. This is important because it will tell you what parameters your function needs to accept. Once your function is created, you must register it with HOOPS. Callbacks are applied to a specific segment. So, to set your callback, open your target segment. Then, set your callback indicating the callback point and your function's callback name.
Once you are done with your callback, you should unset and unregister your callback. To find out if a specific callback has been set, you can use ::Show_Existence as seen in the following sample code:
For C Developers, the process mentioned above for creating and setting callbacks can be followed verbatim. To review, please follow the steps below:
- Create a function which accepts the parameters for the desired callback point.
- Register your callback with ::Define_Callback_Name.
- Open the segment in which you want to intercept the update cycle.
- Set the callback with ::Set_Callback or ::Set_Callback_With_Data passing the callback point and the name you gave your callback in ::Define_Callback_Name.
- Use ::UnSet_Callback and ::UnDefine_Callback_Name to unset and unregister your callback function, respectively.
The following sample code shows how a function is used to intercept the draw dc polylines callback point. The function MyPatternedLine is implemented with same signature as the analogous I.M. function, ::HIC_Draw_DC_Polyline.
In main, MyPatterenedLines is registered with the name patterned lines in a call to ::Define_Callback_Name. After a segment is created with a line inserted in it, the callback point, draw dc polylines, is set with the patterned lines callback function by using ::Set_Callback.
For C++/C#/Java developers, creating and setting callbacks involves a slightly different process although all actions previously described remain the same underneath. Instead of including hic.h, you will include hic_wraph.h. This file defines a set of classes that correspond to each callback point available in HOOPS Intermediate Mode. Once you have included this file, you can follow the steps below to set up your callbacks.
- Find the class that corresponds to the callback point you want to intercept. The class and the callback point have the same name.
Derive your own callback class from the target callback class.
- Override the constructor passing in your own callback name.
- Implement the abstract callback function.
- Open the segment in which you want to intercept the update cycle at the target callback point.
- Create an instance of your new callback class passing the key of the target segment. Now your callback has been defined and set.
- Delete the instance of your callback class when you want to unset and undefine your callback.
The sample code below shows how you can create and set a callback at draw dc polylines. A callback is set up by deriving a new class from Draw_DC_Polyline called MyPatternedLine. A new constructor is created that passes a callback name to the parent constructor. Draw_DC_Polyline::draw_dc_polyline() is an abstract method which HOOPS will call when the interception point is reached. So to use this callback, draw_dc_polyline must implemented be in MyPatternedLine. Like in the C example, the function looks at the value of the user option MY_LINE_PATTERN to see if it is PURPLE_DASHES. Then it draws a purple line with dashes. Otherwise, it calls ::HIC_Draw_DC_Polyline passing the original rendition.
HOOPS I.M. provides a library of functions that you can call from your callback functions to access the services of the HOOPS system. Presently, these functions are available only from callback functions written in C or C++. Their names all begin with HIC_ . You should refrain from calling most of the functions of classic HOOPS from your HOOPS I.M. callback functions. There are some exceptions; in particular, it is generally all right to call the classic Compute_...
functions. But calling classic HOOPS functions that alter or query the database can have unpredictable results. For each callback point, there is a HOOPS I.M. function HIC_ that you can call to pass control back to the standard default method for that callback point. The argument list of the callback is indicated with the HIC_... function. You can find the declarations of the argument types on the reference pages for the HIC_ ... functions. Here is the correspondence between callback points and the standard default functions.
|draw segment||::HIC_Draw_Segment (nr, seg_info)|
|draw segment tree||::HIC_Draw_Segment (nr, seg_info)|
|draw text||::HIC_Draw_Text (nr, text_info)|
|draw 3d marker||::HIC_Draw_3D_Marker (nr, marker)|
|draw 3d polymarker||::HIC_Draw_3D_Polymarker (nr, polymarker)|
|draw 3d polyline||::HIC_Draw_3D_Polyline (nr, polyline)|
|draw 3d infinite line||::HIC_Draw_3D_Infinite_Line (nr, polyline)|
|draw 3d polygon||::HIC_Draw_3D_Polygon (nr, polygon)|
|draw 3d ellipse||::HIC_Draw_3D_Ellipse (nr, ellipse)|
|draw 3d elliptical arc||::HIC_Draw_3D_Elliptical_Arc (nr, arc)|
|draw 3d geometry||::HIC_Draw_3D_Geometry (nr, geometry)|
|draw 3d text||::HIC_Draw_3D_Text (nr, text)|
|draw 3d text stroke||::HIC_Draw_3D_Polyline (nr, polyline)|
|draw 3d text area||::HIC_Draw_3D_Polygon (nr, polygon)|
|draw 3d sphere||::HIC_Draw_3D_Sphere (nr, sphere)|
|draw 3d cylinder||::HIC_Draw_3D_Cylinder (nr, cylinder)|
|draw 3d polycylinder||::HIC_Draw_3D_PolyCylinder (nr, polycylinder)|
|draw 3d nurbs curve||::HIC_Draw_3D_NURBS_Curve (nr, curve)|
|draw 3d nurbs surface||::HIC_Draw_3D_NURBS_Surface (nr, surface)|
|draw 3d polyedge||::HIC_Draw_3D_Polyedge (nr, polyedge)|
|draw 3d isolines||::HIC_Draw_3D_Polyedge (nr, polyedge) |
|draw 3d tristrip||::HIC_Draw_3D_Tristrip (nr, tristrip)|
|draw 3d polyhedron||::HIC_Draw_3D_Polyhedron (nr, polyhedron)|
|draw 3d shell||::HIC_Draw_3D_Shell (nr, shell)|
|draw 3d mesh||::HIC_Draw_3D_Mesh (nr, mesh) |
|draw 3d grid||::HIC_Draw_3D_Grid (nr, grid) |
|draw 3d image||::HIC_Draw_3D_Image (nr, image) |
|draw dc marker||::HIC_Draw_DC_Marker (nr, point)|
|draw dc colorized marker||::HIC_Draw_DC_Colorized_Marker (nr, point, color) |
|draw dc polymarker||::HIC_Draw_DC_Polymarker (nr, count, point, rotations, size_fixups)|
|draw dc colorized polymarker||::HIC_Draw_DC_Colorized_Polymarker (nr, count, point, color, single, rotations, size_fixups)|
|draw dc line||::HIC_Draw_DC_Line (nr, points)|
|draw dc colorized line||::HIC_Draw_DC_Colorized_Line (nr, points, color)|
|draw dc gouraud line||::HIC_Draw_DC_Gouraud_Line (nr, points, colors)|
|draw dc reshaded line||::HIC_Draw_DC_Reshaded_Line (nr, points, colors, planes, params, param_width, param_flags) |
draw dc polyline
::HIC_Draw_DC_Polyline (nr, count, points)
draw dc colorized polyline
::HIC_Draw_DC_Colorized_Polyline (nr, count, points, color, single)
draw dc gouraud polyline
::HIC_Draw_DC_Gouraud_Polyline (nr, count, points, colors)
draw dc phong polyline
::HIC_Draw_DC_Phong_Polyline (nr, count, points, colors, planes)
draw dc textured polyline
::HIC_Draw_DC_Textured_Polyline (nr, count, points, colors, planes, params, param_width, param_flags)
draw dc edge
::HIC_Draw_DC_Polyline (nr, count, point)
draw dc face
::HIC_Draw_DC_Face (nr, count, points)
draw dc colorized face
::HIC_Draw_DC_Colorized_Face (nr, count, points, color)
draw dc triangle
::HIC_Draw_DC_Triangle (nr, points)
draw dc colorized triangle
::HIC_Draw_DC_Colorized_Triangle (nr, points, color)
draw dc gouraud triangle
::HIC_Draw_DC_Gouraud_Triangle (nr, points, colors)
draw dc reshaded triangle
::HIC_Draw_DC_Reshaded_Triangle (nr, points, colors, planes, params, param_width, param_flags)
draw dc polytriangle
::HIC_Draw_DC_Polytriangle (nr, count, points)
draw dc colorized polytriangle
::HIC_Draw_DC_Colorized_Polytriangle (nr, count, points, color, single)
draw dc gouraud polytriangle
::HIC_Draw_DC_Gouraud_Polytriangle (nr, count, points, colors)
draw dc phong polytriangle
::HIC_Draw_DC_Phong_Polytriangle (nr, count, points, colors, planes)
draw dc textured polytriangle
::HIC_Draw_DC_Textured_Polytriangle (nr, count, points, colors, planes, params, param_width, param_flags)
draw dc text stroke
::HIC_Draw_DC_Polyline (nr, count, points)
draw dc text area
::HIC_Draw_DC_Face (nr, count, points)
::HIC_Draw_Window (nr, extent)
draw window frame
::HIC_Draw_Window_Frame (nr, extent frame, calc)
No corresponding HIC functions. User callback MUST return for normal startup and shutdown to continue.
::HIC_Finish_Picture (nr, swap_buffers)
::HIC_Draw_DC_Polyline (nr, count, points)
::HIC_Draw_DC_Marker (nr, point)
hlr hidden polyline
::HIC_Draw_DC_Polyline (nr, count, points)
hlr hidden marker
::HIC_Draw_DC_Marker (nr, point)
select 3d marker
::HIC_Select_Geometry (nr, marker)
select 3d polyline
::HIC_Select_Geometry (nr, polyline )
select 3d polygon
::HIC_Select_Geometry (nr, polygon)
select 3d text
::HIC_Select_Geometry (nr, text)
select 3d geometry
::HIC_Select_Geometry (nr, geometry)
::HIC_Select_Window (nr, wind_info)
select segment tree
::HIC_Select_Segment (nr, seg_info)