0% found this document useful (0 votes)
531 views8 pages

Coin3D-Qt Paper

Coin3D and Qt can be used together to create powerful cross-platform 3D applications. SoQt provides the integration between Coin3D and Qt by allowing Qt applications to easily display complex 3D scenes rendered with Coin3D. The document describes the architecture of SoQt and the different classes available for displaying Coin3D scenegraphs in Qt applications, ranging from high-level viewer classes to lower-level rendering classes that provide more flexibility.

Uploaded by

Hoang Nghia
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
531 views8 pages

Coin3D-Qt Paper

Coin3D and Qt can be used together to create powerful cross-platform 3D applications. SoQt provides the integration between Coin3D and Qt by allowing Qt applications to easily display complex 3D scenes rendered with Coin3D. The document describes the architecture of SoQt and the different classes available for displaying Coin3D scenegraphs in Qt applications, ranging from high-level viewer classes to lower-level rendering classes that provide more flexibility.

Uploaded by

Hoang Nghia
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 8

Coin3D and Qt:

The Solution for Cross-platform 3D Application Development


1 Introduction
Coin3D and Qt together present the easiest way to create powerful, cross-platform 3D applications. Kongsberg
SIM’s Coin3D is an OpenGL based, retained mode 3D graphics rendering library that is fully compatible with SGI’s
Open Inventor. Qt is a high-performance, cross-platform application development framework that makes developing
sophisticated user interfaces a snap. Both are fully cross-platform, allowing a single code-base to work on multiple
platforms, increasing developer productivity, reducing maintenance headaches, and saving money.

Coin3D consists of a core 3D rendering library (Coin), file import/export libraries and GUI-bindings.

This whitepaper will describe how to integrate Coin and Qt using SoQt. SoQt is the GUI-binding between Coin and Qt
that allows Qt applications to display complex 3D scenes with ease. Because Coin is fully compatible with SGI’s Open
Inventor, the de facto standard 3D graphics API for complex visualization applications, legacy Inventor applications
can be updated to use Coin. SoQt’s interface closely matches SGI’s original SoXt GUI bindings, making it easier to port
legacy X Windows Inventor applications to Qt.

2 First Steps with SoQt


Before delving into the details of SoQt and Coin, it is useful to see SoQt in action to illustrate just how simple it can be
to develop a 3D Qt application. The goal is to load an Open Inventor file containing a scene, display it, and provide user
interaction.
int main( int argc, char** argv ) {

// Initializes SoQt library (and implicitly also the Coin and Qt


// libraries). Returns a top-level / shell Qt window to use.
QWidget * mainwin = SoQt::init(argc, argv, argv[0]);

SoInput sceneInput;
if ( !sceneInput.openFile( “stagedancers.iv” ) )
return -1;

SoSeparator *root =SoDB::readAll( &sceneInput );


root->ref();

// Use one of the convenient SoQt viewer classes.


SoQtExaminerViewer * eviewer = new SoQtExaminerViewer(mainwin);
eviewer->setSceneGraph(root);
eviewer->show();

// Pop up the main window.


SoQt::show(mainwin);
// Loop until exit.
SoQt::mainLoop();

// Clean up resources.
delete eviewer;
root->unref();
return 0;
}

KONGSBERG SIM 
Coin3D and Qt:
The Solution for Cross-platform 3D Application Development
This code produces the application shown in Figure 1. Notice that this is a complete scenegraph viewer that handles
drawing, interaction via the mouse, and has several buttons and thumbwheels to control the display. Of course SoQt allows
the use of the complete Qt API to create far more sophisticated user interfaces. This example just demonstrates how easy
it can be load, display, and manipulate a scenegraph in a Qt application using Coin and SoQt.

Figure 1 Output from sample


program demonstrating a complete Qt
application with a scenegraph.

Examining the code in more detail provides some insight into how SoQt and Coin work. The first key piece of code from
the example above is:

QWidget * mainwin = SoQt::init(argc, argv, argv[0]);

