3D/MCAD

 

Organizing the Data

The main concept that dominates scene-graph organization for 3D and Mechanical CAD applications is to use segments/segment-trees to represent parts of the 3D model that are logically grouped together. The HOOPS/3dGS segment-hierarchy should generally mimic the assembly/part hierarchy for an MCAD application, or the part hierarchy for an application that works with kinematics on 3D models. (We should stress the word 'generally' because the scene-graph should also be optimized for graphics drawing, which may cause it to diverge somewhat from the application's assembly/kinematics hierarchy.)

Grouping logical parts of the 3D model into individuals segments facilitates modification of their attributes, such as visibility, color or modelling matrix. For example, if a part will need to be independently moved, it must either reside in it's own unique segment (since each segment has a modelling matrix which affects everything in the segment), or the geometry representing the part would need to be moved into a new segment. Being able to simply change the modelling matrix on the existing segment is easier to manage.

MCAD

MCAD applications usually have an assembly structure and corresponding topology structure. The highest level representation is typically an assembly, which contain parts, each of which contain bodies. Bodies, in turn, can contain the topological concepts of faces (a sub region of a body) and edges.

  • A segment is used to represent each assembly, part and body. The assembly parts/bodies may reference objects from a master 'object_library' to reuse them, and/or the parts/bodies may be defined in place underneath the assembly/part hierarchy.
  • A single shell is used to represent a body. Shells can be independently styled (visibility, color, etc...) Sometimes, applications also need to set attributes on the topological 'faces'. While it may be tempting to use a shell for each 'face' in order to more easily achieve this, the HOOPS/3dGS shell primitive supports attributes on subparts, and also supports a concept of regions (where you would define a region for each 'face'). Therefore, using a single shell per body will permit the desired functionality in the majority of situations, and is the preferred approach since it is more optimal from a memory, performance and HSF data compression standpoint. Thoroughly read Section 2.8 and Section 7.2 of the HOOPS/3dGS Programming Guide for information on proper shell usage and optimization.
  • Lines/polylines/circles/arcs are used to represent the edges of a body, and are inserted in the 'body' segment. (Note: when representing wire circles, it is best to use an elliptical arc. This is discussed in more detail in Section 2.7)

The following scene-graph provides an example:

assembly.gif

The HOOPS/3dGS pseudo-code corresponding with the blue portions of the diagram is listed below. Notice that we set Visibility to 'off' at the top of the object library, since we don't want the contents of those segments to be automatically visible when the scene is drawn. We only want them to be visible as a result of being included into the model's 'layer' segments:

 
// define the model

HC_Open_Segment("?Include Library");

  HC_Open_Segment("Model_0");

    HC_Open_Segment("Object Library");
      HC_Set_Visibility("off");

      HC_Open_Segment("Object_1");
        // insert geometry defining this reusable object
        // set any attributes that are a fixed property of the object
      HC_Close_Segment();

    HC_Close_Segment();


    HC_Open_Segment("Assembly");

      HC_Open_Segment("Part_1");
        HC_Open_Segment("Body_1");
          // define the body using shells, lines, arcs, etc...
        HC_Close_Segment();
        HC_Open_Segment("Body_2");
          // define the body using shells, lines, arcs, etc...
        HC_Close_Segment();
      HC_Close_Segment();

      HC_Open_Segment("Part_2");
        HC_Open_Segment("Body_1");
          HC_Include_Segment("../../../Object Library/Object_1");
          // define the remainder of the body in place, by using shells, lines, arcs, etc...
        HC_Close_Segment();

        HC_Open_Segment("Body_2");
          HC_Include_Segment("../../../Object Library/Object_1");
          // define the remainder of the body in place, by using shells, lines, arcs, etc...
        HC_Close_Segment();
      HC_Close_Segment();

    HC_Close_Segment();  // close "Assembly"
  
  HC_Close_Segment();    // close "Model_0"

HC_Close_Segment();      // close "?Include Library"


// include the model into the scene

HC_Open_Segment("?driver/opengl/window0");
  HC_Open_Segment("Scene");
    HC_Include_Segment("Model_0");
  HC_Close_Segment();
HC_Close_Segment();

 

Let's explore the scene-graph of a real assembly. Run the HOOPS Part Viewer and load in formula1.hsf from your <hoops>/datasets/hsf/cad directory (A screenshot of this HSF file is included at the beginning of this document). Visually explore it's scene graph in a dynamic fashion by opening the 'Segment Browser' dialog. Additionally, review the ASCII readable version of formula1.hsf (and thus the scene-graph), by saving the HSF file out to an HMF file and then loading it into a text editor.

 

General 3D Models

There is not a set of hard and fast rules for organizing the scene-graph when you have arbitrary 3D data. Rather, you should focus on keeping segments to a minimum (i.e. creating new segments when they are actually necessary), and making your shells as large as possible.

Let's take the simple example of the solar system. We'll need to design a segment tree which can enables us to accurately simulate how planets and their moons move about the system over time. Because each object has local behaviors (such as a rotation, etc..), it needs to have it's own local object space, and therefore needs a segment associated with it. The segment containing each solar system object will include a template object called 'celestial object', which contains a shell denoting a sphere. Then, each segment in the solar system hierarchy will apply a scaling factor depending on the size of the object, along with any other attributes specific to that object.

If we want to model the sun, the earth and moon for starters, we would need the segment tree in the following diagram:

solar_system.gif

The HOOPS/3dGS pseudo-code corresponding with the blue portions of the diagram is listed below.

 
// define the model

HC_Open_Segment("?Include Library");

  HC_Open_Segment("Model_0");

    HC_Open_Segment("Object Library");
      HC_Set_Visibility("off");

      HC_Open_Segment("Celestial Object");
        // define the object
        HC_Insert_Shell(...);

        // set attributes that are a fixed property of the master object
        HC_Set_Color(...);
      HC_Close_Segment();

    HC_Close_Segment();


    HC_Open_Segment("Solar System");

      HC_Open_Segment("Earth");
        HC_Open_Segment("Planet");
          HC_Include_Segment("../../../Object Library/Celestial Object");
          HC_Scale_Object(...);
        HC_Close_Segment();
        HC_Open_Segment("Moon");
          HC_Include_Segment("../../../Object Library/Celestial Object");
          HC_Scale_Object(...);
        HC_Close_Segment();
      HC_Close_Segment();

      HC_Open_Segment("Sun");
        HC_Include_Segment("../../../Object Library/Celestial Object");
        HC_Scale_Object(...);
      HC_Close_Segment();


    HC_Close_Segment();  // close "Solar System"
  
  HC_Close_Segment();    // close "Model_0"

HC_Close_Segment();      // close "?Include Library"


// include the model into the scene

HC_Open_Segment("?driver/opengl/window0");

  HC_Open_Segment("Scene");
    HC_Include_Segment("Model_0");
  HC_Close_Segment();

HC_Close_Segment();

 

The 'planet', 'moon', and 'sun' segments would also contain several other rotation/translation operations if we wanted to accurately position/animate them. Refer to HOOPS/3dGS Programming Guide Section 3.3 for more information on how modelling matrixes would be applied to accurately model/animate the solar system example.