Open Inventor Release 2024.2.0
 
Loading...
Searching...
No Matches
Applying a Render Action Inside a GLX Window

C++ : Using a GLX Window creates a GLX window, makes Inventor and OpenGL calls, and then applies a GL render action. It uses OpenGL to render a checked “floor” and Inventor to render a red cube and a blue sphere, in the same window.

Example : Using a GLX Window

C++ :

#include <stdio.h>
#include <unistd.h>
#include <Inventor/SoDB.h>
#include <Inventor/SoSceneManager.h>
#include <Inventor/devices/SoGLContext.h>
#include <Inventor/nodes/SoCube.h>
#include <Inventor/nodes/SoDirectionalLight.h>
#include <Inventor/nodes/SoLightModel.h>
#include <Inventor/nodes/SoMaterial.h>
#include <Inventor/nodes/SoSeparator.h>
#include <Inventor/nodes/SoSphere.h>
#include <Inventor/nodes/SoTransform.h>
// This is related to <GL/GL.h> and <GL/GLX.h> but
// it is handled by GLEW
#include <Inventor/sys/SoGL.h>
#include <Inventor/sys/SoGLX.h>
#define WINWIDTH 400
#define WINHEIGHT 400
float floorObj[81][3];
SoGLContext* oivContext = NULL;
// Build an Inventor scene with two objects and some light
void
buildScene( SoGroup* root )
{
// Some light
root->addChild( new SoLightModel );
root->addChild( new SoDirectionalLight );
// A red cube translated to the left and down
SoTransform* myTrans = new SoTransform;
myTrans->translation.setValue( -2.0, -2.0, 0.0 );
root->addChild( myTrans );
SoMaterial* myMtl = new SoMaterial;
myMtl->diffuseColor.setValue( 1.0, 0.0, 0.0 );
root->addChild( myMtl );
root->addChild( new SoCube );
// A blue sphere translated right
myTrans = new SoTransform;
myTrans->translation.setValue( 4.0, 0.0, 0.0 );
root->addChild( myTrans );
myMtl = new SoMaterial;
myMtl->diffuseColor.setValue( 0.0, 0.0, 1.0 );
root->addChild( myMtl );
root->addChild( new SoSphere );
}
// Build a floor that will be rendered using OpenGL.
void
buildFloor()
{
int a = 0;
for ( float i = -5.0; i <= 5.0; i += 1.25 )
{
for ( float j = -5.0; j <= 5.0; j += 1.25, a++ )
{
floorObj[a][0] = j;
floorObj[a][1] = 0.0;
floorObj[a][2] = i;
}
}
}
// Callback used by GLX window
static Bool
waitForNotify( Display*, XEvent* e, char* arg )
{
return ( e->type == MapNotify ) && ( e->xmap.window == ( Window )arg );
}
// Create and initialize GLX window.
void
openWindow( Display*& display, Window& window )
{
XVisualInfo* vi;
Colormap cmap;
XSetWindowAttributes swa;
GLXContext cx;
XEvent event;
static int attributeList[] = {
GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_DEPTH_SIZE, 1, GLX_DOUBLEBUFFER, None,
};
display = XOpenDisplay( 0 );
vi = glXChooseVisual( display, DefaultScreen( display ), attributeList );
cx = glXCreateContext( display, vi, 0, GL_TRUE );
cmap = XCreateColormap( display, RootWindow( display, vi->screen ), vi->visual, AllocNone );
swa.colormap = cmap;
swa.border_pixel = 0;
swa.event_mask = StructureNotifyMask;
window = XCreateWindow( display,
RootWindow( display, vi->screen ),
100,
100,
WINWIDTH,
WINHEIGHT,
0,
vi->depth,
InputOutput,
vi->visual,
( CWBorderPixel | CWColormap | CWEventMask ),
&swa );
XMapWindow( display, window );
XIfEvent( display, &event, waitForNotify, ( char* )window );
// OIV needs an SoGLContext to perform OpenGL operations
oivContext = new SoGLContext( display, vi, window, cx );
}
// Draw the lines that make up the floor, using OpenGL
void
drawFloor()
{
int i;
glBegin( GL_LINES );
for ( i = 0; i < 4; i++ )
{
glVertex3fv( floorObj[i * 18] );
glVertex3fv( floorObj[( i * 18 ) + 8] );
glVertex3fv( floorObj[( i * 18 ) + 17] );
glVertex3fv( floorObj[( i * 18 ) + 9] );
}
glVertex3fv( floorObj[i * 18] );
glVertex3fv( floorObj[( i * 18 ) + 8] );
glEnd();
glBegin( GL_LINES );
for ( i = 0; i < 4; i++ )
{
glVertex3fv( floorObj[i * 2] );
glVertex3fv( floorObj[( i * 2 ) + 72] );
glVertex3fv( floorObj[( i * 2 ) + 73] );
glVertex3fv( floorObj[( i * 2 ) + 1] );
}
glVertex3fv( floorObj[i * 2] );
glVertex3fv( floorObj[( i * 2 ) + 72] );
glEnd();
}
int
main( int, char** )
{
// Initialize Inventor
SoDB::init();
// Build a simple scene graph
SoSeparator* root = new SoSeparator;
root->ref();
buildScene( root );
// It's better to use an SoSceneManager for some basic operations
// - clear the buffers
// - Handles the SoGLRenderAction
// - Event handling (it is possible to provide the events to the
// scene graph, useful for draggers...)
SoSceneManager* sceneManager = new SoSceneManager();
sceneManager->setSceneGraph( root );
sceneManager->setBackgroundColor( SbColor( 0.8, 0.8, 0.8 ) );
sceneManager->setWindowSize( SbVec2s( WINWIDTH, WINHEIGHT ) );
// Build the floor geometry
buildFloor();
// Create and initialize window
Display* display;
Window window;
openWindow( display, window );
// We need a context here for rendering
// OIV will bind the GL context.
oivContext->bind();
// By default OIV does not enable the depth test.
glEnable( GL_DEPTH_TEST );
// Set up the camera using OpenGL.
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 90.0, 1.0, 2.0, 12.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glTranslatef( 0.0, 0.0, -5.0 );
// Render the OIV scene. The render method will clear
// the OpenGL buffers.
sceneManager->render();
// Render the floor using OpenGL
// - We push the attributes since OIV consider that
// non-OIV code won't modify the OpenGL state.
glPushAttrib( GL_ALL_ATTRIB_BITS );
glPushMatrix();
glTranslatef( 0.0, -3.0, 0.0 );
glColor3f( 0.0, 0.7, 0.0 );
glLineWidth( 2.0 );
glDisable( GL_LIGHTING );
drawFloor();
glEnable( GL_LIGHTING );
glPopMatrix();
glPopAttrib();
// Swap the buffers, the OIV context can handle this.
oivContext->swapBuffers();
oivContext->unbind();
oivContext->unref();
sleep( 10 );
root->unref();
delete sceneManager;
return 0;
}