fixed: auto_ptr -> unique_ptr
[opensg.git] / Source / System / FileIO / Collada / testColladaLoader.cpp
blob7007791b7a9f6433e8e4e4b6be9eb3235e4d2945
1 // OpenSG Tutorial Example: Loading
2 //
3 // This example shows how to load a scene file using OpenSG.
4 // The supported formats right now are VRML97, OBJ, OFF and RAW, so just
5 // calling this program with a scene file as a parameter should load the scene
6 // file.
7 //
9 // Headers
10 #include "OSGGLUT.h"
11 #include "OSGConfig.h"
12 #include "OSGSimpleGeometry.h"
13 #include "OSGGLUTWindow.h"
14 #include "OSGSimpleSceneManager.h"
15 #include "OSGAction.h"
16 #include "OSGSceneGraphUtils.h"
18 // New Headers
20 // the general scene file loading handler
21 #include "OSGSceneFileHandler.h"
23 #include "OSGFieldContainerUtils.h"
24 #include "OSGChunkOverrideGroup.h"
25 #include "OSGPolygonChunk.h"
26 #include "OSGGeoFunctions.h"
28 #include "OSGSkinnedGeometry.h"
29 #include "OSGShaderProgram.h"
30 #include "OSGShaderProgramChunk.h"
32 #include "OSGAnimation.h"
33 #include "OSGAnimBindAction.h"
34 #include "OSGAnimKeyFrameTemplate.h"
35 #include "OSGGlobalsAttachment.h"
36 #include "OSGComponentTransform.h"
37 #include "OSGTransform.h"
38 #include "OSGSkeletonJoint.h"
40 typedef std::vector<OSG::NodeUnrecPtr > NodeStore;
41 typedef std::vector<OSG::MaterialUnrecPtr> MaterialStore;
43 struct AnimInfo
45 OSG::AnimationUnrecPtr anim;
46 bool on;
48 AnimInfo(void) : anim(NULL), on(false) {}
51 typedef std::vector<AnimInfo> AnimStore;
53 // The SimpleSceneManager to manage simple applications
54 OSG::SimpleSceneManagerRefPtr mgr = NULL;
55 OSG::NodeUnrecPtr sceneN; // scene from file
56 OSG::NodeUnrecPtr rootN; // root
57 OSG::ChunkOverrideGroupUnrecPtr root;
58 OSG::PolygonChunkUnrecPtr polyChunk;
60 NodeStore normalsGeoN;
61 NodeStore geoN;
62 NodeStore skinnedGeoN;
63 MaterialStore skinnedGeoMat;
64 AnimStore anims;
65 bool normalsActive = false;
66 OSG::Real32 normalsLen = 1.f;
67 OSG::Int32 currAnim = 0;
70 OSG::ShaderProgramUnrecPtr vpSkin;
71 OSG::ShaderProgramUnrecPtr fpSkin;
72 OSG::ShaderProgramChunkUnrecPtr shSkin;
73 OSG::ChunkMaterialUnrecPtr matSkin;
75 const std::string vpCode(
76 "#version 120"
77 "\n"
78 "// forward decl\n"
79 "void calcSkin(inout vec4 pos, inout vec3 norm,\n"
80 " in vec4 matIdx, in vec4 weight);\n"
81 "\n"
82 "varying vec4 position;\n"
83 "varying vec3 normal;\n"
84 "\n"
85 "void main(void)\n"
86 "{\n"
87 " vec4 pos = gl_Vertex;\n"
88 " vec3 norm = gl_Normal;\n"
89 " vec4 matIdx = gl_MultiTexCoord2;\n"
90 " vec4 weight = gl_MultiTexCoord3;\n"
91 "\n"
92 " calcSkin(pos, norm, matIdx, weight);\n"
93 "\n"
94 " gl_Position = gl_ModelViewProjectionMatrix * pos;\n"
95 " position = gl_Position;\n"
96 " normal = gl_NormalMatrix * norm;\n"
97 "}\n"
100 const std::string fpCode(
101 "#version 120"
102 "\n"
103 "varying vec4 position;\n"
104 "varying vec3 normal;\n"
105 "\n"
106 "void main(void)\n"
107 "{\n"
108 " vec3 pos = position.xyz / position.w;\n"
109 " vec3 norm = normalize(normal);\n"
110 " vec3 lightDir = normalize(vec3(1,1,1));\n"
111 " float NdotL = max(0, dot(norm, lightDir));\n"
112 " vec3 diffCol = vec3(0.4, 0.4, 0.6);\n"
113 " diffCol *= NdotL;\n"
114 " gl_FragColor = vec4(diffCol, 1.);\n"
115 "}\n"
118 // forward declaration so we can have the interesting stuff upfront
119 int setupGLUT( int *argc, char *argv[] );
121 void init (int argc, char *argv[]);
122 void cleanup (void);
123 void printHelp(void);
124 void collectGeometry (OSG::Node *node );
125 void constructNormalsGeo(OSG::Node *pRootN);
127 void processAnim (OSG::Node *node );
130 // Initialize GLUT & OpenSG and set up the scene
131 int main(int argc, char *argv[])
133 init(argc, argv);
135 // GLUT main loop
136 glutMainLoop();
138 cleanup();
139 OSG::osgExit();
141 return 0;
144 void init(int argc, char *argv[])
146 OSG::osgInit(argc, argv);
148 int glutWinId = setupGLUT(&argc, argv);
150 // the connection between GLUT and OpenSG
151 OSG::GLUTWindowUnrecPtr gwin= OSG::GLUTWindow::create();
152 gwin->setGlutId(glutWinId);
153 gwin->init();
155 // load the scene
156 root = OSG::ChunkOverrideGroup::create();
157 rootN = OSG::makeNodeFor(root);
159 if(argc < 2)
161 FWARNING(("No file given!\n"));
162 FWARNING(("Supported file formats:\n"));
164 OSG::SceneFileHandler::the()->print();
165 sceneN = OSG::makeTorus(.5, 2, 16, 16);
167 else
170 All scene file loading is handled via the SceneFileHandler.
172 sceneN = OSG::SceneFileHandler::the()->read(argv[1]);
175 OSG::TransformUnrecPtr xform = OSG::Transform::create();
176 OSG::NodeUnrecPtr xformN = OSG::makeNodeFor(xform);
178 // xform->editMatrix().setTranslate(OSG::Vec3f(100.f, 0.f, 0.f));
179 // xform->editMatrix().setRotate(OSG::Quaternion(OSG::Vec3f(0.f, 1.f, 0.f), 0.3f * OSG::Pi));
181 OSG::NodeUnrecPtr boxN = OSG::makeBox(1.f, 1.f, 5.f, 1, 1, 1);
183 xformN->addChild(sceneN);
184 rootN ->addChild(xformN);
185 rootN ->addChild(boxN );
187 OSG::commitChanges();
189 // collect geometries in the scene
190 collectGeometry(rootN);
192 // construct skin shader
193 vpSkin = OSG::ShaderProgram::createVertexShader ();
194 vpSkin->setProgram(vpCode);
196 fpSkin = OSG::ShaderProgram::createFragmentShader();
197 fpSkin->setProgram(fpCode);
199 shSkin = OSG::ShaderProgramChunk::create();
200 shSkin->addShader(vpSkin);
201 shSkin->addShader(fpSkin);
203 matSkin = OSG::ChunkMaterial::create();
204 matSkin->addChunk(shSkin);
206 // process animations
207 processAnim(sceneN);
209 // create the SimpleSceneManager helper
210 mgr = OSG::SimpleSceneManager::create();
212 // tell the manager what to manage
213 mgr->setWindow(gwin );
214 mgr->setRoot (rootN);
216 // show the whole scene
217 mgr->showAll();
220 void cleanup(void)
222 mgr = NULL;
224 sceneN = NULL;
225 rootN = NULL;
226 root = NULL;
227 polyChunk = NULL;
229 vpSkin = NULL;
230 fpSkin = NULL;
231 shSkin = NULL;
232 matSkin = NULL;
234 normalsGeoN .clear();
235 geoN .clear();
236 skinnedGeoN .clear();
237 skinnedGeoMat.clear();
238 anims .clear();
241 void printHelp(void)
243 std::cout << "Keys:\n"
244 << " ESC exit\n"
245 << " f fly mode\n"
246 << " t trackball mode\n"
247 << " q toggle statistics\n"
248 << " h toggle headlight\n"
249 << " b toggle backface culling\n"
250 << " w toggle wireframe\n"
251 << " n toggle normals\n"
252 << " m/M de/increase normals length\n"
253 << " v toggle bounding volumes\n"
254 << " p print scene graph\n"
255 << " d toggle skinned geo draw mode\n"
256 << std::flush;
259 OSG::Action::ResultE doCollectGeometry(OSG::Node *node)
261 if(node == NULL)
263 std::cerr << "WARNING: collectGeometry called with node == NULL"
264 << std::endl;
265 return OSG::Action::Continue;
268 OSG::NodeCore *core = node->getCore();
270 if(core == NULL)
272 std::cerr << "WARNING: collectGeometry called with core == NULL"
273 << std::endl;
274 return OSG::Action::Continue;
277 if(core->getType().isDerivedFrom(OSG::Geometry::getClassType()))
279 geoN.push_back(node);
282 if(core->getType().isDerivedFrom(OSG::SkinnedGeometry::getClassType()))
284 skinnedGeoN.push_back(node);
286 OSG::SkinnedGeometry *sgeo =
287 dynamic_cast<OSG::SkinnedGeometry *>(core);
288 skinnedGeoMat.push_back(sgeo->getMaterial());
290 sgeo->setRenderMode(OSG::SkinnedGeometry::RMUnskinned);
293 return OSG::Action::Continue;
296 void collectGeometry(OSG::Node *pRootN)
298 OSG::traverse(pRootN, &doCollectGeometry);
300 std::cout << "collectGeometry: num geo [" << geoN.size()
301 << "] num skinned geo [" << skinnedGeoN.size()
302 << "]" << std::endl;
306 void constructNormalsGeo(OSG::Node *pRootN)
308 NodeStore::const_iterator nIt = normalsGeoN.begin();
309 NodeStore::const_iterator nEnd = normalsGeoN.end ();
311 // remove existing normals
312 for(; nIt != nEnd; ++nIt)
313 (*nIt)->getParent()->subChild(*nIt);
315 normalsGeoN.clear();
317 // construct and add new normals
318 nIt = geoN.begin();
319 nEnd = geoN.end ();
321 for(; nIt != nEnd; ++nIt)
323 OSG::Geometry *geo =
324 dynamic_cast<OSG::Geometry *>((*nIt)->getCore());
325 OSG::NodeUnrecPtr normGeoN =
326 OSG::calcVertexNormalsGeo(geo, normalsLen);
328 normalsGeoN.push_back(normGeoN);
330 (*nIt)->addChild(normGeoN);
334 void processAnim(OSG::Node *node)
336 OSG::commitChangesAndClear();
338 // register AnimBindAction callbacks -- temporarily done here
339 OSG::AnimBindAction::registerEnterDefault(
340 OSG::ComponentTransform::getClassType(),
341 &OSG::bindEnterDefault );
342 OSG::AnimBindAction::registerEnterDefault(
343 OSG::Transform::getClassType(),
344 &OSG::bindEnterDefault );
347 OSG::GlobalsAttachment *ga = dynamic_cast<OSG::GlobalsAttachment *>(
348 node->findAttachment(OSG::GlobalsAttachment::getClassType()));
350 if(ga == NULL)
352 std::cerr << "WARNING: processAnim: no GlobalsAttachment found"
353 << std::endl;
354 return;
357 OSG::GlobalsAttachment::MFElementsType::const_iterator eIt =
358 ga->getMFElements()->begin();
359 OSG::GlobalsAttachment::MFElementsType::const_iterator eEnd =
360 ga->getMFElements()->end ();
362 for(; eIt != eEnd; ++eIt)
364 OSG::AnimKeyFrameTemplate *animTmpl =
365 dynamic_cast<OSG::AnimKeyFrameTemplate *>(*eIt);
367 if(animTmpl == NULL)
368 continue;
370 std::cout << "instantiating anim template [" << animTmpl->getName()
371 << "] with [" << animTmpl->getMFSources()->size()
372 << "] sources [" << animTmpl->getMFTargetIds()->size()
373 << "] targetIds" << std::endl;
375 AnimInfo ai;
376 ai.on = false;
377 ai.anim = animTmpl->instantiate(node);
378 ai.anim->setEnabled(false);
380 anims.push_back(ai);
384 void toggleAnim(OSG::UInt32 index, bool loop)
386 if(anims[index].on == true)
388 std::cout << "STOP anim " << index << std::endl;
389 anims[index].anim->stop ();
390 anims[index].anim->reset();
391 anims[index].anim->setEnabled(false);
392 anims[index].on = false;
394 else
396 if(loop == true)
398 std::cout << "START LOOP anim " << index << std::endl;
399 anims[index].anim->startLoop(OSG::FrameHandler::the()->getTimeStamp());
401 else
403 std::cout << "START anim " << index << std::endl;
404 anims[index].anim->start(OSG::FrameHandler::the()->getTimeStamp());
407 anims[index].anim->setEnabled(true);
408 anims[index].on = true;
412 void printXForm(OSG::SceneGraphPrinter *sgp, OSG::NodeCore *core)
414 OSG::Transform *xform = dynamic_cast<OSG::Transform *>(core);
416 sgp->indentStream() << "matrix:\n" << xform->getMatrix();
419 void printJoint(OSG::SceneGraphPrinter *sgp, OSG::NodeCore *core)
421 OSG::SkeletonJoint *joint = dynamic_cast<OSG::SkeletonJoint *>(core);
423 sgp->indentStream() << "matrix:\n" << joint->getMatrix();
426 void printVolume(OSG::SceneGraphPrinter *sgp, OSG::NodeCore *core)
428 sgp->indentStream() << " volume " << sgp->getCurrNode()->getVolume()
429 << "\n";
433 // GLUT callback functions
436 // redraw the window
437 void display(void)
439 // std::cout << ">> FRAME START" << std::endl;
441 static OSG::Time tAcc = 0;
442 static OSG::UInt32 fc = 0;
444 OSG::Time t0 = OSG::getSystemTime();
446 OSG::FrameHandler::the()->frame();
448 OSG::commitChangesAndClear();
450 mgr->idle();
451 mgr->redraw();
453 OSG::Time t1 = OSG::getSystemTime();
455 tAcc += (t1 - t0);
456 fc += 1;
458 if(tAcc >= 1)
460 std::cout << "frame count [" << fc
461 << "] fc/tAcc [" << (fc/tAcc)
462 << "] tAcc/fc [" << (1000.f * (tAcc/fc))
463 << "] ms tAcc [" << tAcc << "] s" << std::endl;
465 tAcc = 0;
466 fc = 0;
469 // std::cout << "<< FRAME END" << std::endl;
471 // mgr->getWindow()->registerConstant(GL_MAX_VERTEX_UNIFORM_COMPONENTS );
472 // mgr->getWindow()->registerConstant(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS);
474 // OSG::Real32 maxVPUniforms =
475 // mgr->getWindow()->getConstantValue(GL_MAX_VERTEX_UNIFORM_COMPONENTS);
476 // OSG::Real32 maxFPUniforms =
477 // mgr->getWindow()->getConstantValue(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS);
479 // std::cout << "GL_MAX_VERTEX_UNIFORM_COMPONENTS [" << maxVPUniforms
480 // << "] GL_MAX_FRAGMENT_UNIFORM_COMPONENTS [" << maxFPUniforms
481 // << "]" << std::endl;
484 // react to size changes
485 void reshape(int w, int h)
487 mgr->resize(w, h);
488 glutPostRedisplay();
491 // react to mouse button presses
492 void mouse(int button, int state, int x, int y)
495 if (state)
496 mgr->mouseButtonRelease(button, x, y);
497 else
498 mgr->mouseButtonPress(button, x, y);
500 glutPostRedisplay();
503 // react to mouse motions with pressed buttons
504 void motion(int x, int y)
507 mgr->mouseMove(x, y);
508 glutPostRedisplay();
511 // react to keys
512 void keyboard(unsigned char k, int , int )
514 switch(k)
516 case 27:
518 cleanup();
520 OSG::osgExit();
521 std::exit(0);
523 break;
524 case 'f':
526 mgr->setNavigationMode(OSG::Navigator::FLY);
527 std::cout << "Fly mode" << std::endl;
529 break;
530 case 't':
532 mgr->setNavigationMode(OSG::Navigator::TRACKBALL);
533 std::cout << "Trackball mode" << std::endl;
535 break;
536 case 'q':
538 mgr->setStatistics(!mgr->getStatistics());
539 std::cout << "Statistics "
540 << (mgr->getStatistics() ? "enabled" : "disabled")
541 << std::endl;
543 break;
544 case 'h':
546 mgr->setHeadlight(!mgr->getHeadlightState());
547 std::cout << "Headlight "
548 << (mgr->getHeadlightState() ? "enabled" : "disabled")
549 << std::endl;
551 break;
552 case 'b':
554 if(polyChunk == NULL)
556 polyChunk = OSG::PolygonChunk::create();
557 root->addChunk(polyChunk);
560 if(polyChunk->getCullFace() == GL_NONE)
562 polyChunk->setCullFace(GL_BACK);
563 std::cout << "Backface culling enabled" << std::endl;
565 else
567 polyChunk->setCullFace(GL_NONE);
568 std::cout << "Backface culling disabled" << std::endl;
571 break;
572 case 'w':
574 if(polyChunk == NULL)
576 polyChunk = OSG::PolygonChunk::create();
577 root->addChunk(polyChunk);
580 if(polyChunk->getFrontMode() == GL_FILL)
582 polyChunk->setFrontMode(GL_LINE);
583 polyChunk->setBackMode (GL_LINE);
584 std::cout << "Wireframe enabled" << std::endl;
586 else
588 polyChunk->setFrontMode(GL_FILL);
589 polyChunk->setBackMode (GL_FILL);
590 std::cout << "Wireframe disabled" << std::endl;
593 break;
594 case 'n':
596 if(normalsActive == true)
598 normalsActive = false;
600 NodeStore::const_iterator ngIt = normalsGeoN.begin();
601 NodeStore::const_iterator ngEnd = normalsGeoN.end ();
603 for(; ngIt != ngEnd; ++ngIt)
605 (*ngIt)->setTravMask(0);
608 std::cout << "Normals disabled" << std::endl;
610 else
612 normalsActive = true;
614 if(normalsGeoN.empty() == true)
615 constructNormalsGeo(sceneN);
617 NodeStore::const_iterator ngIt = normalsGeoN.begin();
618 NodeStore::const_iterator ngEnd = normalsGeoN.end ();
620 for(; ngIt != ngEnd; ++ngIt)
622 (*ngIt)->setTravMask(OSG::TypeTraits<OSG::UInt32>::BitsSet);
625 std::cout << "Normals enabled" << std::endl;
628 break;
629 case 'm':
631 normalsLen /= 1.25f;
632 constructNormalsGeo(sceneN);
633 std::cout << "Normals length " << normalsLen << std::endl;
635 break;
636 case 'M':
638 normalsLen *= 1.25f;
639 constructNormalsGeo(sceneN);
640 std::cout << "Normals length " << normalsLen << std::endl;
642 break;
643 case 'v':
645 mgr->getRenderAction()->setVolumeDrawing(
646 !mgr->getRenderAction()->getVolumeDrawing());
647 std::cout << "Volume drawing: "
648 << (mgr->getRenderAction()->getVolumeDrawing() ? "enabled" : "disabled")
649 << std::endl;
651 break;
652 case 'p':
654 OSG::SceneGraphPrinter sgp(mgr->getRoot());
655 sgp.addPrintFunc(OSG::SkinnedGeometry::getClassType(),
656 &printVolume );
657 sgp.printDownTree(std::cout);
659 NodeStore::const_iterator nIt = skinnedGeoN.begin();
660 NodeStore::const_iterator nEnd = skinnedGeoN.end ();
662 for(OSG::UInt32 i = 0; nIt != nEnd; ++nIt, ++i)
664 OSG::SkinnedGeometry *sgeo = dynamic_cast<OSG::SkinnedGeometry *>(
665 (*nIt)->getCore());
667 std::cout << "Skeleton:\n";
668 OSG::SceneGraphPrinter skelPrinter(sgeo->getSkeleton()->getRoots(0));
669 skelPrinter.addPrintFunc(OSG::Transform ::getClassType(),
670 &printXForm );
671 //skelPrinter.addPrintFunc(OSG::SkeletonJoint::getClassType(),
672 // &printJoint );
673 skelPrinter.printDownTree(std::cout);
676 break;
678 case 'a':
680 mgr->showAll();
682 std::cout << "Showing all of scene." << std::endl;
684 break;
686 case '[':
688 if(anims.empty() == false)
690 currAnim -= 1;
691 if(currAnim < 0)
692 currAnim = anims.size() - 1;
694 std::cout << "Current anim [" << currAnim << "] - ["
695 << anims[currAnim].anim->getTemplate()->getName()
696 << "]" << std::endl;
699 break;
700 case ']':
702 if(anims.empty() == false)
704 currAnim += 1;
705 if(currAnim >= OSG::Int32(anims.size()))
706 currAnim = 0;
708 std::cout << "Current anim [" << currAnim << "] - ["
709 << anims[currAnim].anim->getTemplate()->getName()
710 << "]" << std::endl;
713 break;
715 case 'L':
717 toggleAnim(currAnim, false);
719 break;
721 case 'l':
723 toggleAnim(currAnim, true);
725 break;
726 case 'd':
728 NodeStore::const_iterator nIt = skinnedGeoN.begin();
729 NodeStore::const_iterator nEnd = skinnedGeoN.end ();
731 for(OSG::UInt32 i = 0; nIt != nEnd; ++nIt, ++i)
733 OSG::SkinnedGeometry *sgeo = dynamic_cast<OSG::SkinnedGeometry *>(
734 (*nIt)->getCore());
736 if(sgeo->getRenderMode() == OSG::SkinnedGeometry::RMSkinnedCPU)
738 std::cout << "Enabling SkinnedGeo GPU mode ["
739 << sgeo << "]" << std::endl;
741 sgeo->setRenderMode(OSG::SkinnedGeometry::RMSkinnedGPU);
742 sgeo->setMaterial (matSkin);
744 else if(sgeo->getRenderMode() == OSG::SkinnedGeometry::RMSkinnedGPU)
746 std::cout << "Enabling SkinnedGeo SKELETON mode ["
747 << sgeo << "]" << std::endl;
749 sgeo->setRenderMode(OSG::SkinnedGeometry::RMSkeleton);
750 sgeo->setMaterial (skinnedGeoMat[i]);
752 else if(sgeo->getRenderMode() == OSG::SkinnedGeometry::RMSkeleton)
754 std::cout << "Enabling SkinnedGeo UNSKINNED mode ["
755 << sgeo << "]" << std::endl;
757 sgeo->setRenderMode(OSG::SkinnedGeometry::RMUnskinned);
758 sgeo->setMaterial (skinnedGeoMat[i]);
760 else
762 std::cout << "Enabling SkinnedGeo CPU mode ["
763 << sgeo << "]" << std::endl;
765 sgeo->setRenderMode(OSG::SkinnedGeometry::RMSkinnedCPU);
766 sgeo->setMaterial(skinnedGeoMat[i]);
770 break;
771 case 'c':
773 mgr->getRenderAction()->setFrustumCulling(
774 !mgr->getRenderAction()->getFrustumCulling());
776 std::cout << "Frustum culling: "
777 << (mgr->getRenderAction()->getFrustumCulling() ? "enabled" : "disabled")
778 << std::endl;
780 break;
781 case 's':
783 NodeStore::const_iterator nIt = skinnedGeoN.begin();
784 NodeStore::const_iterator nEnd = skinnedGeoN.end ();
786 for(OSG::UInt32 i = 0; nIt != nEnd; ++nIt, ++i)
788 OSG::SkinnedGeometry *sgeo = dynamic_cast<OSG::SkinnedGeometry *>(
789 (*nIt)->getCore());
791 OSG::Skeleton *skel = sgeo->getSkeleton();
793 OSG::Skeleton::MFRootsType::const_iterator rIt =
794 skel->getMFRoots()->begin();
795 OSG::Skeleton::MFRootsType::const_iterator rEnd =
796 skel->getMFRoots()->end ();
798 for(OSG::UInt32 j = 0; rIt != rEnd; ++rIt, ++j)
800 std::cout << "Skeleton [" << i << "] @ [" << skel
801 << "] root [" << j << "]\n";
803 OSG::SceneGraphPrinter sgp(*rIt);
804 sgp.printDownTree(std::cout);
806 std::cout << std::endl;
810 break;
812 default:
814 printHelp();
816 break;
819 glutPostRedisplay();
822 void idle(void)
824 glutPostRedisplay();
827 // setup the GLUT library which handles the windows for us
828 int setupGLUT(int *argc, char *argv[])
830 glutInit(argc, argv);
831 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
833 int winid = glutCreateWindow("OpenSG");
835 glutReshapeFunc(reshape);
836 glutDisplayFunc(display);
837 glutIdleFunc(idle);
838 glutMouseFunc(mouse);
839 glutMotionFunc(motion);
840 glutKeyboardFunc(keyboard);
842 return winid;