Drivers

HOOPS uses aliases to shield you from worrying about the absolute structure of the database. When you insert new segments and geometry into “?Picture”, they are placed somewhere in the database that causes them to be drawn, but, when you place segments or geometry into “?Include Library” or “?Style Library”, they are placed somewhere else that causes them to not be drawn. How does HOOPS know which geometry to draw?

The values of “?Include Library” and “?Style Library” are simple: They are “/include library” and “/style library”, respectively.

The “?Picture” alias is slightly more complicated. HOOPS defines a segment named “/driver”, and underneath this segment are a dozen or more subsegments with names such as “x11”, “msw”, and “postscript” (because segment names are not case sensitive, the name X11 is the same as x11). There is one segment for each kind of device about which HOOPS knows - these subsegments of “/driver” are called driver segments:

../../_images/013a_driver_segments.gif

Driver segments.

Previously, HOOPS Visualize created segments for all drivers regardless of whether they could be instantiated. Now, HOOPS/3dGS only creates segments under the “/driver” segment for drivers which can be instantiated on a given platform. For instance, this means that the DX11 driver can only be created on Windows platforms and additionally only on the Microsoft Windows platforms which have DirectX installed.

HOOPS Visualize supports a wide range of drivers including “cgm” (computer graphics metafile - a standard file format for transferring graphical information), “hpgl” (Hewlett-Packard graphics language - a printer and plotter format), “image” (the image driver which is used to create images), “printf” (a driver that prints what it would draw, instead of drawing which is useful for debugging), and “null” (a null driver that ignores everything sent to it). If you would like HOOPS Visualize to choose the best available driver supported by the execution environment, you can specify a platform-agnostic driver. All drivers, including the platform-agnostic drivers, are detailed in the HOOPS Visualize Platform Device Guide.

Driver segments have only one special characteristic that differentiate them from any other segment: they each have the driver attribute set on them. The driver attribute is set internally by HOOPS Visualize. Like any attribute, the device-driver attribute is inherited by all subsegments of the driver segment. When HOOPS traverses the graphics database to render a scene, the graphics primitives are sent to their net device-driver function to be drawn.

When HOOPS starts up, it assigns a value to the “?Picture” alias that corresponds to the appropriate driver segment. It normally does so by reading the environment variable HOOPS_PICTURE and resolves ?Picture to be ?driver/<HOOPS_PICTURE>, but it will choose a default value for HOOPS_PICTURE (and will issue a warning message) if it is not set. Note that HOOPS_PICTURE can be set externally in your computer’s environment, or it can be set by your program before the first HOOPS command is executed.

You can show the value of the “?Picture” alias with the Show_Alias command, as shown in the following program.

    char value[128];
    HC_Show_Alias("?Picture", value);
    printf("%s\n", value);

This program will print something like “?driver/msw/window0” or “?driver/x11/unix:0.0” (depending on what platform you are using). The value of the alias “?driver” is just “/driver” - so the value of “?Picture” refers to a segment that is a subsegment of a driver segment. NOTE: MVO explicitly undefines the “?Picture” alias.

As the name “/driver/msw/window0” suggests, each subsegment of the msw driver segment corresponds to a window on the display device. The segment “window0” is created under the Microsoft Windows driver segment “/driver/msw”, and the creation of this segment causes HOOPS to create a new window on the screen. Any geometry placed under the “?Picture” alias (or in subsegments of “?Picture”) is drawn into this window.

Some HOOPS device drivers use the name of the subsegment for information. For example, in X11, the value of the “?Picture” alias would be something like “/driver/x11/unix:0.0”. The X11 driver uses the name “unix:0.0” to identify the display to which to send the picture. The name “unix:0.0” is X11 syntax for the main display on the local computer. For the PostScript driver, the subsegment name is used as the name of the file into which the PostScript output is written.

In summary, each subsegment of “/driver” is a driver segment for a different platform, and each subsegment of a particular driver segment is an instance of that driver. For a display driver on a window system such as X11 or Windows, each instance corresponds to a window on the display. For a hardcopy driver such as PostScript, each instance corresponds to a file to be printed.

../../_images/013b_driver_instances.gif

Driver-instance Segments. Any geometry and attributes placed into a segment under a driver instance will be drawn as part of that instance. In other words, any geometry placed into “/driver/msw/window0” will be drawn into window0, and any geometry placed into “/driver/postscript/file.eps” will be output as PostScript into the file named file.eps.

