Highlighting

After a selection is performed, it is usually necessary to provide visual feedback to the user regarding what was selected. For example, the scene might contain a picture of an airplane wing which is represented by several pieces of geometry. However, HOOPS Visualize knows nothing about the airplane wing as a distinct concept. Therefore, if you wanted to highlight the entire wing after the user selects any part of it, you would need to figure out all the associated pieces of geometry and highlight them all. Depending on model complexity, this can be a non-trivial task.

This section will focus on some of the ways in which geometry can be highlighted as well as a strategy to manage highlighting easily. The details of how to represent highlighting are up to the developer. You could choose to modify the object's color, line weight, face pattern, visibility, shading mode, or any combination of these and other attributes. You must also choose the highlight algorithm, which is discussed below.

Defining a named style


In HOOPS Visualize, a style is a collection of attributes that is applied to a segment as a set. Styles are applied to geometry to differentiate it within a scene. It is also the recommended way to apply highlighting effects. In complex segment trees, you may have segments that are not related hierarchically, but nonetheless share common attributes. One way to apply a style would be to set attributes individually for each segment as needed. However, that is not only inefficient, but also inconvenient - especially when the modifications involve a large number of segments. Instead, defining and using a style provides a convenient way to take a set of attributes and apply them to many segments. Any attribute that can be set on a segment can also be set in a style.

The recommended way to create a style is by creating a new segment (perhaps in your style library) and setting attributes on that segment which define your style. You assign a name to the style segment. When you want to apply that style to highlighted geometry, you would call Define_Highlight, referencing the name of the style segment. UnDefine_Highlight removes the style.

Highlighting a segment

Highlighting at a segment level simply involves opening the segment and calling Define_Highlight with a previously named style. Note that this will affect the open segment, as well as any subsegments which do not have their own opinion about the attributes being modified. If you want all subsegments to have the same highlight attributes, regardless of local explicit settings, you can use the attribute lock rendering option:

HC_Set_Rendering_Options("attribute lock = color"); /* lock the value of color down the tree */

This is useful when you want to highlight an entire piece of the segment tree. For example, let's say the database was representing a drawing with multiple layers, with various systems such as HVAC, piping, and electrical. If the GUI is in 'layer highlight' mode, you could
highlight a selected layer by setting the desired highlight attributes at a top-level layer parent segment, and then setting attribute lock in that segment.

Choosing the highlight algorithm

The choice of highlight algorithm should be made based on how you want the highlight to appear. There are three modes to choose from: "InPlace", "Overlay", and "Spriting". The mode is set in the options "quick moves" parameter of Define_Highlight.

InPlace

The "InPlace" highlighting option is used when you want to use a highlight style that is partially transparent. InPlace will cause Visualize to not draw the highlighted geometry itself, since doing so would cause the color of the geometry to blend with the color of the transparent highlight. Therefore, the geometry is not drawn at all - the highlight is drawn "in its place". One downside to using this method of highlighting is that when the geometry is eventually unhighlighted, the scene will have to be redrawn. This is in contrast to "overlay" or "spriting" highlighting options, which are able to unhighlight without redrawing the scene.

Overlay

Overlay highlights are drawn on top of all other geometry in the scene. This means if you highlight a piece of geometry that is partially obscured, overlay highlights will cause that geometry to "pop out" visually, ignoring z-values. Unhighlighting does not trigger a redraw.

Spriting

Spriting is the default highlight algorithm. In this highlight mode, z-values are preserved, so you won't get the pop-out effect of overlay highlighting. It is also fairly fast, although unlike "InPlace", it does require the geometry to be drawn twice - once for the geometry itself, and once for the highlight.

Fine-tuning highlight behavior

Various options are available to achieve the highlighting behavior that you require when using Define_Highlight. For example, the "passive" option means that locked attributes won't be overridden. The "append" option will override any conflicting styles defined by previous highlights. See the API Reference Manual for more details on Define_Highlight.

Example

Below is an example of how a segment is highlighted. In order for your named style to be found, it must be defined in the segment where you will eventually be using the style, or an ancestor segment:

// creating the highlight style, in this case a root segment contains the highlight attributes which are simply yellow for all geometry
HC_KEY styleKey = HC_Open_Segment("/style");
HC_Set_Color("geometry=yellow");
HC_Close_Segment();
// inserting the shell and setting initial attributes
HC_Open_Segment_By_Key(sceneKey);
HC_Insert_Shell(pcount, pts, flist_count, faces);
HC_Set_Color("faces=white, edges=black, windows=white");
HC_Set_Visibility("edges=on");
// here is where the style is defined
HC_Define_Named_Style("myHighlightStyle", "/style");
HC_Close_Segment();

After the scene is set up, the actual highlighting is done this way:

HC_Define_Highlight(1, &sceneKey, "myHighlightStyle", "quick moves=overlay");
A piece of geometry before (left) and after overlay highlighting

Highlighting a single object

