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

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