You can create new windows for HOOPS Visualize to draw into simply by creating new subsegments of your driver segment. We shall discuss how to do that in a later section. For now, the following provides a simple example:

    char newseg[128];

    HC_Show_Alias("?Picture", newseg);
    strcat(newseg, "+A");

    HC_Open_Segment(newseg);
    HC_Insert_Text(0.0, 0.0, 0.0, "second window");
    HC_Close_Segment();

Creation of a new window.

The program above creates two segments: the default one created by HOOPS (whose name is the value of “?Picture”), plus the new one whose name is formed by concatenating “+A” onto the value of the “?Picture” alias. Because each segment under a driver segment causes HOOPS to create a new output window for the driver, creating a new driver instance segment creates a second window on the screen. Note that because we did not change the position or size of either of the windows, you might have to move the top window to see the one underneath.

If you want the same objects to appear in both windows, you can put the objects into a subsegment of “?Include Segment”, and then use Include_Segment to include the objects in both “?Picture” and “newseg”.

Updating a Single Driver

In review, Update_Display will traverse the entire segment tree and update all driver instances. However, it may be desirable to update a single driver instance; perhaps you only want to generate postscript output, and don’t want to update the display driver segment. A variant of Update_Display can be used to achieve this. It is called Update_One_Display, and instructs HOOPS/3dGS to perform an update on a single driver instance. More sophisticated usage of this function is discussed in the performance section.

Off-Screen Rendering

Many HOOPS-based applications have a need for the model/scene to be drawn to an offscreen image buffer. For instance, the end-user wants to save the results to a screenshot, or save frames for an animation. HOOPS Visualize supports platform-independent rendering to an offscreen image using a software based Image driver.

Platform-dependent offscreen rendering is also supported by the 3D drivers OpenGL2 and DX11 drivers. If a 3D driver is available on your system, it is the preferred approach, since it helps ensure WYSIWYG results with the 3D driver’s on-screen display results, and also performs hardware-accelerated rendering to the offscreen image. The following sample code shows how you can perform offscreen rendering using the OpenGL driver:

    HC_KEY image_key;
    HC_KEY image_seg;

    char buffer[4096];

    image_seg = HC_Open_Segment("/image");
    image_key = HC_Insert_Image(0.0, 0.0, 0.0, "rgb", 3000, 3000, 0);
    HC_Close_Segment();

    HC_Open_Segment("?driver/opengl2/image");
    HC_Insert_Line(-1.0, -1.0, 0.0, 1.0, 1.0, 0.0);

    // Using the image key modifier when setting the window id to indicate that we are rendering offscreen.
    sprintf(
        buffer, "isolated, use window id = image key = %s%p, subscreen = (-1, 1, -1, 1)", EXTRA_POINTER_FORMAT, (void*)image_key);
    HC_Set_Driver_Options(buffer);
    HC_Set_Color("lines=blue , windows=green");
    HC_Close_Segment();

    HC_Update_One_Display("?driver/opengl2/image");
    HC_Delete_Segment("?driver/opengl2/image");

    HC_Open_Segment("?picture");
    HC_Include_Segment_By_Key(image_seg);
    HC_Set_Color("windows=red");
    HC_Close_Segment();

    HC_Delete_Segment("/image");

Refer to the documentation on each driver for information on how to set up the HOOPS/3dGS scene-graph and set the appropriate driver options via Set_Driver_Options().

Rendering With a Transparent Background

Rendering a scene with a transparent background is only supported for offscreen windows. To perform this operation, you must be using “opengl2” or “dx11” drivers.

The interface for this feature is the new “window opacity” driver option. It should be a float between 0 and 1.0 (values outside this range will be clamped). If a value is set, then we will multiply this value into the alpha value for the regular window background, whatever it may be - solid color, gradient, or image - and preserve the alpha values in the frame buffer all the way through to the final image.

    // for a completely transparent window background
    HC_Set_Driver_Options("window opacity = 0.0");

    // for a 50% transparent background
    HC_Set_Driver_Options("window opacity = 0.5");

    // for a background that will preserve alpha values into the final image, but not be made explicitly transparent by Visualize
    HC_Set_Driver_Options("window opacity = 1.0");

    // to disable transparency (the default)
    HC_Set_Driver_Options("no window opacity");