This initializes the SoQt and Qt libraries, and returns a pointer to a QWidget that will act as a container for the viewer once
it is created. The next several lines open an Inventor scene file and load the data into a scene graph..

SoInput sceneInput;
if ( !sceneInput.openFile( “stagedancers.iv” ) )
return -1;

SoSeparator *root =SoDB::readAll( &sceneInput );


root->ref();

SoSeparator is a scenegraph node that holds a group of child nodes and isolates them from transformations made to other
parts of the scenegraph. The next few lines create the viewer and its subwidgets, putting them into the shell widget.

SoQtExaminerViewer * eviewer = new SoQtExaminerViewer(mainwin);

KONGSBERG SIM 
Coin3D and Qt:
The Solution for Cross-platform 3D Application Development
This example uses the high-level SoQtExaminerViewer class to provide a complete viewer with all the features described
above. SoQt offers several classes capable of displaying a scenegraph, each with different levels of features and flexibility.
These will be described in detail later. Next we give the viewer the scenegraph to display and then show it:

eviewer->setSceneGraph(root);
eviewer->show();

Lastly, start the application and begin the Qt event loop.

SoQt::mainLoop();

3 Architecture
Coin is written entirely on top of OpenGL and provides 3D rendering and scene management but no user interface
components. Qt, on the other hand, offers OpenGL integration, but at a fairly low level. It provides a way to wrap an OpenGL
context in QWidget and draw onto that widget using OpenGL; however, it does not provide an easy way to integrate with
more complex rendering libraries like Coin. SoQt is the glue between Qt and Coin, allowing the application programmer to
use the power of Coin for 3D rendering and the simplicity of Qt for the user interface. Both Coin and Qt isolate the developer
from the underlying platform dependencies and are completely cross-platform.

SoQt builds on Qt’s QGL library. Qt interacts with the underlying windowing system to create OpenGL contexts, create
and manage windows, and handle windows system events. SoQt uses the OpenGL widgets created by Qt, but adds an
interface for rendering Coin scenegraphs instead of pure OpenGL. SoQt provides automatic event handling: just as Qt
translates low-level window system events into higher-level QEvents, SoQt translates these QEvents into Coin SoEvents.
SoEvents describe how to manipulate the camera or other objects in the scenegraph. Event types handled by SoQt include
mouse events, keyboard events, and window resizing events.

It is important to note that SoQt classes are NOT instances of QWidget or QObject. SoQt uses delegation rather than
inheritance to integrate with Qt. This allows greater flexibility and a cleaner architecture. Internally, SoQt creates an
instance of a QGLWidget to perform rendering.

4 Displaying a Scenegraph
The fundamental purpose of SoQt is to allow a Coin scenegraph to be rendered in a Qt application. Adding a scenegraph
to a Qt application involves creating an instance of a SoQt class that is capable of rendering the scenegraph. There are
several available classes, each offering differing levels of abstraction and customization. Some can be used directly while
others are abstract and must first be subclassed.

4.1 Inheritance hierarchy of Viewers


Figure 2 shows the inheritance hierarchy of the viewing classes. The bottommost classes, the SoQtFullViewer and its
subclasses, provide the easiest way to display a scenegraph. They are fully functional viewers, complete with working
user interface components. They are mainly useful for rapid development and prototyping because their user interface
components typically will not match an application’s desired look-and feel. The SoQtViewer offers much of the functionality
of these full viewers, but without the UI widgets. It has many convenience functions for easily setting up, displaying, and
manipulating scenegraphs. The SoQtRenderArea and SoQtGLWidget classes are the most general of the classes for
displaying scengraphs. They offer greater flexibility at the cost of more work. This section will examine the details of these
classes along with the benefits and tradeoffs associated with each.

4.2 SoQtGLWidget and SoQtRenderArea


The two classes at the base of the viewing class inheritance hierarchy are the SoQtGLWidget and SoQtRenderArea classes
These classes provide the highest level of abstraction and require the most amount of work to use directly.
It is helpful to begin here because everything that applies to them will apply to derived classes.

