fixed: auto_ptr -> unique_ptr
[opensg.git] / Examples / Simple / dyndrawing2.cpp
blob6b1ef9bf08a907cfe3a7289af844f1fac5bec23b
1 // OpenSG example: dyndrawing2.cpp
2 //
3 // User interface:
4 // a) mouse => standard navigator
5 // b) keyboard =>
6 // '1': toggle between static and dynamic mode
7 //
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string>
12 #include <sstream>
13 #include <fstream>
14 #include <vector>
15 #include <boost/tuple/tuple.hpp>
16 #include <boost/scoped_ptr.hpp>
17 #include <boost/random.hpp>
18 #include <boost/random/lagged_fibonacci.hpp>
20 #ifdef OSG_BUILD_ACTIVE
21 // Headers
22 #include <OSGGLUT.h>
23 #include <OSGConfig.h>
24 #include <OSGSimpleGeometry.h>
25 #include <OSGGLUTWindow.h>
26 #include <OSGGradientBackground.h>
27 #include <OSGSimpleSceneManager.h>
28 #include <OSGSceneFileHandler.h>
29 #include <OSGAction.h>
30 #include <OSGFrameBufferObject.h>
31 #include <OSGRenderBuffer.h>
32 #include <OSGTextureBuffer.h>
33 #include <OSGSimpleStage.h>
34 #include <OSGPassiveViewport.h>
35 #include <OSGVisitSubTree.h>
36 #include <OSGImage.h>
37 #include <OSGTextureObjChunk.h>
38 #include <OSGFBOBackground.h>
39 #include <OSGFBOGrabForeground.h>
41 #else
42 // Headers
43 #include <OpenSG/OSGGLUT.h>
44 #include <OpenSG/OSGConfig.h>
45 #include <OpenSG/OSGSimpleGeometry.h>
46 #include <OpenSG/OSGGLUTWindow.h>
47 #include <OpenSG/OSGGradientBackground.h>
48 #include <OpenSG/OSGSimpleSceneManager.h>
49 #include <OpenSG/OSGSceneFileHandler.h>
50 #include <OpenSG/OSGAction.h>
51 #include <OpenSG/OSGFrameBufferObject.h>
52 #include <OpenSG/OSGRenderBuffer.h>
53 #include <OpenSG/OSGTextureBuffer.h>
54 #include <OpenSG/OSGSimpleStage.h>
55 #include <OpenSG/OSGPassiveViewport.h>
56 #include <OpenSG/OSGVisitSubTree.h>
57 #include <OpenSG/OSGImage.h>
58 #include <OpenSG/OSGTextureObjChunk.h>
59 #include <OpenSG/OSGFBOBackground.h>
61 #endif
63 OSG_USING_NAMESPACE // just for convenience but not recommended
65 //#define USE_MULTISAMPLING
68 // The number of tori to render
69 // ============================
71 #ifdef _DEBUG
72 const int max_tori = 500;
73 #else
74 const int max_tori = 10000;
75 #endif
78 // Helper class for building FBO used by SimpleFBO see below
79 // =========================================================
81 class FBOBuilder
83 public:
84 struct TextureData {
85 TextureData()
86 : enable(true)
87 , pixel_format(Image::OSG_RGBA_PF)
88 , type(Image::OSG_UINT8_IMAGEDATA)
89 , main_memory(true)
90 , texObj(NULL)
91 , image(NULL) {}
92 ~TextureData() {texObj = NULL; image = NULL; }
94 bool enable;
95 UInt32 pixel_format;
96 Int32 type;
97 bool main_memory;
98 TextureObjChunkUnrecPtr texObj;
99 ImageUnrecPtr image;
102 typedef std::vector<TextureData> VecTextureDataT;
104 public:
105 FBOBuilder(const VecTextureDataT& buffers, bool depth, bool stencil, const TextureData& ds_buffer)
106 : _buffers(buffers) , _depth(depth) , _stencil(stencil) , _ds_buffer(ds_buffer) {}
107 ~FBOBuilder() {}
109 public:
110 FrameBufferObjectTransitPtr operator()(UInt32 width, UInt32 height) const;
112 private:
113 VecTextureDataT _buffers;
114 bool _depth;
115 bool _stencil;
116 TextureData _ds_buffer;
119 FrameBufferObjectTransitPtr FBOBuilder::operator()(
120 UInt32 width,
121 UInt32 height) const
124 // Setup the FBO
126 FrameBufferObjectUnrecPtr fbo = FrameBufferObject::create();
128 // multiple color buffers
130 for (UInt32 idx = 0; idx < _buffers.size(); ++idx) {
132 // use textures?
134 if (_buffers[idx].enable) {
135 ImageUnrecPtr texImg = (_buffers[idx].image == NULL ? Image::create() : _buffers[idx].image);
136 TextureObjChunkUnrecPtr texObj = (_buffers[idx].texObj == NULL ? TextureObjChunk::create() : _buffers[idx].texObj);
137 TextureBufferUnrecPtr texBuf = TextureBuffer::create();
139 if (_buffers[idx].image == NULL)
140 texImg->set(_buffers[idx].pixel_format,
141 width, height, 1, 1, 1, 0.f, NULL,
142 _buffers[idx].type,
143 _buffers[idx].main_memory);
145 texObj->setImage(texImg);
146 texBuf->setTexture(texObj);
148 fbo->setColorAttachment(texBuf, idx);
149 } else
151 // no, then use simple render buffer
154 RenderBufferUnrecPtr renBuf = RenderBuffer::create();
155 renBuf->setInternalFormat(_buffers[idx].pixel_format);
156 fbo->setColorAttachment(renBuf, idx);
158 fbo->editMFDrawBuffers()->push_back(GL_COLOR_ATTACHMENT0_EXT + idx);
161 // a sole depth buffer
163 if (_depth && !_stencil) {
165 // use textures?
167 if (_ds_buffer.enable) {
168 ImageUnrecPtr texImg = (_ds_buffer.image == NULL ? Image::create() : _ds_buffer.image);
169 TextureObjChunkUnrecPtr texObj = (_ds_buffer.texObj == NULL ? TextureObjChunk::create() : _ds_buffer.texObj);
170 TextureBufferUnrecPtr texBuf = TextureBuffer::create();
172 if (_ds_buffer.image == NULL)
173 texImg->set(_ds_buffer.pixel_format,
174 width, height, 1, 1, 1, 0.f, NULL,
175 _ds_buffer.type,
176 _ds_buffer.main_memory);
178 texObj->setImage(texImg);
180 if (_ds_buffer.texObj == NULL) {
181 texObj->setInternalFormat(GL_DEPTH_COMPONENT24);
182 texObj->setExternalFormat(GL_DEPTH_COMPONENT24);
184 texBuf->setTexture(texObj);
186 fbo->setDepthAttachment(texBuf);
187 } else
189 // no, then use simple render buffer
192 RenderBufferUnrecPtr renBuf = RenderBuffer::create();
193 renBuf->setInternalFormat(GL_DEPTH_COMPONENT24);
194 fbo->setDepthAttachment(renBuf);
196 } else
198 // or a combined depth/stencil buffer
200 if (_depth && _stencil) {
202 // use textures?
204 if (_ds_buffer.enable) {
205 ImageUnrecPtr texImg = (_ds_buffer.image == NULL ? Image::create() : _ds_buffer.image);
206 TextureObjChunkUnrecPtr texObj = (_ds_buffer.texObj == NULL ? TextureObjChunk::create() : _ds_buffer.texObj);
207 TextureBufferUnrecPtr texBuf = TextureBuffer::create();
209 if (_ds_buffer.image == NULL)
210 texImg->set(GL_DEPTH_STENCIL_EXT,
211 width, height, 1, 1, 1, 0.f, NULL,
212 GL_UNSIGNED_INT_24_8,
213 _ds_buffer.main_memory);
215 texObj->setImage(texImg);
216 texObj->setInternalFormat(GL_DEPTH24_STENCIL8_EXT);
217 texObj->setExternalFormat(GL_DEPTH_STENCIL_EXT);
218 texBuf->setTexture(texObj);
220 fbo->setDepthAttachment(texBuf);
221 fbo->setStencilAttachment(texBuf);
222 } else
224 // no, then use simple render buffer
227 RenderBufferUnrecPtr renBuf = RenderBuffer::create();
228 renBuf->setInternalFormat(GL_DEPTH24_STENCIL8);
229 fbo->setDepthAttachment(renBuf);
230 fbo->setStencilAttachment(renBuf);
234 fbo->setWidth (width );
235 fbo->setHeight(height);
237 return FrameBufferObjectTransitPtr(fbo);
241 // Convenience helper object wrapping the FBO uses FBOBuilder internally
242 // =====================================================================
244 class SimpleFBO
246 public:
247 SimpleFBO(UInt32 width,
248 UInt32 height,
249 bool color_textured,
250 bool depth_stencil_textured,
251 bool read_back_color = true,
252 bool read_back_depth_stencil = false);
254 SimpleFBO(UInt32 width,
255 UInt32 height,
256 const std::vector<FBOBuilder::TextureData>& buffers,
257 bool depth,
258 bool stencil,
259 const FBOBuilder::TextureData& ds_buffer);
261 ~SimpleFBO() { _fbo = NULL; }
263 public:
264 FrameBufferObject* fbo () const { return _fbo; }
266 FrameBufferAttachment* colorBuffer (UInt32 idx = 0) const { return _fbo ? _fbo->getColorAttachments(idx) : NULL; }
267 FrameBufferAttachment* depthBuffer () const { return _fbo ? _fbo->getDepthAttachment() : NULL; }
268 FrameBufferAttachment* stencilBuffer () const { return _fbo ? _fbo->getStencilAttachment() : NULL;}
270 TextureObjChunk* colorTexObj (UInt32 idx = 0) const;
271 TextureObjChunk* depthTexObj () const;
272 TextureObjChunk* stencilTexObj () const;
274 private:
275 FrameBufferObjectRecPtr _fbo;
278 SimpleFBO::SimpleFBO(
279 UInt32 width,
280 UInt32 height,
281 bool color_textured,
282 bool depth_stencil_textured,
283 bool read_back_color,
284 bool read_back_depth_stencil)
285 : _fbo(NULL)
287 FBOBuilder::TextureData color_data;
288 color_data.enable = color_textured;
289 color_data.main_memory = read_back_color;
291 FBOBuilder::TextureData depth_stencil_data;
292 depth_stencil_data.enable = depth_stencil_textured;
293 depth_stencil_data.main_memory = read_back_depth_stencil;
295 FBOBuilder::VecTextureDataT color_vec;
296 color_vec.push_back(color_data);
298 FBOBuilder fbo_builder(color_vec, true, true, depth_stencil_data);
300 _fbo = fbo_builder(width, height);
303 SimpleFBO::SimpleFBO(
304 UInt32 width,
305 UInt32 height,
306 const std::vector<FBOBuilder::TextureData>& buffers,
307 bool depth,
308 bool stencil,
309 const FBOBuilder::TextureData& ds_buffer)
310 : _fbo(NULL)
312 FBOBuilder fbo_builder(buffers, depth, stencil, ds_buffer);
314 _fbo = fbo_builder(width, height);
317 TextureObjChunk* SimpleFBO::colorTexObj(UInt32 idx) const
319 TextureBuffer* texBuf = dynamic_cast<TextureBuffer*>(colorBuffer(idx));
320 if (texBuf)
321 return texBuf->getTexture();
323 return NULL;
326 TextureObjChunk* SimpleFBO::depthTexObj() const
328 TextureBuffer* texBuf = dynamic_cast<TextureBuffer*>(depthBuffer());
329 if (texBuf)
330 return texBuf->getTexture();
332 return NULL;
335 TextureObjChunk* SimpleFBO::stencilTexObj() const
337 TextureBuffer* texBuf = dynamic_cast<TextureBuffer*>(stencilBuffer());
338 if (texBuf)
339 return texBuf->getTexture();
341 return NULL;
345 // function forward declarations
346 // =============================
348 static void cleanup(void);
349 static void display(void);
350 static void reshape(int w, int h);
351 static void mouse(int button, int state, int x, int y);
352 static void motion(int x, int y);
353 static void keyboard(unsigned char k, int, int);
354 static int setupGLUT(int *argc, char *argv[]);
355 static int doMain(int argc, char *argv[]);
358 static NodeTransitPtr createStaticScene();
359 static NodeTransitPtr createDynamicScene();
361 static void applyRenderMode();
362 static void enableStaticRendering();
363 static void enableDynamicRendering();
365 #if 0
366 static Node* rootNode(Node* node);
367 #endif
370 // global state of example
371 // =======================
373 bool static_render_mode;
374 SimpleSceneManagerRefPtr mgr;
375 NodeRefPtr staticScene;
376 NodeRefPtr dynamicScene;
377 GLUTWindowRefPtr win;
378 ViewportRefPtr viewport;
379 GradientBackgroundRefPtr background;
381 boost::scoped_ptr<SimpleFBO> spSimpleFBO;
384 // functions implementation
385 // ========================
388 static void cleanup(void)
390 mgr = NULL;
391 staticScene = NULL;
392 dynamicScene = NULL;
393 win = NULL;
394 viewport = NULL;
395 background = NULL;
396 spSimpleFBO.reset();
399 static void display(void)
401 commitChanges();
402 mgr->redraw();
405 static void reshape(int w, int h)
407 mgr->resize(w,h);
408 glutPostRedisplay();
411 static void mouse(int button, int state, int x, int y)
413 if (state)
414 mgr->mouseButtonRelease(button, x, y);
415 else
416 mgr->mouseButtonPress(button, x, y);
418 glutPostRedisplay();
421 static void motion(int x, int y)
423 mgr->mouseMove(x, y);
424 glutPostRedisplay();
427 static void keyboard(unsigned char k, int, int)
429 switch(k)
431 case 27:
432 case 'q':
433 case 'Q':
435 cleanup();
436 osgExit();
438 std::exit(EXIT_SUCCESS);
440 break;
442 case '1':
444 static_render_mode = !static_render_mode;
445 applyRenderMode();
447 break;
449 glutPostRedisplay();
453 // initialize GLUT
455 static int setupGLUT(int *argc, char *argv[])
457 glutInit(argc, argv);
459 glutInitDisplayMode(
460 GLUT_RGB | GLUT_DEPTH | GLUT_STENCIL | GLUT_DOUBLE
461 #ifdef USE_MULTISAMPLING
462 | GLUT_MULTISAMPLE
463 #endif
466 int winid = glutCreateWindow("OpenSG");
468 glutReshapeFunc(reshape);
469 glutDisplayFunc(display);
470 glutIdleFunc(display);
471 glutMouseFunc(mouse);
472 glutMotionFunc(motion);
473 glutKeyboardFunc(keyboard);
475 return winid;
479 // setup scene
481 static int doMain(int argc, char *argv[])
483 preloadSharedObject("OSGFileIO");
484 preloadSharedObject("OSGImageFileIO");
486 osgInit(argc,argv);
488 int winid = setupGLUT(&argc, argv);
490 win = GLUTWindow::create();
491 win->setGlutId(winid);
492 win->init();
494 if(argc < 2)
496 FWARNING(("No file given!\n"));
497 FWARNING(("Supported file formats:\n"));
499 std::list<const char*> suffixes;
500 SceneFileHandler::the()->getSuffixList(suffixes);
502 for(std::list<const char*>::iterator it = suffixes.begin();
503 it != suffixes.end();
504 ++it)
506 FWARNING(("%s\n", *it));
509 staticScene = createStaticScene();
511 else
513 staticScene = SceneFileHandler::the()->read(argv[1]);
516 dynamicScene = createDynamicScene();
518 spSimpleFBO.reset(new SimpleFBO(2, 2, true, true, true, false));
520 commitChanges();
522 NodeUnrecPtr root = makeCoredNode<Group>();
524 mgr = SimpleSceneManager::create();
525 mgr->setWindow(win);
526 mgr->setRoot (root);
528 background = GradientBackground::create();
529 background->addLine(Color3f(0,0,0), 0);
530 background->addLine(Color3f(1,1,1), 1);
532 viewport = win->getPort(0);
533 viewport->setBackground(background);
535 static_render_mode = true;
536 applyRenderMode();
538 mgr->showAll();
540 return 0;
544 // create an arbitrarly complex render scene
546 static NodeTransitPtr createStaticScene()
548 NodeUnrecPtr root = makeCoredNode<Group>();
550 typedef boost::mt19937 base_generator_type;
551 static base_generator_type generator(0);
552 static boost::uniform_01<float> value;
553 static boost::variate_generator< base_generator_type, boost::uniform_01<float> > die(generator, value);
555 for (int i = 0; i < max_tori; ++i) {
556 NodeUnrecPtr scene = makeTorus(.5, 2, 32, 32);
558 TransformUnrecPtr transformCore = Transform::create();
559 Matrix mat;
561 mat.setIdentity();
563 float x = 500.f * die();
564 float y = 500.f * die();
565 float z = 500.f * die();
567 float e1 = die();
568 float e2 = die();
569 float e3 = die();
571 Vec3f v(e1,e2,e3);
572 v.normalize();
574 float a = TwoPi * die();
576 Quaternion q(v, a);
578 mat.setTranslate(x,y,z);
579 mat.setRotate(q);
581 transformCore->setMatrix(mat);
583 NodeUnrecPtr trafo = makeNodeFor(transformCore);
585 trafo->addChild(scene);
587 root->addChild(trafo);
590 return NodeTransitPtr(root);
593 static NodeTransitPtr createDynamicScene()
595 NodeUnrecPtr scene = makeCylinder(30, 100, 16, true, true, true);
596 return NodeTransitPtr(scene);
599 static void applyRenderMode()
601 if (static_render_mode)
603 enableStaticRendering();
605 else
607 enableDynamicRendering();
611 static void enableStaticRendering()
613 // UInt32 width = win->getWidth();
614 // UInt32 height = win->getHeight();
616 FBOGrabForegroundUnrecPtr fboGrabForeground = FBOGrabForeground::create();
617 fboGrabForeground->setFrameBufferObject(spSimpleFBO->fbo());
618 fboGrabForeground->setAutoResize(true);
620 viewport->addForeground(fboGrabForeground);
621 viewport->setBackground(background);
623 NodeUnrecPtr root = makeCoredNode<Group>();
624 root->addChild(staticScene);
625 mgr->setRoot(root);
628 static void enableDynamicRendering()
630 FBOBackgroundUnrecPtr fboBckgnd = FBOBackground::create();
631 fboBckgnd->setFrameBufferObject(spSimpleFBO->fbo());
633 viewport->clearForegrounds();
634 viewport->setBackground(fboBckgnd);
636 NodeUnrecPtr root = makeCoredNode<Group>();
637 root->addChild(dynamicScene);
638 mgr->setRoot(root);
641 #if 0
642 static Node* rootNode(Node* node)
644 Node* root = NULL;
645 while (node) {
646 root = node;
647 node = node->getParent();
649 return root;
651 #endif
654 // main entry point
656 int main(int argc, char *argv[])
658 int ret = doMain(argc, argv);
660 glutMainLoop();
662 cleanup();
664 osgExit();
666 return ret;