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

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