KONGSBERG SIM 
Coin3D and Qt:
The Solution for Cross-platform 3D Application Development
Figure 2 The inheritance hierarchy of
the viewing classes

4.2.1 SoQtGLWidget
While it is rare to need to inherit directly from SoQtGLWidget, this class does contain several virtual functions that can be
overridden in derived classes. Two of the most important are processEvent() and buildWidget(). The processEvent() function
makes the translation from QEvents to SoEvents, while the buildWidget() function takes constructs all the necessary viewer
GUI components including the internal QGL. These functions will be discussed in more detail in Section 5.1.

SoQtGLWidget also has several functions for controlling the OpenGL rendering context. The setDoubleBuffer() function
specifies whether OpenGL should use double buffering. There are analogous functions for setting stereo buffers, stencil
buffers, overlay planes, alpha channels, etc. The SoQtGLWidget class also gives you access to the underlying QGLWidget
used to render the scenegraph via the getGLWidget() function.

4.2.2 SoQtRenderArea
SoQtRenderArea inherits from SoQtGLWidget and adds a SoSceneManager and a scenegraph. The SoSceneManager class
is part of the Coin API and contains functions for querying/setting the size of the render area, redrawing the screen, getting
to the “real root” of a scenegraph, among others. When using the SoQtRenderArea, it is the programmer’s responsibility to
create a scenegraph that contains a camera and at least one light source.

4.2.2.1 SoQtRenderArea Functions


To set the scene graph use setSceneGraph(). SoQt supports rendering into overlay planes by calling setOverlaySceneGraph().
SoQtRenderArea will automatically configure the OpenGL context to include overlay planes if they are available. Set and
get the SoSceneManager using setSceneManager() and getSceneManager(). SoQtRenderArea also contains functions to
set rendering options including antialiasing, background color, and whether to clear the screen before rendering.

To trigger a redraw of the scenegraph, SoQtRenderArea offers several options. The redraw() function immediately redraws
the scenegraph, while the scheduleRedraw() function will schedule a redraw on the event loop. After the event loop
processes any pending events, the scene will be redrawn. This can often be more efficient as several consecutive redraw
requests can be compressed into a single redraw. Another way to redraw the scenegraph is use setAutoRedraw() to enable
automatic redraws when the scenegraph data changes.

KONGSBERG SIM 
Coin3D and Qt:
The Solution for Cross-platform 3D Application Development

4.2.2.2 Customizing Drawing in SoQtRenderArea


SoQtRenderArea allows advanced drawing control by overriding the actualRedraw() function. The redraw() function sets up
the OpenGL context for rendering, then calls actualRedraw() to do the work. By default this renders the main scenegraph
set with setSceneGraph(), but overriding it allows more complex behavior. A common use for this would be to render some
foreground geometry in front of the entire scene, such as displaying coordinate axes. The coordinate axes should not be
transformed with the full scenegraph, so they can’t be placed into the main scene. The desired effect can be accomplished
easily by having actualRedraw() redraw the main scene, then clear the depth buffer, and finally draw a 2nd scenegraph
containing the axes:

// Render main scenegraph.


ParentViewer::actualRedraw();

// Render axes in front of scenegraph.


glClear(GL_DEPTH_BUFFER_BIT);
getRenderAction()->apply(axesRoot);

4.3 SoQtViewer
The abstract SoQtViewer class is derived from the SoQtRenderArea. It adds many convenience functions, mostly for
camera handling. It will either detect a camera in the scenegraph or will automatically create one when none exists. Other
functionality includes toggling the camera between orthographic and perspective projection, setting the camera such that
the entire scene is visible, changing stereo modes, saving/restoring “home” camera positions, and automatically configuring
the clipping planes to ensure optimal use of the z-buffer. SoQtViewer also has a built-in headlight that will always illuminate
the scene. This can be useful during development to ensure the scene will always be lit correctly until a custom lighting
configuration can be established and tested.

