HOOPS/3dGS API Conventions
Learning a few simple principles will make it easier to use HOOPS. As its name specifies, HOOPS is a hierarchical, object-oriented picture system. HOOPS takes advantage of this hierarchy in ways significantly beyond those found in any other graphics system. Because the objects in this hierarchy are segments, the majority of operations in HOOPS are performed on segments.
Language
The language of HOOPS has just a few dozen nouns and verbs, but there are many combinations. There are about 1000 commands in HOOPS - far too many for you to learn all of them - but if you know the vocabulary of HOOPS, you will almost always guess the right command for a particular task on the first try.
A HOOPS command consists of a verb followed by a noun; for example, in Set_Color
, the verb is “Set” and the noun is “Color”. There are also adverbs, prepositions, and a few other common parts of speech.
Nouns
The nouns in HOOPS are:
Attributes: for example, Color or Line_Weight
Geometry: for example, Circle or Polygon
Events: for example, Location_Event or Selection_Event
Other Objects: for example, Segment
Verbs
The following describes the most common HOOPS verbs:
Set: Set assigns a value for an attribute. The Set verb is used with a noun that is an attribute - for example, Set_Color
or Set_Line_Weight
. A Set command sets the value of an attribute on the currently open segment. If this segment already has a value for the attribute being set, the old value is discarded.
UnSet: UnSet is the opposite of Set. It removes a local attribute from a segment, so that the attribute can be inherited. On a newly created segment, all attributes are initially unset, so you typically need to unset an attribute only if you set it previously. For attributes that have values on and off, setting the attribute off is not the same as unsetting it. For example:
HC_Set_Visibility("off");
…makes the current segment invisible, whereas:
HC_UnSet_Visibility();
…removes any local visibility on the current segment, and says that the current segment inherits its visibility attribute from its parent segment (whose visibility may be on or off, or itself inherited).
UnSet_One: Although many attributes have single values (such as visibility and line weight), a few attributes are composite - they are made up of multiple values. For example, the color attribute is a composite attribute. We can use the Set_Color
command to set the color of lines, polygon faces, text, and lights, and we can also use it to set lighting attributes, such as the diffuse, specular, gloss, and transmissive colors. The UnSet_Color
command discards all color information in a segment. If you want to unset a single color attribute, use the UnSet_One_Color
command. For example, to unset the line color only, you can say
HC_UnSet_One_Color("lines");
…and the line color will be inherited, and the other color attributes (face color, diffuse color, and so on) will be left alone.
Insert: The “Insert” verb inserts a new piece of geometry into the currently open segment. The arguments depend on the kind of geometric entity being inserted. Examples are:
HC_Insert_Circle(point1, point2, point3);
HC_Insert_Cutting_Plane(a, b, c, d);
HC_Insert_Local_Light(0.0, 5.0, 10.0);
HC_Insert_Text(0.0, 0.0, 0.0, "hello, world!");
Define: In HOOPS, almost every possible setting on the graphics system is implemented as an attribute on a segment. This characteristic is one of the ways that HOOPS is object oriented and declarative. Even so, there are a few settings that are global - they affect all the HOOPS system, rather than only a segment. For example, the Define_Alias
command defines aliases such as “?Picture”, the Define_System_Options
command defines options that apply to the entire system, and the Define_Color_Name
command lets you add new color names (such as “avocado” or “harvest gold”) to the ones HOOPS knows. Commands that change global settings always use the verb Define.
Show: Commands that use the verb “Show” always return information about HOOPS to the caller, and are what enable the developer to query the contents of the HOOPS database. This information may be an attribute that was set with the Set verb, the geometry of an object created by an Insert command, global information that was set with the Define verb, information about an input event, or system information. Here are examples:
// the color of the current segment
char color[256];
HC_Show_Color(color);
// the definition of a named color
char definition[256];
HC_Show_Color_Name("moose brown", definition);
// the elapsed time
float time;
HC_Show_Time(&time);
Show_One: Like the UnSet_One verb, the Show_One verb is used to display one attribute of a compound attribute. For example, to show the diffuse color attribute of the current segment, we can use
char diffuse_color[80];
HC_Show_One_Color("faces", diffuse_color);
Show_Net and Show_One_Net: As of HOOPS 3DF 19.00, most Show_Net and Show_One_Net functions have been deprecated (if your Show_<one>_Net function cannot be found in the full reference index, it has been deprecated). If you use these functions in your code, you can include the header hc_legacy.h in your files to successfully compile your code with the latest version of HOOPS Visualize. However, we suggest that you carefully review your code to determine if it is feasible for you to use a PShow function.
PShow: This variant allows the net attributes of an include segment to be calculated along a singular path through the HOOPS scene graph. For example, if Show_Net_Modelling_Matrix
(deprecated) is called on a segment “Tire” in the Include Library, the result will consist of the combined matrices of “Tire” and its parents in the Include Library. On the other hand, if “Tire” has been included and rotated within the view segment, then presumably a call to Show_Net_Modelling_Matrix("Tire")
would provide the net rotation on the scene rather than the include library. Since the included segment has no knowledge of where it has been included in the scene, such a call will not return the desired information. By using PShow_Net_Modelling_Matrix
, the user can obtain the correct information (in this case, the net rotation of the car and the tire) by passing in a string of keys that correspond to the path through the view. This can be called on each tire of the car even though the tires are repeated instances of the same included geometry.
Sometimes we don’t want the entire net attribute hierarchy from a leaf all the way up to the root, rather we want just the attributes of a segment relative to one of its ancestors. You can force the PShow_Net
routines to return this information by providing a list of keys from the leaf to the ancestor segment, and appending a value of -1
as the last array entry of the keys
parameter. In this case, PShow_Net
will not calculate attributes beyond the end of the last specified key. Imagine you have a factory full of robots, where you want to know the modelling matrix from the arm of the robot relative to the robot’s base. Using -1
will return this information instead of the global position of the robot arm within the entire factory.
Compute: The Compute verb is used by utility commands. The utility commands are usually not strictly necessary to the operation of HOOPS; they are simply there to help you write your application. For example, the Compute_Dot_Product
function computes the vector dot product of two input vectors.
Adverbs
There is a variation on HOOPS verbs indicated by the suffix “By_Key”.
By_Key: Commands that take a key as an argument are suffixed by the adverb “By_Key”. An example is Delete_By_Key
. A few commands, such as Edit_Polygon
, whose noun is some kind of geometry, always take a key (since geometry is always referred to with a key), so they do not bother with the “By_Key” suffix.
As of HOOPS 3DF 19.00, most variants that begin with Q, K or QK have been deprecated (if your Show_Net function cannot be found in the reference index, it has been deprecated). If your application uses these functions, you can successfully compile your code with the latest version of HOOPS Visualize by including the hc_legacy header in any files that use the Q, K or QK variants. However, we suggest that you carefully review your code to determine if it is feasible for you to use the non-variant function.
Verbs That Apply to Specific Objects
Several verbs are categorized most accurately by the object of the verb.
Verbs For Segments: Some commands - for example, the Open_Segment
, Close_Segment
, Copy_Segment
, Create_Segment
, Delete_Segment
, Include_Segment
, Rename_Segment
, and Style_Segment
commands - all have the same noun, “Segment”. With the exception of Open, Close, and Delete, these verbs are used only with segments. The command Flush_Contents
, and its variants Flush_Geometry
and Flush_Attributes
, also operate on segments.
Verbs For Deleting Entities By Key: If you have a key for an entity (a segment or some geometry), you can delete that entity with the Delete_By_Key
command. You can also delete the contents of an entity with the Flush_By_Key
command. These commands do not take a noun, because the key can refer to different kinds of entities (segments or geometry).
Verbs For Transformations: Even though transformations are attributes, they are different from other attributes in that performing a transformation on a segment does not replace the existing transformation. Instead, the new transformation is concatenated onto the old transformation. For example, a rotation of 5 degrees followed by a rotation of 10 degrees results in a total rotation of 15 degrees. Consequently, HOOPS has no Set_Rotation
command (since the Set verb would imply replacement of the existing attribute value); instead, this command is called Rotate_Object
. The Scale_Object
and Translate_Object
commands are similar. There is a Set_Modelling_Matrix
command that explicitly sets the modelling matrix (replacing any previous modelling matrix, and so deleting any previous Rotate, Scale, or Translate), and also an Append_Modelling_Matrix
command that appends a modelling matrix onto the existing transformation matrix. These two commands are used rarely. (Note that these two commands spell modelling as “modelling”, with two letter ls).
Verbs For Editing Geometry: You can modify complex geometric entities - such as images, shells, meshes, polygons, polylines, and text - to change their geometry. The Edit verb takes one of these kinds of geometry as a noun (for example, Edit_Polygon
). In the case of a shell, you can edit the faces or the points separately with Edit_Shell_Faces
and Edit_Shell_Points
.
Verbs For Moving Geometry: You can change the position of images and text using the Move verb (for example, Move_Image
and Move_Text
). You can also move the position of a light (with Move_Light_Position
or Move_Distant_Light
), or the direction in which the light is shining (for example, Move_Light_Target
for a spot light).
The one exceptional use of the Move verb is for the Move_By_Key
command, which is used to move an object (subsegment or geometry) from one segment to another (rather than to change the object’s coordinates).
Verbs for Opening and Closing Geometry: Shells and meshes are complex enough that you can set attributes on their subparts. For example, you can set a color on each face of a shell or mesh. To do so, you open the entity (in the same way that you open a segment) using the Open_Geometry
command, then open the subpart (edge, face, or vertex) on which you want to set an attribute, set the attribute, close the subpart, then close the entity.
There is one special verb, MSet, used to set attributes on multiple shell or mesh vertices simultaneously, for speed.
Verbs For Cameras: The noun “Camera” has its own set of verbs using terminology from the film-making industry. The verbs that can be used with a camera are Dolly, Orbit, Pan, Roll, and Zoom (for example, Zoom_Camera
).
Verbs For Events: Another group of verbs is used for events. Some of these verbs are used with the noun “Event”, such as Await_Event
, Requeue_Event
, and Check_For_Events
(note plural). Others are used with specific kinds of events. For example, the Enable, Disable, and Queue verbs can be used for Button_Events, Location_Events, Selection_Events, String_Events, or Wakeup_Events (for example, Enable_Selection_Events
). You can also define your own kind of event with Queue_Special_Event
, and can get rid of all current events with Flush_All_Events
.
Verbs For Direct Input: The verb Get is used to get one piece of input. Get can be used with the nouns Button, Location, Selection, String, and Wakeup (note the similarity to verbs for events). The Get commands are convenience commands that enable a certain kind of event, wait for one event, and then return the value from the event. Although simple to use, they are limited to getting one kind of input. For example, if your application calls Get_Selection
, HOOPS dutifully waits for a selection and ignores all other input. If the user instead types on the keyboard, those events will be lost. We avoid using the Get commands in this book.
Verbs For Metafiles: The Read and Write verbs are used to read and write HOOPS metafiles (for example, Write_Metafile
).
Verbs For Searching: The Begin, Find, and End verbs are used for searching the database. The possible kinds of searches are Alias, Callback_Name, Color_Name, Contents, Font, Open_Segment, Segment, and Texture. For example, to print out all aliases about which HOOPS knows, you can use the following:
char alias_name[256];
char alias_value[256];
HC_Begin_Alias_Search();
while (HC_Find_Alias(alias_name)) {
HC_Show_Alias(alias_name, alias_value);
printf("%s = %s\n", alias_name, alias_value);
}
HC_End_Alias_Search();
You can perform the same task with a color-name search to print out all the color names that HOOPS knows.
Miscellaneous Commands
For completeness, this section contains a complete list of the HOOPS commands that do not fall into one of the categories listed in the previous sections:
Abort_Program
Bring_To_Front
Control_Update
Exit_Program
Modify_Color_Map
Parse_String
andPause
Print_Version
Relinquish_Memory
Renumber_Key
Report_Error
Reset_System
Restart_Ink
Scroll_Text
Update_Display
Most of these commands are self-explanatory (you can look up those that are not in the HOOPS Reference Manual).
Idioms
There are two different ways that you can delete objects in HOOPS, and correspondingly there are two verbs: Delete and Flush. You can use Delete_By_Key
, and you can use Flush_By_Key
. The Delete verb deletes the object indicated by the key, whereas the Flush verb deletes the object’s contents, leaving the object itself intact. So far, so good. You can also use Delete_Segment
to delete a named segment, but you cannot use Flush_Segment
- instead, you can use Flush_Geometry
, Flush_Attributes
, or Flush_Contents
. These commands allow you fine control over what you flush out of a segment. (An earlier version of HOOPS had an Flush_Segment
command, but that command was made obsolete when the others were introduced.)
HOOPS distinguishes between attributes (set with the verb Set) and global settings (defined with the verb Define), but both of them use the same verb (Show) to show what was set or defined.
Even though the camera attribute is a compound attribute consisting of a camera position, camera target, up vector, field of view, and projection, it does not use the Show_One verb in the same way as other compound attributes do. For example, to show the camera position, you use the command Show_Camera_Position
, rather than Show_One_Camera("position")
. This syntax was necessary because the different components of the camera attribute return different values, so they need to have different commands with different arguments. In addition, there is no way to unset one camera attribute (because individual camera attributes do not inherit).
There are three commands that use the Set verb, but do not set an attribute on a segment: Set_Normal
, Set_Priority
, and Set_Parameter
. These commands set attributes on a subpart of a geometric entity. For example, Set_Normal
is used to set the normal vector of a face, edge, or vertex of a polygon mesh or shell.
HOOPS is not consistent in its use of names for different coordinate spaces. Most of the time, the words “world” and “user” are used interchangeably to refer to world (user) coordinates, and the word camera to refer to camera coordinates. One command (Compute_Coordinates
), however, uses the word camera to refer to world coordinates (the claim is that this coordinate system is the one in which the position of the camera is set), and calls camera coordinates viewpoint coordinates.
Philosophy
HOOPS has a definite philosophy. We have witnessed more than one discussion, when a new feature was being added to HOOPS, concerning the “HOOPS way” to implement the feature. Writing down that philosophy might entail a few chapters itself. The following sections review a few points that might affect you as a user of HOOPS.
Lights, Camera, Action
In other graphics systems, the graphics database is used to store only primitives (geometry and attributes); other information needed to render a scene is kept separately. For example, we have already seen how HOOPS rendering options and driver options are stored as attributes in the database. Other information that is needed before a scene can be drawn includes the location and kind of lights, and the location and orientation of the camera. HOOPS takes the bold step of storing this information in the database too, right along with the graphics primitives.
For example, HOOPS treats lights as geometry. Thus, you use the Insert verb to insert a light (for example, Insert_Spot_Light
). On the other hand, a camera is an attribute, so you create a camera using the Set verb (e.g., Set_Camera
).
Because a light is geometry, it can be affected by attributes, so you can use Set_Color
to set the color of a light, or you can let the light inherit its color from a parent. Because a camera is an attribute, it can be inherited by the children of the segment on which it is set. Storage of information such as lights, cameras, and rendering options in the database reflects the declarative nature of HOOPS.
Defaults
Many graphics systems require you to specify a substantial amount of information before you can draw anything. For example, you might have to specify a color and a line width before you can draw a line, or a font before you can draw a character. HOOPS has reasonable defaults for every possible attribute, so drawing a picture with HOOPS can be as simple as writing three lines of code. HOOPS uses inheritance to allow the programmer to accept or override these values as needed.
Convenience
HOOPS often provides multiple ways to accomplish the same goal, so you can choose the one that is most convenient for you. For example, colors can be specified by name (e.g., “dark reddish orange”) or with an RGB (red, green, blue), HSV (hue, saturation, value), HLS (hue, lightness, saturation), or HIC (hue, intensity, chromaticity) triple, or as an index into a color map.
One problem with allowing attributes to be set in multiple ways is that, if you show such an attribute (for example, with Show_Color
), you may not get back the exact value that you specified (you will get back an equivalent value, but it may be represented differently). To solve this problem, you can use a command such as Compute_Color
to convert the returned value back to your preferred color system.
Consistency Across Platforms
HOOPS attempts to create the same image on all platforms, regardless of the underlying hardware. If you request a certain feature and the hardware does not provide it, HOOPS will fill in with software. For example, in many graphics systems, if you request Phong shading and the hardware provides only Gouraud shading, you get Gouraud shading. When you use HOOPS, you get Phong shading. The image may come up slower than it would were it computed with special hardware, but if speed is important, your application can always ask whether a specific kind of hardware is available with the Show_Device_Info
command.
Of course, if you request the color red and you have only a black-and-white display, there is nothing HOOPS can do short of writing you a check for a new system. Nevertheless, HOOPS goes significantly beyond any other commercial graphics system in delivering the same image across multiple platforms, regardless of hardware.
Heuristics
HOOPS takes the view that it is good for the application writer to provide HOOPS with hints on the most effective ways to render a scene; these hints are called heuristics. Often, specifying a few heuristics can speed up your application dramatically.
Strings
Many attributes in HOOPS are specified as character strings. For example, colors can be specified with names such as “dark reddish orange” (there is also a way to specify a color by numeric value). One advantage of using strings is portability - HOOPS runs on platforms where an integer is as short as 16 bits and as long as 64 bits. Character strings are much more portable (even on systems that use 16-bit characters or Unicode).
The use of strings also allows you to set attributes using environment variables, and to save them in ASCII metafiles. HOOPS contains a fast parser for character strings. The use of strings also lets the programmer specify variable amounts of information clearly and succinctly. For example, you can use the Set_Color
command to set simple colors; to set different colors for the diffuse, specular, and ambient lighting; and to set separate colors for different kinds of geometry - and you can do so using your choice of color spaces (RGB, HLS, HSV, HIC). Likewise, you can use Set_Rendering_Options
, Set_Driver_Options
, and similar commands to set many different options, with different kinds of values. Without the use of strings, commands such as these would be complicated and would be much more difficult to use.
The only problem with the use of strings is that your compiler cannot check commands to change attributes to see whether they make sense. For example, if a program tries to pass a color to Set_Driver_Options
, the problem will be detected at run time, rather than at compile time.
Segments
As previously reviewed, segments are the primary organizational principle in HOOPS. In HOOPS, however, segments primarily organize attributes, rather than geometry. In particular, attribute inheritance is controlled through the segment structure of the database. Consequently, the most effective way to use segments is to group together primitives with similar attributes.
Although segments are meant to be cheap in terms of memory usage an traversal overhead, their overuse can swell the execution size of your program and can slow down rendering.