Creating and Rendering Parasolid Entities
Rendering Parasolid entities requires a sequence of steps, most of which are encapsulated by the HOOPS/Parasolid Integration functions.
- First, a 'Frustum', which includes a set of Graphical Output (GO) routines, must be implemented and registered with Parasolid.
- Second, the tessellated geometric data intercepted by the GO routines must be stored and displayed to various devices (rendered).
- Once these are accomplished, the Parasolid render routines (PK_TOPOL_render_xxx) must be called in order that the geometry associated with each Parasolid object can be rendered via the frustum.
The HOOPS/Parasolid Integration fully encapsulates the first two items. Additionally, when a Parasolid file is read via the HP_Read_Xmt_File() function, all the necessary PK_TOPOL_render_xxx calls are made automatically as each Parasolid part/entity is parsed. However, the HP_Render_Entity routine needs to be manually called when Parasolid entities are being dynamically created and edited via the application's user-interface and underlying logic.
As an example, we will go through the process for inserting a cylinder object into Parasolid, and passing the tessellated information to HOOPS for subsequent rendering and interaction. This and future sections assume familiarity with the types of Parasolid entities, denoted by the Parasolid type PK_CLASS_t.
Defining Parasolid Geometry
A cylinder, along with many other predefined Parasolid objects, is represented by a PK_BODY entity, and is created via the routine:
Parasolid entities are referred to by a 'TagID', so this function populates the Parasolid kernel with a cylinder of the specified radius and basis_set, and returns the TagID of the associated Parasolid body. However, the cylinder will not actually be rendered (mapped to corresponding HOOPS segments and geometry) until a call is made to the HP_Rendering_Entity() routine, discussed in the next section.
The following code demonstrates how to create a Parasolid cylinder. Note that it calls HP_Render_Entity().
Rendering Parasolid Geometry
After a Parasolid entity is defined and inserted into the Parasolid database, the tessellated geometric information that represents the entity must be generated. PK_BODY entities (along with many others) are composed of PK_FACE and PK_EDGE entities. These entities denote the logical surface and edge/boundary information associated with the body. Specifically, a cylinder body object is composed of three PK_FACE entities, one for the top, one for the bottom, and one for the 'tubular' part of the cylinder. It is composed of two PK_EDGE entities, one for a circle denoting the top edge, and one for a circle denoting the bottom edge. The tessellated geometric information associated with the PK_FACE and PK_EDGE entities would typically need to be generated by manually calling the following Parasolid routines:
In addition to tessellating the body into facets and lines, these functions will send the tessellated information to the Graphical Output routines.
The HOOPS/Parasolid Integration includes a function which automatically makes the above PK_TOPOL_render_facet calls, and because the HOOPS/Parasolid Integration implements the underlying GO routines, the geometric data that represents the cylinder is automatically mapped to a group of geometric primitives in the HOOPS database. (By default, these primitives are inserted in the currently open HOOPS segment. The HP_Set_Rendering_Options function discussed later in this document, provides for control of this behavior, including creation of subsegments and optimization of the geometry.)
To render Parasolid entities and have their tessellated representation automatically mapped to HOOPS graphical primitives, you may simply call:
where 'count' is the number of entities, and 'entities' is the array of Parasolid
entities (of type PK_Entity_t). This function also updates the bi-directional
mapping (which uses a hash table) maintained by the HOOPS/Parasolid integration.
Inserting Parasolid Geometry into the HOOPS database
Recall that the HOOPS geometry and any additional segments generated as a result of the HP_Render_Entity and HP_Render_Entities routines will be placed in the currently open HOOPS segment. The following code ties together the code necessary to insert a cylinder object into both Parasolid and HOOPS. It assumes that we have obtained the creation parameters for a cylinder from the UI, opens a segment and then calls the 'CreateSolidCylinder' function discussed previously. After CreateSolidCylinder is called (which calls HP_Render_Entity, discussed above), the Parasolid database will contain a parametric representation of the cylinder (a Parasolid 'body'), and the HOOPS database will contain the corresponding geometric representation (a HOOPS 'shell'):
The Parasolid 'body' entity that represents the cylinder is accessible via the 'cyl_tag' TagID. Details on how to identify the HOOPS geometric primitives associated with the Parasolid entity are covered later in this document, in the section entitled 'Operating on Parasolid Entities'.
The HOOPS/Parasolid Reference Application implements and uses the platform-independent creation/rendering functions discussed above. It also includes additional geometry creation functions:
- The HOpCreateSolidCone, HOpCreateSolidCylinder and HOpCreateSolidSphere classes are all derived from the HBaseOperator MVO class, and provide for creation of 'rubberband' construction geometry in addition to creation/rendering of the Parasolid and HOOPS entities. They contain implementations of CreateSolidCone, CreateSolidCylinder, and CreateSolidSphere functions as outlined above.
Deleting Parasolid and HOOPS Geometry
We will recall that the HOOPS/Parasolid Integration maintains a mapping between Parasolid entities and HOOPS Geometry, which enables the developer to determine the Parasolid entities associated with a given HOOPS geometric primitive or segment, and vice versa. The HP_Render_Entities function causes this mapping to be created/updated each time it is called to populate the HOOPS database with the tessellated representation of Parasolid entities.
As a result, another HOOPS/Parasolid function must be called when deleting HOOPS geometry associated with Parasolid entities to ensure that the internal mapping is kept up to date. The function is called HP_Delete_Entity_Geometry, and would be used to delete the HOOPS geometry associated with a Parasolid entity after the latter is deleted. For example, the following function is a wrapper function which deletes a Parasolid entity along with its associated HOOPS geometry:
It is important to use the HP_Delete_Entity_Geometry function whenever deleting HOOPS geometric primitives associated with deleted Parasolid entities. If only the normal HOOPS/3DGS deletion functions were called (HC_Delete_By_Key, etc...), then the HOOPS/Parasolid mapping would not be correct, and problems would occur during subsequent operations.
Retesselation of Geometry into the same Segment Structure
A call to HP_Delete_Entity_Geometry() normally deletes all associated entities from HOOPS including segments. Sometimes however it is desirable to preserve the segment structure if e.g. extra information with no connection to the solid modeller has been previously associated to a body. To allow that there is a third parameter in the call to HP_Delete_Entity_Geometry() called "PreserveSegments". If this boolean is set to "true" (it defaults to false) then only true HOOPS geometry is deleted and keys that are associated with segments are disregarded. This means that if a body is deleted it will be retesselated into the same segment again on the next call to HP_Render_Entity().
However, let's consider the following scenario. Say we have a simple cylinder
body which contains (among other things) two edges. After normal tesselation
we want to move one of the edges (consisting of 2 HOOPS ellipses) into a separate
segment (let's call it "special") which contains e.g. some text annotation and
a different line weight attribute. We can do this with HC_Move_By_Key().
Unfortunately after a retesselation (even when using HP_Delete_Entity_Geometry
with PreserveSegments = true) the two HOOPS ellipses are recreated in their
default segment again and the newly created "special" segment is empty.
To avoid this HP_Associate_Entity_To_Key() can be used which associates a HOOPS keys to a Parasolid entity. In our example we use it to associate the key of the "special" segment to the Parasolid edge entity that we want to store underneath it. Whenever the Parasolid body needs to be rerendered we delete it's associated geometry by using "HP_Delete_Entity_Geometry" with the PreserveSegment flag set to true. This way even though all the HOOPS geometry of the body is deleted there is still the connection to the "special" segment in the database.
Here is some example code:
View Dependent Tesselation
HP_Render_Entity() and HP_Render_Entities() have a third parameter which is a Parasolid transformation entity (0 by default) that represents the view matrix for view dependent tessellation. It is the responsibility of the caller to set the appropriate tessellation options for the frustum routines. This example demonstrates how to temporarily overwrite tesselation options to render the body in a view dependent way.