HOOPS Visualize uses a generic component hierarchy to represent third-party CAD models which feature topological entities. The component hierarchy is a way to organize the scene graph uniformly across disparate file formats. It also provides developers the ability to extend the capabilities of our importers, as well as to create entirely new importers in a way that is compatible with the Visualize scene graph. The HOOPS Exchange and Parasolid importers produce CADModel objects that abstract the structure of the model into a Component hierarchy.
The major parts of the hierarchy are described below:
|HPS::CADModel||The root entity of the 3D model. Files loaded with the HOOPS Exchange importer will have a root entity of type HPS::Exchange::CADModel. The Parasolid importer uses HPS::Parasolid::CADModel.|
|HPS::Capture||A specific view of an object, including the camera, materials, transforms, etc.|
|HPS::Filter||A collection of visibility settings for a HPS::CADModel|
|HPS::*::Component||A complex object which can represent a variety of model components, including non-geometric components|
In general, components refer to Visualize objects, whereas entities refer to the underlying object of the model's native platform. However, there is not a perfect one-to-one mapping between components and entities. For example, some modeling APIs represent faces and edges as two separate entities, but Visualize groups the two into a single shell. For a list of all supported entities and their corresponding components, see the reference manual entry for HPS::Component.
Using a model browser
When loading a model using HOOPS Exchange, a common operation is to navigate the model hierarchy using a tree control. HOOPS Visualize does not provide such a control as part of its API, but you can see an example of one in use in the WPF or MFC sandboxes.
A ComponentPath is an explicit list of components that form a path from an individual component to the top of the scene graph. A ComponentPath is very similar to a KeyPath, except that it forms a list of Component objects instead of Key objects (key path objects are discussed in this section). If necessary, you can get a component path from a key path by calling CADModel::GetComponentPath().
When using GetComponentPath(), it is important to understand that only unambiguous portions of paths are returned. For example, consider the cube below – specifically, the edge between the red and green faces:
If you ask Visualize to return a path describing this edge, what should that component path look like? Since the component path is ordered leaf to root, it should start with the edge that was selected and should make its way towards the CADModel object. But as we go up the hierarchy we find that we have a problem: which face will be part of the path? The red or the green one?
The edge selected belongs to both faces, and there is no information provided to indicate whether the user is interested in the red one, the green one, or neither. The situation is ambiguous.
- Edge / Shell / Connex / Body / RI BRep Model / Part Definition / P. Occurrence / Model
Visualize also provides an option to return a complete component path. What this means is that HPS will make an assumption as to which face the user needs in the example above. In this case, the returned path will look like this:
- Edge / Co-Edge / Loop / Face / Shell / Connex / Body / RI BRep Model / Part Definition / P. Occurrence / Model
Which face was returned in the above component path? The red or the green one? Visualize returns the face encountered first – therefore, the result is not guaranteed.
CADModel and the associated Component hierarchy provide a convenient interface to visualize, traverse, and interrogate the imported model, but have more complicated visibility management than a standard HOOPS Visualize segment tree. This is because CADModel objects can describe multiple views of a single assembly, each of which may contain different visibility and material settings. Thus, the visibility of a given component and its underlying geometry is conditional depending on its view. Furthermore, the types of geometry (edges, faces, lines, etc.) that are visible are also determined by how the view is being rendered.
The mechanism for changing the visibilities of CADModel components after import is available through the HPS::ComponentPath and HPS::ComponentTreeItem classes. ComponentPath objects describe a unique path from the component of interest to the root of your CADModel. ComponentTreeItem objects are intended to represent a unique component path in a GUI tree control. Each of these classes contain Show(), Hide(), Isolate(), and ResetVisibility() functions which let you control the visibility of the related components.
These functions not only act on a specific component path, but are also bound to a single view at a time, which enables visibility states of the model to be modified differently in several views simultaneously. The changes made by these functions are intended to be transient in nature. They are purely visual and will not be encoded in the structure of the model if exported.
Hide() forces the visibility of the associated ComponentPath and all components under this path to invisible. Any visibility changes made previously at or below this path are flushed. Any visibility changes made subsequently at or below this path are honored unless they are redundant.
Show() makes the associated ComponentPath visible while components that exist underneath the chosen path retain the visibility of previous Hide(), Show(), or Isolate() calls and otherwise preserve the visibility defined for the components by this view. Any visibility changes made subsequently at or below this path are honored unless they are redundant.
Isolate() invokes a Hide() call at the root of the model and a Show() at the leaf of the chosen path. All rules stated for Show() apply under the leaf of the chosen path while similarly all rules stated for Hide() apply under the root component.
ResetVisibility() reverts the visibility of components at or below the associated ComponentPath back to what the model dictates for the associated view. Effects of all previous Hide() / Show() calls at or below this point should be gone.
- Geometry modified by HPS::ComponentPath::Show(), HPS::ComponentPath::Hide(), and HPS::ComponentPath::Isolate() may not interact properly with other transparent geometry contained in the scene.
- If HPS::ComponentPath::Isolate() is called on an assembly containing only hidden subcomponents (and subcomponents visibility is preserved) the scene may become empty (unless the part being isolated contains geometry directly at the specified path).
- Components shown using Show or Isolate may not preserve post-process effects used in the scene.
Show, Isolate, and Hide are implemented internally with highlights. Thus, extra care must go into making sure other highlights interact properly in a scene that invokes the aforementioned functions. When using highlights in combination with Show, Hide, and Isolate, please utilize the following rules:
- Any highlight under a ComponentPath hidden by Hide() will not appear regardless of style or overlay.
- Any highlight under a ComponentPath shown by Show() should appear as long as the highlight uses the overlay HPS::Drawing::Overlay::InPlace.
- Styles used by highlights under a shown component should not define their own visibility settings as these will conflict with the visibilities of Show().
The following example shows the process of loading a file through sprk_exchange, using the resulting CADModel to create multiple views, and using component visibility functions in combination with highlights to display different content on each view.
First, we start by loading our file through sprk_exchange and setting up our views to each take up a quarter of our window. For this example we are using our Micro Engine model, but setup should be similar for other datasets.
Next, we modify the visibilities of component paths within the different views to achieve different visual states:
At the end of this procedure we end up with the following scene:
When working with components of types Exchange, Parasolid, and ExchangeParasolid, there are two data layers associated with any model: the Visualize scene graph, and the underlying PRC data. Making changes to the Visualize scene graph may produce a distinct visual result, but generally does not modify the PRC. For example, if you apply a transform to a segment which contains part of an Exchange model, then save the file, that transform will not be present in the saved model.
To make a transform to both the scene graph and to the PRC data, use Component::SetTransform() or Component::AddTransform(). The transform will be applied both visually and to the underlying native data.
NOTE: When you apply a transform using Component::SetTransform(), the new transform will REPLACE any existing transforms set on that component. When you apply a transform using Component::AddTransform(), the new transform is APPENDED to the existing transform.
Only certain types of components can have transforms applied to them:
- For Parasolid components, valid choices are components of any of these types: ParasolidAssembly, ParasolidInstance, and ParasolidTopoBody
Deinstancing a component refers to analyzing a geometry's HPS::ComponentPath to determine the level at which changes can be made without interefering with other instanced geometry. This is done using HPS::Factory::DeInstanceComponent, which is available for components of types Exchange, Parasolid, and ExchangeParasolid.
For example, imagine a model of a car which contains four wheels. Each wheel is just an instance of one original wheel geometry. When a user wants to move a wheel, setting a transform on the wheel itself will cause all four wheels to move.
This function will analyze the path and return a component along it at which level it is safe to apply a transform, such that only the selected wheel will be affected.