1 // OpenSG Tutorial Example: OpenGL slave
3 // Many thanks to Gernot Ziegler <gz@lysator.liu.se> for distributing this example.
5 // It is often necessary to mix non-OpenSG code with OpenSG.
6 // This is a quick way to melt such code-bases together.
7 // But remember that transparencies will be handled incorrectly
8 // as no polygon sorting happens between OpenSG and OpenGL.
9 // And since the OpenGL part will be never be culled like the OpenSG
10 // scenegraph, it can easily happen that large OpenGL objects significantly
11 // affect performance.
13 // Thanks to nehe.gamedev.net for the BMP image loading routines
14 // The mouse code is based on a tutorial from Dennis Gustavsson (dennis@meqon.com)
16 #ifdef OSG_BUILD_ACTIVE
18 #include <OSGConfig.h>
22 #include <OSGSimpleGeometry.h>
23 #include <OSGCamera.h>
24 #include <OSGMatrixCamera.h>
25 #include <OSGPerspectiveCamera.h>
26 #include <OSGViewport.h>
27 #include <OSGPassiveWindow.h>
28 #include <OSGPassiveBackground.h>
29 #include <OSGSimpleSceneManager.h>
30 #include <OSGSceneFileHandler.h>
31 #include <OSGComponentTransform.h>
33 #include <OSGFileSystem.h>
36 #include <OpenSG/OSGConfig.h>
37 #include <OpenSG/OSGGL.h>
38 #include <OpenSG/OSGGLU.h>
39 #include <OpenSG/OSGGLUT.h>
40 #include <OpenSG/OSGSimpleGeometry.h>
41 #include <OpenSG/OSGCamera.h>
42 #include <OpenSG/OSGMatrixCamera.h>
43 #include <OpenSG/OSGPerspectiveCamera.h>
44 #include <OpenSG/OSGViewport.h>
45 #include <OpenSG/OSGPassiveWindow.h>
46 #include <OpenSG/OSGPassiveBackground.h>
47 #include <OpenSG/OSGSimpleSceneManager.h>
48 #include <OpenSG/OSGSceneFileHandler.h>
49 #include <OpenSG/OSGComponentTransform.h>
50 #include <OpenSG/OSGImage.h>
51 #include <OpenSG/OSGFileSystem.h>
54 OSG::PassiveWindowRefPtr pwin
;
55 OSG::SimpleSceneManagerRefPtr mgr
;
57 int window
; // The number of our GLUT window
58 GLuint texture
[3]; // Storage for 3 textures.
60 int Width
= 640, Height
= 480;
62 GLUquadricObj
*quadric
; // Storage For Our Quadric Objects
64 // The pointer to the transformation
65 OSG::TransformRefPtr trans
;
66 OSG::ViewportRefPtr vp
;
67 OSG::PerspectiveCameraRefPtr cam
;
68 OSG::MatrixCameraRefPtr newcam
;
69 OSG::NodeRefPtr scene
;
70 OSG::NodeRefPtr world
;
77 bool m_bLeftMouseButtonDown
;
78 bool m_bRightMouseButtonDown
;
79 unsigned int m_lastTick
; // last idle calc timestamp
80 unsigned int m_lastRenderTick
; // last rendering timestamp
82 bool m_bFullscreen
, m_bCalibrate
= false;
84 // Load texture into memory
85 void LoadGLTextures(void)
87 OSG::ImageRefPtr image
= OSG::Image::create();
88 if(!image
->read("./worldground.jpg"))
90 printf("Could not read worldground.jpg!!\n");
95 glGenTextures(1, &texture
[0]);
97 // texture 2 (linear scaling)
98 glBindTexture(GL_TEXTURE_2D
, texture
[0]); // 2d texture (x and y size)
99 glTexParameteri(GL_TEXTURE_2D
,GL_TEXTURE_MAG_FILTER
,GL_LINEAR
); // scale linearly when image bigger than texture
100 glTexParameteri(GL_TEXTURE_2D
,GL_TEXTURE_MIN_FILTER
,GL_LINEAR
); // scale linearly when image smalled than texture
101 glTexImage2D(GL_TEXTURE_2D
, 0, 3, image
->getWidth(), image
->getHeight(), 0, GL_RGB
, GL_UNSIGNED_BYTE
, image
->getData());
104 /* A general OpenGL initialization function. Sets all of the initial parameters. */
105 GLvoid
InitGL(GLsizei sWidth
, GLsizei sHeight
) // We call this right after our OpenGL window is created.
107 LoadGLTextures(); // Load the textures
109 glClearColor(0.0f
, 0.0f
, 0.0f
, 0.0f
); // This Will Clear The Background Color To Black
110 glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
111 glDepthFunc(GL_LESS
); // The Type Of Depth Test To Do
112 glEnable(GL_DEPTH_TEST
); // Enables Depth Testing
113 glShadeModel(GL_SMOOTH
); // Enables Smooth Color Shading
115 glMatrixMode(GL_PROJECTION
);
116 glLoadIdentity(); // Reset The Projection Matrix
118 gluPerspective(45.0, GLfloat(sWidth
)/GLfloat(sHeight
),0.1f
,100.0f
); // Calculate The Aspect Ratio Of The Window
119 quadric
=gluNewQuadric(); // Create A Pointer To The Quadric Object ( NEW )
121 // Can also use GLU_NONE, GLU_FLAT
122 gluQuadricNormals(quadric
, GLU_SMOOTH
); // Create Smooth Normals
123 gluQuadricTexture(quadric
, GL_TRUE
); // Create Texture Coords ( NEW )
125 m_bFullscreen
= false;
128 m_tiltAngle
= -70.0f
;
129 m_twistAngle
= -45.0f
;
131 m_bLeftMouseButtonDown
= false;
132 m_bRightMouseButtonDown
= false;
134 m_lastRenderTick
= 0;
138 //----------------------------------------------------------------------------//
139 // Handle an idle event
140 // does all the animation calculations //
141 //----------------------------------------------------------------------------//
148 //----------------------------------------------------------------------------//
149 // Render the cursor //
150 //----------------------------------------------------------------------------//
154 //printf("Cursor redraw\n");
155 // switch to orthogonal projection for the cursor
156 glMatrixMode(GL_PROJECTION
);
159 glOrtho(0, GLdouble(Width
), 0, GLdouble(Height
), -1.0f
, 1.0f
);
161 glMatrixMode(GL_MODELVIEW
);
166 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
168 glBegin(GL_TRIANGLES
);
169 glColor4f(1.0f
, 1.0f
, 1.0f
, 1.0f
);
170 glVertex2i(m_mouseX
, m_mouseY
);
171 glColor4f(1.0f
, 1.0f
, 1.0f
, 0.2f
);
172 glVertex2i(m_mouseX
+ 16, m_mouseY
- 32);
173 glColor4f(1.0f
, 1.0f
, 1.0f
, 0.2f
);
174 glVertex2i(m_mouseX
+ 32, m_mouseY
- 16);
179 glMatrixMode(GL_PROJECTION
);
182 glMatrixMode(GL_MODELVIEW
);
185 /* ascii code for various keys */
190 #define DOWN_ARROW 80
191 #define LEFT_ARROW 75
192 #define RIGHT_ARROW 77
195 /* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */
196 void ReSizeGLScene(int mWidth
, int mHeight
)
201 if (Height
==0) // Prevent A Divide By Zero If The Window Is Too Small
204 glViewport(0, 0, Width
, Height
); // Reset The Current Viewport And Perspective Transformation
206 glMatrixMode(GL_PROJECTION
);
208 gluPerspective(45.0, GLfloat(Width
) / GLfloat(Height
), 1, 1000.0f
);
209 glMatrixMode(GL_MODELVIEW
);
211 mgr
->resize(mWidth
,mHeight
);
214 void onMouseMove(int x
, int y
)
216 // update twist/tilt angles
217 if(m_bLeftMouseButtonDown
)
219 // calculate new angles
220 m_twistAngle
+= static_cast<float>(x
- m_mouseX
);
221 m_tiltAngle
-= static_cast<float>(y
- m_mouseY
);
225 if(m_bRightMouseButtonDown
)
227 // calculate new distance
228 m_distance
-= static_cast<float>(y
- m_mouseY
) / 3.0f
;
229 if(m_distance
< 0.0f
)
233 // update internal mouse position
238 void motionFunc(int x
, int y
)
240 // redirect the message to the viewer instance
241 onMouseMove(x
, Height
- y
- 1);
243 //mgr->mouseMove(x, y);
246 //----------------------------------------------------------------------------//
247 // Handle a mouse button down event //
248 //----------------------------------------------------------------------------//
250 void onMouseButtonDown(int button
, int x
, int y
)
252 // update mouse button states
253 if(button
== GLUT_LEFT_BUTTON
)
254 m_bLeftMouseButtonDown
= true;
256 if(button
== GLUT_RIGHT_BUTTON
)
257 m_bRightMouseButtonDown
= true;
259 // update internal mouse position
264 //----------------------------------------------------------------------------//
265 // Handle a mouse button up event //
266 //----------------------------------------------------------------------------//
268 void onMouseButtonUp(int button
, int x
, int y
)
270 // update mouse button states
271 if(button
== GLUT_LEFT_BUTTON
)
272 m_bLeftMouseButtonDown
= false;
274 if(button
== GLUT_RIGHT_BUTTON
)
275 m_bRightMouseButtonDown
= false;
277 // update internal mouse position
282 void mouseFunc(int button
, int state
, int x
, int y
)
286 mgr
->mouseButtonRelease(button
, x
, y
);
288 mgr
->mouseButtonPress(button
, x
, y
);
291 // redirect the message to the viewer instance
292 if(state
== GLUT_DOWN
)
294 onMouseButtonDown(button
, x
, Height
- y
- 1);
296 else if(state
== GLUT_UP
)
298 onMouseButtonUp(button
, x
, Height
- y
- 1);
302 /* The function called whenever a key is pressed. */
303 void keyPressed(unsigned char key
, int x
, int y
)
305 /* avoid thrashing this procedure */
311 // clean up gobal variables
321 /* shut down our window */
322 //glutDestroyWindow(window);
324 /* exit the program...normal termination. */
330 printf ("Key %d pressed. No action there yet.\n", key
);
335 /* The main drawing function. */
336 void DrawGLScene(void)
338 glMatrixMode(GL_MODELVIEW
);
340 // clear all the buffers - gives OpenGL full control
341 // OpenSG doesn't clear the background because of the PassiveBackground object
342 glClearColor(0.0f
, 0.0f
, 0.0f
, 0.0f
);
343 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
345 // set the model transformation
346 glMatrixMode(GL_MODELVIEW
);
349 // set camera position from mouse movement
350 glTranslatef(0.0f
, 0.0f
, -m_distance
);
351 glRotatef(m_tiltAngle
, 1.0f
, 0.0f
, 0.0f
);
352 glRotatef(m_twistAngle
, 0.0f
, 0.0f
, 1.0f
);
353 //glTranslatef(0.0f, 0.0f, -90.0f);
355 glPushMatrix(); // OpenSG will overwrite
357 OSG::Real32 proj_matrix
[16], model_matrix
[16];
358 glGetFloatv(GL_PROJECTION_MATRIX
, proj_matrix
);
359 glGetFloatv(GL_MODELVIEW_MATRIX
, model_matrix
);
361 // retrieve OpenGL's matrices
362 OSG::Matrix proj
, model
;
363 proj
.setValue(proj_matrix
);
364 model
.setValue(model_matrix
);
366 newcam
->setProjectionMatrix(proj
);
368 // transform the world just like the OpenGL content
369 // necessary since OpenSG's modelview transforms start from the unity matrix.
370 newcam
->setModelviewMatrix(model
);
372 // setup an initial transformation
376 // mind that the VRML base coordinate system has different meanings for X, Y, Z, hence the rotation for 90 degrees.
377 // this, together with the MatrixCamera code above hooks OpenSG to OpenGL !
379 q1
.setValueAsAxisDeg(1, 0, 0., 90); // rotation
381 trans
->setMatrix(m1
);
383 OSG::commitChanges();
385 // redraw the OpenSG window content - the calls are a bit after one's own taste
386 pwin
->render(mgr
->getRenderAction());
391 glMatrixMode(GL_MODELVIEW
);
393 //################ START FOR OPENGL STUFF
396 const GLfloat light_ambient
[] = { 0.3f
, 0.3f
, 0.3f
, 1.0f
};
397 const GLfloat light_diffuse
[] = { 0.52f
, 0.5f
, 0.5f
, 1.0f
};
398 const GLfloat light_specular
[] = { 0.1f
, 0.1f
, 0.1f
, 1.0f
};
400 // setup the light attributes
401 glLightfv(GL_LIGHT0
, GL_AMBIENT
, light_ambient
);
402 glLightfv(GL_LIGHT0
, GL_DIFFUSE
, light_diffuse
);
403 glLightfv(GL_LIGHT0
, GL_SPECULAR
, light_specular
);
406 glEnable(GL_LIGHTING
);
408 // set the light position
409 GLfloat lightPosition
[] = { 0.0f
, -10.0f
, 10.0f
, 0.0f
};
410 glLightfv(GL_LIGHT0
, GL_POSITION
, lightPosition
);
412 glEnable(GL_NORMALIZE
);
414 glDisable(GL_NORMALIZE
);
415 //glDisable(GL_BLEND);
417 glEnable(GL_LIGHTING
);
418 glEnable(GL_TEXTURE_2D
);
419 glBindTexture(GL_TEXTURE_2D
, texture
[0]); // choose the texture to use.
421 GLfloat TableDiffuse
[] = { 0.3f
, 0.0f
, 1.0f
, 0.5f
};
422 GLfloat TableSpecular
[] = { 0.6f
, 0.0f
, 0.8f
, 0.5f
};
423 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, TableDiffuse
);
424 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, TableSpecular
);
425 glMaterialf(GL_FRONT_AND_BACK
, GL_SHININESS
, 0.4f
);
428 gluPartialDisk(quadric
,0,12.0f
,32,16, 0, 360); // A Disk Like The One Before
430 glDisable(GL_TEXTURE_2D
);
431 glDisable(GL_LIGHTING
);
436 glVertex3f(0,0,0.1f
);
437 glVertex3f(120,0,0.1f
);
443 glVertex3f(0,0,0.1f
);
444 glVertex3f(0,120,0.1f
);
447 glEnable(GL_LIGHTING
);
450 glDisable(GL_TEXTURE_2D
);
453 glDisable(GL_LIGHTING
);
458 // swap the front- and back-buffer
462 int main(int argc
, char **argv
)
464 // we need to load some relative images and geometry files.
465 // to make this work reliable (e.g. starting the tutorial via link)
466 // we use the argv[0] parameter.
468 std::string
sep("\\");
470 std::string
sep("/");
472 std::string path
= argv
[0];
474 std::string::size_type i
= path
.rfind(sep
);
475 if(i
!= std::string::npos
)
476 path
= path
.substr(0, i
);
477 // set the current dir to the application dir.
478 OSG::Directory::setCurrent(path
.c_str());
481 OSG::osgInit(argc
, argv
);
483 /* Initialize GLUT state - glut will take any command line arguments that pertain to it or
484 X Windows - look at its documentation at http://reality.sgi.com/mjk/spec3/spec3.html */
485 glutInit(&argc
, argv
);
487 /* Select type of Display mode:
490 Alpha components supported (use GLUT_ALPHA)
492 glutInitDisplayMode(GLUT_RGB
| GLUT_DOUBLE
| GLUT_DEPTH
);
494 /* get a 640 x 480 window */
495 //glutInitWindowSize(640, 480);
496 glutInitWindowSize(Width
, Height
);
498 /* the window starts at the upper left corner of the screen */
499 glutInitWindowPosition(300, 0);
502 window
= glutCreateWindow("Oz, Mouse Control");
506 glutSetCursor(GLUT_CURSOR_NONE
);
508 glutDisplayFunc(&DrawGLScene
);
510 // register all GLUT callback functions
511 glutIdleFunc(idleFunc
);
513 /* Register the function called when our window is resized. */
514 glutReshapeFunc(ReSizeGLScene
);
516 /* Register the function called when the keyboard is pressed. */
517 glutKeyboardFunc(keyPressed
);
519 /* Register the function called when special keys (arrows, page down, etc) are pressed. */
520 //glutSpecialFunc(&specialKeyPressed);
522 glutMouseFunc(mouseFunc
);
523 glutMotionFunc(motionFunc
);
524 glutPassiveMotionFunc(motionFunc
);
526 /* Initialize our window. */
529 pwin
= OSG::PassiveWindow::create();
533 All scene file loading is handled via the SceneFileHandler.
535 world
= OSG::SceneFileHandler::the()->read("Data/tie.wrl");
536 // create the main scene transformation node
538 // 1. create the Node
539 scene
=OSG:: Node::create();
541 // 2. create the core
542 trans
= OSG::Transform::create();
544 // 3. associate the core with the node
545 scene
->setCore(trans
);
546 scene
->addChild(world
); // add the world as a child
548 // create the SimpleSceneManager helper - it will be only partially used
549 mgr
= OSG::SimpleSceneManager::create();
551 // tell the manager what to manage
552 mgr
->setWindow(pwin
);
553 mgr
->setRoot (scene
);
555 if (pwin
->getMFPort()->size() != 0)
557 OSG::PassiveBackgroundRefPtr bg
= OSG::PassiveBackground::create();
559 vp
= pwin
->getPort(0);
560 cam
= dynamic_cast<OSG::PerspectiveCamera
*>(vp
->getCamera());
561 newcam
= OSG::MatrixCamera::create(); // the MatrixCamera will only be a slave to the OpenGL matrices
562 vp
->setCamera(newcam
); // replace the cam
563 vp
->setBackground(bg
); // keep OpenSG from deleting the background, we will do that ourselves
569 printf("Could not acquire pointer to camera !!\n");
573 OSG::commitChanges();
575 /* Start Event Processing Engine */