3D InterOp Graphical: Navigating the Data
By Leah Morgan, Software Developer
With the release of 3D InterOp Graphical, Spatial has expanded the functionality available to you as a 3D application developer by providing you access to high-quality graphical data for all your 3D CAD models. Along with the Product Structure, B-rep, and semantic PMI representations, many 3D CAD file formats also include graphical data. How does access to this graphical data benefit you as a 3D application developer? Here are a few examples:
Viewer-only Applications: Many applications need only the graphical representation of the 3D model for simple viewing or to support PDM/PLM, collision detection, clearance, or distance calculations. For these types of applications there is no need to access the model’s exact geometry, so there is no need to waste any precious time in loading it.
Search/Preview Functions: In today’s world of near limitless amounts of data to sort through, application users often need more than simply the ability to search for or open a file based only on its name. With 3D InterOp Graphical you can quickly create a preview of a model to display a file’s contents without having to spend time importing all the heavyweight data such as its B-rep – which can be quite costly for very large files.
Interaction with very large data files: 3D InterOp Graphical allows your application to import the graphical representation of a large model, allowing your users to view and manipulate the lightweight graphical representation of the model while the heavyweight B-rep data is loaded in the background. This allows your application to increase your user’s productivity – although they might miss the excuse to go get a cup of coffee while they wait for the model to load
What do you need to do to take advantage of our new APIs for graphical data? The new APIs are pretty simple, but there are a few things you need to know before you dive in. In fact, when working with 3D InterOp Graphical, it is important to understand the organization of the various data structures. So let’s take a look at some of the things you need to know to successfully use the 3D InterOp Graphical APIs.
Before you can access the graphical data for a model, you first need to import the model’s Product Structure. In 3D InterOp Graphical, all files are loaded into memory as a Product Structure – this is true for both single parts and whole assemblies. The Product Structure is a very lightweight description of the associativity of the instances and references within the assembly. Note that it does not, however, contain any of the part’s data like its B-rep, semantic PMI or graphical data. Providing the Product Structure this way allows you to selectively load only the parts of the model you want in the workflow that makes the most sense for your application.
Once you’ve imported the Product Structure, you need to navigate its instances and references to locate the specific part reference you want the graphical data for. Since you can only get graphical data for part references, not sub-assembly references, you need to recursively descend the Product Structure until you get the specific reference for the part file you want. Be aware, though, a single reference may be instanced many times in an assembly. Even so, you only need to import the graphical data once for each unique part reference, not once for each instance. Processing each reference only once can save you a lot of time and wasted effort, so be sure to keep track of the references you’ve already processed by using its unique ID.
Having found the targeted part reference, you then need to get its document. You can think of the document as a “handle” to the source file. If you are building a CGM based application, then here is where you need to decide what kind of data you want to get from the document, B-rep or graphical. If you are building an ACIS or Parasolid based application, however, then you would use this document to get the graphical data from the source file.
With the document in hand, you need to run an import operation to load the graphical data from the source file into memory. You do this by calling CGMPartVisualizationImporter::Import() while feeding it the document. This will return the graphical data in a CGMPartVisualizationImportResult object.
To get the graphical data, you first need to retrieve the CGMPartVisualizationData object from the result object. This simple object provides information about the data’s scaling factor as well as giving access to the graphical data in the form of a simplified scene graph. The scene graph is a tree structure comprised of CGMPartVisualizationNodes, each of which may have a CGMPartVisualizationAttributes object attached to it. Navigation of the scene graph uses a depth-first iterator retrieved from the CGMPartVisualizationData object.
The 3D InterOp Graphical scene graph is very simple. It does not have lights, cameras, material properties or texture maps. A scene graph used for rendering would typically have these, but our scene graph is built to get you the graphical data quickly and simply. The scene graph is organized in such a way as to allow you to skip over specific types of data you are not interested in processing.
In the diagram below, we have highlighted the scene graph nodes. You will notice that the Geometry is in a separate branch from the PMI. Furthermore, within the Geometry branch, the Meshes are in a separate branch than the Wires. Lastly, the leaf nodes hold on to the graphical data and you would query them for high-level graphical data objects that are associated with the various bodies in the model.
Once you have identified a leaf node, you will need to get the graphical data from the node. Each node can have one of three types of body-level data attached to it: Mesh, Wire or PMI. You have to know the node’s type to know which kind of data is attached to a given leaf node. For example, while traversing the scene graph, you might identify that a leaf node is of type “Mesh” which corresponds to a solid or sheet body in the model. You can then query that node for its mesh data. Querying for PMI or wire data on this same node will not provide any valid data, however.
Attributes have the potential to affect the display properties of every element of the scene graph. They are defined hierarchically such that any attribute defined anywhere in the scene graph effects all elements that appear below it. Under these rules, any attribute that appears below the same attribute in the hierarchy will override the previously defined attribute value. Looking at just the scene graph nodes, you can see the effect of defining a color at different levels in the scene graph structure.
Here we see that the root has its color attribute set to “orange”. We can see that “Wire B” does not have any intervening nodes that have a color attribute set, so its final color is also “orange”. In contrast, “Mesh A” does have an intervening node with its color attribute set to “green”, so its final color is “green” instead of “orange”. What this all this means is that you will need to track the attribute information during your scene graph processing to correctly determine the final color for a given data element.
Now, here’s the most practical advice I can give you: Copy the graphical data into your own data structures! Because the memory for the graphical data is owned by the translation sub-system, it’s not well suited for direct usage by your application for rendering or data analysis. In fact the data is only valid as long as you have the managing objects in memory and in scope.
Specifically, you need to keep the following objects alive:
- CGMInputPSReference (or its CGMInteropPartDocument)
This high level overview of the process of navigating various data structures within 3D InterOp Graphical should provide you enough information to get you started on your way to successfully employing our new API for graphical data. To learn more, visit the Spatial Webinars & Tutorials page at http://www.spatial.com/resources/webinars. Here you will find materials covering 3D InterOp Graphical as well as a host of other topics.