A segment will commonly contain graphical primitives that represent discrete pieces of the model. Let's say we have an 'asteroid' segment which contains a shell for each asteroid. If the GUI is in 'single asteroid selection mode', then we need to highlight a single asteroid. Setting highlight attributes at the segment-level won't work since all the asteroids will be affected by that new attribute. So, we need to modify the database so that only the selected object will be drawn with the new highlight attributes.

A brute force way to achieve this is to move the object (Move_By_Key) to a highlight segment, and move it back to the original segment to unhighlight. However, this has a major performance implication, since changing the contents of a segment segment will cause HOOPS to trigger a full screen redraw. To avoid such a full screen redraw and provide very fast highlighting/unhighlighting, an approach called 'quickmoves include/reference highlighting' should be used.

Quickmoves Include/Reference Highlighting

The scene-interaction section reviews how only making changes to the contents of a quickmoves segment between updates will not cause HOOPS to perform a full update. Instead, HOOPS will only clear/redraw the graphical primitives in the segments that have the 'quickmoves' attribute. We can leverage this capability in conjunction with HOOPS 'include' and 'reference' capabilities, to perform fast highlighting/unhighlighting.

To prepare for highlighting, we would first create a 'highlight' segment that contains the 'quickmoves' setting and desired highlight attributes (color, line-pattern, etc...) When a segment, segment tree, or list of graphical primitives needs to be highlighted, either Include_Segment or Reference_Geometry can be called in the highlight segment. The documentation for include segments and reference geometry will help you determine which one may be appropriate. But simply stated, Include_Segment would be used to highlight a whole segment tree, while Reference_Geometry would be used to highlight a single segment or set of graphical primitives.

Let's imagine we are modelling an airplane fuselage which has a few subcomponents. The fuselage is located in the airplane_fuselage segment and the subcomponents are in the subsegments fuse1, fuse2, and fuse3. You can control highlighting in the following way:

// set up the highlighting attributes segment
HC_KEY style_key = HC_Open_Segment("my_highlight_attributes");
HC_Set_Color("lines = red, faces = yellow");
HC_Set_Edge_Weight(3.0);
HC_Set_Rendering_Options("general displacement = -8");
HC_Close_Segment();
// example of highlighting the entire fuselage, which might be used if your application's 'selection mode' was 'part selection'
HC_Open_Segment("highlight");
HC_Set_Heuristics("quick moves");
HC_Style_Segment_By_Key(style_key);
HC_Include_Segment_By_Key(fuselageSegment);
HC_Close_Segment();
// example of highlighting just one piece of the fuselage, which might be used if your application's 'selection mode' was 'sub-object selection'
HC_Open_Segment("highlight");
HC_Set_Heuristics("quick moves");
HC_Style_Segment_By_Key(style_key);
HC_Reference_Geometry_By_Key(fuse3);
HC_Close_Segment();

Because we have 'quickmoves' set in the highlight segment(s), making changes to those segments to effectively 'unhighlight' (such as deleting the Reference or Include by deleting the include_key and reference_key, respectively) will not cause HOOPS to redraw the entire scene. HOOPS will simply 'undraw' the quickmoves geometry.

There is one caveat with the highlighting technique above. We're highlighting by drawing a new instance (reference/include) of the geometry, and that instance would have the same position. That means it will come out directly 'superimposed' on top of the original, unhighlighted geometry, resulting in geometry that 'bleeds' together. To address that, we can set the 'general displacement' value in the highlight-attributes segment to -8. This will 'pull' the highlighted copy forward a bit in the z-buffer, and avoid superimposition and thus any edge/face bleeding.

In certain circumstances, it may be useful to know if a segment is highlighted, or to know which highlight modes are currently in use. Visualize provides a few functions for this purpose.

To determine if a segment is highlighted, call Determine_Highlight_Status with a key path to the segment you want to query. You may also specify a filter to further narrow results, such as which type of highlight you are interested in. This function will return a value which indicates specifics about how the highlighting is applied. See the API Reference for more details on Determine_Highlight_Status.

Find_Highlight is used to find which highlights are applied to the open segment, and works in a similar fashion to other scene graph searches with Begin and End guards:

int total_count = 0, max_path = 0;
HC_Begin_Highlight_Search(0, 0, ""); // search all
HC_Show_Highlight_Count(&total_count, &max_path);
HC_KEY keys[32];
char options[256];
int count = 0;
while (HC_Find_Highlight(&count, keys, options)) {
// make use of 'count', 'keys', and 'options' variables to process your results here
}
HC_End_Highlight_Search();

HOOPS/MVO Highlighting example

The HOOPS/MVO Classes contain a class called HSelectionSet which provides higher level highlighting support. This class is intended to be used along with the other HOOPS/MVO classes, but its methods can be referred to for a reference implementation of segment and single object highlighting. The code handles other issues that were not mentioned above, such as dealing with include segments, and storing away a segment's original set of attributes (so that they can be restored later). It manages a selection array, and provides methods to Select, DeSelect, DeSelectAll and to query if an object IsSelected.

top_level:2 prog_guide:0 prog_guide/3DGS:3