fixed: compile issue
[opensg.git] / Examples / Simple / dyndrawing1.cpp
blobf97ca6315eb2a3578a1c39eb52518378022b8b16
1 // OpenSG example: dyndrawing1.cpp
2 //
3 // Description:
4 // This example shows how to create a render setup that allows the rendering
5 // of a complex scene in its first viewport and on request (key '1') switches
6 // into a 'dynamic' mode that allows you to render additional scenery dynamically.
7 //
8 // Problem:
9 // In some domains such as CAD it is possible that the render scene is very
10 // complex so that it is not possible to reach any reasonable frame rate.
11 // However you still need to be able to draw dynamic content in such a scenery.
12 // Imagine for instance that you must dynamically resposion some 100 lines of grafic.
14 // Solution:
15 // Separate the static and the dynamic rendering and render the static scenery from
16 // an image. This is of course limited to dynamic modifications that leave the static
17 // scenenry rendered from one perspective. Still it is very useful.
19 // Implementation:
20 // The complex scene is rendered into a FBO that is subsequentely given to a
21 // FBOBackground used by the dynamic viewport, i.e. the viewport that should handle
22 // dynamic graphic.
24 // User interface:
25 // a) mouse => standard navigator
26 // b) keyboard =>
27 // '1': toggle between static and dynamic mode
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string>
33 #include <sstream>
34 #include <fstream>
35 #include <vector>
36 #include <boost/tuple/tuple.hpp>
37 #include <boost/scoped_ptr.hpp>
38 #include <boost/random.hpp>
39 #include <boost/random/lagged_fibonacci.hpp>
41 #ifdef OSG_BUILD_ACTIVE
42 // Headers
43 #include <OSGGLUT.h>
44 #include <OSGConfig.h>
45 #include <OSGSimpleGeometry.h>
46 #include <OSGGLUTWindow.h>
47 #include <OSGGradientBackground.h>
48 #include <OSGSimpleSceneManager.h>
49 #include <OSGSceneFileHandler.h>
50 #include <OSGAction.h>
51 #include <OSGFrameBufferObject.h>
52 #include <OSGRenderBuffer.h>
53 #include <OSGTextureBuffer.h>
54 #include <OSGSimpleStage.h>
55 #include <OSGPassiveViewport.h>
56 #include <OSGVisitSubTree.h>
57 #include <OSGImage.h>
58 #include <OSGTextureObjChunk.h>
59 #include <OSGFBOBackground.h>
61 #else
62 // Headers
63 #include <OpenSG/OSGGLUT.h>
64 #include <OpenSG/OSGConfig.h>
65 #include <OpenSG/OSGSimpleGeometry.h>
66 #include <OpenSG/OSGGLUTWindow.h>
67 #include <OpenSG/OSGGradientBackground.h>
68 #include <OpenSG/OSGSimpleSceneManager.h>
69 #include <OpenSG/OSGSceneFileHandler.h>
70 #include <OpenSG/OSGAction.h>
71 #include <OpenSG/OSGFrameBufferObject.h>
72 #include <OpenSG/OSGRenderBuffer.h>
73 #include <OpenSG/OSGTextureBuffer.h>
74 #include <OpenSG/OSGSimpleStage.h>
75 #include <OpenSG/OSGPassiveViewport.h>
76 #include <OpenSG/OSGVisitSubTree.h>
77 #include <OpenSG/OSGImage.h>
78 #include <OpenSG/OSGTextureObjChunk.h>
79 #include <OpenSG/OSGFBOBackground.h>
81 #endif
83 OSG_USING_NAMESPACE // just for convenience but not recommended
85 //#define USE_MULTISAMPLING
88 // The number of tori to render
89 // ============================
91 #ifdef _DEBUG
92 const int max_tori = 500;
93 #else
94 const int max_tori = 10000;
95 #endif
98 // Helper class for building FBO used by SimpleFBO see below
99 // =========================================================
101 class FBOBuilder
103 public:
104 struct TextureData {
105 TextureData()
106 : enable(true)
107 , pixel_format(Image::OSG_RGBA_PF)
108 , type(Image::OSG_UINT8_IMAGEDATA)
109 , main_memory(true)
110 , texObj(NULL)
111 , image(NULL) {}
112 ~TextureData() {texObj = NULL; image = NULL; }
114 bool enable;
115 UInt32 pixel_format;
116 Int32 type;
117 bool main_memory;
118 TextureObjChunkUnrecPtr texObj;
119 ImageUnrecPtr image;
122 typedef std::vector<TextureData> VecTextureDataT;
124 public:
125 FBOBuilder(const VecTextureDataT& buffers, bool depth, bool stencil, const TextureData& ds_buffer)
126 : _buffers(buffers) , _depth(depth) , _stencil(stencil) , _ds_buffer(ds_buffer) {}
127 ~FBOBuilder() {}
129 public:
130 FrameBufferObjectTransitPtr operator()(UInt32 width, UInt32 height) const;
132 private:
133 VecTextureDataT _buffers;
134 bool _depth;
135 bool _stencil;
136 TextureData _ds_buffer;
139 FrameBufferObjectTransitPtr FBOBuilder::operator()(
140 UInt32 width,
141 UInt32 height) const
144 // Setup the FBO
146 FrameBufferObjectUnrecPtr fbo = FrameBufferObject::create();
148 // multiple color buffers
150 for (UInt32 idx = 0; idx < _buffers.size(); ++idx) {
152 // use textures?
154 if (_buffers[idx].enable) {
155 ImageUnrecPtr texImg = (_buffers[idx].image == NULL ? Image::create() : _buffers[idx].image);
156 TextureObjChunkUnrecPtr texObj = (_buffers[idx].texObj == NULL ? TextureObjChunk::create() : _buffers[idx].texObj);
157 TextureBufferUnrecPtr texBuf = TextureBuffer::create();
159 if (_buffers[idx].image == NULL)
160 texImg->set(_buffers[idx].pixel_format,
161 width, height, 1, 1, 1, 0.f, NULL,
162 _buffers[idx].type,
163 _buffers[idx].main_memory);
165 texObj->setImage(texImg);
166 texBuf->setTexture(texObj);
168 fbo->setColorAttachment(texBuf, idx);
169 } else
171 // no, then use simple render buffer
174 RenderBufferUnrecPtr renBuf = RenderBuffer::create();
175 renBuf->setInternalFormat(_buffers[idx].pixel_format);
176 fbo->setColorAttachment(renBuf, idx);
178 fbo->editMFDrawBuffers()->push_back(GL_COLOR_ATTACHMENT0_EXT + idx);
181 // a sole depth buffer
183 if (_depth && !_stencil) {
185 // use textures?
187 if (_ds_buffer.enable) {
188 ImageUnrecPtr texImg = (_ds_buffer.image == NULL ? Image::create() : _ds_buffer.image);
189 TextureObjChunkUnrecPtr texObj = (_ds_buffer.texObj == NULL ? TextureObjChunk::create() : _ds_buffer.texObj);
190 TextureBufferUnrecPtr texBuf = TextureBuffer::create();
192 if (_ds_buffer.image == NULL)
193 texImg->set(_ds_buffer.pixel_format,
194 width, height, 1, 1, 1, 0.f, NULL,
195 _ds_buffer.type,
196 _ds_buffer.main_memory);
198 texObj->setImage(texImg);
200 if (_ds_buffer.texObj == NULL) {
201 texObj->setInternalFormat(GL_DEPTH_COMPONENT24);
202 texObj->setExternalFormat(GL_DEPTH_COMPONENT24);
204 texBuf->setTexture(texObj);
206 fbo->setDepthAttachment(texBuf);
207 } else
209 // no, then use simple render buffer
212 RenderBufferUnrecPtr renBuf = RenderBuffer::create();
213 renBuf->setInternalFormat(GL_DEPTH_COMPONENT24);
214 fbo->setDepthAttachment(renBuf);
216 } else
218 // or a combined depth/stencil buffer
220 if (_depth && _stencil) {
222 // use textures?
224 if (_ds_buffer.enable) {
225 ImageUnrecPtr texImg = (_ds_buffer.image == NULL ? Image::create() : _ds_buffer.image);
226 TextureObjChunkUnrecPtr texObj = (_ds_buffer.texObj == NULL ? TextureObjChunk::create() : _ds_buffer.texObj);
227 TextureBufferUnrecPtr texBuf = TextureBuffer::create();
229 if (_ds_buffer.image == NULL)
230 texImg->set(GL_DEPTH_STENCIL_EXT,
231 width, height, 1, 1, 1, 0.f, NULL,
232 GL_UNSIGNED_INT_24_8,
233 _ds_buffer.main_memory);
235 texObj->setImage(texImg);
236 texObj->setInternalFormat(GL_DEPTH24_STENCIL8_EXT);
237 texObj->setExternalFormat(GL_DEPTH_STENCIL_EXT);
238 texBuf->setTexture(texObj);
240 fbo->setDepthAttachment(texBuf);
241 fbo->setStencilAttachment(texBuf);
242 } else
244 // no, then use simple render buffer
247 RenderBufferUnrecPtr renBuf = RenderBuffer::create();
248 renBuf->setInternalFormat(GL_DEPTH24_STENCIL8);
249 fbo->setDepthAttachment(renBuf);
250 fbo->setStencilAttachment(renBuf);
254 fbo->setWidth (width );
255 fbo->setHeight(height);
257 return FrameBufferObjectTransitPtr(fbo);
261 // Convenience helper object wrapping the FBO uses FBOBuilder internally
262 // =====================================================================
264 class SimpleFBO
266 public:
267 SimpleFBO(UInt32 width,
268 UInt32 height,
269 bool color_textured,
270 bool depth_stencil_textured,
271 bool read_back_color = true,
272 bool read_back_depth_stencil = false);
274 SimpleFBO(UInt32 width,
275 UInt32 height,
276 const std::vector<FBOBuilder::TextureData>& buffers,
277 bool depth,
278 bool stencil,
279 const FBOBuilder::TextureData& ds_buffer);
281 ~SimpleFBO() { _fbo = NULL; }
283 public:
284 FrameBufferObject* fbo () const { return _fbo; }
286 FrameBufferAttachment* colorBuffer (UInt32 idx = 0) const { return _fbo ? _fbo->getColorAttachments(idx) : NULL; }
287 FrameBufferAttachment* depthBuffer () const { return _fbo ? _fbo->getDepthAttachment() : NULL; }
288 FrameBufferAttachment* stencilBuffer () const { return _fbo ? _fbo->getStencilAttachment() : NULL;}
290 TextureObjChunk* colorTexObj (UInt32 idx = 0) const;
291 TextureObjChunk* depthTexObj () const;
292 TextureObjChunk* stencilTexObj () const;
294 private:
295 FrameBufferObjectRecPtr _fbo;
298 SimpleFBO::SimpleFBO(
299 UInt32 width,
300 UInt32 height,
301 bool color_textured,
302 bool depth_stencil_textured,
303 bool read_back_color,
304 bool read_back_depth_stencil)
305 : _fbo(NULL)
307 FBOBuilder::TextureData color_data;
308 color_data.enable = color_textured;
309 color_data.main_memory = read_back_color;
311 FBOBuilder::TextureData depth_stencil_data;
312 depth_stencil_data.enable = depth_stencil_textured;
313 depth_stencil_data.main_memory = read_back_depth_stencil;
315 FBOBuilder::VecTextureDataT color_vec;
316 color_vec.push_back(color_data);
318 FBOBuilder fbo_builder(color_vec, true, true, depth_stencil_data);
320 _fbo = fbo_builder(width, height);
323 SimpleFBO::SimpleFBO(
324 UInt32 width,
325 UInt32 height,
326 const std::vector<FBOBuilder::TextureData>& buffers,
327 bool depth,
328 bool stencil,
329 const FBOBuilder::TextureData& ds_buffer)
330 : _fbo(NULL)
332 FBOBuilder fbo_builder(buffers, depth, stencil, ds_buffer);
334 _fbo = fbo_builder(width, height);
337 TextureObjChunk* SimpleFBO::colorTexObj(UInt32 idx) const
339 TextureBuffer* texBuf = dynamic_cast<TextureBuffer*>(colorBuffer(idx));
340 if (texBuf)
341 return texBuf->getTexture();
343 return NULL;
346 TextureObjChunk* SimpleFBO::depthTexObj() const
348 TextureBuffer* texBuf = dynamic_cast<TextureBuffer*>(depthBuffer());
349 if (texBuf)
350 return texBuf->getTexture();
352 return NULL;
355 TextureObjChunk* SimpleFBO::stencilTexObj() const
357 TextureBuffer* texBuf = dynamic_cast<TextureBuffer*>(stencilBuffer());
358 if (texBuf)
359 return texBuf->getTexture();
361 return NULL;
366 // function forward declarations
367 // =============================
369 static void cleanup(void);
370 static void display(void);
371 static void reshape(int w, int h);
372 static void mouse(int button, int state, int x, int y);
373 static void motion(int x, int y);
374 static void keyboard(unsigned char k, int, int);
375 static int setupGLUT(int *argc, char *argv[]);
376 static int doMain(int argc, char *argv[]);
378 static NodeTransitPtr createStaticScene();
379 static NodeTransitPtr createDynamicScene();
380 static void createAcquisitionStage();
381 static void createDynamicViewport();
382 static void enableStaticScene();
383 static Node* rootNode(Node* node);
386 // global state of example
387 // =======================
389 SimpleSceneManagerRefPtr mgr;
390 NodeRefPtr staticScene;
391 NodeRefPtr dynamicScene;
392 GLUTWindowRefPtr win;
393 ViewportRefPtr staticVp;
394 ViewportRefPtr dynamicVp;
395 CameraRefPtr camera;
397 boost::scoped_ptr<SimpleFBO> spSimpleFBO;
400 // functions implementation
401 // ========================
404 static void cleanup(void)
406 mgr = NULL;
407 staticScene = NULL;
408 dynamicScene = NULL;
409 win = NULL;
410 dynamicVp = NULL;
411 spSimpleFBO.reset();
414 static void display(void)
416 commitChanges();
417 mgr->redraw();
420 static void reshape(int w, int h)
422 mgr->resize(w,h);
423 glutPostRedisplay();
426 static void mouse(int button, int state, int x, int y)
428 if (state)
429 mgr->mouseButtonRelease(button, x, y);
430 else
431 mgr->mouseButtonPress(button, x, y);
433 glutPostRedisplay();
436 static void motion(int x, int y)
438 mgr->mouseMove(x, y);
439 glutPostRedisplay();
442 static void keyboard(unsigned char k, int, int)
444 switch(k)
446 case 27:
447 case 'q':
448 case 'Q':
450 cleanup();
451 osgExit();
453 std::exit(EXIT_SUCCESS);
455 break;
457 case '1':
459 UInt32 width = win->getWidth();
460 UInt32 height = win->getHeight();
462 std::cout << "Creating acquisition stage "
463 << width << "x" << height
464 << std::endl;
466 if (!dynamicVp) {
467 createAcquisitionStage();
468 createDynamicViewport();
469 } else {
470 enableStaticScene();
473 break;
475 glutPostRedisplay();
479 // initialize GLUT
481 static int setupGLUT(int *argc, char *argv[])
483 glutInit(argc, argv);
485 glutInitDisplayMode(
486 GLUT_RGB | GLUT_DEPTH | GLUT_STENCIL | GLUT_DOUBLE
487 #ifdef USE_MULTISAMPLING
488 | GLUT_MULTISAMPLE
489 #endif
492 int winid = glutCreateWindow("OpenSG");
494 glutReshapeFunc(reshape);
495 glutDisplayFunc(display);
496 glutIdleFunc(display);
497 glutMouseFunc(mouse);
498 glutMotionFunc(motion);
499 glutKeyboardFunc(keyboard);
501 return winid;
505 // setup scene
507 static int doMain(int argc, char *argv[])
509 preloadSharedObject("OSGFileIO");
510 preloadSharedObject("OSGImageFileIO");
512 osgInit(argc,argv);
514 int winid = setupGLUT(&argc, argv);
516 win = GLUTWindow::create();
517 win->setGlutId(winid);
518 win->init();
520 if(argc < 2)
522 FWARNING(("No file given!\n"));
523 FWARNING(("Supported file formats:\n"));
525 std::list<const char*> suffixes;
526 SceneFileHandler::the()->getSuffixList(suffixes);
528 for(std::list<const char*>::iterator it = suffixes.begin();
529 it != suffixes.end();
530 ++it)
532 FWARNING(("%s\n", *it));
535 staticScene = createStaticScene();
537 else
539 staticScene = SceneFileHandler::the()->read(argv[1]);
542 dynamicScene = createDynamicScene();
544 commitChanges();
546 mgr = SimpleSceneManager::create();
548 NodeUnrecPtr root = makeCoredNode<Group>();
549 root->addChild(staticScene);
551 mgr->setWindow(win);
552 mgr->setRoot (root);
554 GradientBackgroundUnrecPtr background = GradientBackground::create();
555 background->addLine(Color3f(0,0,0), 0);
556 background->addLine(Color3f(1,1,1), 1);
558 staticVp = win->getPort(0);
559 staticVp->setBackground(background);
561 camera = staticVp->getCamera();
563 mgr->showAll();
565 return 0;
569 // create an arbitrarly complex render scene
571 static NodeTransitPtr createStaticScene()
573 NodeUnrecPtr root = makeCoredNode<Group>();
575 typedef boost::mt19937 base_generator_type;
576 static base_generator_type generator(0);
577 static boost::uniform_01<float> value;
578 static boost::variate_generator< base_generator_type, boost::uniform_01<float> > die(generator, value);
580 for (int i = 0; i < max_tori; ++i) {
581 NodeUnrecPtr scene = makeTorus(.5, 2, 32, 32);
583 TransformUnrecPtr transformCore = Transform::create();
584 Matrix mat;
586 mat.setIdentity();
588 float x = 500.f * die();
589 float y = 500.f * die();
590 float z = 500.f * die();
592 float e1 = die();
593 float e2 = die();
594 float e3 = die();
596 Vec3f v(e1,e2,e3);
597 v.normalize();
599 float a = TwoPi * die();
601 Quaternion q(v, a);
603 mat.setTranslate(x,y,z);
604 mat.setRotate(q);
606 transformCore->setMatrix(mat);
608 NodeUnrecPtr trafo = makeNodeFor(transformCore);
610 trafo->addChild(scene);
612 root->addChild(trafo);
615 return NodeTransitPtr(root);
618 static NodeTransitPtr createDynamicScene()
620 NodeUnrecPtr scene = makeCylinder(30, 100, 16, true, true, true);
621 return NodeTransitPtr(scene);
625 // setup of the image generation stage
627 static void createAcquisitionStage()
629 size_t num_ports = win->getMFPort()->size();
630 if (num_ports == 0)
631 return;
633 UInt32 width = win->getWidth();
634 UInt32 height = win->getHeight();
636 Real32 a = Real32(width) / Real32(height);
637 width = UInt32(a*height);
639 Viewport* vp = staticVp;
641 Node* internalRoot = rootNode(mgr->getRoot());
644 // Setup the FBO
646 spSimpleFBO.reset(new SimpleFBO(width, height, true, true, true, false));
648 //spSimpleFBO->fbo()->setPostProcessOnDeactivate(true);
649 //spSimpleFBO->colorBuffer(0)->setReadBack(true);
652 // We would like to render the scene but won't detach it from its parent.
653 // The VisitSubTree allows just that.
655 VisitSubTreeUnrecPtr visitor = VisitSubTree::create();
656 visitor->setSubTreeRoot(internalRoot);
657 NodeUnrecPtr visit_node = makeNodeFor(visitor);
660 // The stage object does provide a render target for the frame buffer attachment.
661 // SimpleStage has a camera, a background and the left, right, top, bottom
662 // fields to let you restrict rendering to a sub-rectangle of your FBO, i.e.
663 // they give you a viewport.
665 SimpleStageUnrecPtr stage = SimpleStage::create();
666 stage->setRenderTarget(spSimpleFBO->fbo());
667 stage->setCamera (vp->getCamera());
668 stage->setBackground (vp->getBackground());
670 // Give the stage core a place to live
672 NodeUnrecPtr stage_node = makeNodeFor(stage);
673 stage_node->addChild(visit_node);
676 // root
677 // |
678 // +- SimpleStage
679 // |
680 // +- VisitSubTree -> ApplicationScene
682 NodeUnrecPtr root = makeCoredNode<Group>();
683 root->addChild(stage_node);
686 // Give the root node a place to live, i.e. create a passive
687 // viewport and add it to the window.
689 ViewportUnrecPtr stage_viewport = PassiveViewport::create();
690 stage_viewport->setRoot (stage_node);
691 stage_viewport->setBackground(vp->getBackground());
692 stage_viewport->setCamera (vp->getCamera());
694 win->addPort(stage_viewport);
696 mgr->update();
697 win->renderNoFinish(mgr->getRenderAction());
698 win->frameExit();
699 win->deactivate ();
701 //ImageUnrecPtr col_image = Image::create();
702 //col_image->set(Image::OSG_RGBA_PF, width, height);
704 //TextureObjChunk* texObj = spSimpleFBO->colorTexObj(0);
705 //texObj->getImage()->subImage(0, 0, 0, width, height, 1, col_image);
706 //col_image->write("d:/my_Test_opensg.png");
708 win->subPortByObj(stage_viewport);
711 static void createDynamicViewport()
713 win->subPortByObj(staticVp);
715 FBOBackgroundUnrecPtr fboBckgnd = FBOBackground::create();
716 fboBckgnd->setFrameBufferObject(spSimpleFBO->fbo());
718 NodeUnrecPtr root = makeCoredNode<Group>();
719 root->addChild(dynamicScene);
721 mgr->setRoot(root);
723 dynamicVp = Viewport::create();
724 dynamicVp->setRoot (rootNode(root));
725 dynamicVp->setBackground(fboBckgnd);
726 dynamicVp->setCamera (camera);
727 dynamicVp->setSize (0,0, 1,1);
729 mgr->getNavigator()->setViewport(dynamicVp);
731 win->addPort(dynamicVp);
733 mgr->update();
736 static void enableStaticScene()
738 win->subPortByObj(dynamicVp);
739 dynamicVp = NULL;
741 NodeUnrecPtr root = makeCoredNode<Group>();
742 root->addChild(staticScene);
743 mgr->setRoot(root);
745 mgr->getNavigator()->setViewport(staticVp);
747 staticVp->setCamera(camera);
749 win->addPort(staticVp);
752 static Node* rootNode(Node* node)
754 Node* root = NULL;
755 while (node) {
756 root = node;
757 node = node->getParent();
759 return root;
763 // main entry point
765 int main(int argc, char *argv[])
767 int ret = doMain(argc, argv);
769 glutMainLoop();
771 cleanup();
773 osgExit();
775 return ret;