Priority Sorting in 3DF and HPS

3DF has HC_Set_Priority (cf. hc_proto.h — HOOPS Visualize 3DF Documentation) and HPS has SetPriority() as a method on several classes (cf. [Segment|Geometry][Kit|Key]::SetPriority - e.g. SegmentKey — HOOPS Visualize Desktop Documentation).

Originally, this capability was developed for a very specific and limited application. A couple different uses were written using the same interface in 3DF (to try to keep down the number of functions); since HPS is more class-based that turned into being present on many classes.

The original usage was for a partner that wanted to draw everything in their scene in the order it was inserted, regardless of the segment organization, and without having to insert at progressively greater Z values (which would cause other problems, such as in a perspective view). This was done by having every Insert record an increasing priority value, and adding the Priority hidden surface algorithm to simply sort using that value. The partner also wanted to be able to Include predefined groups of geometry as an object which would sort together, so an Include would also get an automatic priority value and the sorting would keep the contents of the included group together (sorted within the group). An obvious extension to this was to be able to change the priority of something, for instance to pop it to the front or put it back, so Set_Priority was added.

This software algorithm was later implemented as a hardware algorithm for performance, basically using Z-buffer but with the final Z values replaced by the priority. This has limitations as priority is a 32-bit value where the Z-buffer typically has 24 bits of resolution. Additionally, Includes need an even finer mapping to draw directly.

NOTE: Priority was never intended to work with anything that would resemble 3D objects. Anything that would normally be associated with 3D details, such as face displacement is not supported by this algorithm.

Separately, segments are normally sorted alphabetically within their parent. With hidden surfaces turned off you could control drawing order by appropriately naming segments. With hidden surfaces on you could draw large, important stuff first and details later so if the drawing was interrupted you could at least see the basic shape of the drawing. Keeping track of unique segment names (or even naming them at all) was sometimes considered too clumsy. As a result, Bring_To_Front was added to mark the segment and physically put it at the end of the parent’s subsegment list. Setting a Window on a segment would include an automatic Bring_To_Front; drawing a subwindow would be deferred after drawing the parent’s unwindowed contents anyway, but in case of multiple subwindows they were to be drawn in the order they were defined, so the ones set later needed to be visited last.

Trying to control the drawing order with just Bring_To_Front was still clumsy. For example, if you wanted to rearrange everything, or even just push something to the back, you would need to basically bubble sort the segments with many Bring_To_Front calls.

Allowing Set_Priority to act on Segments allows direct control. Segment are now sorted in their parent primarily based on their priority, and by name when they have the same priority. The default priority for segments is 0, and Bring_To_Front sets the priority 1 higher than the last segment preserving the original behavior if you don’t use it. Segment priority has no real affect on the Priority hidden surface algorithm.