source: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/chcdemo.cpp @ 3276

Revision 3276, 67.5 KB checked in by mattausch, 15 years ago (diff)
Line 
1// chcdemo.cpp : Defines the entry point for the console application.
2//
3
4
5#include "common.h"
6
7#ifdef _CRT_SET
8        #define _CRTDBG_MAP_ALLOC
9        #include <stdlib.h>
10        #include <crtdbg.h>
11
12        // redefine new operator
13        #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
14        #define new DEBUG_NEW
15#endif
16
17#include <math.h>
18#include <time.h>
19#include "glInterface.h"
20
21
22#include "RenderTraverser.h"
23#include "SceneEntity.h"
24#include "Vector3.h"
25#include "Matrix4x4.h"
26#include "ResourceManager.h"
27#include "Bvh.h"
28#include "Camera.h"
29#include "Geometry.h"
30#include "BvhLoader.h"
31#include "FrustumCullingTraverser.h"
32#include "StopAndWaitTraverser.h"
33#include "CHCTraverser.h"
34#include "CHCPlusPlusTraverser.h"
35#include "Visualization.h"
36#include "RenderState.h"
37#include "Timer/PerfTimer.h"
38#include "SceneQuery.h"
39#include "RenderQueue.h"
40#include "Material.h"
41#include "glfont2.h"
42#include "PerformanceGraph.h"
43#include "Environment.h"
44#include "Halton.h"
45#include "Transform3.h"
46#include "SampleGenerator.h"
47#include "FrameBufferObject.h"
48#include "DeferredRenderer.h"
49#include "ShadowMapping.h"
50#include "Light.h"
51#include "SceneEntityConverter.h"
52#include "SkyPreetham.h"
53#include "Texture.h"
54#include "ShaderManager.h"
55#include "MotionPath.h"
56#include "ShaderProgram.h"
57#include "Shape.h"
58#include "WalkThroughRecorder.h"
59#include "StatsWriter.h"
60#include "VisibilitySolutionLoader.h"
61#include "ViewCellsTree.h"
62#include "PvsCollectionRenderer.h"
63#include "ObjExporter.h"
64#include "BvhExporter.h"
65
66
67using namespace std;
68using namespace CHCDemoEngine;
69
70
71/// the environment for the program parameter
72static Environment env;
73
74
75GLuint fontTex;
76/// the fbo used for MRT
77FrameBufferObject *fbo = NULL;
78/// the renderable scene geometry
79SceneEntityContainer staticObjects;
80/// the dynamic objects in the scene
81SceneEntityContainer dynamicObjects;
82// traverses and renders the hierarchy
83RenderTraverser *traverser = NULL;
84/// the hierarchy
85Bvh *bvh = NULL;
86/// handles scene loading
87ResourceManager *resourceManager = NULL;
88/// handles scene loading
89ShaderManager *shaderManager = NULL;
90/// the scene camera
91PerspectiveCamera *camera = NULL;
92/// the scene camera
93PerspectiveCamera *visCamera = NULL;
94/// the visualization
95Visualization *visualization = NULL;
96/// the current render renderState
97RenderState renderState;
98/// the rendering algorithm
99int renderMode = RenderTraverser::CHCPLUSPLUS;
100/// eye near plane distance
101const float nearDist = 0.2f;
102//const float nearDist = 1.0f;
103/// eye far plane distance
104float farDist = 1e6f;
105/// the field of view
106const float fov = 50.0f;
107
108SceneQuery *sceneQuery = NULL;
109RenderQueue *renderQueue = NULL;
110/// traverses and renders the hierarchy
111RenderTraverser *shadowTraverser = NULL;
112/// the skylight + skydome model
113SkyPreetham *preetham = NULL;
114
115MotionPath *motionPath = NULL;
116/// max depth where candidates for tighter bounds are searched
117int maxDepthForTestingChildren = 3;
118/// use full resolution for ssao or half
119bool ssaoUseFullResolution = false;
120
121/// store the frames as tga
122bool recordFrames = false;
123/// record the taken path
124bool recordPath = false;
125/// replays the recorded path
126bool replayPath = false;
127/// frame number for replay
128int currentReplayFrame = -1;
129
130string recordedFramesSuffix("frames");
131string statsFilename("stats");
132
133string filename("city");
134string bvhname("");
135string visibilitySolution("");
136
137
138/// the walkThroughRecorder
139WalkThroughRecorder *walkThroughRecorder = NULL;
140WalkThroughPlayer *walkThroughPlayer = NULL;
141StatsWriter *statsWriter = NULL;
142
143bool makeSnapShot = false;
144
145ViewCellsTree *viewCellsTree = NULL;
146ViewCell *viewCell = NULL;
147
148bool useSkylightForIllum = true;
149
150bool showFPS = true;
151
152static int globalVisibleId = 0;
153
154
155
156/// the technique used for rendering
157enum RenderTechnique
158{
159        FORWARD,
160        DEFERRED,
161        DEPTH_PASS
162};
163
164
165/// the used render type for this render pass
166enum RenderMethod
167{
168        RENDER_FORWARD,
169        RENDER_DEPTH_PASS,
170        RENDER_DEFERRED,
171        RENDER_DEPTH_PASS_DEFERRED,
172        RENDER_NUM_RENDER_TYPES
173};
174
175/// one of four possible render methods
176int renderMethod = RENDER_FORWARD;
177
178static int winWidth = 1024;
179static int winHeight = 768;
180static float winAspectRatio = 1.0f;
181
182/// these values get scaled with the frame rate
183static float keyForwardMotion = 30.0f;
184static float keyRotation = 1.5f;
185
186/// elapsed time in milliseconds
187double elapsedTime = 1000.0;
188double algTime = 1000.0;
189double accumulatedTime = 1000.0;
190float fps = 1e3f;
191float turbitity = 5.0f;
192
193// ssao parameters
194float ssaoKernelRadius = 1e-8f;
195float ssaoSampleIntensity = 0.2f;
196float ssaoFilterRadius = 12.0f;
197float ssaoTempCohFactor = 255.0;
198bool sortSamples = true;
199
200int shadowSize = 2048;
201
202/// the hud font
203glfont::GLFont myfont;
204
205// rendertexture
206int texWidth = 1024;
207int texHeight = 768;
208
209int renderedObjects = 0;
210int renderedNodes = 0;
211int renderedTriangles = 0;
212
213int issuedQueries = 0;
214int traversedNodes = 0;
215int frustumCulledNodes = 0;
216int queryCulledNodes = 0;
217int stateChanges = 0;
218int numBatches = 0;
219
220// mouse navigation renderState
221int xEyeBegin = 0;
222int yEyeBegin = 0;
223int yMotionBegin = 0;
224int verticalMotionBegin = 0;
225int horizontalMotionBegin = 0;
226
227bool leftKeyPressed = false;
228bool rightKeyPressed = false;
229bool upKeyPressed = false;
230bool downKeyPressed = false;
231bool descendKeyPressed = false;
232bool ascendKeyPressed = false;
233bool leftStrafeKeyPressed = false;
234bool rightStrafeKeyPressed = false;
235
236bool altKeyPressed = false;
237
238bool showHelp = false;
239bool showStatistics = false;
240bool showOptions = true;
241bool showBoundingVolumes = false;
242bool visMode = false;
243
244bool useOptimization = false;
245bool useTightBounds = true;
246bool useRenderQueue = true;
247bool useMultiQueries = true;
248bool flyMode = true;
249
250bool useGlobIllum = false;
251bool useTemporalCoherence = true;
252bool showAlgorithmTime = false;
253
254bool useFullScreen = false;
255bool useLODs = true;
256bool moveLight = false;
257
258bool useAdvancedShading = false;
259bool showShadowMap = false;
260bool renderLightView = false;
261bool useHDR = true;
262bool useAntiAliasing = true;
263bool useLenseFlare = true;
264
265bool usePvs = false;
266
267
268PerfTimer frameTimer, algTimer;
269/// the performance graph window
270PerformanceGraph *perfGraph = NULL;
271
272int sCurrentMrtSet = 0;
273static Matrix4x4 invTrafo = IdentityMatrix();
274float mouseMotion = 0.2f;
275
276float viewCellsScaleFactor = 1.0f;
277
278
279//////////////
280//-- chc++ algorithm parameters
281
282/// the pixel threshold where a node is still considered invisible
283/// (should be zero for conservative visibility)
284int threshold;
285int assumedVisibleFrames = 10;
286int maxBatchSize = 50;
287int trianglesPerVirtualLeaf = INITIAL_TRIANGLES_PER_VIRTUAL_LEAVES;
288
289
290//////////////
291
292enum {CAMERA_PASS = 0, LIGHT_PASS = 1};
293
294
295//DeferredRenderer::SAMPLING_METHOD samplingMethod = DeferredRenderer::SAMPLING_POISSON;
296DeferredRenderer::SAMPLING_METHOD samplingMethod = DeferredRenderer::SAMPLING_QUADRATIC;
297
298ShadowMap *shadowMap = NULL;
299DirectionalLight *light = NULL;
300DeferredRenderer *deferredShader = NULL;
301
302
303SceneEntity *buddha = NULL;
304SceneEntity *skyDome = NULL;
305SceneEntity *sunBox = NULL;
306
307GLuint sunQuery = 0;
308
309string walkThroughSuffix("frames");
310
311
312////////////////////
313//--- function forward declarations
314
315void InitExtensions();
316void InitGLstate();
317
318void DisplayVisualization();
319/// destroys all allocated resources
320void CleanUp();
321void SetupEyeView();
322void SetupLighting();
323void DisplayStats();
324/// draw the help screen
325void DrawHelpMessage();
326/// render the sky dome
327void RenderSky();
328/// render the objects found visible in the depth pass
329void RenderVisibleObjects();
330
331int TestSunVisible();
332
333void Begin2D();
334void End2D();
335/// the main loop
336void MainLoop();
337
338void KeyBoard(unsigned char c, int x, int y);
339void Special(int c, int x, int y);
340void KeyUp(unsigned char c, int x, int y);
341void SpecialKeyUp(int c, int x, int y);
342void Reshape(int w, int h);
343void Mouse(int button, int renderState, int x, int y);
344void LeftMotion(int x, int y);
345void RightMotion(int x, int y);
346void MiddleMotion(int x, int y);
347void KeyHorizontalMotion(float shift);
348void KeyVerticalMotion(float shift);
349/// returns the string representation of a number with the decimal points
350void CalcDecimalPoint(string &str, int d);
351/// Creates the traversal method (vfc, stopandwait, chc, chc++)
352RenderTraverser *CreateTraverser(PerspectiveCamera *cam);
353/// place the viewer on the floor plane
354void PlaceViewer(const Vector3 &oldPos);
355// initialise the frame buffer objects
356void InitFBO();
357/// changes the sunlight direction
358void RightMotionLight(int x, int y);
359/// render the shader map
360void RenderShadowMap(float newfar);
361/// function that touches each material once in order to accelarate render queue
362void PrepareRenderQueue();
363/// loads the specified model
364int LoadModel(const string &model, SceneEntityContainer &entities);
365
366inline float KeyRotationAngle() { return keyRotation * elapsedTime * 1e-3f; }
367inline float KeyShift() { return keyForwardMotion * elapsedTime * 1e-3f; }
368
369void CreateAnimation();
370
371SceneQuery *GetOrCreateSceneQuery();
372
373void LoadPvs();
374
375void LoadVisibilitySolution();
376
377void RenderViewCell();
378
379void LoadPompeiiScene();
380
381
382// new view projection matrix of the camera
383static Matrix4x4 viewProjMat = IdentityMatrix();
384// the old view projection matrix of the camera
385static Matrix4x4 oldViewProjMat = IdentityMatrix();
386
387
388
389static void PrintGLerror(char *msg)
390{
391        GLenum errCode;
392        const GLubyte *errStr;
393       
394        if ((errCode = glGetError()) != GL_NO_ERROR)
395        {
396                errStr = gluErrorString(errCode);
397                fprintf(stderr,"OpenGL ERROR: %s: %s\n", errStr, msg);
398        }
399}
400
401
402int main(int argc, char* argv[])
403{
404#ifdef _CRT_SET
405        //Now just call this function at the start of your program and if you're
406        //compiling in debug mode (F5), any leaks will be displayed in the Output
407        //window when the program shuts down. If you're not in debug mode this will
408        //be ignored. Use it as you will!
409        //note: from GDNet Direct [3.8.04 - 3.14.04] void detectMemoryLeaks() {
410
411        _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF|_CRTDBG_ALLOC_MEM_DF);
412        _CrtSetReportMode(_CRT_ASSERT,_CRTDBG_MODE_FILE);
413        _CrtSetReportFile(_CRT_ASSERT,_CRTDBG_FILE_STDERR);
414#endif
415
416
417        int returnCode = 0;
418
419        Vector3 camPos(.0f, .0f, .0f);
420        Vector3 camDir(.0f, 1.0f, .0f);
421        Vector3 lightDir(-0.8f, 1.0f, -0.7f);
422
423        cout << "=== reading environment file ===" << endl << endl;
424
425        const string envFileName = "default.env";
426        if (!env.Read(envFileName))
427        {
428                cerr << "loading environment " << envFileName << " failed!" << endl;
429        }
430        else
431        {
432                env.GetIntParam(string("assumedVisibleFrames"), assumedVisibleFrames);
433                env.GetIntParam(string("maxBatchSize"), maxBatchSize);
434                env.GetIntParam(string("trianglesPerVirtualLeaf"), trianglesPerVirtualLeaf);
435                env.GetIntParam(string("winWidth"), winWidth);
436                env.GetIntParam(string("winHeight"), winHeight);
437                env.GetIntParam(string("shadowSize"), shadowSize);
438                env.GetIntParam(string("maxDepthForTestingChildren"), maxDepthForTestingChildren);
439
440                env.GetFloatParam(string("keyForwardMotion"), keyForwardMotion);
441                env.GetFloatParam(string("keyRotation"), keyRotation);
442                env.GetFloatParam(string("mouseMotion"), mouseMotion);
443                env.GetFloatParam(string("tempCohFactor"), ssaoTempCohFactor);
444                env.GetFloatParam(string("turbitity"), turbitity);
445               
446                env.GetVectorParam(string("camPosition"), camPos);
447                env.GetVectorParam(string("camDirection"), camDir);
448                env.GetVectorParam(string("lightDirection"), lightDir);
449
450                env.GetBoolParam(string("useFullScreen"), useFullScreen);
451                env.GetBoolParam(string("useLODs"), useLODs);
452                env.GetBoolParam(string("useHDR"), useHDR);
453                env.GetBoolParam(string("useAA"), useAntiAliasing);
454                env.GetBoolParam(string("useLenseFlare"), useLenseFlare);
455                env.GetBoolParam(string("useAdvancedShading"), useAdvancedShading);
456
457                env.GetIntParam(string("renderMethod"), renderMethod);
458
459                env.GetFloatParam(string("ssaoKernelRadius"), ssaoKernelRadius);
460                env.GetFloatParam(string("ssaoSampleIntensity"), ssaoSampleIntensity);
461                env.GetBoolParam(string("ssaoUseFullResolution"), ssaoUseFullResolution);
462
463                env.GetStringParam(string("recordedFramesSuffix"), recordedFramesSuffix);
464                env.GetStringParam(string("walkThroughSuffix"), walkThroughSuffix);
465                env.GetStringParam(string("statsFilename"), statsFilename);
466                env.GetStringParam(string("filename"), filename);
467                env.GetStringParam(string("bvhname"), bvhname);
468                env.GetStringParam(string("visibilitySolution"), visibilitySolution);
469
470                env.GetBoolParam(string("usePvs"), usePvs);
471                env.GetBoolParam(string("useSkylightForIllum"), useSkylightForIllum);
472                env.GetFloatParam(string("viewCellsScaleFactor"), viewCellsScaleFactor);
473
474                //env.GetStringParam(string("modelPath"), model_path);
475                //env.GetIntParam(string("numSssaoSamples"), numSsaoSamples);
476
477                texWidth = winWidth;
478                texHeight = winHeight;
479
480                cout << "assumed visible frames: " << assumedVisibleFrames << endl;
481                cout << "max batch size: " << maxBatchSize << endl;
482                cout << "triangles per virtual leaf: " << trianglesPerVirtualLeaf << endl;
483
484                cout << "static scene filename prefix: " << filename << endl;
485                cout << "bvh filename prefix: " << bvhname << endl;
486
487                cout << "key forward motion: " << keyForwardMotion << endl;
488                cout << "key rotation: " << keyRotation << endl;
489                cout << "win width: " << winWidth << endl;
490                cout << "win height: " << winHeight << endl;
491                cout << "use full screen: " << useFullScreen << endl;
492                cout << "use LODs: " << useLODs << endl;
493                cout << "camera position: " << camPos << endl;
494                cout << "shadow size: " << shadowSize << endl;
495                cout << "render method: " << renderMethod << endl;
496                cout << "use antialiasing: " << useAntiAliasing << endl;
497                cout << "use lense flare: " << useLenseFlare << endl;
498                cout << "use advanced shading: " << useAdvancedShading << endl;
499                cout << "turbitity: " << turbitity << endl;
500                cout << "temporal coherence factor: " << ssaoTempCohFactor << endl;
501                cout << "sample intensity: " << ssaoSampleIntensity << endl;
502                cout << "kernel radius: " << ssaoKernelRadius << endl;
503                cout << "use ssao full resolution: " << ssaoUseFullResolution << endl;
504                cout << "recorded frames suffix: " << recordedFramesSuffix << endl;
505                cout << "walkthrough suffix: " << walkThroughSuffix << endl;
506                cout << "stats filename: " << statsFilename << endl;
507                cout << "use PVSs: " << usePvs << endl;
508                cout << "visibility solution: " << visibilitySolution << endl;
509                cout << "view cells scale factor: " << viewCellsScaleFactor << endl;
510                cout << "use skylight for illumination: " << useSkylightForIllum << endl;
511
512                //cout << "model path: " << model_path << endl;
513                cout << "**** end parameters ****" << endl << endl;
514        }
515
516        ///////////////////////////
517
518        camera = new PerspectiveCamera(winWidth / winHeight, fov);
519        camera->SetNear(nearDist);
520        camera->SetFar(1000);
521
522        camera->SetDirection(camDir);
523        camera->SetPosition(camPos);
524
525        visCamera = new PerspectiveCamera(winWidth / winHeight, fov);
526        visCamera->SetNear(0.0f);
527        visCamera->Yaw(.5 * M_PI);
528
529        // create a new light
530        light = new DirectionalLight(lightDir, RgbaColor(1, 1, 1, 1), RgbaColor(1, 1, 1, 1));
531        // the render queue for material sorting
532        renderQueue = new RenderQueue(&renderState);
533
534        glutInitWindowSize(winWidth, winHeight);
535        glutInit(&argc, argv);
536        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_MULTISAMPLE);
537        //glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
538        //glutInitDisplayString("samples=2");
539
540        SceneEntity::SetUseLODs(useLODs);
541
542
543        if (!useFullScreen)
544        {
545                glutCreateWindow("FriendlyCulling");
546        }
547        else
548        {
549                glutGameModeString( "1024x768:32@75" );
550                glutEnterGameMode();
551        }
552
553        glutDisplayFunc(MainLoop);
554        glutKeyboardFunc(KeyBoard);
555        glutSpecialFunc(Special);
556        glutReshapeFunc(Reshape);
557        glutMouseFunc(Mouse);
558        glutIdleFunc(MainLoop);
559        glutKeyboardUpFunc(KeyUp);
560        glutSpecialUpFunc(SpecialKeyUp);
561        glutIgnoreKeyRepeat(true);
562
563        // initialise gl graphics
564        InitExtensions();
565        InitGLstate();
566
567        glEnable(GL_MULTISAMPLE_ARB);
568        glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST);
569
570        LeftMotion(0, 0);
571        MiddleMotion(0, 0);
572
573        perfGraph = new PerformanceGraph(1000);
574
575        resourceManager = ResourceManager::GetSingleton();
576        shaderManager = ShaderManager::GetSingleton();
577
578
579        ///////////
580        //-- load the static scene geometry
581
582        LoadModel(filename + ".dem", staticObjects);
583
584
585        //////////
586        //-- load some dynamic stuff
587
588        //resourceManager->mUseNormalMapping = true;
589        //resourceManager->mUseNormalMapping = false;
590
591        resourceManager->mUseSpecialColors = true;
592
593        //LoadModel("fisch.dem", dynamicObjects);
594
595        //LoadModel("venusm.dem", dynamicObjects);
596        //LoadModel("camel.dem", dynamicObjects);
597        //LoadModel("toyplane2.dem", dynamicObjects);
598        //LoadModel("elephal.dem", dynamicObjects);
599        //LoadModel("sibenik.dem", dynamicObjects);
600
601        if (1) LoadPompeiiScene();
602
603#if 0
604        const Vector3 sceneCenter(470.398f, 240.364f, 181.7f);
605        //const Vector3 sceneCenter(470.398f, 240.364f, 180.3);
606        Matrix4x4 transl = TranslationMatrix(sceneCenter);
607       
608        LoadModel("hbuddha.dem", dynamicObjects);
609
610        buddha = dynamicObjects.back();
611        buddha->GetTransform()->SetMatrix(transl);
612
613        for (int i = 0; i < 10; ++ i)
614        {
615                SceneEntity *ent = new SceneEntity(*buddha);
616                resourceManager->AddSceneEntity(ent);
617
618                Vector3 offs = Vector3::ZERO();
619
620                offs.x = RandomValue(.0f, 50.0f);
621                offs.y = RandomValue(.0f, 50.0f);
622
623                Vector3 newPos = sceneCenter + offs;
624
625                transl = TranslationMatrix(newPos);
626                Transform3 *transform = resourceManager->CreateTransform(transl);
627
628                ent->SetTransform(transform);
629                dynamicObjects.push_back(ent);
630        }
631#endif
632
633       
634        resourceManager->mUseNormalMapping = false;
635        resourceManager->mUseSpecialColors = false;
636
637
638        ///////////
639        //-- load the associated static bvh
640
641        BvhFactory bvhFactory;
642
643        if (bvhname != "")
644        {
645                cout << "loading bvh from disc" << endl;
646                const string bvh_fullpath = string(model_path + bvhname + ".bvh");
647                bvh = bvhFactory.Create(bvh_fullpath, staticObjects, dynamicObjects, maxDepthForTestingChildren);
648
649                if (!bvh)
650                {
651                        cerr << "loading bvh " << bvh_fullpath << " failed" << endl;
652                        CleanUp();
653                        exit(0);
654                }
655        }
656        else
657        {
658                cout << "creating new bvh" << endl;
659                bvh = bvhFactory.Create(staticObjects, dynamicObjects, maxDepthForTestingChildren);
660        }
661
662        /// set the depth of the bvh depending on the triangles per leaf node
663        bvh->SetVirtualLeaves(trianglesPerVirtualLeaf);
664
665        // set far plane based on scene extent
666        farDist = 10.0f * Magnitude(bvh->GetBox().Diagonal());
667        camera->SetFar(farDist);
668
669
670        //ObjExporter().Export(model_path + "mypompeii.obj", bvh);
671        //BvhExporter().Export(model_path + "mypompeii.bv", bvh);
672
673
674
675        //////////////////
676        //-- setup the skydome model
677
678        LoadModel("sky.dem", staticObjects);
679        skyDome = staticObjects.back();
680
681        /// the turbitity of the sky (from clear to hazy, use <3 for clear sky)
682        preetham = new SkyPreetham(turbitity, skyDome);
683
684        CreateAnimation();
685
686
687        //////////////////////////
688        //-- a bounding box representing the sun pos in order to test visibility
689
690        Transform3 *trafo = resourceManager->CreateTransform(IdentityMatrix());
691
692        // make it slightly bigger to simulate sun diameter
693        const float size = 25.0f;
694        AxisAlignedBox3 sbox(Vector3(-size), Vector3(size));
695
696        SceneEntityConverter conv;
697
698
699        //////////////////
700        //-- occlusion query for sun
701
702        Material *mat = resourceManager->CreateMaterial();
703
704        mat->GetTechnique(0)->SetDepthWriteEnabled(false);
705        mat->GetTechnique(0)->SetColorWriteEnabled(false);
706
707        sunBox = conv.ConvertBox(sbox, mat, trafo);
708        resourceManager->AddSceneEntity(sunBox);
709
710        /// create single occlusion query that handles sun visibility
711        glGenQueriesARB(1, &sunQuery);
712
713
714        //////////
715        //-- initialize the traversal algorithm
716
717        traverser = CreateTraverser(camera);
718       
719        // the bird-eye visualization
720        visualization = new Visualization(bvh, camera, NULL, &renderState);
721
722        // this function assign the render queue bucket ids of the materials in beforehand
723        // => probably less overhead for new parts of the scene that are not yet assigned
724        PrepareRenderQueue();
725        /// forward rendering is the default
726        renderState.SetRenderTechnique(FORWARD);
727        // frame time is restarted every frame
728        frameTimer.Start();
729
730        //Halton::TestHalton(7, 2);
731        //HaltonSequence::TestHalton(15, 2);
732        //Halton::TestPrime();
733
734        // the rendering loop
735        glutMainLoop();
736       
737        // clean up
738        CleanUp();
739       
740        return 0;
741}
742
743
744void InitFBO()
745{
746        PrintGLerror("fbo start");
747
748        // this fbo basicly stores the scene information we get from standard rendering of a frame
749        // we store diffuse colors, eye space depth and normals
750        fbo = new FrameBufferObject(texWidth, texHeight, FrameBufferObject::DEPTH_32);
751
752        // the diffuse color buffer
753        fbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR, ColorBufferObject::FILTER_NEAREST);
754        // the normals buffer
755        //fbo->AddColorBuffer(ColorBufferObject::RGB_FLOAT_16, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_NEAREST);
756        fbo->AddColorBuffer(ColorBufferObject::RGB_FLOAT_16, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
757        // a rgb buffer which could hold material properties
758        //fbo->AddColorBuffer(ColorBufferObject::RGB_UBYTE, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_NEAREST);
759        // buffer holding the difference vector to the old frame
760        fbo->AddColorBuffer(ColorBufferObject::RGB_FLOAT_16, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
761        // another color buffer
762        fbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR, ColorBufferObject::FILTER_NEAREST);
763
764        for (int i = 0; i < 4; ++ i)
765        {
766                FrameBufferObject::InitBuffer(fbo, i);
767        }
768
769        PrintGLerror("init fbo");
770}
771
772
773bool InitFont(void)
774{
775        glEnable(GL_TEXTURE_2D);
776
777        glGenTextures(1, &fontTex);
778        glBindTexture(GL_TEXTURE_2D, fontTex);
779
780        if (!myfont.Create("data/fonts/verdana.glf", fontTex))
781                return false;
782
783        glDisable(GL_TEXTURE_2D);
784       
785        return true;
786}
787
788
789void InitGLstate()
790{
791        glClearColor(0.4f, 0.4f, 0.4f, 1e20f);
792       
793        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
794        glPixelStorei(GL_PACK_ALIGNMENT,1);
795       
796        glDepthFunc(GL_LESS);
797        glEnable(GL_DEPTH_TEST);
798
799        glColor3f(1.0f, 1.0f, 1.0f);
800        glShadeModel(GL_SMOOTH);
801       
802        glMaterialf(GL_FRONT, GL_SHININESS, 64);
803        glEnable(GL_NORMALIZE);
804               
805        glDisable(GL_ALPHA_TEST);
806        glAlphaFunc(GL_GEQUAL, 0.5f);
807
808        glFrontFace(GL_CCW);
809        glCullFace(GL_BACK);
810        glEnable(GL_CULL_FACE);
811
812        glDisable(GL_TEXTURE_2D);
813
814        GLfloat ambientColor[] = {0.2, 0.2, 0.2, 1.0};
815        GLfloat diffuseColor[] = {1.0, 0.0, 0.0, 1.0};
816        GLfloat specularColor[] = {0.0, 0.0, 0.0, 1.0};
817
818        glMaterialfv(GL_FRONT, GL_AMBIENT, ambientColor);
819        glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuseColor);
820        glMaterialfv(GL_FRONT, GL_SPECULAR, specularColor);
821
822        glDepthFunc(GL_LESS);
823
824        if (!InitFont())
825                cerr << "font creation failed" << endl;
826        else
827                cout << "successfully created font" << endl;
828
829
830        //////////////////////////////
831
832        //GLfloat lmodel_ambient[] = {1.0f, 1.0f, 1.0f, 1.0f};
833        GLfloat lmodel_ambient[] = {0.7f, 0.7f, 0.8f, 1.0f};
834
835        glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
836        //glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
837        glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
838        glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL_EXT, GL_SINGLE_COLOR_EXT);
839}
840
841
842void DrawHelpMessage()
843{
844        const char *message[] =
845        {
846                "Help information",
847                "",
848                "'F1'           - shows/dismisses this message",
849                "'F2'           - shows/hides bird eye view",
850                "'F3'           - shows/hides bounds (boxes or tight bounds)",
851                "'F4',          - shows/hides parameters",
852                "'F5'           - shows/hides statistics",
853                "'F6',          - toggles between fly/walkmode",
854                "'F7',          - cycles throw render modes",
855                "'F8',          - enables/disables ambient occlusion (only deferred)",
856                "'F9',          - shows pure algorithm render time (using glFinish)",
857                "'SPACE'        - cycles through occlusion culling algorithms",
858                "",
859                "'MOUSE LEFT'        - turn left/right, move forward/backward",
860                "'MOUSE RIGHT'       - turn left/right, move forward/backward",
861                "'MOUSE MIDDLE'      - move up/down, left/right",
862                "'CURSOR UP/DOWN'    - move forward/backward",
863                "'CURSOR LEFT/RIGHT' - turn left/right",
864                "",
865                "'-'/'+'        - decreases/increases max batch size",
866                "'1'/'2'        - downward/upward motion",
867                "'3'/'4'        - decreases/increases triangles per virtual bvh leaf (sets bvh depth)",
868                "'5'/'6'        - decreases/increases assumed visible frames",
869                "",
870                "'R'            - use render queue",
871                "'B'            - use tight bounds",
872                "'M'            - use multiqueries",
873                "'O'            - use CHC optimization (geometry queries for leaves)",
874                0,
875        };
876       
877       
878        glColor4f(0.0f, 1.0f , 0.0f, 0.2f); // 20% green.
879
880        glRecti(30, 30, winWidth - 30, winHeight - 30);
881
882        glEnd();
883
884        glColor3f(1.0f, 1.0f, 1.0f);
885       
886        glEnable(GL_TEXTURE_2D);
887        myfont.Begin();
888
889        int x = 40, y = 30;
890
891        for(int i = 0; message[i] != 0; ++ i)
892        {
893                if(message[i][0] == '\0')
894                {
895                        y += 15;
896                }
897                else
898                {
899                        myfont.DrawString(message[i], x, winHeight - y);
900                        y += 25;
901                }
902        }
903        glDisable(GL_TEXTURE_2D);
904}
905
906
907RenderTraverser *CreateTraverser(PerspectiveCamera *cam)
908{
909        RenderTraverser *tr;
910       
911        switch (renderMode)
912        {
913        case RenderTraverser::CULL_FRUSTUM:
914                tr = new FrustumCullingTraverser();
915                break;
916        case RenderTraverser::STOP_AND_WAIT:
917                tr = new StopAndWaitTraverser();
918                break;
919        case RenderTraverser::CHC:
920                tr = new CHCTraverser();
921                break;
922        case RenderTraverser::CHCPLUSPLUS:
923                tr = new CHCPlusPlusTraverser();
924                break;
925        case RenderTraverser::CULL_COLLECTOR:
926                tr = new PvsCollectionRenderer();
927                break;
928        default:
929                tr = new FrustumCullingTraverser();
930        }
931
932        tr->SetCamera(cam);
933        tr->SetHierarchy(bvh);
934        tr->SetRenderQueue(renderQueue);
935        tr->SetRenderState(&renderState);
936        tr->SetUseOptimization(useOptimization);
937        tr->SetUseRenderQueue(useRenderQueue);
938        tr->SetVisibilityThreshold(threshold);
939        tr->SetAssumedVisibleFrames(assumedVisibleFrames);
940        tr->SetMaxBatchSize(maxBatchSize);
941        tr->SetUseMultiQueries(useMultiQueries);
942        tr->SetUseTightBounds(useTightBounds);
943        tr->SetUseDepthPass((renderMethod == RENDER_DEPTH_PASS) || (renderMethod == RENDER_DEPTH_PASS_DEFERRED));
944        tr->SetRenderQueue(renderQueue);
945        tr->SetShowBounds(showBoundingVolumes);
946
947        bvh->ResetNodeClassifications();
948
949
950        return tr;
951}
952
953/** Setup sunlight
954*/
955void SetupLighting()
956{
957        glEnable(GL_LIGHT0);
958        glDisable(GL_LIGHT1);
959       
960        Vector3 lightDir = -light->GetDirection();
961
962
963        ///////////
964        //-- first light: sunlight
965
966        GLfloat ambient[] = {0.25f, 0.25f, 0.3f, 1.0f};
967        GLfloat diffuse[] = {1.0f, 0.95f, 0.85f, 1.0f};
968        GLfloat specular[] = {1.0f, 1.0f, 1.0f, 1.0f};
969       
970
971        const bool useHDRValues =
972                ((renderMethod == RENDER_DEPTH_PASS_DEFERRED) ||
973                 (renderMethod == RENDER_DEFERRED)) && useHDR;
974
975
976        Vector3 sunAmbient;
977        Vector3 sunDiffuse;
978
979        if (useSkylightForIllum)
980        {
981                preetham->ComputeSunColor(lightDir, sunAmbient, sunDiffuse, !useHDRValues);
982
983                ambient[0] = sunAmbient.x;
984                ambient[1] = sunAmbient.y;
985                ambient[2] = sunAmbient.z;
986
987                diffuse[0] = sunDiffuse.x;
988                diffuse[1] = sunDiffuse.y;
989                diffuse[2] = sunDiffuse.z;
990        }
991        else
992        {
993
994                ambient[0] = .2f;
995                ambient[1] = .2f;
996                ambient[2] = .2f;
997
998                diffuse[0] = 1.0f;
999                diffuse[1] = 1.0f;
1000                diffuse[2] = 1.0f;
1001        }
1002
1003        glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
1004        glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
1005        glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
1006
1007        GLfloat position[] = {lightDir.x, lightDir.y, lightDir.z, 0.0f};
1008        glLightfv(GL_LIGHT0, GL_POSITION, position);
1009}
1010
1011
1012void SetupEyeView()
1013{
1014        // store matrix of last frame
1015        oldViewProjMat = viewProjMat;
1016
1017        camera->SetupViewProjection();
1018
1019
1020        /////////////////
1021        //-- compute view projection matrix and store for later use
1022
1023        Matrix4x4 matViewing, matProjection;
1024
1025        camera->GetModelViewMatrix(matViewing);
1026        camera->GetProjectionMatrix(matProjection);
1027
1028        viewProjMat = matViewing * matProjection;
1029}
1030
1031
1032void KeyHorizontalMotion(float shift)
1033{
1034        Vector3 hvec = -camera->GetDirection();
1035        hvec.z = 0;
1036
1037        Vector3 pos = camera->GetPosition();
1038        pos += hvec * shift;
1039       
1040        camera->SetPosition(pos);
1041}
1042
1043
1044void KeyVerticalMotion(float shift)
1045{
1046        Vector3 uvec = Vector3(0, 0, shift);
1047
1048        Vector3 pos = camera->GetPosition();
1049        pos += uvec;
1050       
1051        camera->SetPosition(pos);
1052}
1053
1054
1055void KeyStrafe(float shift)
1056{
1057        Vector3 viewDir = camera->GetDirection();
1058        Vector3 pos = camera->GetPosition();
1059
1060        // the 90 degree rotated view vector
1061        // z zero so we don't move in the vertical
1062        Vector3 rVec(viewDir[0], viewDir[1], 0);
1063
1064        Matrix4x4 rot = RotationZMatrix(M_PI * 0.5f);
1065        rVec = rot * rVec;
1066        pos += rVec * shift;
1067
1068        camera->SetPosition(pos);
1069}
1070
1071
1072/** Initialize the deferred rendering pass.
1073*/
1074void InitDeferredRendering()
1075{
1076        if (!fbo) InitFBO();
1077        fbo->Bind();
1078
1079        // multisampling does not work with deferred shading
1080        glDisable(GL_MULTISAMPLE_ARB);
1081        renderState.SetRenderTechnique(DEFERRED);
1082
1083
1084        // draw to 3 render targets
1085        if (sCurrentMrtSet == 0)
1086        {
1087                DeferredRenderer::colorBufferIdx = 0;
1088                glDrawBuffers(3, mrt);
1089        }
1090        else
1091        {
1092                DeferredRenderer::colorBufferIdx = 3;
1093                glDrawBuffers(3, mrt2);
1094        }
1095
1096        sCurrentMrtSet = 1 - sCurrentMrtSet;
1097}
1098
1099
1100/** the main rendering loop
1101*/
1102void MainLoop()
1103{       
1104        if (buddha)
1105        {
1106                Matrix4x4 oldTrafo = buddha->GetTransform()->GetMatrix();
1107                Vector3 buddhaPos = motionPath->GetCurrentPosition();
1108                Matrix4x4 trafo = TranslationMatrix(buddhaPos);
1109
1110                buddha->GetTransform()->SetMatrix(trafo);
1111
1112#if TODO // drop objects on ground floor
1113                for (int i = 0; i < 10; ++ i)
1114                {
1115                        SceneEntity *ent = dynamicObjects[i];
1116                        Vector3 newPos = ent->GetWorldCenter();
1117
1118                        if (GetOrCreateSceneQuery()->CalcIntersection(newPos))
1119                        {
1120                                Matrix4x4 mat = TranslationMatrix(newPos - ent->GetCenter());
1121                                ent->GetTransform()->SetMatrix(mat);
1122                        }
1123                }
1124#endif
1125
1126/*
1127                /////////////////////////
1128                //-- update animations
1129
1130                //const float rotAngle = M_PI * 1e-3f;
1131                const float rotAngle = 1.0f * M_PI / 180.0f;
1132
1133                Matrix4x4 rotMatrix = RotationZMatrix(rotAngle);
1134                dynamicObjects[2]->GetTransform()->MultMatrix(rotMatrix);
1135
1136                motionPath->Move(0.01f);
1137                */
1138        }
1139
1140
1141        /////////////
1142
1143        static Vector3 oldPos = camera->GetPosition();
1144        static Vector3 oldDir = camera->GetDirection();
1145
1146        if (leftKeyPressed)
1147                camera->Pitch(KeyRotationAngle());
1148        if (rightKeyPressed)
1149                camera->Pitch(-KeyRotationAngle());
1150        if (upKeyPressed)
1151                KeyHorizontalMotion(-KeyShift());
1152        if (downKeyPressed)
1153                KeyHorizontalMotion(KeyShift());
1154        if (ascendKeyPressed)
1155                KeyVerticalMotion(KeyShift());
1156        if (descendKeyPressed)
1157                KeyVerticalMotion(-KeyShift());
1158        if (leftStrafeKeyPressed)
1159                KeyStrafe(KeyShift());
1160        if (rightStrafeKeyPressed)
1161                KeyStrafe(-KeyShift());
1162
1163
1164        // place view on ground
1165        if (!flyMode) PlaceViewer(oldPos);
1166
1167        if (showAlgorithmTime)
1168        {
1169                glFinish();
1170                algTimer.Start();
1171        }
1172       
1173        // don't allow replay on record
1174        if (replayPath && !recordPath)
1175        {
1176                if (!walkThroughPlayer)
1177                        walkThroughPlayer = new WalkThroughPlayer(walkThroughSuffix + ".log");
1178               
1179                ++ currentReplayFrame;
1180
1181                // reset if end of walkthrough is reached
1182                if (!walkThroughPlayer->ReadNextFrame(camera))
1183                {
1184                        currentReplayFrame = -1;
1185                        replayPath = false;
1186                }
1187        }
1188
1189        if ((!shadowMap || !shadowTraverser) && (showShadowMap || renderLightView))
1190        {
1191                if (!shadowMap)
1192                        shadowMap = new ShadowMap(light, shadowSize, bvh->GetBox(), camera);
1193
1194                if (!shadowTraverser)
1195                        shadowTraverser = CreateTraverser(shadowMap->GetShadowCamera());
1196
1197        }
1198       
1199        // bring eye modelview matrix up-to-date
1200        SetupEyeView();
1201       
1202        // set frame related parameters for GPU programs
1203        GPUProgramParameters::InitFrame(camera, light);
1204
1205        if (recordPath)
1206        {
1207                if (!walkThroughRecorder)
1208                        walkThroughRecorder = new WalkThroughRecorder(walkThroughSuffix + ".log");
1209               
1210                if ((Distance(oldPos, camera->GetPosition()) > 1e-6f) ||
1211                        (DotProd(oldDir, camera->GetDirection()) < 1.0f - 1e-6f))
1212                {
1213                        walkThroughRecorder->WriteFrame(camera);
1214                }
1215        }
1216
1217        // hack: store current rendering method and restore later
1218        int oldRenderMethod = renderMethod;
1219        // for rendering the light view, we use forward rendering
1220        if (renderLightView) renderMethod = FORWARD;
1221
1222        /// enable vbo vertex array
1223        glEnableClientState(GL_VERTEX_ARRAY);
1224
1225        if (1 && usePvs)
1226        {
1227                if (!viewCellsTree)     LoadVisibilitySolution();
1228
1229                if (viewCellsTree) LoadPvs();
1230        }
1231
1232        // render with the specified method (forward rendering, forward + depth, deferred)
1233        switch (renderMethod)
1234        {
1235        case RENDER_FORWARD:
1236       
1237                glEnable(GL_MULTISAMPLE_ARB);
1238                renderState.SetRenderTechnique(FORWARD);
1239               
1240                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1241                glEnableClientState(GL_NORMAL_ARRAY);
1242                break;
1243
1244        case RENDER_DEPTH_PASS_DEFERRED:
1245
1246                glDisable(GL_MULTISAMPLE_ARB);
1247                renderState.SetUseAlphaToCoverage(false);
1248                renderState.SetRenderTechnique(DEPTH_PASS);
1249
1250                if (!fbo) InitFBO();
1251                fbo->Bind();
1252                // render to single depth texture
1253                glDrawBuffers(1, mrt);
1254                // clear buffer once
1255                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1256
1257                // the scene is rendered withouth any shading
1258                // (should be handled by render renderState)
1259                glShadeModel(GL_FLAT);
1260                break;
1261
1262        case RENDER_DEPTH_PASS:
1263
1264                glEnable(GL_MULTISAMPLE_ARB);
1265                renderState.SetRenderTechnique(DEPTH_PASS);
1266
1267                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1268
1269                // the scene is rendered withouth any shading
1270                // (should be handled by render renderState)
1271                glShadeModel(GL_FLAT);
1272                break;
1273       
1274        case RENDER_DEFERRED:
1275
1276                if (showShadowMap && !renderLightView)
1277                        RenderShadowMap(camera->GetFar());
1278
1279                //glPushAttrib(GL_VIEWPORT_BIT);
1280                glViewport(0, 0, texWidth, texHeight);
1281
1282                InitDeferredRendering();
1283               
1284                glEnableClientState(GL_NORMAL_ARRAY);
1285                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1286                break;
1287        }
1288
1289        glDepthFunc(GL_LESS);
1290        glDisable(GL_TEXTURE_2D);
1291        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1292               
1293
1294        // set proper lod levels for current frame using current eye point
1295        LODLevel::InitFrame(camera->GetPosition());
1296        // set up sunlight
1297        SetupLighting();
1298
1299
1300        if (renderLightView)
1301        {
1302                // change CHC++ set of renderState variables:
1303                // must be done for each change of camera because otherwise
1304                // the temporal coherency is broken
1305                BvhNode::SetCurrentState(LIGHT_PASS);
1306                shadowMap->RenderShadowView(shadowTraverser, viewProjMat);
1307                BvhNode::SetCurrentState(CAMERA_PASS);
1308        }
1309        else
1310        {
1311                if (traverser->GetType() == RenderTraverser::CULL_COLLECTOR)
1312                        ((PvsCollectionRenderer *)traverser)->SetViewCell(usePvs ? viewCell : NULL);
1313
1314                //for (size_t i = 0; i < staticObjects.size(); ++ i)
1315                //      staticObjects[i]->Render(&renderState);
1316               
1317                // actually render the scene geometry using the specified algorithm
1318                traverser->RenderScene();
1319        }
1320
1321
1322        /////////
1323        //-- do the rest of the rendering
1324       
1325        // return from depth pass and render visible objects
1326        if ((renderMethod == RENDER_DEPTH_PASS) ||
1327                (renderMethod == RENDER_DEPTH_PASS_DEFERRED))
1328        {
1329                RenderVisibleObjects();
1330        }
1331
1332        const bool useDeferred =
1333                ((renderMethod == RENDER_DEFERRED) || (renderMethod == RENDER_DEPTH_PASS_DEFERRED));
1334
1335        // if no lense flare => just set sun to invisible
1336        const int sunVisiblePixels = useLenseFlare  &&  useDeferred ? TestSunVisible() : 0;
1337
1338       
1339
1340        ///////////////
1341        //-- render sky
1342
1343        // q: should we render sky after deferred shading?
1344        // this would conveniently solves some issues (e.g, skys without shadows)
1345
1346        RenderSky();
1347
1348
1349        //////////////////////////////
1350
1351        if (useDeferred)
1352        {
1353                FrameBufferObject::Release();
1354
1355                if (!deferredShader)
1356                {
1357                        deferredShader =
1358                                new DeferredRenderer(texWidth, texHeight, camera, ssaoUseFullResolution);
1359
1360                        deferredShader->SetKernelRadius(ssaoKernelRadius);
1361                        deferredShader->SetSampleIntensity(ssaoSampleIntensity);
1362                        deferredShader->SetSsaoFilterRadius(ssaoFilterRadius);
1363                }
1364
1365                DeferredRenderer::SHADING_METHOD shadingMethod;
1366
1367                if (useAdvancedShading)
1368                {
1369                        if (useGlobIllum)
1370                                shadingMethod = DeferredRenderer::GI;
1371                        else
1372                                shadingMethod = DeferredRenderer::SSAO;
1373                }
1374                else
1375                {
1376                        shadingMethod = DeferredRenderer::DEFAULT;
1377                }
1378
1379                static int snapShotIdx = 0;
1380
1381                deferredShader->SetSunVisiblePixels(sunVisiblePixels);
1382                deferredShader->SetShadingMethod(shadingMethod);
1383                deferredShader->SetSamplingMethod(samplingMethod);
1384               
1385                deferredShader->SetUseTemporalCoherence(useTemporalCoherence);
1386                //deferredShader->SetSortSamples(sortSamples);
1387                deferredShader->SetTemporalCoherenceFactorForSsao(ssaoTempCohFactor);
1388                deferredShader->SetUseToneMapping(useHDR);
1389                deferredShader->SetUseAntiAliasing(useAntiAliasing);
1390
1391
1392                if (recordFrames && replayPath)
1393                {
1394                        // record all frames of the walkthrough
1395                        deferredShader->SetSaveFrame(recordedFramesSuffix, currentReplayFrame);
1396                }
1397                else if (makeSnapShot)
1398                {
1399                        // make snap shot
1400                        deferredShader->SetSaveFrame("snap", snapShotIdx ++);
1401                }
1402                else
1403                {
1404                        // do nothing
1405                        deferredShader->SetSaveFrame("", -1);           
1406                }
1407               
1408                if (makeSnapShot) makeSnapShot = false;
1409
1410                ShadowMap *sm = showShadowMap ? shadowMap : NULL;
1411                deferredShader->Render(fbo, light, sm);
1412        }
1413
1414
1415        renderState.SetRenderTechnique(FORWARD);
1416        renderState.Reset();
1417
1418        glDisableClientState(GL_VERTEX_ARRAY);
1419        glDisableClientState(GL_NORMAL_ARRAY);
1420       
1421        renderMethod = oldRenderMethod;
1422
1423
1424        ///////////
1425
1426
1427        if (showAlgorithmTime)
1428        {
1429                glFinish();
1430
1431                algTime = algTimer.Elapsedms();
1432                perfGraph->AddData(algTime);
1433
1434                perfGraph->Draw();
1435        }
1436        else
1437        {
1438                if (visMode) DisplayVisualization();
1439        }
1440
1441        glFlush();
1442
1443        const bool restart = true;
1444        elapsedTime = frameTimer.Elapsedms(restart);
1445
1446        // statistics
1447        DisplayStats();
1448
1449        glutSwapBuffers();
1450
1451        oldPos = camera->GetPosition();
1452        oldDir = camera->GetDirection();
1453}
1454
1455
1456#pragma warning(disable : 4100)
1457void KeyBoard(unsigned char c, int x, int y)
1458{
1459        switch(c)
1460        {
1461        case 27:
1462                // write out current position on exit
1463                Debug << "camPosition=" << camera->GetPosition().x << " " << camera->GetPosition().y << " " << camera->GetPosition().z << endl;
1464                Debug << "camDirection=" << camera->GetDirection().x << " " << camera->GetDirection().y << " " << camera->GetDirection().z << endl;
1465
1466                CleanUp();
1467                exit(0);
1468        case 32: // space
1469                renderMode = (renderMode + 1) % RenderTraverser::NUM_TRAVERSAL_TYPES;
1470                //renderMode = (renderMode + 1) % 4;
1471
1472                DEL_PTR(traverser);
1473                traverser = CreateTraverser(camera);
1474
1475                if (shadowTraverser)
1476                {
1477                        // shadow traverser has to be recomputed
1478                        DEL_PTR(shadowTraverser);
1479                        shadowTraverser = CreateTraverser(shadowMap->GetShadowCamera());
1480                }
1481
1482                break;
1483        case '+':
1484                if (maxBatchSize < 10)
1485                        maxBatchSize = 10;
1486                else
1487                        maxBatchSize += 10;
1488
1489                traverser->SetMaxBatchSize(maxBatchSize);
1490                break;
1491        case '-':
1492                maxBatchSize -= 10;
1493                if (maxBatchSize < 0) maxBatchSize = 1;
1494                traverser->SetMaxBatchSize(maxBatchSize);               
1495                break;
1496        case 'M':
1497        case 'm':
1498                useMultiQueries = !useMultiQueries;
1499                traverser->SetUseMultiQueries(useMultiQueries);
1500                break;
1501        case '1':
1502                descendKeyPressed = true;
1503                break;
1504        case '2':
1505                ascendKeyPressed = true;
1506                break;
1507        case '3':
1508                if (trianglesPerVirtualLeaf >= 100) trianglesPerVirtualLeaf -= 100;
1509                bvh->SetVirtualLeaves(trianglesPerVirtualLeaf);
1510                break;
1511        case '4':
1512                trianglesPerVirtualLeaf += 100;
1513                bvh->SetVirtualLeaves(trianglesPerVirtualLeaf);
1514                break;
1515        case '5':
1516                assumedVisibleFrames -= 1;
1517                if (assumedVisibleFrames < 1) assumedVisibleFrames = 1;
1518                traverser->SetAssumedVisibleFrames(assumedVisibleFrames);
1519                break;
1520        case '6':
1521                assumedVisibleFrames += 1;
1522                traverser->SetAssumedVisibleFrames(assumedVisibleFrames);               
1523                break;
1524        case '7':
1525                ssaoTempCohFactor *= 1.0f / 1.2f;
1526                cout << "new temporal coherence factor: " << ssaoTempCohFactor << endl;
1527                break;
1528        case '8':
1529                ssaoTempCohFactor *= 1.2f;
1530                cout << "new temporal coherence factor: " << ssaoTempCohFactor << endl;
1531                break;
1532        case '9':
1533                ssaoKernelRadius *= 0.8f;
1534                cout << "new ssao kernel radius: " << ssaoKernelRadius << endl;
1535                if (deferredShader) deferredShader->SetKernelRadius(ssaoKernelRadius);
1536                break;
1537        case '0':
1538                ssaoKernelRadius *= 1.0f / 0.8f;
1539                if (deferredShader) deferredShader->SetKernelRadius(ssaoKernelRadius);
1540                cout << "new ssao kernel radius: " << ssaoKernelRadius << endl;
1541                break;
1542        case 'n':
1543                ssaoSampleIntensity *= 0.9f;
1544                if (deferredShader) deferredShader->SetSampleIntensity(ssaoSampleIntensity);
1545                cout << "new ssao sample intensity: " << ssaoSampleIntensity << endl;
1546                break;
1547        case 'N':
1548                ssaoSampleIntensity *= 1.0f / 0.9f;
1549                if (deferredShader) deferredShader->SetSampleIntensity(ssaoSampleIntensity);
1550                cout << "new ssao sample intensity: " << ssaoSampleIntensity << endl;
1551                break;
1552        case 'o':
1553                ssaoFilterRadius *= 0.9f;
1554                if (deferredShader) deferredShader->SetSsaoFilterRadius(ssaoFilterRadius);
1555                cout << "new ssao filter radius: " << ssaoFilterRadius << endl;
1556                break;
1557        case 'O':
1558                ssaoFilterRadius *= 1.0f / 0.9f;
1559                if (deferredShader) deferredShader->SetSsaoFilterRadius(ssaoFilterRadius);
1560                cout << "new ssao filter radius: " << ssaoFilterRadius << endl;
1561                break;
1562        /*      case 'o':
1563        case 'O':
1564                useOptimization = !useOptimization;
1565                // chc optimization of using the objects instead of
1566                // the bounding boxes for querying previously visible nodes
1567                traverser->SetUseOptimization(useOptimization);
1568                break;*/
1569        case 'l':
1570        case 'L':
1571                useLODs = !useLODs;
1572                SceneEntity::SetUseLODs(useLODs);
1573                cout << "using LODs: " << useLODs << endl;
1574                break;
1575        case 'P':
1576        case 'p':
1577                samplingMethod = DeferredRenderer::SAMPLING_METHOD((samplingMethod + 1) % 3);
1578                cout << "ssao sampling method: " << samplingMethod << endl;
1579                break;
1580        case 'Y':
1581        case 'y':
1582                showShadowMap = !showShadowMap;
1583                break;
1584        case 'g':
1585        case 'G':
1586                useGlobIllum = !useGlobIllum;
1587                break;
1588        case 't':
1589        case 'T':
1590                useTemporalCoherence = !useTemporalCoherence;
1591                break;
1592        case 'a':
1593        case 'A':
1594                leftKeyPressed = true;
1595                break;
1596        case 'd':
1597        case 'D':
1598                rightKeyPressed = true;
1599                break;
1600        case 'w':
1601        case 'W':
1602                upKeyPressed = true;
1603                break;
1604        case 's':
1605        case 'S':
1606                downKeyPressed = true;
1607                break;
1608        case 'j':
1609        case 'J':
1610                leftStrafeKeyPressed = true;
1611                break;
1612        case 'k':
1613        case 'K':
1614                rightStrafeKeyPressed = true;
1615                break;
1616        case 'r':
1617        case 'R':
1618                useRenderQueue = !useRenderQueue;
1619                traverser->SetUseRenderQueue(useRenderQueue);
1620                break;
1621        case 'b':
1622        case 'B':
1623                useTightBounds = !useTightBounds;
1624                traverser->SetUseTightBounds(useTightBounds);
1625                break;
1626        case 'v':
1627        case 'V':
1628                renderLightView = !renderLightView;
1629                break;
1630        case 'h':
1631        case 'H':
1632                useHDR = !useHDR;
1633                break;
1634        case 'i':
1635        case 'I':
1636                useAntiAliasing = !useAntiAliasing;
1637                break;
1638        case 'c':
1639        case 'C':
1640                useLenseFlare = !useLenseFlare;
1641                break;
1642        case 'u':
1643        case 'U':
1644                // move light source instead of camera tilt
1645                moveLight = !moveLight;
1646                break;
1647        case '#':
1648                // make a snapshot of the current frame
1649                makeSnapShot = true;
1650                break;
1651        case '.':
1652                // enable / disable view cells
1653                usePvs = !usePvs;
1654                if (!usePvs) SceneEntity::SetCurrentVisibleId(-1);
1655                break;
1656        case ',':
1657                // show / hide FPS
1658                showFPS = !showFPS;
1659                break;
1660       
1661        default:
1662                return;
1663        }
1664
1665        glutPostRedisplay();
1666}
1667
1668
1669void SpecialKeyUp(int c, int x, int y)
1670{
1671        switch (c)
1672        {
1673        case GLUT_KEY_LEFT:
1674                leftKeyPressed = false;
1675                break;
1676        case GLUT_KEY_RIGHT:
1677                rightKeyPressed = false;
1678                break;
1679        case GLUT_KEY_UP:
1680                upKeyPressed = false;
1681                break;
1682        case GLUT_KEY_DOWN:
1683                downKeyPressed = false;
1684                break;
1685        case GLUT_ACTIVE_ALT:
1686                altKeyPressed = false;
1687                break;
1688        default:
1689                return;
1690        }
1691}
1692
1693
1694void KeyUp(unsigned char c, int x, int y)
1695{
1696        switch (c)
1697        {
1698
1699        case 'A':
1700        case 'a':
1701                leftKeyPressed = false;
1702                break;
1703        case 'D':
1704        case 'd':
1705                rightKeyPressed = false;
1706                break;
1707        case 'W':
1708        case 'w':
1709                upKeyPressed = false;
1710                break;
1711        case 'S':
1712        case 's':
1713                downKeyPressed = false;
1714                break;
1715        case '1':
1716                descendKeyPressed = false;
1717                break;
1718        case '2':
1719                ascendKeyPressed = false;
1720                break;
1721        case 'j':
1722        case 'J':
1723                leftStrafeKeyPressed = false;
1724                break;
1725        case 'k':
1726        case 'K':
1727                rightStrafeKeyPressed = false;
1728                break;
1729        default:
1730                return;
1731        }
1732        //glutPostRedisplay();
1733}
1734
1735
1736void Special(int c, int x, int y)
1737{
1738        switch(c)
1739        {
1740        case GLUT_KEY_F1:
1741                showHelp = !showHelp;
1742                break;
1743        case GLUT_KEY_F2:
1744                visMode = !visMode;
1745                break;
1746        case GLUT_KEY_F3:
1747                showBoundingVolumes = !showBoundingVolumes;
1748                traverser->SetShowBounds(showBoundingVolumes);
1749                break;
1750        case GLUT_KEY_F4:
1751                showOptions = !showOptions;
1752                break;
1753        case GLUT_KEY_F5:
1754                showStatistics = !showStatistics;
1755                break;
1756        case GLUT_KEY_F6:
1757                flyMode = !flyMode;
1758                break;
1759        case GLUT_KEY_F7:
1760
1761                renderMethod = (renderMethod + 1) % 4;
1762
1763                traverser->SetUseDepthPass(
1764                        (renderMethod == RENDER_DEPTH_PASS) ||
1765                        (renderMethod == RENDER_DEPTH_PASS_DEFERRED)
1766                        );
1767               
1768                break;
1769        case GLUT_KEY_F8:
1770                useAdvancedShading = !useAdvancedShading;
1771                break;
1772        case GLUT_KEY_F9:
1773                showAlgorithmTime = !showAlgorithmTime;
1774                break;
1775        case GLUT_KEY_F10:
1776                replayPath = !replayPath;
1777
1778                if (replayPath)
1779                {
1780                        cout << "replaying path" << endl;
1781                        currentReplayFrame = -1;
1782                }
1783                else
1784                {
1785                        cout << "finished replaying path" << endl;
1786                }
1787
1788                break;
1789        case GLUT_KEY_F11:
1790                recordPath = !recordPath;
1791               
1792                if (recordPath)
1793                {
1794                        cout << "recording path" << endl;
1795                }
1796                else
1797                {
1798                        cout << "finished recording path" << endl;
1799                        // start over with new frame recording next time
1800                        DEL_PTR(walkThroughRecorder);
1801                }
1802
1803                break;
1804        case GLUT_KEY_F12:
1805                recordFrames = !recordFrames;
1806
1807                if (recordFrames)
1808                        cout << "recording frames on replaying" << endl;
1809                else
1810                        cout << "finished recording frames on replaying" << endl;
1811                break;
1812        case GLUT_KEY_LEFT:
1813                {
1814                        leftKeyPressed = true;
1815                        camera->Pitch(KeyRotationAngle());
1816                }
1817                break;
1818        case GLUT_KEY_RIGHT:
1819                {
1820                        rightKeyPressed = true;
1821                        camera->Pitch(-KeyRotationAngle());
1822                }
1823                break;
1824        case GLUT_KEY_UP:
1825                {
1826                        upKeyPressed = true;
1827                        KeyHorizontalMotion(KeyShift());
1828                }
1829                break;
1830        case GLUT_KEY_DOWN:
1831                {
1832                        downKeyPressed = true;
1833                        KeyHorizontalMotion(-KeyShift());
1834                }
1835                break;
1836        default:
1837                return;
1838
1839        }
1840
1841        glutPostRedisplay();
1842}
1843
1844#pragma warning( default : 4100 )
1845
1846
1847void Reshape(int w, int h)
1848{
1849        winAspectRatio = 1.0f;
1850
1851        glViewport(0, 0, w, h);
1852       
1853        winWidth = w;
1854        winHeight = h;
1855
1856        if (w) winAspectRatio = (float) w / (float) h;
1857
1858        glMatrixMode(GL_PROJECTION);
1859        glLoadIdentity();
1860
1861        gluPerspective(fov, winAspectRatio, nearDist, farDist);
1862
1863        glMatrixMode(GL_MODELVIEW);
1864
1865        glutPostRedisplay();
1866}
1867
1868
1869void Mouse(int button, int renderState, int x, int y)
1870{
1871        if ((button == GLUT_LEFT_BUTTON) && (renderState == GLUT_DOWN))
1872        {
1873                xEyeBegin = x;
1874                yMotionBegin = y;
1875
1876                glutMotionFunc(LeftMotion);
1877        }
1878        else if ((button == GLUT_RIGHT_BUTTON) && (renderState == GLUT_DOWN))
1879        {
1880                xEyeBegin = x;
1881                yEyeBegin = y;
1882                yMotionBegin = y;
1883
1884                if (!moveLight)
1885                        glutMotionFunc(RightMotion);
1886                else
1887                        glutMotionFunc(RightMotionLight);
1888        }
1889        else if ((button == GLUT_MIDDLE_BUTTON) && (renderState == GLUT_DOWN))
1890        {
1891                horizontalMotionBegin = x;
1892                verticalMotionBegin = y;
1893                glutMotionFunc(MiddleMotion);
1894        }
1895
1896        glutPostRedisplay();
1897}
1898
1899
1900/**     rotation for left/right mouse drag
1901        motion for up/down mouse drag
1902*/
1903void LeftMotion(int x, int y)
1904{
1905        Vector3 viewDir = camera->GetDirection();
1906        Vector3 pos = camera->GetPosition();
1907
1908        // don't move in the vertical direction
1909        Vector3 horView(viewDir[0], viewDir[1], 0);
1910       
1911        float eyeXAngle = 0.2f *  M_PI * (xEyeBegin - x) / 180.0;
1912
1913        camera->Pitch(eyeXAngle);
1914
1915        pos += horView * (yMotionBegin - y) * mouseMotion;
1916       
1917        camera->SetPosition(pos);
1918       
1919        xEyeBegin = x;
1920        yMotionBegin = y;
1921
1922        glutPostRedisplay();
1923}
1924
1925
1926void RightMotionLight(int x, int y)
1927{
1928        float theta = 0.2f * M_PI * (xEyeBegin - x) / 180.0f;
1929        float phi = 0.2f * M_PI * (yMotionBegin - y) / 180.0f;
1930       
1931        Vector3 lightDir = light->GetDirection();
1932
1933        Matrix4x4 roty = RotationYMatrix(theta);
1934        Matrix4x4 rotx = RotationXMatrix(phi);
1935
1936        lightDir = roty * lightDir;
1937        lightDir = rotx * lightDir;
1938
1939        // normalize to avoid accumulating errors
1940        lightDir.Normalize();
1941
1942        light->SetDirection(lightDir);
1943
1944        xEyeBegin = x;
1945        yMotionBegin = y;
1946
1947        glutPostRedisplay();
1948}
1949
1950
1951/**     rotation for left / right mouse drag
1952        motion for up / down mouse drag
1953*/
1954void RightMotion(int x, int y)
1955{
1956        float eyeXAngle = 0.2f *  M_PI * (xEyeBegin - x) / 180.0;
1957        float eyeYAngle = -0.2f *  M_PI * (yEyeBegin - y) / 180.0;
1958
1959        camera->Yaw(eyeYAngle);
1960        camera->Pitch(eyeXAngle);
1961
1962        xEyeBegin = x;
1963        yEyeBegin = y;
1964
1965        glutPostRedisplay();
1966}
1967
1968
1969/** strafe
1970*/
1971void MiddleMotion(int x, int y)
1972{
1973        Vector3 viewDir = camera->GetDirection();
1974        Vector3 pos = camera->GetPosition();
1975
1976        // the 90 degree rotated view vector
1977        // y zero so we don't move in the vertical
1978        Vector3 rVec(viewDir[0], viewDir[1], 0);
1979       
1980        Matrix4x4 rot = RotationZMatrix(M_PI * 0.5f);
1981        rVec = rot * rVec;
1982       
1983        pos -= rVec * (x - horizontalMotionBegin) * mouseMotion;
1984        pos[2] += (verticalMotionBegin - y) * mouseMotion;
1985
1986        camera->SetPosition(pos);
1987
1988        horizontalMotionBegin = x;
1989        verticalMotionBegin = y;
1990
1991        glutPostRedisplay();
1992}
1993
1994
1995void InitExtensions(void)
1996{
1997        GLenum err = glewInit();
1998
1999        if (GLEW_OK != err)
2000        {
2001                // problem: glewInit failed, something is seriously wrong
2002                fprintf(stderr,"Error: %s\n", glewGetErrorString(err));
2003                exit(1);
2004        }
2005        if  (!GLEW_ARB_occlusion_query)
2006        {
2007                printf("I require the GL_ARB_occlusion_query to work.\n");
2008                exit(1);
2009        }
2010}
2011
2012
2013void Begin2D()
2014{
2015        glDisable(GL_LIGHTING);
2016        glDisable(GL_DEPTH_TEST);
2017
2018        glMatrixMode(GL_PROJECTION);
2019        glPushMatrix();
2020        glLoadIdentity();
2021
2022        gluOrtho2D(0, winWidth, 0, winHeight);
2023
2024        glMatrixMode(GL_MODELVIEW);
2025        glPushMatrix();
2026        glLoadIdentity();
2027}
2028
2029
2030void End2D()
2031{
2032        glMatrixMode(GL_PROJECTION);
2033        glPopMatrix();
2034
2035        glMatrixMode(GL_MODELVIEW);
2036        glPopMatrix();
2037
2038        glEnable(GL_LIGHTING);
2039        glEnable(GL_DEPTH_TEST);
2040}
2041
2042
2043// displays the visualisation of culling algorithm
2044void DisplayVisualization()
2045{
2046        // render current view cell
2047        if (usePvs) RenderViewCell();
2048       
2049        visualization->SetViewCell(usePvs ? viewCell : NULL);
2050        visualization->SetFrameId(traverser->GetCurrentFrameId());
2051       
2052
2053        Begin2D();
2054        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2055        glEnable(GL_BLEND);
2056        glColor4f(0.0f ,0.0f, 0.0f, 0.5f);
2057
2058        glRecti(winWidth - winWidth / 3, winHeight - winHeight / 3, winWidth, winHeight);
2059        glDisable(GL_BLEND);
2060        End2D();
2061       
2062       
2063        AxisAlignedBox3 box = bvh->GetBox();
2064
2065        const float offs = box.Size().x * 0.3f;
2066       
2067        Vector3 vizpos = Vector3(box.Min().x, box.Min().y  - box.Size().y * 0.35f, box.Min().z + box.Size().z * 50);
2068       
2069        visCamera->SetPosition(vizpos);
2070        visCamera->ResetPitchAndYaw();
2071       
2072        glPushAttrib(GL_VIEWPORT_BIT);
2073        glViewport(winWidth - winWidth / 3, winHeight - winHeight / 3, winWidth / 3, winHeight / 3);
2074
2075        glMatrixMode(GL_PROJECTION);
2076        glPushMatrix();
2077
2078        glLoadIdentity();
2079        glOrtho(-offs, offs, -offs, offs, 0.0f, box.Size().z * 100.0f);
2080
2081        glMatrixMode(GL_MODELVIEW);
2082        glPushMatrix();
2083
2084        visCamera->SetupCameraView();
2085
2086        Matrix4x4 rotZ = RotationZMatrix(-camera->GetPitch());
2087        glMultMatrixf((float *)rotZ.x);
2088
2089        // inverse translation in order to fix current position
2090        Vector3 pos = camera->GetPosition();
2091        glTranslatef(-pos.x, -pos.y, -pos.z);
2092
2093
2094        GLfloat position[] = {0.8f, 1.0f, 1.5f, 0.0f};
2095        glLightfv(GL_LIGHT0, GL_POSITION, position);
2096
2097        GLfloat position1[] = {bvh->GetBox().Center().x, bvh->GetBox().Max().y, bvh->GetBox().Center().z, 1.0f};
2098        glLightfv(GL_LIGHT1, GL_POSITION, position1);
2099
2100        glClear(GL_DEPTH_BUFFER_BIT);
2101
2102
2103        ////////////
2104        //-- visualization of the occlusion culling
2105
2106        visualization->Render(showShadowMap);
2107
2108       
2109        // reset previous settings
2110        glPopAttrib();
2111
2112        glMatrixMode(GL_PROJECTION);
2113        glPopMatrix();
2114        glMatrixMode(GL_MODELVIEW);
2115        glPopMatrix();
2116}
2117
2118
2119// cleanup routine after the main loop
2120void CleanUp()
2121{
2122        DEL_PTR(traverser);
2123        DEL_PTR(sceneQuery);
2124        DEL_PTR(bvh);
2125        DEL_PTR(visualization);
2126        DEL_PTR(camera);
2127        DEL_PTR(renderQueue);
2128        DEL_PTR(perfGraph);
2129        DEL_PTR(fbo);
2130        DEL_PTR(deferredShader);
2131        DEL_PTR(light);
2132        DEL_PTR(visCamera);
2133        DEL_PTR(preetham);
2134        DEL_PTR(shadowMap);
2135        DEL_PTR(shadowTraverser);
2136        DEL_PTR(motionPath);
2137        DEL_PTR(walkThroughRecorder);
2138        DEL_PTR(walkThroughPlayer);
2139        DEL_PTR(statsWriter);
2140        DEL_PTR(viewCellsTree);
2141
2142        ResourceManager::DelSingleton();
2143        ShaderManager::DelSingleton();
2144
2145        resourceManager = NULL;
2146        shaderManager = NULL;
2147}
2148
2149
2150// this function inserts a dezimal point after each 1000
2151void CalcDecimalPoint(string &str, int d, int len)
2152{
2153        static vector<int> numbers;
2154        numbers.clear();
2155
2156        static string shortStr;
2157        shortStr.clear();
2158
2159        static char hstr[100];
2160
2161        while (d != 0)
2162        {
2163                numbers.push_back(d % 1000);
2164                d /= 1000;
2165        }
2166
2167        // first element without leading zeros
2168        if (numbers.size() > 0)
2169        {
2170                sprintf(hstr, "%d", numbers.back());
2171                shortStr.append(hstr);
2172        }
2173       
2174        for (int i = (int)numbers.size() - 2; i >= 0; i--)
2175        {
2176                sprintf(hstr, ",%03d", numbers[i]);
2177                shortStr.append(hstr);
2178        }
2179
2180        int dif = len - (int)shortStr.size();
2181
2182        for (int i = 0; i < dif; ++ i)
2183        {
2184                str += " ";
2185        }
2186
2187        str.append(shortStr);
2188}
2189
2190
2191void DisplayStats()
2192{
2193        static char msg[9][300];
2194
2195        static double frameTime = elapsedTime;
2196        static double renderTime = algTime;
2197
2198        const float expFactor = 0.1f;
2199
2200        // if some strange render time spike happened in this frame => don't count
2201        if (elapsedTime < 500) frameTime = elapsedTime * expFactor + (1.0f - expFactor) * elapsedTime;
2202       
2203        static float rTime = 1000.0f;
2204
2205        // the render time used up purely for the traversal algorithm using glfinish
2206        if (showAlgorithmTime)
2207        {
2208                if (algTime < 500) renderTime = algTime * expFactor + (1.0f - expFactor) * renderTime;
2209        }
2210
2211        accumulatedTime += elapsedTime;
2212
2213        if (accumulatedTime > 500) // update every fraction of a second
2214        {       
2215                accumulatedTime = 0;
2216
2217                if (frameTime) fps = 1e3f / (float)frameTime;
2218
2219                rTime = renderTime;
2220
2221                if (renderLightView && shadowTraverser)
2222                {
2223                        renderedTriangles = shadowTraverser->GetStats().mNumRenderedTriangles;
2224                        renderedObjects = shadowTraverser->GetStats().mNumRenderedGeometry;
2225                        renderedNodes = shadowTraverser->GetStats().mNumRenderedNodes;
2226                }
2227                else if (showShadowMap && shadowTraverser)
2228                {
2229                        renderedNodes = traverser->GetStats().mNumRenderedNodes + shadowTraverser->GetStats().mNumRenderedNodes;
2230                        renderedObjects = traverser->GetStats().mNumRenderedGeometry + shadowTraverser->GetStats().mNumRenderedGeometry;
2231                        renderedTriangles = traverser->GetStats().mNumRenderedTriangles + shadowTraverser->GetStats().mNumRenderedTriangles;
2232                }
2233                else
2234                {
2235                        renderedTriangles = traverser->GetStats().mNumRenderedTriangles;
2236                        renderedObjects = traverser->GetStats().mNumRenderedGeometry;
2237                        renderedNodes = traverser->GetStats().mNumRenderedNodes;
2238                }
2239
2240                traversedNodes = traverser->GetStats().mNumTraversedNodes;
2241                frustumCulledNodes = traverser->GetStats().mNumFrustumCulledNodes;
2242                queryCulledNodes = traverser->GetStats().mNumQueryCulledNodes;
2243                issuedQueries = traverser->GetStats().mNumIssuedQueries;
2244                stateChanges = traverser->GetStats().mNumStateChanges;
2245                numBatches = traverser->GetStats().mNumBatches;
2246        }
2247
2248
2249        ////////////////
2250        //-- record stats on walkthrough
2251
2252        static float accTime = .0f;
2253        static float averageTime = .0f;
2254
2255        if (currentReplayFrame > -1)
2256        {
2257                accTime += frameTime;
2258                averageTime = accTime / (currentReplayFrame + 1);
2259
2260                if (!statsWriter)
2261                        statsWriter = new StatsWriter(statsFilename);
2262                       
2263                FrameStats frameStats;
2264                frameStats.mFrame = currentReplayFrame;
2265                frameStats.mFPS = 1e3f / (float)frameTime;
2266                frameStats.mTime = frameTime;
2267                frameStats.mNodes = renderedNodes;
2268                frameStats.mObjects = renderedObjects;
2269                frameStats.mTriangles = renderedTriangles;
2270
2271                statsWriter->WriteFrameStats(frameStats);
2272        }
2273        else if (statsWriter)
2274        {
2275                Debug << "average frame time " << averageTime << " for traversal algorithm " << renderMode << endl;
2276
2277                // reset average frame time
2278                averageTime = accTime = .0f;
2279
2280                DEL_PTR(statsWriter);
2281        }
2282
2283
2284        Begin2D();
2285
2286        glEnable(GL_BLEND);
2287        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2288
2289        if (showHelp)
2290        {       
2291                DrawHelpMessage();
2292        }
2293        else
2294        {
2295                if (showOptions)
2296                {
2297                        glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
2298                        glRecti(5, winHeight - 95, winWidth * 2 / 3 - 5, winHeight - 5);
2299                }
2300
2301                if (showStatistics)
2302                {
2303                        glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
2304                        glRecti(5, winHeight - 165, winWidth * 2 / 3 - 5, winHeight - 100);
2305                }
2306
2307                glEnable(GL_TEXTURE_2D);
2308                myfont.Begin();
2309
2310                if (showOptions)
2311                {
2312                        glColor3f(0.0f, 1.0f, 0.0f);
2313                        int i = 0;
2314
2315                        static char *renderMethodStr[] =
2316                                {"forward", "depth pass + forward", "deferred shading", "depth pass + deferred"};
2317                        sprintf(msg[i ++], "multiqueries: %d, tight bounds: %d, render queue: %d",
2318                                        useMultiQueries, useTightBounds, useRenderQueue);
2319                        sprintf(msg[i ++], "render technique: %s, use pvss: %d", renderMethodStr[renderMethod], usePvs);
2320                        sprintf(msg[i ++], "triangles per virtual leaf: %5d", trianglesPerVirtualLeaf);
2321                        sprintf(msg[i ++], "assumed visible frames: %4d, max batch size: %4d",
2322                                assumedVisibleFrames, maxBatchSize);
2323
2324                        for (int j = 0; j < 4; ++ j)
2325                                myfont.DrawString(msg[j], 10.0f, winHeight - 5 - j * 20);
2326                }
2327
2328                if (showStatistics)
2329                {
2330                        glColor3f(1.0f, 1.0f, 0.0f);
2331
2332                        string objStr, totalObjStr;
2333                        string triStr, totalTriStr;
2334
2335                        int len = 10;
2336                        CalcDecimalPoint(objStr, renderedObjects, len);
2337                        CalcDecimalPoint(totalObjStr, (int)resourceManager->GetNumEntities(), len);
2338
2339                        CalcDecimalPoint(triStr, renderedTriangles, len);
2340                        CalcDecimalPoint(totalTriStr, bvh->GetBvhStats().mTriangles, len);
2341
2342                        int i = 4;
2343
2344                        if (0) // q: show rendered objects or nodes (no space for both)
2345                        {
2346                                sprintf(msg[i ++], "rendered: %s of %s objects, %s of %s triangles",
2347                                        objStr.c_str(), totalObjStr.c_str(), triStr.c_str(), totalTriStr.c_str());
2348                        }
2349                        else
2350                        {
2351                                sprintf(msg[i ++], "rendered: %6d of %6d nodes, %s of %s triangles",
2352                                        renderedNodes, bvh->GetNumVirtualNodes(), triStr.c_str(), totalTriStr.c_str());
2353                        }
2354
2355                        sprintf(msg[i ++], "traversed: %5d, frustum culled: %5d, query culled: %5d nodes",
2356                                traversedNodes, frustumCulledNodes, queryCulledNodes);
2357                        sprintf(msg[i ++], "issued queries: %5d, state changes: %5d, render batches: %5d",
2358                                issuedQueries, stateChanges, numBatches);
2359
2360                        for (int j = 4; j < 7; ++ j)
2361                                myfont.DrawString(msg[j], 10.0f, winHeight - (j + 1) * 20);
2362                }
2363
2364                glColor3f(1.0f, 1.0f, 1.0f);
2365                static char *alg_str[] = {
2366                        "Frustum Cull"
2367                        , "Stop and Wait"
2368                        , "CHC"
2369                        , "CHC ++"
2370                        , "Collector"
2371                };
2372               
2373                if (!showAlgorithmTime)
2374                {
2375                        if (showFPS)
2376                        {                       
2377                                sprintf(msg[7], "%s:  %6.1f fps", alg_str[renderMode], fps);           
2378                                myfont.DrawString(msg[7], 1.3f, 690.0f, 760.0f);//, top_color, bottom_color);
2379                        }
2380                }
2381                else
2382                {
2383                        sprintf(msg[7], "%s:  %6.1f ms", alg_str[renderMode], rTime);
2384                        myfont.DrawString(msg[7], 1.3f, 690.0f, 760.0f);//, top_color, bottom_color);
2385                }
2386
2387               
2388                //sprintf(msg[8], "algorithm time: %6.1f ms", rTime);
2389                //myfont.DrawString(msg[8], 720.0f, 730.0f);           
2390        }
2391
2392        glDisable(GL_BLEND);
2393        glDisable(GL_TEXTURE_2D);
2394
2395        End2D();
2396}       
2397
2398
2399void RenderSky()
2400{
2401        if ((renderMethod == RENDER_DEFERRED) || (renderMethod == RENDER_DEPTH_PASS_DEFERRED))
2402                renderState.SetRenderTechnique(DEFERRED);
2403
2404        const bool useToneMapping =
2405                ((renderMethod == RENDER_DEPTH_PASS_DEFERRED) ||
2406                 (renderMethod == RENDER_DEFERRED)) && useHDR;
2407       
2408        preetham->RenderSkyDome(-light->GetDirection(), camera, &renderState, !useToneMapping);
2409
2410        /// once again reset the renderState just to make sure
2411        renderState.Reset();
2412}
2413
2414
2415// render visible object from depth pass
2416void RenderVisibleObjects()
2417{
2418        if (renderMethod == RENDER_DEPTH_PASS_DEFERRED)
2419        {
2420                if (showShadowMap && !renderLightView)
2421                {
2422                        // usethe maximal visible distance to focus shadow map
2423                        const float newFar = min(camera->GetFar(), traverser->GetMaxVisibleDistance());
2424                        RenderShadowMap(newFar);
2425                }
2426                // initialize deferred rendering
2427                InitDeferredRendering();
2428        }
2429        else
2430        {
2431                renderState.SetRenderTechnique(FORWARD);
2432        }
2433
2434
2435        /////////////////
2436        //-- reset gl renderState before the final visible objects pass
2437
2438        renderState.Reset();
2439
2440        glEnableClientState(GL_NORMAL_ARRAY);
2441        /// switch back to smooth shading
2442        glShadeModel(GL_SMOOTH);
2443        /// reset alpha to coverage flag
2444        renderState.SetUseAlphaToCoverage(true);
2445        // clear color
2446        glClear(GL_COLOR_BUFFER_BIT);
2447       
2448        // draw only objects having exactly the same depth as the current sample
2449        glDepthFunc(GL_EQUAL);
2450
2451        //cout << "visible: " << (int)traverser->GetVisibleObjects().size() << endl;
2452
2453        SceneEntityContainer::const_iterator sit,
2454                sit_end = traverser->GetVisibleObjects().end();
2455
2456        for (sit = traverser->GetVisibleObjects().begin(); sit != sit_end; ++ sit)
2457        {
2458                renderQueue->Enqueue(*sit);
2459        }
2460
2461        /// now render out everything in one giant pass
2462        renderQueue->Apply();
2463
2464        // switch back to standard depth func
2465        glDepthFunc(GL_LESS);
2466        renderState.Reset();
2467
2468        PrintGLerror("visible objects");
2469}
2470
2471
2472SceneQuery *GetOrCreateSceneQuery()
2473{
2474        if (!sceneQuery)
2475        {
2476                sceneQuery = new SceneQuery(bvh->GetBox(), traverser, &renderState);
2477        }
2478
2479        return sceneQuery;
2480}
2481
2482
2483void PlaceViewer(const Vector3 &oldPos)
2484{
2485        Vector3 playerPos = camera->GetPosition();
2486        bool validIntersect = GetOrCreateSceneQuery()->CalcIntersection(playerPos);
2487
2488        if (validIntersect)
2489                //&& ((playerPos.z - oldPos.z) < bvh->GetBox().Size(2) * 1e-1f))
2490        {
2491                camera->SetPosition(playerPos);
2492        }
2493}
2494
2495
2496void RenderShadowMap(float newfar)
2497{
2498        glDisableClientState(GL_NORMAL_ARRAY);
2499        renderState.SetRenderTechnique(DEPTH_PASS);
2500       
2501        // hack: disable cull face because of alpha textured balconies
2502        glDisable(GL_CULL_FACE);
2503        renderState.LockCullFaceEnabled(true);
2504
2505        /// don't use alpha to coverage for the depth map (problems with fbo rendering)
2506        renderState.SetUseAlphaToCoverage(false);
2507
2508        // change CHC++ set of renderState variables
2509        // this must be done for each change of camera because
2510        // otherwise the temporal coherency is broken
2511        BvhNode::SetCurrentState(LIGHT_PASS);
2512        // hack: temporarily change camera far plane
2513        camera->SetFar(newfar);
2514        // the scene is rendered withouth any shading   
2515        shadowMap->ComputeShadowMap(shadowTraverser, viewProjMat);
2516
2517        camera->SetFar(farDist);
2518
2519        renderState.SetUseAlphaToCoverage(true);
2520        renderState.LockCullFaceEnabled(false);
2521        glEnable(GL_CULL_FACE);
2522
2523        glEnableClientState(GL_NORMAL_ARRAY);
2524        // change back renderState
2525        BvhNode::SetCurrentState(CAMERA_PASS);
2526}
2527
2528
2529/** Touch each material once in order to preload the render queue
2530        bucket id of each material
2531*/
2532void PrepareRenderQueue()
2533{
2534        for (int i = 0; i < 3; ++ i)
2535        {
2536                renderState.SetRenderTechnique(i);
2537
2538                // fill all shapes into the render queue        once so we can establish the buckets
2539                ShapeContainer::const_iterator sit, sit_end = (*resourceManager->GetShapes()).end();
2540
2541                for (sit = (*resourceManager->GetShapes()).begin(); sit != sit_end; ++ sit)
2542                {
2543                        static Transform3 dummy(IdentityMatrix());
2544                        renderQueue->Enqueue(*sit, NULL);
2545                }
2546       
2547                // just clear queue again
2548                renderQueue->Clear();
2549        }
2550}
2551
2552
2553int LoadModel(const string &model, SceneEntityContainer &entities)
2554{
2555        const string filename = string(model_path + model);
2556        int numEntities = 0;
2557
2558        cout << "\nloading model " << filename << endl;
2559
2560        if (numEntities = resourceManager->Load(filename, entities))
2561        {
2562                cout << "model " << filename << " successfully loaded" << endl;
2563        }
2564        else
2565        {
2566                cerr << "loading model " << filename << " failed" << endl;
2567
2568                CleanUp();
2569                exit(0);
2570        }
2571
2572        return numEntities;
2573}
2574
2575
2576void CreateAnimation()
2577{
2578        const float radius = 5.0f;
2579        const Vector3 center(480.398f, 268.364f, 181.3);
2580
2581        VertexArray vertices;
2582
2583        /*for (int i = 0; i < 360; ++ i)
2584        {
2585                float angle = (float)i * M_PI / 180.0f;
2586
2587                Vector3 offs = Vector3(cos(angle) * radius, sin(angle) * radius, 0);
2588                vertices.push_back(center + offs);
2589        }*/
2590
2591        for (int i = 0; i < 5; ++ i)
2592        {
2593                Vector3 offs = Vector3(i, 0, 0);
2594                vertices.push_back(center + offs);
2595        }
2596
2597       
2598        for (int i = 0; i < 5; ++ i)
2599        {
2600                Vector3 offs = Vector3(4 -i, 0, 0);
2601                vertices.push_back(center + offs);
2602        }
2603
2604        motionPath = new MotionPath(vertices);
2605}
2606
2607/** This function returns the number of visible pixels of a
2608        bounding box representing the sun.
2609*/
2610int TestSunVisible()
2611{
2612        // assume sun is at a far away point along the light vector
2613        Vector3 sunPos = light->GetDirection() * -1e3f;
2614        sunPos += camera->GetPosition();
2615
2616        sunBox->GetTransform()->SetMatrix(TranslationMatrix(sunPos));
2617
2618        glBeginQueryARB(GL_SAMPLES_PASSED_ARB, sunQuery);
2619
2620        sunBox->Render(&renderState);
2621
2622        glEndQueryARB(GL_SAMPLES_PASSED_ARB);
2623
2624        GLuint sampleCount;
2625
2626        glGetQueryObjectuivARB(sunQuery, GL_QUERY_RESULT_ARB, &sampleCount);
2627
2628        return sampleCount;
2629}
2630
2631
2632static Technique GetVizTechnique()
2633{
2634        Technique tech;
2635        tech.Init();
2636
2637        tech.SetEmmisive(RgbaColor(1.0f, 1.0f, 1.0f, 1.0f));
2638        tech.SetDiffuse(RgbaColor(1.0f, 1.0f, 1.0f, 1.0f));
2639        tech.SetAmbient(RgbaColor(1.0f, 1.0f, 1.0f, 1.0f));
2640
2641        return tech;
2642}
2643
2644
2645void LoadPvs()
2646{
2647        viewCell = viewCellsTree->GetViewCell(camera->GetPosition());
2648
2649        int numTriangles = 0;
2650
2651        SceneEntity::SetCurrentVisibleId(globalVisibleId);
2652
2653        for (int i = 0; i < viewCell->mPvs.GetSize(); ++ i)
2654        {
2655                SceneEntity *ent = viewCell->mPvs.GetEntry(i);
2656                ent->SetVisibleId(globalVisibleId);
2657                //ent->Render(&renderState);
2658
2659                numTriangles += ent->CountNumTriangles();
2660        }
2661
2662        ++ globalVisibleId;
2663}
2664
2665
2666void LoadVisibilitySolution()
2667{
2668        ///////////
2669        //-- load the visibility solution
2670
2671        const string vis_filename =
2672                string(model_path + visibilitySolution + ".vis");
2673
2674        VisibilitySolutionLoader visLoader;
2675
2676        viewCellsTree = visLoader.Load(vis_filename, bvh, viewCellsScaleFactor);
2677
2678        if (!viewCellsTree)
2679        {
2680                cerr << "loading pvs failed" << endl;
2681                CleanUp();
2682                exit(0);
2683        }
2684}
2685
2686
2687void RenderViewCell()
2688{
2689        // render current view cell
2690        static Technique vcTechnique = GetVizTechnique();
2691
2692        vcTechnique.Render(&renderState);
2693        Visualization::RenderBoxForViz(viewCell->GetBox());
2694}
2695
2696
2697void LoadPompeiiScene()
2698{
2699        AxisAlignedBox3 pompeiiBox = SceneEntity::ComputeBoundingBox(staticObjects);
2700
2701        // todo: dispose texture
2702        Texture *floorTex = new Texture(model_path + "stairs.c.01.tif");
2703
2704        floorTex->SetBoundaryModeS(Texture::REPEAT);
2705        floorTex->SetBoundaryModeT(Texture::REPEAT);
2706
2707        floorTex->Create();
2708        Material *mymat = resourceManager->CreateMaterial();
2709
2710        Technique *tech = mymat->GetDefaultTechnique();
2711        tech->SetDiffuse(RgbaColor(1, 1, 1, 1));
2712        tech->SetTexture(floorTex);
2713
2714        Technique *depthPass = new Technique(*tech);
2715        Technique *deferred = new Technique(*tech);
2716
2717        depthPass->SetColorWriteEnabled(false);
2718        depthPass->SetLightingEnabled(false);
2719
2720        ShaderProgram *defaultFragmentTexProgramMrt = ShaderManager::GetSingleton()->GetShaderProgram("defaultFragmentTexMrt");
2721        ShaderProgram *defaultVertexProgramMrt = ShaderManager::GetSingleton()->GetShaderProgram("defaultVertexMrt");
2722
2723        deferred->SetFragmentProgram(defaultFragmentTexProgramMrt);
2724        deferred->SetVertexProgram(defaultVertexProgramMrt);
2725
2726        deferred->GetFragmentProgramParameters()->SetViewMatrixParam(0);
2727        deferred->GetVertexProgramParameters()->SetModelMatrixParam(1);
2728        deferred->GetVertexProgramParameters()->SetOldModelMatrixParam(2);
2729
2730        deferred->SetTexture(floorTex);
2731       
2732        mymat->AddTechnique(deferred);
2733        mymat->AddTechnique(depthPass);
2734
2735
2736        //const Vector3 offs(1300.0f, -2500.0f, .0f);
2737        const Vector3 offs(pompeiiBox.Center(0), pompeiiBox.Center(1), 0);
2738        Matrix4x4 moffs = TranslationMatrix(offs);
2739
2740        Plane3 plane;
2741        Transform3 *mytrafo = resourceManager->CreateTransform(moffs);
2742
2743        SceneEntity *myplane =
2744                SceneEntityConverter().ConvertPlane(plane,
2745                                                    pompeiiBox.Size(0),
2746                                                                                        pompeiiBox.Size(1),
2747                                                                                        5,
2748                                                                                        5,
2749                                                                                        mymat,
2750                                                                                        mytrafo);
2751
2752        resourceManager->AddSceneEntity(myplane);
2753        staticObjects.push_back(myplane);
2754}
Note: See TracBrowser for help on using the repository browser.