The SoQtViewer class does not handle camera movement. To handle camera motion, the programmer will need to override
SoQtRenderArea::processSoEvent (). This function is called after SoQt has translated QEvents into SoEvents and gives
the programmer a chance to processes the SoEvent. The easiest way to get started writing a custom processSoEvent()
function is to look at the source code for one of the full viewers, such as the SoQtExaminerViewer. A typical implementation
will determine the event type, check which mouse button is pressed, then update the camera based on these parameters and
the movements of the mouse. Because Coin is fully compatible with SGI’s Open Inventor, developers can leverage legacy
Inventor code that already contains routines to handle SoEvents. Because SoQt translates QEvents into full SoEvents,
integration is simple, with no need to interpret the Qt events directly.

4.4 The Full Viewers


There bottommost classes in the inheritance hierarchy in Figure 2 are the fully functional viewers: SoQtExaminerViewer,
SoQtPlaneViewer, and SoQtFlyViewer. These all inherit from SoQtFullViewer, which provides common functionality for its
derived classes.

These classes are meant primarily for prototyping and rapid development as well as writing test bed applications for
developing scenegraphs. The opening example demonstrated how little code is required to use these classes. These
classes allow programmers to view and interact with the scenegraph very early in the development process, ensuring the
maximum amount of time for perfecting and debugging what is often the most complex part of the application. While the
SoQtFullViewer and derived classes are excellent for prototyping, they impose a lot of functionality and look-and-feel that
is typically either not appropriate or not necessary for an application. As the application architecture becomes more stable,
the application will switch to the more flexible classes to create a custom user interface.

The SoQtFullViewer is an abstract class that provides everything from the SoQtViewer, plus the widgets visible in Figure 1. It
also provides a popup menu with options to change many rendering parameters and viewer configuration. The SoQtFlyViewer
adds controls to move the camera in a flying motion while keeping the camera upright. The SoQtPlaneViewer includes
controls to move the camera into orthogonal planes for CAD-style viewing along the x-y-z axes. The SoQtExaminerViewer
is the most complete viewer class and contains controls for panning, rotating, and zooming via the mouse or keyboard.

KONGSBERG SIM 
Coin3D and Qt:
The Solution for Cross-platform 3D Application Development
5 Linking the GUI to Coin
SoQt makes it easy to harness the power of Qt to create sophisticated user interfaces that control and interact with the
scenegraph. One of the most powerful aspects of Qt is its signal/slot mechanism. But what is the best way create and link
Qt widgets to the scenegraph?

5.1 Creating and Linking Widgets


To create the UI components, subclass one of the viewing classes described in section 4 and override the buildWidget()
function. This function takes a QWidget* parameter indicating the shell widget that will contain all the viewer widgets. This
is most useful when creating a self-contained, reusable viewer class similar to the SoQtFullViewer subclasses where the
main OpenGL rendering area and related widgets are packaged together. SoQtGLWidget uses buildWidget() to construct
its internal QGLWidget for rendering the scenegraph, so it is important to call the base class version of buildWidget(). For
example, inheriting from SoQtViewer, a buildWidget() function could look something like:


QWidget * MyViewer::buildWidget(QWidget * parent)
{
//have the superclass build and return it’s widget.
QWidget * viewerWidget = SoQtViewer::buildWidget(parent);

//call private fns to create some widgets
createToolbars(parent);
createPopupMenus(parent);

//create a horizontal layout, add widgets to it


QHBoxLayout *mainLayout = new QHBoxLayout(parent);
mainLayout->addWidget(viewerWidget);
mainLayout->addWidget(toolBar);
...
//make some connections here
}

Commonly used widgets can be stored as member variables for later access, including connecting signals and slots.
Providing accessor functions to allow outside access to these widgets will facilitate making signal/slot connections to
widgets outside the viewer class.

The next step is to connect widgets using signals and slots. In addition to the viewer widgets created in buildWidget(), there
are will also be outside widgets from the rest of the application that need to be connected. The best way to handle this is to
create a “manager” class that inherits from QObject and holds references to the various classes that need to be connected.
This class will typically contain: a custom viewing class discussed in section 4, any scenegraphs, and managers holding
the actual objects represented in the scenegraph. It will have slots to perform common functions and provide signals for
other widgets to connect to. For example:

