fixed: auto_ptr -> unique_ptr
[opensg.git] / Examples / Advanced / DeferredShading / deferredshading.cpp
blobf0e0987e60619055f4a36c0cc26d60c53a55018d
2 // Work In Progress
3 //
4 // This demonstates the use of the DeferredShadingStage and the
5 // Shader/TrapezoidalShadowMapEngine with it.
6 //
7 // The program must be run from the Examples/Advanced/DeferredShading directory
8 // so that it can find the files with the GLSL source for the shader programs.
9 //
10 // Please take a look at the keyboard glut callback for the interface
12 // Work In Progress
14 #ifdef OSG_BUILD_ACTIVE
16 #include <OSGGL.h>
17 #include <OSGGLUT.h>
18 #include <OSGGLUTWindow.h>
19 #include <OSGSceneFileHandler.h>
20 #include <OSGSimpleGeometry.h>
21 #include <OSGSimpleSceneManager.h>
22 #include <OSGSimpleTexturedMaterial.h>
24 #include <OSGDeferredShadingStage.h>
25 #include <OSGDirectionalLight.h>
26 #include <OSGPointLight.h>
27 #include <OSGSpotLight.h>
29 #include <OSGShaderShadowMapEngine.h>
30 #include <OSGTrapezoidalShadowMapEngine.h>
32 // OpenSG Shaders
33 #include <OSGShaderProgram.h>
34 #include <OSGShaderProgramChunk.h>
36 #else // OSG_BUILD_INTEGRATED
38 #include <OpenSG/OSGGL.h>
39 #include <OpenSG/OSGGLUT.h>
40 #include <OpenSG/OSGGLUTWindow.h>
41 #include <OpenSG/OSGSceneFileHandler.h>
42 #include <OpenSG/OSGSimpleGeometry.h>
43 #include <OpenSG/OSGSimpleSceneManager.h>
44 #include <OpenSG/OSGSimpleTexturedMaterial.h>
46 #include <OpenSG/OSGDeferredShadingStage.h>
47 #include <OpenSG/OSGDirectionalLight.h>
48 #include <OpenSG/OSGPointLight.h>
49 #include <OpenSG/OSGSpotLight.h>
51 #include <OpenSG/OSGShaderShadowMapEngine.h>
52 #include <OpenSG/OSGTrapezoidalShadowMapEngine.h>
54 // OpenSG Shaders
55 #include <OpenSG/OSGShaderProgram.h>
56 #include <OpenSG/OSGShaderProgramChunk.h>
58 #endif // OSG_BUILD_INTEGRATED
60 #include <iostream>
62 OSG_USING_NAMESPACE
64 enum ShadowTypeE
66 ST_NONE = 0,
67 ST_STANDARD = 1,
68 ST_TRAPEZOID = 2
71 struct LightInfo
73 LightEngine::LightTypeE lightType;
74 ShadowTypeE shadowType;
75 LightUnrecPtr light;
76 NodeUnrecPtr lightN;
77 NodeUnrecPtr beaconN;
79 ShaderProgramUnrecPtr lightVP;
80 ShaderProgramUnrecPtr lightFP;
81 ShaderProgramChunkUnrecPtr lightSH;
83 LightInfo(void) :
84 lightType (LightEngine::Spot),
85 shadowType(ST_NONE ),
86 light (NULL ),
87 lightN (NULL ),
88 beaconN (NULL ),
90 lightVP (NULL ),
91 lightFP (NULL ),
92 lightSH (NULL )
98 std::ostream &operator << (std::ostream &os, const LightInfo &li);
100 struct GlobalValues
102 SimpleSceneManagerRefPtr mgr;
103 GLUTWindowUnrecPtr glutWin;
105 NodeUnrecPtr rootN;
107 NodeUnrecPtr dsStageN;
108 DeferredShadingStageUnrecPtr dsStage;
110 NodeUnrecPtr sceneN;
111 NodeUnrecPtr objN;
113 std::vector<LightInfo> lightInfos;
115 bool animateLights;
116 bool colorLights;
118 LightEngine::LightTypeE newLightType;
119 ShadowTypeE newShadowType;
121 Int32 currentLight;
123 UInt32 shadowMapWidth;
124 UInt32 shadowMapHeight;
126 GlobalValues(void) :
127 mgr (NULL ),
128 glutWin (NULL ),
130 rootN (NULL ),
132 dsStageN (NULL ),
133 dsStage (NULL ),
135 sceneN (NULL ),
136 objN (NULL ),
138 lightInfos ( ),
140 animateLights (false ),
141 colorLights (false ),
143 newLightType (LightEngine::Spot),
144 newShadowType (ST_NONE ),
146 currentLight (0 ),
148 shadowMapWidth (128 ),
149 shadowMapHeight(128 )
154 GlobalValues *gv;
156 const std::string dsGBufferVPFile ("DSGBuffer.vp.glsl" );
157 const std::string dsGBufferFPFile ("DSGBuffer.fp.glsl" );
159 const std::string dsAmbientVPFile ("DSAmbient.vp.glsl" );
160 const std::string dsAmbientFPFile ("DSAmbient.fp.glsl" );
162 const std::string dsDirLightVPFile ("DSDirLight.vp.glsl" );
163 const std::string dsDirLightFPFile ("DSDirLight.fp.glsl" );
164 const std::string dsDirLightShadowFPFile ("DSDirLightShadow.fp.glsl" );
166 const std::string dsPointLightVPFile ("DSPointLight.vp.glsl" );
167 const std::string dsPointLightFPFile ("DSPointLight.fp.glsl" );
168 const std::string dsPointLightShadowFPFile("DSPointLightShadow.fp.glsl");
170 const std::string dsSpotLightVPFile ("DSSpotLight.vp.glsl" );
171 const std::string dsSpotLightFPFile ("DSSpotLight.fp.glsl" );
172 const std::string dsSpotLightShadowFPFile ("DSSpotLightShadow.fp.glsl" );
174 const std::string dsUnknownFile ("unknownFile");
176 void initialize(int argc, char *argv[]);
177 void cleanup (void );
179 void buildDSStage (void );
180 NodeTransitPtr loadScene (const std::string &fileName);
181 NodeTransitPtr buildTestScene(UInt32 nX, UInt32 nZ);
183 void addLight (LightEngine::LightTypeE lightType, ShadowTypeE shadowType);
184 void setShadow(UInt32 lightIdx, ShadowTypeE shadowType);
185 void setColorLights(bool colLights);
187 int setupGLUT (int *argc, char *argv[]);
188 void keyboard(unsigned char k, int , int );
190 int main(int argc, char *argv[])
192 initialize(argc, argv);
194 keyboard('+', 0, 0);
195 // keyboard('+', 0, 0);
196 keyboard('.', 0, 0);
198 keyboard('a', 0, 0);
200 commitChanges();
202 glutMainLoop();
204 return 0;
208 void initialize(int argc, char *argv[])
210 osgInit(argc, argv);
212 gv = new GlobalValues;
213 gv->animateLights = false;
214 gv->colorLights = false;
215 gv->newLightType = LightEngine::Spot;
216 gv->newShadowType = ST_NONE;
217 gv->currentLight = -1;
218 gv->shadowMapWidth = 1024;
219 gv->shadowMapHeight = 1024;
221 int glutWinId = setupGLUT(&argc, argv);
223 gv->glutWin = GLUTWindow::create();
224 gv->glutWin->setGlutId(glutWinId);
225 gv->glutWin->init ( );
227 gv->mgr = SimpleSceneManager::create();
229 // tell the manager what to manage
230 gv->mgr->setWindow(gv->glutWin);
232 // HACK: force creation of internal SSM objects (vp, cam, bg etc)
233 gv->mgr->setRoot(NULL);
235 gv->mgr->getWindow()->getPort(0)->setSize(0.1f, 0.f, 0.8f, 1.f);
237 // create a "scene" to show
238 if(argc >= 2)
240 std::string fileName = argv[1];
242 gv->sceneN = makeCoredNode<Group>();
244 gv->objN = loadScene(fileName);
245 gv->sceneN->addChild(gv->objN);
248 if(gv->sceneN == NULL)
250 gv->sceneN = makeCoredNode<Group>();
251 gv->objN = buildTestScene(5, 5);
253 gv->sceneN->addChild(gv->objN);
256 gv->rootN = makeCoredNode<Group>();
258 buildDSStage();
260 gv->dsStageN->addChild(gv->sceneN );
261 gv->rootN ->addChild(gv->dsStageN);
263 gv->mgr->setRoot(gv->rootN);
264 gv->mgr->showAll();
267 void cleanup(void)
269 gv->mgr = NULL;
271 delete gv;
272 gv = NULL;
274 osgExit();
278 // creates the deferred shading stage and configures the required buffers.
279 // this assumes that all materials in the scene are regular enough as to be
280 // written with a single shader to the buffers (e.g. everything has a single
281 // diffuse texture).
282 // alternatively the GBufferProgram can be left empty and all materials in the
283 // scene are set up to write to the correct buffers.
284 void buildDSStage(void)
286 ShaderProgramUnrecPtr vpGBuffer = ShaderProgram::createVertexShader ();
287 ShaderProgramUnrecPtr fpGBuffer = ShaderProgram::createFragmentShader();
289 ShaderProgramUnrecPtr vpAmbient = ShaderProgram::createVertexShader ();
290 ShaderProgramUnrecPtr fpAmbient = ShaderProgram::createFragmentShader();
292 ShaderProgramChunkUnrecPtr shGBuffer = ShaderProgramChunk::create();
293 ShaderProgramChunkUnrecPtr shAmbient = ShaderProgramChunk::create();
295 gv->dsStage = DeferredShadingStage::create();
296 gv->dsStageN = makeNodeFor(gv->dsStage);
298 gv->dsStage->setCamera(gv->mgr->getCamera());
300 // positions (RGB) + ambient (A) term buffer
301 gv->dsStage->editMFPixelFormats()->push_back(Image::OSG_RGBA_PF );
302 gv->dsStage->editMFPixelTypes ()->push_back(Image::OSG_FLOAT32_IMAGEDATA);
304 // normals (RGB) buffer
305 gv->dsStage->editMFPixelFormats()->push_back(Image::OSG_RGB_PF );
306 gv->dsStage->editMFPixelTypes ()->push_back(Image::OSG_FLOAT32_IMAGEDATA);
308 // diffuse (RGB) buffer
309 gv->dsStage->editMFPixelFormats()->push_back(Image::OSG_RGB_PF);
310 gv->dsStage->editMFPixelTypes ()->push_back(Image::OSG_UINT8_IMAGEDATA);
312 // G Buffer shader (one for the whole scene)
313 vpGBuffer->readProgram(dsGBufferVPFile.c_str());
314 fpGBuffer->readProgram(dsGBufferFPFile.c_str());
316 fpGBuffer->addUniformVariable<Int32>("tex0", 0);
318 shGBuffer->addShader(vpGBuffer);
319 shGBuffer->addShader(fpGBuffer);
321 gv->dsStage->setGBufferProgram(shGBuffer);
323 // ambient shader
324 vpAmbient->readProgram(dsAmbientVPFile.c_str());
325 fpAmbient->readProgram(dsAmbientFPFile.c_str());
327 fpAmbient->addUniformVariable<Int32>("texBufNorm", 1);
329 shAmbient->addShader(vpAmbient);
330 shAmbient->addShader(fpAmbient);
332 gv->dsStage->setAmbientProgram(shAmbient);
335 std::string mapShadowType(ShadowTypeE shadowType)
337 std::string shadow = "unknown";
339 switch(shadowType)
341 case ST_NONE:
342 shadow = "None";
343 break;
345 case ST_STANDARD:
346 shadow = "Standard";
347 break;
349 case ST_TRAPEZOID:
350 shadow = "Trapezoidal";
351 break;
354 return shadow;;
357 std::string mapLightType(LightEngine::LightTypeE lightType)
359 std::string light = "unknown";
361 switch(lightType)
363 case LightEngine::Directional:
364 light = "Directional";
365 break;
367 case LightEngine::Point:
368 light = "Point";
369 break;
371 case LightEngine::Spot:
372 light = "Spot";
373 break;
376 return light;
379 // file containing vertex shader code for the light type
380 const std::string &getLightVPFile(
381 LightEngine::LightTypeE lightType,
382 ShadowTypeE shadowType)
384 switch(lightType)
386 case LightEngine::Directional:
387 return dsDirLightVPFile;
389 case LightEngine::Point:
390 return dsPointLightVPFile;
392 case LightEngine::Spot:
393 return dsSpotLightVPFile;
396 return dsUnknownFile;
399 // file containing fragment shader code for the light type
400 const std::string &getLightFPFile(
401 LightEngine::LightTypeE lightType,
402 ShadowTypeE shadowType)
404 switch(lightType)
406 case LightEngine::Directional:
407 if(shadowType == ST_NONE)
408 return dsDirLightFPFile;
409 else
410 return dsDirLightShadowFPFile;
412 case LightEngine::Point:
413 if(shadowType == ST_NONE)
414 return dsPointLightFPFile;
415 else
416 return dsPointLightShadowFPFile;
418 case LightEngine::Spot:
419 if(shadowType == ST_NONE)
420 return dsSpotLightFPFile;
421 else
422 return dsSpotLightShadowFPFile;
425 return dsUnknownFile;
429 // adds a light of given type to the scene and makes it cast shadows
430 // of the given type.
431 void addLight(LightEngine::LightTypeE lightType, ShadowTypeE shadowType)
433 LightInfo li;
434 TransformUnrecPtr beacon = Transform::create();
435 li.beaconN = makeNodeFor(beacon);
437 li.lightVP = ShaderProgram ::createVertexShader ();
438 li.lightFP = ShaderProgram ::createFragmentShader();
439 li.lightSH = ShaderProgramChunk::create ();
440 li.lightType = lightType;
441 li.shadowType = shadowType;
443 switch(lightType)
445 case LightEngine::Directional:
447 DirectionalLightUnrecPtr dirL = DirectionalLight::create();
449 li.light = dirL;
451 break;
453 case LightEngine::Point:
455 PointLightUnrecPtr pointL = PointLight::create();
456 pointL->setConstantAttenuation(1.0);
457 //pointL->setLinearAttenuation (1.e-5);
458 //pointL->setQuadraticAttenuation(2.e-5);
460 li.light = pointL;
462 break;
464 case LightEngine::Spot:
466 SpotLightUnrecPtr spotL = SpotLight::create();
467 spotL->setPosition (Pnt3f(0.f, 0.f, 0.f));
468 spotL->setDirection(Vec3f(0.f, 0.f, -1.f));
469 spotL->setSpotCutOff(Pi/6.f);
470 spotL->setSpotExponent(3.f);
471 spotL->setConstantAttenuation(1.0);
472 //spotL->setLinearAttenuation (1.e-5);
473 //spotL->setQuadraticAttenuation(2.e-5);
475 li.light = spotL;
477 break;
480 li.light->setBeacon(li.beaconN);
481 li.lightN = makeNodeFor(li.light);
483 li.lightFP->addUniformVariable<Int32>("texBufPos", 0);
484 li.lightFP->addUniformVariable<Int32>("texBufNorm", 1);
485 li.lightFP->addUniformVariable<Int32>("texBufDiff", 2);
487 li.lightSH->addShader(li.lightVP);
488 li.lightSH->addShader(li.lightFP);
490 gv->rootN->addChild(li.beaconN);
491 //gv->rootN->addChild(li.lightN );
493 gv->dsStage->editMFLights ()->push_back(li.light );
494 gv->dsStage->editMFLightPrograms()->push_back(li.lightSH);
496 gv->lightInfos.push_back(li);
498 setShadow(gv->lightInfos.size() - 1, shadowType);
500 setColorLights(gv->colorLights);
502 // add a coordinate system to show light position
503 // OSG::NodeUnrecPtr lightAxisN = OSG::makeCoordAxis(2.f);
504 // li.beaconN->addChild(lightAxisN);
507 void subLight(UInt32 lightIdx)
509 OSG_ASSERT(lightIdx < gv->lightInfos .size());
510 OSG_ASSERT(lightIdx < gv->dsStage->getMFLights ()->size());
511 OSG_ASSERT(lightIdx < gv->dsStage->getMFLightPrograms()->size());
513 gv->dsStage->editMFLights ()->erase(lightIdx);
514 // gv->dsStage->editMFLights ()->begin() + lightIdx);
515 gv->dsStage->editMFLightPrograms()->erase(lightIdx);
516 // gv->dsStage->editMFLightPrograms()->begin() + lightIdx);
518 LightInfo &li = gv->lightInfos[lightIdx];
519 gv->rootN->subChild(li.beaconN);
521 //gv->rootN->subChild(li.lightN );
523 gv->lightInfos.erase(gv->lightInfos.begin() + lightIdx);
525 setColorLights(gv->colorLights);
528 void setShadow(UInt32 lightIdx, ShadowTypeE shadowType)
530 OSG_ASSERT(lightIdx < gv->lightInfos .size());
531 OSG_ASSERT(lightIdx < gv->dsStage->getMFLights ()->size());
532 OSG_ASSERT(lightIdx < gv->dsStage->getMFLightPrograms()->size());
534 LightInfo &li = gv->lightInfos[lightIdx];
536 // li.lightSH->removeObjFromVertexShader (li.lightVP);
537 // li.lightSH->removeObjFromFragmentShader(li.lightFP);
539 switch(shadowType)
541 case ST_NONE:
543 li.light->setLightEngine(NULL);
545 gv->dsStage->editMFLights ();
546 gv->dsStage->editMFLightPrograms();
548 li.shadowType = ST_NONE;
550 break;
552 case ST_STANDARD:
554 ShaderShadowMapEngineUnrecPtr shadowEng =
555 ShaderShadowMapEngine::create();
557 shadowEng->setWidth (gv->shadowMapWidth );
558 shadowEng->setHeight(gv->shadowMapHeight);
559 shadowEng->setOffsetFactor( 4.5f);
560 shadowEng->setOffsetBias (16.f );
561 shadowEng->setForceTextureUnit(3);
563 gv->dsStage->editMFLights ();
564 gv->dsStage->editMFLightPrograms();
566 li.light->setLightEngine(shadowEng);
567 li.shadowType = ST_STANDARD;
569 break;
571 case ST_TRAPEZOID:
573 if(li.lightType != LightEngine::Directional)
575 TrapezoidalShadowMapEngineUnrecPtr shadowEng =
576 TrapezoidalShadowMapEngine::create();
578 shadowEng->setWidth (gv->shadowMapWidth );
579 shadowEng->setHeight(gv->shadowMapHeight);
580 shadowEng->setOffsetFactor( 4.5f);
581 shadowEng->setOffsetBias (16.f );
582 shadowEng->setForceTextureUnit(3);
584 gv->dsStage->editMFLights ();
585 gv->dsStage->editMFLightPrograms();
587 li.light->setLightEngine(shadowEng);
588 li.shadowType = ST_TRAPEZOID;
590 else
592 std::cout << "TSM not supported for diretional lights."
593 << std::endl;
596 break;
599 std::string vpFile = getLightVPFile(li.lightType, li.shadowType);
600 std::string fpFile = getLightFPFile(li.lightType, li.shadowType);
602 std::cerr << "vpFile [" << vpFile << "]" <<std::endl;
603 std::cerr << "fpFile [" << fpFile << "]" <<std::endl;
605 li.lightVP->readProgram(vpFile.c_str());
606 li.lightFP->readProgram(fpFile.c_str());
608 li.lightFP->addUniformVariable<Int32>("texBufPos", 0);
609 li.lightFP->addUniformVariable<Int32>("texBufNorm", 1);
610 li.lightFP->addUniformVariable<Int32>("texBufDiff", 2);
612 // li.lightSH->addVertexShader (li.lightVP);
613 // li.lightSH->addFragmentShader(li.lightFP);
616 void setColorLights(bool colLights)
618 if(gv->lightInfos.size() > 1)
620 if(colLights == true)
622 // set colorful
623 for(UInt32 i = 0; i < gv->lightInfos.size(); ++i)
625 gv->lightInfos[i].light->setDiffuse(
626 Color4f( Real32(i+1) / gv->lightInfos.size(),
627 0.f,
628 1.f - (Real32(i+1) / gv->lightInfos.size()),
629 1.f));
632 else
634 // set lights to grey
635 for(UInt32 i = 0; i < gv->lightInfos.size(); ++i)
637 gv->lightInfos[i].light->setDiffuse(
638 Color4f(1.f / gv->lightInfos.size(),
639 1.f / gv->lightInfos.size(),
640 1.f / gv->lightInfos.size(),
641 1.f ));
645 else if(gv->lightInfos.empty() == false)
647 gv->lightInfos[0].light->setDiffuse(Color4f(1.f, 1.f, 1.f, 1.f));
650 // trigger update
651 gv->dsStage->editMFLights();
653 gv->colorLights = colLights;
656 void updateLightBeacon(OSG::UInt32 lightIdx, OSG::Time t)
658 OSG_ASSERT(lightIdx < gv->lightInfos .size());
659 OSG_ASSERT(lightIdx < gv->dsStage->getMFLights ()->size());
660 OSG_ASSERT(lightIdx < gv->dsStage->getMFLightPrograms()->size());
662 Transform *beacon = dynamic_cast<Transform *>(
663 gv->lightInfos[lightIdx].beaconN->getCore());
665 if(beacon == NULL)
666 return;
668 Pnt3f bbMin;
669 Pnt3f bbMax;
670 Pnt3f bbCenter;
672 gv->objN->updateVolume();
673 gv->objN->getVolume().getBounds(bbMin, bbMax);
674 gv->objN->getVolume().getCenter(bbCenter );
676 UInt32 numLights = gv->lightInfos.size();
677 Real32 lightFract = Real32(lightIdx + 1) / Real32(numLights);
679 Vec3f bbDiag = (bbMax - bbMin);
680 Real32 bbDiagLen = bbDiag.length();
682 Real32 angle1 = osgMod(t / 10.0, Real64(2.f * Pi));
683 Real32 angle2 = (2.f * Pi / numLights);
684 Real32 shiftVal = 0.5f * osgSin(4.f * (lightFract * angle2 + angle1)) + 0.25;
686 // translate to "above" center of the model
687 Matrix matXform0;
688 matXform0.setTranslate(bbCenter.subZero() +
689 Vec3f(0.f, shiftVal * bbDiag[1] * 1.1, 0.f));
691 // rotate around y
692 Matrix matXform1;
693 Quaternion rot1(Vec3f(0.f, 1.f, 0.f), (lightIdx + 1) * angle2 + angle1);
694 matXform1.setRotate(rot1);
696 // translate 0.5 * bb diag along x
697 Matrix matXform2;
698 matXform2.setTranslate(Vec3f(0.5f * bbDiagLen, 0.f, 0.f));
700 matXform0.mult(matXform1);
701 matXform0.mult(matXform2);
703 // align to face center
704 Pnt3f lightAt(bbCenter - Vec3f(0.f, 0.25 * bbDiag[1], 0.f));
705 Matrix matXform0Inv;
706 matXform0Inv.invertFrom(matXform0);
707 matXform0Inv.mult (lightAt, lightAt);
709 Matrix matXform3;
710 Quaternion rot2(Vec3f(0.f, 0.f, -1.),
711 lightAt.subZero() );
712 matXform3.setRotate(rot2);
714 matXform0.mult(matXform3);
716 // shift towards center
717 //Matrix matXform4;
718 //matXform4.setTranslate(Vec3f(0.f, 0.f, shiftVal * bbDiagLen));
720 //matXform0.mult(matXform4);
723 beacon->setMatrix(matXform0);
726 NodeTransitPtr loadScene(const std::string &fileName)
728 NodeTransitPtr retVal;
729 NodeUnrecPtr fileSceneN = SceneFileHandler::the()->read(fileName.c_str());
731 if(fileSceneN == NULL)
732 return retVal;
734 commitChanges();
736 fileSceneN->updateVolume();
737 const BoxVolume &bvol = fileSceneN->getVolume();
738 Pnt3f pmin;
739 Pnt3f pmax;
740 bvol.getBounds(pmin, pmax);
741 Vec3f vdiag = pmax - pmin;
742 Real32 diag = vdiag.length();
744 TransformUnrecPtr xform = Transform::create();
745 NodeUnrecPtr xformN = makeNodeFor(xform);
747 Matrix matXForm;
748 Matrix mat;
749 matXForm.setRotate(Quaternion(Vec3f(1.f, 0.f, 0.f), -Pi/2));
751 mat.setTranslate(Vec3f(0.f, 0.f, - 0.4 * diag));
753 matXForm.mult(mat);
755 xform->setMatrix(matXForm);
757 GeometryUnrecPtr plane = makePlaneGeo(4.f * diag, 4.f * diag, 1, 1);
758 NodeUnrecPtr planeN = makeNodeFor(plane);
760 UInt8 pixelData[] =
762 128, 128, 128, 255, 255, 255,
763 255, 255, 255, 128, 128, 128
766 ImageUnrecPtr texImg = Image::create();
767 texImg->set(Image::OSG_RGB_PF, 2, 2, 1, 1, 1, 0.0, pixelData);
769 SimpleTexturedMaterialUnrecPtr smat = SimpleTexturedMaterial::create();
770 smat->setImage(texImg);
771 smat->setMinFilter(GL_NEAREST);
772 smat->setMagFilter(GL_NEAREST);
774 // plane->setMaterial(smat);
775 plane->setMaterial(getDefaultMaterial());
777 xformN ->addChild(planeN);
778 gv->sceneN->addChild(xformN);
780 retVal = fileSceneN;
782 return retVal;
785 NodeTransitPtr buildTestScene(UInt32 nX, UInt32 nZ)
787 Real32 stepX = 10.f;
788 Real32 stepZ = 10.f;
790 Real32 startX = - stepX * (nX-1) / 2.;
791 Real32 startZ = - stepZ * (nZ-1) / 2.;
793 NodeTransitPtr groupN = makeCoredNode<Group>();
794 // GeometryUnrecPtr objGeo = makeBoxGeo(1.f, 1.f, 1.f, 1, 1, 1);
795 // GeometryUnrecPtr objGeo = makeLatLongSphereGeo(16, 16, 1.f);
796 GeometryUnrecPtr objGeo = makeSphereGeo(2, 1.f);
798 for(UInt32 iX = 0; iX < nX; ++iX)
800 for(UInt32 iZ = 0; iZ < nZ; ++iZ)
802 NodeUnrecPtr objGeoN = makeNodeFor(objGeo);
803 TransformUnrecPtr xform = Transform::create();
804 NodeUnrecPtr xformN = makeNodeFor(xform);
806 Matrix matXForm;
807 Vec3f vecTrans(startX + iX * stepX,
808 4.f * osgCos(Pi/5.f * Real32(iX + iZ)),
809 startZ + iZ * stepZ );
811 std::cout << "iX " << iX << " iZ " << iZ << " vecTrans " << vecTrans << std::endl;
812 matXForm.setTranslate(vecTrans);
813 xform->setMatrix(matXForm);
815 xformN->addChild(objGeoN);
816 groupN->addChild(xformN );
818 // add a 2nd layer of objects
819 NodeUnrecPtr objGeoN2 = makeNodeFor(objGeo);
820 TransformUnrecPtr xform2 = Transform::create();
821 NodeUnrecPtr xformN2 = makeNodeFor(xform2);
823 Matrix matXForm2;
824 matXForm2.setTranslate(Vec3f(startX + iX * stepX,
825 15.f,
826 startZ + iZ * stepZ ));
827 xform2->setMatrix(matXForm2);
829 xformN2->addChild(objGeoN2);
830 groupN ->addChild(xformN2 );
834 // ground plane
835 TransformUnrecPtr xform = Transform::create();
836 NodeUnrecPtr xformN = makeNodeFor(xform);
838 Matrix matXForm;
839 matXForm.setTranslate(Vec3f(0.f, -5.f, 0.f));
840 matXForm.setRotate (Quaternion(Vec3f(1.f, 0.f, 0.f), -PiHalf));
841 xform->setMatrix(matXForm);
843 NodeUnrecPtr planeGeoN = makePlane(nX * stepX, nZ * stepZ, 1, 1);
845 xformN->addChild(planeGeoN);
846 groupN->addChild(xformN );
849 // back box
850 xform = Transform::create();
851 xformN = makeNodeFor(xform);
853 matXForm.setIdentity();
854 matXForm.setTranslate(Vec3f(0.f, 15.f, -20.f));
855 xform->setMatrix(matXForm);
857 NodeUnrecPtr boxGeoN = makeBox(nX * stepX, 35.f, 2.f, 1, 1, 1);
859 xformN->addChild(boxGeoN);
860 groupN->addChild(xformN );
862 return groupN;
865 std::ostream &operator << (std::ostream &os, const LightInfo &li)
867 os << "lightType " << mapLightType(li.lightType)
868 << " " << (li.light->getOn() ? "on" : "off")
869 << " shadowType " << mapShadowType(li.shadowType);
871 return os;
875 // GLUT callback functions
878 // react to size changes
879 void reshape(int w, int h)
881 gv->mgr->resize(w, h);
882 glutPostRedisplay();
885 void display(void)
887 // static OSG::Time tStart = OSG::getSystemTime();
888 static OSG::Time tLast = OSG::getSystemTime();
889 static OSG::Time tAnim = OSG::getSystemTime();
890 static OSG::Time tFrames = OSG::getSystemTime();
891 static OSG::UInt32 frames = 0;
893 OSG::Time tNow = OSG::getSystemTime();
895 if(gv->animateLights == true)
897 tAnim += (tNow - tLast);
900 for(UInt32 i = 0; i < gv->lightInfos.size(); ++i)
902 updateLightBeacon(i, tAnim);
905 ++frames;
907 if(tNow - tFrames > 1.f)
909 std::cout << "delta t: " << (tNow - tFrames) << " frames: " << frames << std::endl;
910 tFrames = tNow;
911 frames = 0;
914 tLast = tNow;
916 commitChangesAndClear();
918 gv->mgr->redraw();
921 // react to mouse button presses
922 void mouse(int button, int state, int x, int y)
924 if (state)
925 gv->mgr->mouseButtonRelease(button, x, y);
926 else
927 gv->mgr->mouseButtonPress(button, x, y);
929 glutPostRedisplay();
932 // react to mouse motions with pressed buttons
933 void motion(int x, int y)
935 gv->mgr->mouseMove(x, y);
936 glutPostRedisplay();
939 void keyboard(unsigned char k, int , int )
941 switch(k)
943 case 27:
945 // exit
946 cleanup();
947 exit(0);
949 break;
951 case '1':
953 // all lights no shadow
954 for(UInt32 i = 0; i < gv->lightInfos.size(); ++i)
956 setShadow(i, ST_NONE);
957 std::cout << "changed shadow type for light "
958 << i << " " << gv->lightInfos[i]
959 << std::endl;
962 break;
964 case '2':
966 // all lights standard shadows
967 for(UInt32 i = 0; i < gv->lightInfos.size(); ++i)
969 setShadow(i, ST_STANDARD);
970 std::cout << "changed shadow type for light "
971 << i << " " << gv->lightInfos[i]
972 << std::endl;
975 break;
977 case '3':
979 // all lights TSM shadows
980 for(UInt32 i = 0; i < gv->lightInfos.size(); ++i)
982 setShadow(i, ST_TRAPEZOID);
983 std::cout << "changed shadow type for light "
984 << i << " " << gv->lightInfos[i]
985 << std::endl;
988 break;
990 case 'a':
992 // toggle lights moving
993 gv->animateLights = !gv->animateLights;
995 std::cout << "animating lights: " << gv->animateLights << std::endl;
997 break;
999 case 'c':
1001 // toggle all lights white/colorful
1002 gv->colorLights = !gv->colorLights;
1004 std::cout << "color lights: " << gv->colorLights << std::endl;
1006 setColorLights(gv->colorLights);
1008 break;
1010 case 'o':
1012 // toggle current light on/off
1013 if(gv->currentLight < Int32(gv->lightInfos.size()) &&
1014 gv->currentLight >= 0 )
1016 Light *light = gv->lightInfos[gv->currentLight].light;
1018 light->setOn(!light->getOn());
1020 std::cout << gv->lightInfos[gv->currentLight] << std::endl;
1023 break;
1025 case '+':
1027 // add new light
1028 addLight (gv->newLightType, gv->newShadowType);
1030 std::cout << "added light " << (gv->lightInfos.size() - 1) << " "
1031 << gv->lightInfos.back()
1032 << std::endl;
1034 break;
1036 case '-':
1038 // remove current light
1039 if(gv->currentLight < Int32(gv->lightInfos.size()) &&
1040 gv->currentLight >= 0 )
1042 std::cout << "removing light " << gv->currentLight << " "
1043 << gv->lightInfos[gv->currentLight]
1044 << std::endl;
1046 subLight(gv->currentLight);
1049 break;
1051 case 's':
1053 // cycle through shadow types for current light
1054 if(gv->currentLight < Int32(gv->lightInfos.size()) &&
1055 gv->currentLight >= 0 )
1057 if(gv->lightInfos[gv->currentLight].shadowType == ST_NONE)
1059 setShadow(gv->currentLight, ST_STANDARD);
1061 else if(gv->lightInfos[gv->currentLight].shadowType == ST_STANDARD)
1063 setShadow(gv->currentLight, ST_TRAPEZOID);
1065 else
1067 setShadow(gv->currentLight, ST_NONE);
1070 std::cout << "changed shadow type for light "
1071 << gv->currentLight << " "
1072 << gv->lightInfos[gv->currentLight]
1073 << std::endl;
1076 break;
1078 case '.':
1080 // select previous light
1081 gv->currentLight += 1;
1082 if(gv->currentLight >= Int32(gv->lightInfos.size()))
1083 gv->currentLight = 0;
1085 if(gv->currentLight < Int32(gv->lightInfos.size()) &&
1086 gv->currentLight >= 0 )
1088 std::cout << "currentLight " << gv->currentLight
1089 << " (total: " << gv->lightInfos.size() << ") "
1090 << gv->lightInfos[gv->currentLight]
1091 << std::endl;
1094 break;
1096 case ',':
1098 // select next light
1099 gv->currentLight -= 1;
1101 if(gv->currentLight < 0)
1102 gv->currentLight = gv->lightInfos.size() - 1;
1104 if(gv->currentLight < Int32(gv->lightInfos.size()) &&
1105 gv->currentLight >= 0 )
1107 std::cout << "currentLight " << gv->currentLight
1108 << " (total: " << gv->lightInfos.size() << ") "
1109 << gv->lightInfos[gv->currentLight]
1110 << std::endl;
1113 break;
1117 glutPostRedisplay();
1120 // just request a redraw
1121 void idle(void)
1123 glutPostRedisplay();
1126 // setup the GLUT library which handles the windows for us
1127 int setupGLUT(int *argc, char *argv[])
1129 glutInit(argc, argv);
1130 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
1132 int winid = glutCreateWindow("OpenSG");
1134 glutReshapeFunc(reshape);
1135 glutDisplayFunc(display);
1136 glutMouseFunc(mouse);
1137 glutMotionFunc(motion);
1138 glutKeyboardFunc(keyboard);
1139 glutIdleFunc(idle);
1141 glutReshapeWindow(1400, 1050);
1143 return winid;