class MySceneManager: public QObject


{
Q_OBJECT
public:
MySceneManager(QObject *parent);
~MySceneManager();

public slots:
void redrawScene();
void setBackgroundColor(const SbColor &color);

KONGSBERG SIM 
Coin3D and Qt:
The Solution for Cross-platform 3D Application Development
signals:
void objectSelected(Object *picked);

private:
ViewerWidget *viewerWidget;
SoSeparator *rootSceneGraph;
SoSceneManager *sceneManager;
ObjectManager *objectManager;
};

In this example, the ViewerWidget class is one of the viewing classes, such as a SoQtRenderArea or SoQtExaminerViewer.
The MySceneManager class is the class that the rest of the UI components will interact with. It is a QObject, so it can
implement the signal/slot mechanism. The objectSelected() signal notifies outside listeners that a new object in the
scenegraph has been selected. For more details on selection, see section 5.3

5.2 Event Handling


SoQt makes event handling easy because it takes QEvents and translates them into events that Coin/Inventor can
understand. This enables the application developer to work directly with SoEvents without ever having to worry about what
a QMouseEvent means for to scenegraph. However, SoQt also offers the flexibility to control how QEvent are translated to
SoEvents. A typical use for this would be to support additional input devices beyond a mouse and keyboard.

To handle custom translation from QEvents to SoEvents, override the processEvent() function from SoQtRenderArea.
This is the function that parses QEvents and creates the appropriate SoEvents. The SoEvents are then passed on to the
processSoEvent() function described above in section 4.3

5.3 Handling Selection


Picking objects in a scene is one of the most common tasks in a 3D application and often one of the most difficult to
implement. SoQt and Coin simplify this by translating the mouse clicks into SoEvents that the scenegraph can use to select
objects. To allow selection in a scenegraph, simply insert a SoSelectionNode as a parent for all the selectable nodes; SoQt
and Coin will handle the rest. To be notified when the selection changes, use SoSelection::addSelectionCallback(), which
specifies a callback function. The callback function has a SoPath parameter representing the current selection, which can
be used to determine the corresponding object to select in application space.

The following code shows the basic principles of selection and editing with Qt and Coin. It is similar to the example from
section 2, but this time with a simple scenegraph consisting of a yellow cone. When user clicks the cone, a QColorDialog is
shown to allow the user to change its color. It is quite easy to extend this basic example to pop up a custom editing widget
based on the type of object selected and populate it with the object’s current parameters.

//save the root and color nodes for use in the callback
static SoSeparator *root = 0;
static SoBaseColor *coneCol = 0;

void selectionCB( void *userdata, SoPath *path )


{
//get a new color using a QColorDialog, then set color for the cone
QColor c = QColorDialog::getColor();
coneCol->rgb = SbColor(c.red()/255.0, c.green()/255.0, c.blue()/255.0);

//redraw the scenegraph


root->touch();
}

KONGSBERG SIM 
Coin3D and Qt:
The Solution for Cross-platform 3D Application Development

int main( int argc, char** argv )


{
//initialize the Coin library
//create the root node of the scenegraph as in the first example
...

//Create a new SoSelection and add it to the root node.
SoSelection *selection = new SoSelection();
root->addChild( selection );

//set selection callback


selection->addSelectionCallback( selectionCB, (void *)0 );

//create a color and a cone and insert them under the selection node
coneCol = new SoBaseColor;
coneCol->rgb = SbColor(1, 1, 0);
selection->addChild(coneCol);
selection->addChild(new SoCone);

//Rest of main() goes here


...
}

6 Conclusion
This paper has demonstrated multiple ways to integrate Coin and Qt using SoQt. SoQt is easy-to-use, powerful and
flexible, offering both ready-made viewers for prototyping and classes that support complete customization. Events and
selection can be handled with ease. SoQt makes it possible to efficiently create cross-platform 3D applications that using
the full power of both Coin and Qt.

KONGSBERG SIM 

You might also like