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

Revision 3288, 69.4 KB checked in by mattausch, 16 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                /////////////////////////
1145                //-- update animations
1146
1147                //const float rotAngle = M_PI * 1e-3f;
1148                const float rotAngle = 1.0f * M_PI / 180.0f;
1149
1150                Matrix4x4 rotMatrix = RotationZMatrix(rotAngle);
1151                dynamicObjects[2]->GetTransform()->MultMatrix(rotMatrix);
1152
1153                motionPath->Move(0.01f);
1154                */
1155        }
1156
1157
1158        /////////////
1159
1160        static Vector3 oldPos = camera->GetPosition();
1161        static Vector3 oldDir = camera->GetDirection();
1162
1163        if (leftKeyPressed)
1164                camera->Pitch(KeyRotationAngle());
1165        if (rightKeyPressed)
1166                camera->Pitch(-KeyRotationAngle());
1167        if (upKeyPressed)
1168                KeyHorizontalMotion(-KeyShift());
1169        if (downKeyPressed)
1170                KeyHorizontalMotion(KeyShift());
1171        if (ascendKeyPressed)
1172                KeyVerticalMotion(KeyShift());
1173        if (descendKeyPressed)
1174                KeyVerticalMotion(-KeyShift());
1175        if (leftStrafeKeyPressed)
1176                KeyStrafe(KeyShift());
1177        if (rightStrafeKeyPressed)
1178                KeyStrafe(-KeyShift());
1179
1180
1181        // place view on ground
1182        if (!flyMode) PlaceViewer(oldPos);
1183
1184        if (showAlgorithmTime)
1185        {
1186                glFinish();
1187                algTimer.Start();
1188        }
1189       
1190        // don't allow replay on record
1191        if (replayPath && !recordPath)
1192        {
1193                if (!walkThroughPlayer)
1194                        walkThroughPlayer = new WalkThroughPlayer(walkThroughSuffix + ".log");
1195               
1196                ++ currentReplayFrame;
1197
1198                // reset if end of walkthrough is reached
1199                if (!walkThroughPlayer->ReadNextFrame(camera))
1200                {
1201                        cout << "reached end of walkthrough" << endl;
1202                        currentReplayFrame = -1;
1203                        replayPath = false;
1204                }
1205        }
1206
1207        if ((!shadowMap || !shadowTraverser) && (showShadowMap || renderLightView))
1208        {
1209                if (!shadowMap)
1210                        shadowMap = new ShadowMap(light, shadowSize, bvh->GetBox(), camera);
1211
1212                if (!shadowTraverser)
1213                        shadowTraverser = CreateTraverser(shadowMap->GetShadowCamera());
1214
1215        }
1216       
1217        // bring eye modelview matrix up-to-date
1218        SetupEyeView();
1219       
1220
1221        // set frame related parameters for GPU programs
1222        GPUProgramParameters::InitFrame(camera, light);
1223
1224        if (recordPath)
1225        {
1226                if (!walkThroughRecorder)
1227                {
1228                        walkThroughRecorder = new WalkThroughRecorder(walkThroughSuffix + ".log");
1229                }
1230
1231                // question: check if player has moved more than a minimum distance?
1232
1233                if (0 ||
1234                        (Distance(oldPos, camera->GetPosition()) > 1e-6f) ||
1235                        (DotProd(oldDir, camera->GetDirection()) < 1.0f - 1e-6f))
1236                {
1237                        walkThroughRecorder->WriteFrame(camera);
1238                }
1239        }
1240
1241        // hack: store current rendering method and restore later
1242        int oldRenderMethod = renderMethod;
1243        // for rendering the light view, we use forward rendering
1244        if (renderLightView) renderMethod = FORWARD;
1245
1246        /// enable vbo vertex array
1247        glEnableClientState(GL_VERTEX_ARRAY);
1248
1249        if (usePvs) LoadOrUpdatePVSs(camera->GetPosition());
1250
1251
1252        // render with the specified method (forward rendering, forward + depth, deferred)
1253        switch (renderMethod)
1254        {
1255        case RENDER_FORWARD:
1256       
1257                glEnable(GL_MULTISAMPLE_ARB);
1258                renderState.SetRenderTechnique(FORWARD);
1259               
1260                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1261                glEnableClientState(GL_NORMAL_ARRAY);
1262                break;
1263
1264        case RENDER_DEPTH_PASS_DEFERRED:
1265
1266                glDisable(GL_MULTISAMPLE_ARB);
1267                renderState.SetUseAlphaToCoverage(false);
1268                renderState.SetRenderTechnique(DEPTH_PASS);
1269
1270                if (!fbo) InitFBO();
1271                fbo->Bind();
1272                // render to single depth texture
1273                glDrawBuffers(1, mrt);
1274                // clear buffer once
1275                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1276
1277                // the scene is rendered withouth any shading
1278                // (should be handled by render renderState)
1279                glShadeModel(GL_FLAT);
1280                break;
1281
1282        case RENDER_DEPTH_PASS:
1283
1284                glEnable(GL_MULTISAMPLE_ARB);
1285                renderState.SetRenderTechnique(DEPTH_PASS);
1286
1287                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1288
1289                // the scene is rendered withouth any shading
1290                // (should be handled by render renderState)
1291                glShadeModel(GL_FLAT);
1292                break;
1293       
1294        case RENDER_DEFERRED:
1295
1296                if (showShadowMap && !renderLightView)
1297                        RenderShadowMap(camera->GetFar());
1298
1299                //glPushAttrib(GL_VIEWPORT_BIT);
1300                glViewport(0, 0, texWidth, texHeight);
1301
1302                InitDeferredRendering();
1303               
1304                glEnableClientState(GL_NORMAL_ARRAY);
1305                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1306                break;
1307        }
1308
1309        glDepthFunc(GL_LESS);
1310        glDisable(GL_TEXTURE_2D);
1311        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1312               
1313
1314        // set proper lod levels for current frame using current eye point
1315        LODLevel::InitFrame(camera->GetPosition());
1316        // set up sunlight
1317        SetupLighting();
1318
1319
1320        if (renderLightView)
1321        {
1322                // change CHC++ set of renderState variables:
1323                // must be done for each change of camera because otherwise
1324                // the temporal coherency is broken
1325                BvhNode::SetCurrentState(LIGHT_PASS);
1326                shadowMap->RenderShadowView(shadowTraverser, viewProjMat);
1327                BvhNode::SetCurrentState(CAMERA_PASS);
1328        }
1329        else
1330        {
1331                //if (traverser->GetType() == RenderTraverser::CULL_COLLECTOR)
1332                //      ((PvsCollectionRenderer *)traverser)->SetViewCell(usePvs ? viewCell : NULL);
1333
1334                //renderState.LockCullFaceEnabled(true);
1335
1336                // actually render the scene geometry using the specified algorithm
1337                traverser->RenderScene();
1338        }
1339
1340
1341        /////////
1342        //-- do the rest of the rendering
1343       
1344        // return from depth pass and render visible objects
1345        if ((renderMethod == RENDER_DEPTH_PASS) ||
1346                (renderMethod == RENDER_DEPTH_PASS_DEFERRED))
1347        {
1348                RenderVisibleObjects();
1349        }
1350
1351        const bool useDeferred =
1352                ((renderMethod == RENDER_DEFERRED) || (renderMethod == RENDER_DEPTH_PASS_DEFERRED));
1353
1354        // if no lense flare => just set sun to invisible
1355        const int sunVisiblePixels = useLenseFlare  &&  useDeferred ? TestSunVisible() : 0;
1356
1357       
1358
1359        ///////////////
1360        //-- render sky
1361
1362        // q: should we render sky after deferred shading?
1363        // this would conveniently solves some issues (e.g, skys without shadows)
1364
1365        RenderSky();
1366
1367
1368        //////////////////////////////
1369
1370        if (useDeferred)
1371        {
1372                FrameBufferObject::Release();
1373
1374                if (!deferredShader)
1375                {
1376                        deferredShader =
1377                                new DeferredRenderer(texWidth, texHeight, camera, ssaoUseFullResolution);
1378
1379                        deferredShader->SetKernelRadius(ssaoKernelRadius);
1380                        deferredShader->SetSampleIntensity(ssaoSampleIntensity);
1381                        deferredShader->SetSsaoFilterRadius(ssaoFilterRadius);
1382                }
1383
1384                DeferredRenderer::SHADING_METHOD shadingMethod;
1385
1386                if (useAdvancedShading)
1387                {
1388                        if (useGlobIllum)
1389                                shadingMethod = DeferredRenderer::GI;
1390                        else
1391                                shadingMethod = DeferredRenderer::SSAO;
1392                }
1393                else
1394                {
1395                        shadingMethod = DeferredRenderer::DEFAULT;
1396                }
1397
1398                static int snapShotIdx = 0;
1399
1400                deferredShader->SetSunVisiblePixels(sunVisiblePixels);
1401                deferredShader->SetShadingMethod(shadingMethod);
1402                deferredShader->SetSamplingMethod(samplingMethod);
1403               
1404                deferredShader->SetUseTemporalCoherence(useTemporalCoherence);
1405                //deferredShader->SetSortSamples(sortSamples);
1406                deferredShader->SetTemporalCoherenceFactorForSsao(ssaoTempCohFactor);
1407                deferredShader->SetUseToneMapping(useHDR);
1408                deferredShader->SetUseAntiAliasing(useAntiAliasing);
1409
1410
1411                if (recordFrames && replayPath)
1412                {
1413                        // record all frames of the walkthrough
1414                        deferredShader->SetSaveFrame(recordedFramesSuffix, currentReplayFrame);
1415                }
1416                else if (makeSnapShot)
1417                {
1418                        // make snap shot
1419                        deferredShader->SetSaveFrame("snap", snapShotIdx ++);
1420                }
1421                else
1422                {
1423                        // do nothing
1424                        deferredShader->SetSaveFrame("", -1);           
1425                }
1426               
1427                if (makeSnapShot) makeSnapShot = false;
1428
1429                ShadowMap *sm = showShadowMap ? shadowMap : NULL;
1430                deferredShader->Render(fbo, light, sm);
1431        }
1432
1433
1434        renderState.SetRenderTechnique(FORWARD);
1435        renderState.Reset();
1436
1437        glDisableClientState(GL_VERTEX_ARRAY);
1438        glDisableClientState(GL_NORMAL_ARRAY);
1439       
1440        renderMethod = oldRenderMethod;
1441
1442
1443        ///////////
1444
1445
1446        if (showAlgorithmTime)
1447        {
1448                glFinish();
1449
1450                algTime = algTimer.Elapsedms();
1451                perfGraph->AddData(algTime);
1452
1453                perfGraph->Draw();
1454        }
1455        else
1456        {
1457                if (visMode) DisplayVisualization();
1458        }
1459
1460        glFlush();
1461
1462        const bool restart = true;
1463        elapsedTime = frameTimer.Elapsedms(restart);
1464
1465        // statistics
1466        DisplayStats();
1467
1468        glutSwapBuffers();
1469
1470        oldPos = camera->GetPosition();
1471        oldDir = camera->GetDirection();
1472}
1473
1474
1475#pragma warning(disable : 4100)
1476void KeyBoard(unsigned char c, int x, int y)
1477{
1478        switch(c)
1479        {
1480        case 27:
1481                // write out current position on exit
1482                Debug << "camPosition=" << camera->GetPosition().x << " " << camera->GetPosition().y << " " << camera->GetPosition().z << endl;
1483                Debug << "camDirection=" << camera->GetDirection().x << " " << camera->GetDirection().y << " " << camera->GetDirection().z << endl;
1484                Debug << "lightDirection=" << light->GetDirection().x << " " << light->GetDirection().y << " " << light->GetDirection().z << endl;
1485
1486                CleanUp();
1487                exit(0);
1488        case 32: // space
1489                renderMode = (renderMode + 1) % RenderTraverser::NUM_TRAVERSAL_TYPES;
1490                //renderMode = (renderMode + 1) % 4;
1491
1492                DEL_PTR(traverser);
1493                traverser = CreateTraverser(camera);
1494
1495                if (shadowTraverser)
1496                {
1497                        // shadow traverser has to be recomputed
1498                        DEL_PTR(shadowTraverser);
1499                        shadowTraverser = CreateTraverser(shadowMap->GetShadowCamera());
1500                }
1501
1502                break;
1503        case '+':
1504                if (maxBatchSize < 10)
1505                        maxBatchSize = 10;
1506                else
1507                        maxBatchSize += 10;
1508
1509                traverser->SetMaxBatchSize(maxBatchSize);
1510                break;
1511        case '-':
1512                maxBatchSize -= 10;
1513                if (maxBatchSize < 0) maxBatchSize = 1;
1514                traverser->SetMaxBatchSize(maxBatchSize);               
1515                break;
1516        case 'M':
1517        case 'm':
1518                useMultiQueries = !useMultiQueries;
1519                traverser->SetUseMultiQueries(useMultiQueries);
1520                break;
1521        case '1':
1522                descendKeyPressed = true;
1523                break;
1524        case '2':
1525                ascendKeyPressed = true;
1526                break;
1527        case '3':
1528                if (trianglesPerVirtualLeaf >= 100) trianglesPerVirtualLeaf -= 100;
1529                bvh->SetVirtualLeaves(trianglesPerVirtualLeaf);
1530                break;
1531        case '4':
1532                trianglesPerVirtualLeaf += 100;
1533                bvh->SetVirtualLeaves(trianglesPerVirtualLeaf);
1534                break;
1535        case '5':
1536                assumedVisibleFrames -= 1;
1537                if (assumedVisibleFrames < 1) assumedVisibleFrames = 1;
1538                traverser->SetAssumedVisibleFrames(assumedVisibleFrames);
1539                break;
1540        case '6':
1541                assumedVisibleFrames += 1;
1542                traverser->SetAssumedVisibleFrames(assumedVisibleFrames);               
1543                break;
1544        case '7':
1545                ssaoTempCohFactor *= 1.0f / 1.2f;
1546                cout << "new temporal coherence factor: " << ssaoTempCohFactor << endl;
1547                break;
1548        case '8':
1549                ssaoTempCohFactor *= 1.2f;
1550                cout << "new temporal coherence factor: " << ssaoTempCohFactor << endl;
1551                break;
1552        case '9':
1553                ssaoKernelRadius *= 0.8f;
1554                cout << "new ssao kernel radius: " << ssaoKernelRadius << endl;
1555                if (deferredShader) deferredShader->SetKernelRadius(ssaoKernelRadius);
1556                break;
1557        case '0':
1558                ssaoKernelRadius *= 1.0f / 0.8f;
1559                if (deferredShader) deferredShader->SetKernelRadius(ssaoKernelRadius);
1560                cout << "new ssao kernel radius: " << ssaoKernelRadius << endl;
1561                break;
1562        case 'n':
1563                ssaoSampleIntensity *= 0.9f;
1564                if (deferredShader) deferredShader->SetSampleIntensity(ssaoSampleIntensity);
1565                cout << "new ssao sample intensity: " << ssaoSampleIntensity << endl;
1566                break;
1567        case 'N':
1568                ssaoSampleIntensity *= 1.0f / 0.9f;
1569                if (deferredShader) deferredShader->SetSampleIntensity(ssaoSampleIntensity);
1570                cout << "new ssao sample intensity: " << ssaoSampleIntensity << endl;
1571                break;
1572        case 'o':
1573                ssaoFilterRadius *= 0.9f;
1574                if (deferredShader) deferredShader->SetSsaoFilterRadius(ssaoFilterRadius);
1575                cout << "new ssao filter radius: " << ssaoFilterRadius << endl;
1576                break;
1577        case 'O':
1578                ssaoFilterRadius *= 1.0f / 0.9f;
1579                if (deferredShader) deferredShader->SetSsaoFilterRadius(ssaoFilterRadius);
1580                cout << "new ssao filter radius: " << ssaoFilterRadius << endl;
1581                break;
1582        /*      case 'o':
1583        case 'O':
1584                useOptimization = !useOptimization;
1585                // chc optimization of using the objects instead of
1586                // the bounding boxes for querying previously visible nodes
1587                traverser->SetUseOptimization(useOptimization);
1588                break;*/
1589        case 'l':
1590        case 'L':
1591                useLODs = !useLODs;
1592                SceneEntity::SetUseLODs(useLODs);
1593                cout << "using LODs: " << useLODs << endl;
1594                break;
1595        case 'P':
1596        case 'p':
1597                samplingMethod = DeferredRenderer::SAMPLING_METHOD((samplingMethod + 1) % 3);
1598                cout << "ssao sampling method: " << samplingMethod << endl;
1599                break;
1600        case 'Y':
1601        case 'y':
1602                showShadowMap = !showShadowMap;
1603                break;
1604        case 'g':
1605        case 'G':
1606                useGlobIllum = !useGlobIllum;
1607                break;
1608        case 't':
1609        case 'T':
1610                useTemporalCoherence = !useTemporalCoherence;
1611                break;
1612        case 'a':
1613        case 'A':
1614                leftKeyPressed = true;
1615                break;
1616        case 'd':
1617        case 'D':
1618                rightKeyPressed = true;
1619                break;
1620        case 'w':
1621        case 'W':
1622                upKeyPressed = true;
1623                break;
1624        case 's':
1625        case 'S':
1626                downKeyPressed = true;
1627                break;
1628        case 'j':
1629        case 'J':
1630                leftStrafeKeyPressed = true;
1631                break;
1632        case 'k':
1633        case 'K':
1634                rightStrafeKeyPressed = true;
1635                break;
1636        case 'r':
1637        case 'R':
1638                useRenderQueue = !useRenderQueue;
1639                traverser->SetUseRenderQueue(useRenderQueue);
1640                break;
1641        case 'b':
1642        case 'B':
1643                useTightBounds = !useTightBounds;
1644                traverser->SetUseTightBounds(useTightBounds);
1645                break;
1646        case 'v':
1647        case 'V':
1648                renderLightView = !renderLightView;
1649                break;
1650        case 'h':
1651        case 'H':
1652                useHDR = !useHDR;
1653                break;
1654        case 'i':
1655        case 'I':
1656                useAntiAliasing = !useAntiAliasing;
1657                break;
1658        case 'c':
1659        case 'C':
1660                useLenseFlare = !useLenseFlare;
1661                break;
1662        case 'u':
1663        case 'U':
1664                // move light source instead of camera tilt
1665                moveLight = !moveLight;
1666                break;
1667        case '#':
1668                // make a snapshot of the current frame
1669                makeSnapShot = true;
1670                break;
1671        case '.':
1672                // enable / disable view cells
1673                usePvs = !usePvs;
1674                if (!usePvs) SceneEntity::SetCurrentVisibleId(-1);
1675                break;
1676        case ',':
1677                // show / hide FPS
1678                showFPS = !showFPS;
1679                break;
1680       
1681        default:
1682                return;
1683        }
1684
1685        glutPostRedisplay();
1686}
1687
1688
1689void SpecialKeyUp(int c, int x, int y)
1690{
1691        switch (c)
1692        {
1693        case GLUT_KEY_LEFT:
1694                leftKeyPressed = false;
1695                break;
1696        case GLUT_KEY_RIGHT:
1697                rightKeyPressed = false;
1698                break;
1699        case GLUT_KEY_UP:
1700                upKeyPressed = false;
1701                break;
1702        case GLUT_KEY_DOWN:
1703                downKeyPressed = false;
1704                break;
1705        case GLUT_ACTIVE_ALT:
1706                altKeyPressed = false;
1707                break;
1708        default:
1709                return;
1710        }
1711}
1712
1713
1714void KeyUp(unsigned char c, int x, int y)
1715{
1716        switch (c)
1717        {
1718
1719        case 'A':
1720        case 'a':
1721                leftKeyPressed = false;
1722                break;
1723        case 'D':
1724        case 'd':
1725                rightKeyPressed = false;
1726                break;
1727        case 'W':
1728        case 'w':
1729                upKeyPressed = false;
1730                break;
1731        case 'S':
1732        case 's':
1733                downKeyPressed = false;
1734                break;
1735        case '1':
1736                descendKeyPressed = false;
1737                break;
1738        case '2':
1739                ascendKeyPressed = false;
1740                break;
1741        case 'j':
1742        case 'J':
1743                leftStrafeKeyPressed = false;
1744                break;
1745        case 'k':
1746        case 'K':
1747                rightStrafeKeyPressed = false;
1748                break;
1749        default:
1750                return;
1751        }
1752        //glutPostRedisplay();
1753}
1754
1755
1756void Special(int c, int x, int y)
1757{
1758        switch(c)
1759        {
1760        case GLUT_KEY_F1:
1761                showHelp = !showHelp;
1762                break;
1763        case GLUT_KEY_F2:
1764                visMode = !visMode;
1765                break;
1766        case GLUT_KEY_F3:
1767                showBoundingVolumes = !showBoundingVolumes;
1768                traverser->SetShowBounds(showBoundingVolumes);
1769                break;
1770        case GLUT_KEY_F4:
1771                showOptions = !showOptions;
1772                break;
1773        case GLUT_KEY_F5:
1774                showStatistics = !showStatistics;
1775                break;
1776        case GLUT_KEY_F6:
1777                flyMode = !flyMode;
1778                break;
1779        case GLUT_KEY_F7:
1780
1781                renderMethod = (renderMethod + 1) % 4;
1782
1783                traverser->SetUseDepthPass(
1784                        (renderMethod == RENDER_DEPTH_PASS) ||
1785                        (renderMethod == RENDER_DEPTH_PASS_DEFERRED)
1786                        );
1787               
1788                break;
1789        case GLUT_KEY_F8:
1790                useAdvancedShading = !useAdvancedShading;
1791                break;
1792        case GLUT_KEY_F9:
1793                showAlgorithmTime = !showAlgorithmTime;
1794                break;
1795        case GLUT_KEY_F10:
1796                replayPath = !replayPath;
1797
1798                if (replayPath)
1799                {
1800                        cout << "replaying path" << endl;
1801
1802                        currentReplayFrame = -1;
1803
1804                        // hack: load pvs on replay (remove later!)
1805                        //usePvs = true;
1806                }
1807                else
1808                {
1809                        cout << "finished replaying path" << endl;
1810                }
1811
1812                break;
1813        case GLUT_KEY_F11:
1814                recordPath = !recordPath;
1815               
1816                if (recordPath)
1817                {
1818                        cout << "recording path" << endl;
1819                }
1820                else
1821                {
1822                        cout << "finished recording path" << endl;
1823                        // start over with new frame recording next time
1824                        DEL_PTR(walkThroughRecorder);
1825                }
1826
1827                break;
1828        case GLUT_KEY_F12:
1829                recordFrames = !recordFrames;
1830
1831                if (recordFrames)
1832                        cout << "recording frames on replaying" << endl;
1833                else
1834                        cout << "not recording frames on replaying" << endl;
1835                break;
1836        case GLUT_KEY_LEFT:
1837                {
1838                        leftKeyPressed = true;
1839                        camera->Pitch(KeyRotationAngle());
1840                }
1841                break;
1842        case GLUT_KEY_RIGHT:
1843                {
1844                        rightKeyPressed = true;
1845                        camera->Pitch(-KeyRotationAngle());
1846                }
1847                break;
1848        case GLUT_KEY_UP:
1849                {
1850                        upKeyPressed = true;
1851                        KeyHorizontalMotion(KeyShift());
1852                }
1853                break;
1854        case GLUT_KEY_DOWN:
1855                {
1856                        downKeyPressed = true;
1857                        KeyHorizontalMotion(-KeyShift());
1858                }
1859                break;
1860        default:
1861                return;
1862
1863        }
1864
1865        glutPostRedisplay();
1866}
1867
1868#pragma warning( default : 4100 )
1869
1870
1871void Reshape(int w, int h)
1872{
1873        winAspectRatio = 1.0f;
1874
1875        glViewport(0, 0, w, h);
1876       
1877        winWidth = w;
1878        winHeight = h;
1879
1880        if (w) winAspectRatio = (float) w / (float) h;
1881
1882        glMatrixMode(GL_PROJECTION);
1883        glLoadIdentity();
1884
1885        gluPerspective(fov, winAspectRatio, nearDist, farDist);
1886
1887        glMatrixMode(GL_MODELVIEW);
1888
1889        glutPostRedisplay();
1890}
1891
1892
1893void Mouse(int button, int renderState, int x, int y)
1894{
1895        if ((button == GLUT_LEFT_BUTTON) && (renderState == GLUT_DOWN))
1896        {
1897                xEyeBegin = x;
1898                yMotionBegin = y;
1899
1900                glutMotionFunc(LeftMotion);
1901        }
1902        else if ((button == GLUT_RIGHT_BUTTON) && (renderState == GLUT_DOWN))
1903        {
1904                xEyeBegin = x;
1905                yEyeBegin = y;
1906                yMotionBegin = y;
1907
1908                if (!moveLight)
1909                        glutMotionFunc(RightMotion);
1910                else
1911                        glutMotionFunc(RightMotionLight);
1912        }
1913        else if ((button == GLUT_MIDDLE_BUTTON) && (renderState == GLUT_DOWN))
1914        {
1915                horizontalMotionBegin = x;
1916                verticalMotionBegin = y;
1917                glutMotionFunc(MiddleMotion);
1918        }
1919
1920        glutPostRedisplay();
1921}
1922
1923
1924/**     rotation for left/right mouse drag
1925        motion for up/down mouse drag
1926*/
1927void LeftMotion(int x, int y)
1928{
1929        Vector3 viewDir = camera->GetDirection();
1930        Vector3 pos = camera->GetPosition();
1931
1932        // don't move in the vertical direction
1933        Vector3 horView(viewDir[0], viewDir[1], 0);
1934       
1935        float eyeXAngle = 0.2f *  M_PI * (xEyeBegin - x) / 180.0;
1936
1937        camera->Pitch(eyeXAngle);
1938
1939        pos += horView * (yMotionBegin - y) * mouseMotion;
1940       
1941        camera->SetPosition(pos);
1942       
1943        xEyeBegin = x;
1944        yMotionBegin = y;
1945
1946        glutPostRedisplay();
1947}
1948
1949
1950void RightMotionLight(int x, int y)
1951{
1952        float theta = 0.2f * M_PI * (xEyeBegin - x) / 180.0f;
1953        float phi = 0.2f * M_PI * (yMotionBegin - y) / 180.0f;
1954       
1955        Vector3 lightDir = light->GetDirection();
1956
1957        Matrix4x4 roty = RotationYMatrix(theta);
1958        Matrix4x4 rotx = RotationXMatrix(phi);
1959
1960        lightDir = roty * lightDir;
1961        lightDir = rotx * lightDir;
1962
1963        // normalize to avoid accumulating errors
1964        lightDir.Normalize();
1965
1966        light->SetDirection(lightDir);
1967
1968        xEyeBegin = x;
1969        yMotionBegin = y;
1970
1971        glutPostRedisplay();
1972}
1973
1974
1975/**     rotation for left / right mouse drag
1976        motion for up / down mouse drag
1977*/
1978void RightMotion(int x, int y)
1979{
1980        float eyeXAngle = 0.2f *  M_PI * (xEyeBegin - x) / 180.0;
1981        float eyeYAngle = -0.2f *  M_PI * (yEyeBegin - y) / 180.0;
1982
1983        camera->Yaw(eyeYAngle);
1984        camera->Pitch(eyeXAngle);
1985
1986        xEyeBegin = x;
1987        yEyeBegin = y;
1988
1989        glutPostRedisplay();
1990}
1991
1992
1993/** strafe
1994*/
1995void MiddleMotion(int x, int y)
1996{
1997        Vector3 viewDir = camera->GetDirection();
1998        Vector3 pos = camera->GetPosition();
1999
2000        // the 90 degree rotated view vector
2001        // y zero so we don't move in the vertical
2002        Vector3 rVec(viewDir[0], viewDir[1], 0);
2003       
2004        Matrix4x4 rot = RotationZMatrix(M_PI * 0.5f);
2005        rVec = rot * rVec;
2006       
2007        pos -= rVec * (x - horizontalMotionBegin) * mouseMotion;
2008        pos[2] += (verticalMotionBegin - y) * mouseMotion;
2009
2010        camera->SetPosition(pos);
2011
2012        horizontalMotionBegin = x;
2013        verticalMotionBegin = y;
2014
2015        glutPostRedisplay();
2016}
2017
2018
2019void InitExtensions(void)
2020{
2021        GLenum err = glewInit();
2022
2023        if (GLEW_OK != err)
2024        {
2025                // problem: glewInit failed, something is seriously wrong
2026                fprintf(stderr,"Error: %s\n", glewGetErrorString(err));
2027                exit(1);
2028        }
2029        if  (!GLEW_ARB_occlusion_query)
2030        {
2031                printf("I require the GL_ARB_occlusion_query to work.\n");
2032                exit(1);
2033        }
2034}
2035
2036
2037void Begin2D()
2038{
2039        glDisable(GL_LIGHTING);
2040        glDisable(GL_DEPTH_TEST);
2041
2042        glMatrixMode(GL_PROJECTION);
2043        glPushMatrix();
2044        glLoadIdentity();
2045
2046        gluOrtho2D(0, winWidth, 0, winHeight);
2047
2048        glMatrixMode(GL_MODELVIEW);
2049        glPushMatrix();
2050        glLoadIdentity();
2051}
2052
2053
2054void End2D()
2055{
2056        glMatrixMode(GL_PROJECTION);
2057        glPopMatrix();
2058
2059        glMatrixMode(GL_MODELVIEW);
2060        glPopMatrix();
2061
2062        glEnable(GL_LIGHTING);
2063        glEnable(GL_DEPTH_TEST);
2064}
2065
2066
2067// displays the visualisation of culling algorithm
2068void DisplayVisualization()
2069{
2070        // render current view cell
2071        if (usePvs) RenderViewCell();
2072       
2073        visualization->SetViewCell(usePvs ? viewCell : NULL);
2074        visualization->SetFrameId(traverser->GetCurrentFrameId());
2075       
2076
2077        Begin2D();
2078        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2079        glEnable(GL_BLEND);
2080        glColor4f(0.0f ,0.0f, 0.0f, 0.5f);
2081
2082        glRecti(winWidth - winWidth / 3, winHeight - winHeight / 3, winWidth, winHeight);
2083        glDisable(GL_BLEND);
2084        End2D();
2085       
2086       
2087        AxisAlignedBox3 box = bvh->GetBox();
2088
2089        const float offs = box.Size().x * 0.3f;
2090       
2091        Vector3 vizpos = Vector3(box.Min().x, box.Min().y  - box.Size().y * 0.35f, box.Min().z + box.Size().z * 50);
2092       
2093        visCamera->SetPosition(vizpos);
2094        visCamera->ResetPitchAndYaw();
2095       
2096        glPushAttrib(GL_VIEWPORT_BIT);
2097        glViewport(winWidth - winWidth / 3, winHeight - winHeight / 3, winWidth / 3, winHeight / 3);
2098
2099        glMatrixMode(GL_PROJECTION);
2100        glPushMatrix();
2101
2102        glLoadIdentity();
2103        glOrtho(-offs, offs, -offs, offs, 0.0f, box.Size().z * 100.0f);
2104
2105        glMatrixMode(GL_MODELVIEW);
2106        glPushMatrix();
2107
2108        visCamera->SetupCameraView();
2109
2110        Matrix4x4 rotZ = RotationZMatrix(-camera->GetPitch());
2111        glMultMatrixf((float *)rotZ.x);
2112
2113        // inverse translation in order to fix current position
2114        Vector3 pos = camera->GetPosition();
2115        glTranslatef(-pos.x, -pos.y, -pos.z);
2116
2117
2118        GLfloat position[] = {0.8f, 1.0f, 1.5f, 0.0f};
2119        glLightfv(GL_LIGHT0, GL_POSITION, position);
2120
2121        GLfloat position1[] = {bvh->GetBox().Center().x, bvh->GetBox().Max().y, bvh->GetBox().Center().z, 1.0f};
2122        glLightfv(GL_LIGHT1, GL_POSITION, position1);
2123
2124        glClear(GL_DEPTH_BUFFER_BIT);
2125
2126
2127        ////////////
2128        //-- visualization of the occlusion culling
2129
2130        visualization->Render(showShadowMap);
2131
2132       
2133        // reset previous settings
2134        glPopAttrib();
2135
2136        glMatrixMode(GL_PROJECTION);
2137        glPopMatrix();
2138        glMatrixMode(GL_MODELVIEW);
2139        glPopMatrix();
2140}
2141
2142
2143// cleanup routine after the main loop
2144void CleanUp()
2145{
2146        DEL_PTR(traverser);
2147        DEL_PTR(sceneQuery);
2148        DEL_PTR(bvh);
2149        DEL_PTR(visualization);
2150        DEL_PTR(camera);
2151        DEL_PTR(renderQueue);
2152        DEL_PTR(perfGraph);
2153        DEL_PTR(fbo);
2154        DEL_PTR(deferredShader);
2155        DEL_PTR(light);
2156        DEL_PTR(visCamera);
2157        DEL_PTR(preetham);
2158        DEL_PTR(shadowMap);
2159        DEL_PTR(shadowTraverser);
2160        DEL_PTR(motionPath);
2161        DEL_PTR(walkThroughRecorder);
2162        DEL_PTR(walkThroughPlayer);
2163        DEL_PTR(statsWriter);
2164        DEL_PTR(viewCellsTree);
2165
2166        ResourceManager::DelSingleton();
2167        ShaderManager::DelSingleton();
2168
2169        resourceManager = NULL;
2170        shaderManager = NULL;
2171}
2172
2173
2174// this function inserts a dezimal point after each 1000
2175void CalcDecimalPoint(string &str, int d, int len)
2176{
2177        static vector<int> numbers;
2178        numbers.clear();
2179
2180        static string shortStr;
2181        shortStr.clear();
2182
2183        static char hstr[100];
2184
2185        while (d != 0)
2186        {
2187                numbers.push_back(d % 1000);
2188                d /= 1000;
2189        }
2190
2191        // first element without leading zeros
2192        if (numbers.size() > 0)
2193        {
2194                sprintf(hstr, "%d", numbers.back());
2195                shortStr.append(hstr);
2196        }
2197       
2198        for (int i = (int)numbers.size() - 2; i >= 0; i--)
2199        {
2200                sprintf(hstr, ",%03d", numbers[i]);
2201                shortStr.append(hstr);
2202        }
2203
2204        int dif = len - (int)shortStr.size();
2205
2206        for (int i = 0; i < dif; ++ i)
2207        {
2208                str += " ";
2209        }
2210
2211        str.append(shortStr);
2212}
2213
2214
2215void DisplayStats()
2216{
2217        static char msg[9][300];
2218
2219        static double frameTime = elapsedTime;
2220        static double renderTime = algTime;
2221
2222        const float expFactor = 0.1f;
2223
2224        // if some strange render time spike happened in this frame => don't count
2225        if (elapsedTime < 500) frameTime = elapsedTime * expFactor + (1.0f - expFactor) * elapsedTime;
2226       
2227        static float rTime = 1000.0f;
2228
2229        // the render time is used only for the traversal algorithm using glfinish
2230        if (algTime < 500) renderTime = algTime * expFactor + (1.0f - expFactor) * renderTime;
2231       
2232
2233        accumulatedTime += elapsedTime;
2234
2235        if (accumulatedTime > 500) // update every fraction of a second
2236        {       
2237                accumulatedTime = 0;
2238
2239                if (frameTime) fps = 1e3f / (float)frameTime;
2240                rTime = renderTime;
2241
2242                if (renderLightView && shadowTraverser)
2243                {
2244                        renderedTriangles = shadowTraverser->GetStats().mNumRenderedTriangles;
2245                        renderedObjects = shadowTraverser->GetStats().mNumRenderedGeometry;
2246                        renderedNodes = shadowTraverser->GetStats().mNumRenderedNodes;
2247                }
2248                else if (showShadowMap && shadowTraverser)
2249                {
2250                        renderedNodes = traverser->GetStats().mNumRenderedNodes + shadowTraverser->GetStats().mNumRenderedNodes;
2251                        renderedObjects = traverser->GetStats().mNumRenderedGeometry + shadowTraverser->GetStats().mNumRenderedGeometry;
2252                        renderedTriangles = traverser->GetStats().mNumRenderedTriangles + shadowTraverser->GetStats().mNumRenderedTriangles;
2253                }
2254                else
2255                {
2256                        renderedTriangles = traverser->GetStats().mNumRenderedTriangles;
2257                        renderedObjects = traverser->GetStats().mNumRenderedGeometry;
2258                        renderedNodes = traverser->GetStats().mNumRenderedNodes;
2259                }
2260
2261                traversedNodes = traverser->GetStats().mNumTraversedNodes;
2262                frustumCulledNodes = traverser->GetStats().mNumFrustumCulledNodes;
2263                queryCulledNodes = traverser->GetStats().mNumQueryCulledNodes;
2264                issuedQueries = traverser->GetStats().mNumIssuedQueries;
2265                stateChanges = traverser->GetStats().mNumStateChanges;
2266                numBatches = traverser->GetStats().mNumBatches;
2267        }
2268
2269
2270        ////////////////
2271        //-- record stats on walkthrough
2272
2273        static float accTime = .0f;
2274        static float averageTime = .0f;
2275
2276        if (currentReplayFrame > -1)
2277        {
2278                accTime += frameTime;
2279                averageTime = accTime / (currentReplayFrame + 1);
2280
2281                if (!statsWriter)
2282                        statsWriter = new StatsWriter(statsFilename + ".log");
2283                       
2284                FrameStats frameStats;
2285                frameStats.mFrame = currentReplayFrame;
2286                frameStats.mFPS = 1e3f / (float)frameTime;
2287                frameStats.mTime = frameTime;
2288                frameStats.mNodes = renderedNodes;
2289                frameStats.mObjects = renderedObjects;
2290                frameStats.mTriangles = renderedTriangles;
2291
2292                statsWriter->WriteFrameStats(frameStats);
2293        }
2294        else if (statsWriter)
2295        {
2296                Debug << "average frame time " << averageTime << " for traversal algorithm " << renderMode << endl;
2297
2298                // reset average frame time
2299                averageTime = accTime = .0f;
2300
2301                DEL_PTR(statsWriter);
2302        }
2303
2304
2305        Begin2D();
2306
2307        glEnable(GL_BLEND);
2308        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2309
2310        if (showHelp)
2311        {       
2312                DrawHelpMessage();
2313        }
2314        else
2315        {
2316                if (showOptions)
2317                {
2318                        glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
2319                        glRecti(5, winHeight - 95, winWidth * 2 / 3 - 5, winHeight - 5);
2320                }
2321
2322                if (showStatistics)
2323                {
2324                        glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
2325                        glRecti(5, winHeight - 165, winWidth * 2 / 3 - 5, winHeight - 100);
2326                }
2327
2328                glEnable(GL_TEXTURE_2D);
2329                myfont.Begin();
2330
2331                if (showOptions)
2332                {
2333                        glColor3f(0.0f, 1.0f, 0.0f);
2334                        int i = 0;
2335
2336                        static char *renderMethodStr[] =
2337                                {"forward", "depth pass + forward", "deferred shading", "depth pass + deferred"};
2338                        sprintf(msg[i ++], "multiqueries: %d, tight bounds: %d, render queue: %d",
2339                                        useMultiQueries, useTightBounds, useRenderQueue);
2340                        sprintf(msg[i ++], "render technique: %s, use pvss: %d", renderMethodStr[renderMethod], usePvs);
2341                        sprintf(msg[i ++], "triangles per virtual leaf: %5d", trianglesPerVirtualLeaf);
2342                        sprintf(msg[i ++], "assumed visible frames: %4d, max batch size: %4d",
2343                                assumedVisibleFrames, maxBatchSize);
2344
2345                        for (int j = 0; j < 4; ++ j)
2346                                myfont.DrawString(msg[j], 10.0f, winHeight - 5 - j * 20);
2347                }
2348
2349                if (showStatistics)
2350                {
2351                        glColor3f(1.0f, 1.0f, 0.0f);
2352
2353                        string objStr, totalObjStr;
2354                        string triStr, totalTriStr;
2355
2356                        int len = 10;
2357                        CalcDecimalPoint(objStr, renderedObjects, len);
2358                        CalcDecimalPoint(totalObjStr, (int)resourceManager->GetNumEntities(), len);
2359
2360                        CalcDecimalPoint(triStr, renderedTriangles, len);
2361                        CalcDecimalPoint(totalTriStr, bvh->GetBvhStats().mTriangles, len);
2362
2363                        int i = 4;
2364
2365                        if (0) // q: show rendered objects or nodes (no space for both)
2366                        {
2367                                sprintf(msg[i ++], "rendered: %s of %s objects, %s of %s triangles",
2368                                        objStr.c_str(), totalObjStr.c_str(), triStr.c_str(), totalTriStr.c_str());
2369                        }
2370                        else
2371                        {
2372                                sprintf(msg[i ++], "rendered: %6d of %6d nodes, %s of %s triangles",
2373                                        renderedNodes, bvh->GetNumVirtualNodes(), triStr.c_str(), totalTriStr.c_str());
2374                        }
2375
2376                        sprintf(msg[i ++], "traversed: %5d, frustum culled: %5d, query culled: %5d nodes",
2377                                traversedNodes, frustumCulledNodes, queryCulledNodes);
2378                        sprintf(msg[i ++], "issued queries: %5d, state changes: %5d, render batches: %5d",
2379                                issuedQueries, stateChanges, numBatches);
2380
2381                        for (int j = 4; j < 7; ++ j)
2382                                myfont.DrawString(msg[j], 10.0f, winHeight - (j + 1) * 20);
2383                }
2384
2385                glColor3f(0.0f, 1.0f, 0.0f);
2386
2387                static char *alg_str[] = {
2388                        "Frustum Cull"
2389                        , "Stop and Wait"
2390                        , "CHC"
2391                        , "CHC ++"
2392            //, "Collector"
2393                };
2394       
2395                if (!showAlgorithmTime)
2396                {
2397                        if (showFPS)
2398                        {                       
2399                                sprintf(msg[7], "%s:  %6.1f fps", alg_str[renderMode], fps);           
2400                                myfont.DrawString(msg[7], 1.3f, winWidth - 350, winHeight - 30.0f);
2401
2402                                //int mrays = (int)shotRays / 1000000;
2403                                //sprintf(msg[7], "%s:  %04d M rays", alg_str[renderMode], mrays);     
2404                                //myfont.DrawString(msg[7], 1.3f, winWidth - 350, winHeight - 60.0f);           
2405                        }
2406                }
2407                else
2408                {
2409                        sprintf(msg[7], "%s:  %6.1f ms", alg_str[renderMode], rTime);
2410                        myfont.DrawString(msg[7], 1.3f, winWidth - 350, winHeight - 30.0f);
2411                }
2412
2413                glColor3f(1.0f, 1.0f, 1.0f);
2414        }
2415
2416        glColor3f(1, 1, 1);
2417        glDisable(GL_BLEND);
2418        glDisable(GL_TEXTURE_2D);
2419
2420        End2D();
2421}       
2422
2423
2424void RenderSky()
2425{
2426        if ((renderMethod == RENDER_DEFERRED) || (renderMethod == RENDER_DEPTH_PASS_DEFERRED))
2427                renderState.SetRenderTechnique(DEFERRED);
2428
2429        const bool useToneMapping =
2430                ((renderMethod == RENDER_DEPTH_PASS_DEFERRED) ||
2431                 (renderMethod == RENDER_DEFERRED)) && useHDR;
2432       
2433        preetham->RenderSkyDome(-light->GetDirection(), camera, &renderState, !useToneMapping, skyDomeScaleFactor);
2434
2435        /// once again reset the renderState just to make sure
2436        renderState.Reset();
2437}
2438
2439
2440// render visible object from depth pass
2441void RenderVisibleObjects()
2442{
2443        if (renderMethod == RENDER_DEPTH_PASS_DEFERRED)
2444        {
2445                if (showShadowMap && !renderLightView)
2446                {
2447                        // usethe maximal visible distance to focus shadow map
2448                        const float newFar = min(camera->GetFar(), traverser->GetMaxVisibleDistance());
2449                        RenderShadowMap(newFar);
2450                }
2451
2452                // initialize deferred rendering
2453                InitDeferredRendering();
2454        }
2455        else
2456        {
2457                renderState.SetRenderTechnique(FORWARD);
2458        }
2459
2460
2461        /////////////////
2462        //-- reset gl renderState before the final visible objects pass
2463
2464        renderState.Reset();
2465
2466        glEnableClientState(GL_NORMAL_ARRAY);
2467        /// switch back to smooth shading
2468        glShadeModel(GL_SMOOTH);
2469        /// reset alpha to coverage flag
2470        renderState.SetUseAlphaToCoverage(true);
2471        // clear color
2472        glClear(GL_COLOR_BUFFER_BIT);
2473       
2474        // draw only objects having exactly the same depth as the current sample
2475        glDepthFunc(GL_EQUAL);
2476
2477        //cout << "visible: " << (int)traverser->GetVisibleObjects().size() << endl;
2478
2479        SceneEntityContainer::const_iterator sit,
2480                sit_end = traverser->GetVisibleObjects().end();
2481
2482        for (sit = traverser->GetVisibleObjects().begin(); sit != sit_end; ++ sit)
2483        {
2484                renderQueue->Enqueue(*sit);
2485        }
2486
2487        /// now render out everything in one giant pass
2488        renderQueue->Apply();
2489
2490        // switch back to standard depth func
2491        glDepthFunc(GL_LESS);
2492        renderState.Reset();
2493
2494        PrintGLerror("visible objects");
2495}
2496
2497
2498SceneQuery *GetOrCreateSceneQuery()
2499{
2500        if (!sceneQuery)
2501        {
2502                sceneQuery = new SceneQuery(bvh->GetBox(), traverser, &renderState);
2503        }
2504
2505        return sceneQuery;
2506}
2507
2508
2509void PlaceViewer(const Vector3 &oldPos)
2510{
2511        Vector3 playerPos = camera->GetPosition();
2512        bool validIntersect = GetOrCreateSceneQuery()->CalcIntersection(playerPos);
2513
2514        if (validIntersect)
2515                //&& ((playerPos.z - oldPos.z) < bvh->GetBox().Size(2) * 1e-1f))
2516        {
2517                camera->SetPosition(playerPos);
2518        }
2519}
2520
2521
2522void RenderShadowMap(float newfar)
2523{
2524        glDisableClientState(GL_NORMAL_ARRAY);
2525        renderState.SetRenderTechnique(DEPTH_PASS);
2526       
2527        // hack: disable cull face because of alpha textured balconies
2528        glDisable(GL_CULL_FACE);
2529        renderState.LockCullFaceEnabled(true);
2530
2531        /// don't use alpha to coverage for the depth map (problems with fbo rendering)
2532        renderState.SetUseAlphaToCoverage(false);
2533
2534        const Vector3 lightPos = light->GetDirection() * -1e3f;
2535        if (usePvs) LoadOrUpdatePVSs(lightPos);
2536
2537
2538        // change CHC++ set of renderState variables
2539        // this must be done for each change of camera because
2540        // otherwise the temporal coherency is broken
2541        BvhNode::SetCurrentState(LIGHT_PASS);
2542        // hack: temporarily change camera far plane
2543        camera->SetFar(newfar);
2544        // the scene is rendered withouth any shading   
2545        shadowMap->ComputeShadowMap(shadowTraverser, viewProjMat);
2546
2547        camera->SetFar(farDist);
2548
2549        renderState.SetUseAlphaToCoverage(true);
2550        renderState.LockCullFaceEnabled(false);
2551        glEnable(GL_CULL_FACE);
2552
2553        glEnableClientState(GL_NORMAL_ARRAY);
2554        // change back renderState
2555        BvhNode::SetCurrentState(CAMERA_PASS);
2556}
2557
2558
2559/** Touch each material once in order to preload the render queue
2560        bucket id of each material
2561*/
2562void PrepareRenderQueue()
2563{
2564        for (int i = 0; i < 3; ++ i)
2565        {
2566                renderState.SetRenderTechnique(i);
2567
2568                // fill all shapes into the render queue        once so we can establish the buckets
2569                ShapeContainer::const_iterator sit, sit_end = (*resourceManager->GetShapes()).end();
2570
2571                for (sit = (*resourceManager->GetShapes()).begin(); sit != sit_end; ++ sit)
2572                {
2573                        static Transform3 dummy(IdentityMatrix());
2574                        renderQueue->Enqueue(*sit, NULL);
2575                }
2576       
2577                // just clear queue again
2578                renderQueue->Clear();
2579        }
2580}
2581
2582
2583int LoadModel(const string &model, SceneEntityContainer &entities)
2584{
2585        const string filename = string(model_path + model);
2586        int numEntities = 0;
2587
2588        cout << "\nloading model " << filename << endl;
2589
2590        if (numEntities = resourceManager->Load(filename, entities))
2591        {
2592                cout << "model " << filename << " successfully loaded" << endl;
2593        }
2594        else
2595        {
2596                cerr << "loading model " << filename << " failed" << endl;
2597
2598                CleanUp();
2599                exit(0);
2600        }
2601
2602        return numEntities;
2603}
2604
2605
2606void CreateAnimation()
2607{
2608        const float radius = 5.0f;
2609        const Vector3 center(480.398f, 268.364f, 181.3);
2610
2611        VertexArray vertices;
2612
2613        /*for (int i = 0; i < 360; ++ i)
2614        {
2615                float angle = (float)i * M_PI / 180.0f;
2616
2617                Vector3 offs = Vector3(cos(angle) * radius, sin(angle) * radius, 0);
2618                vertices.push_back(center + offs);
2619        }*/
2620
2621        for (int i = 0; i < 5; ++ i)
2622        {
2623                Vector3 offs = Vector3(i, 0, 0);
2624                vertices.push_back(center + offs);
2625        }
2626
2627       
2628        for (int i = 0; i < 5; ++ i)
2629        {
2630                Vector3 offs = Vector3(4 -i, 0, 0);
2631                vertices.push_back(center + offs);
2632        }
2633
2634        motionPath = new MotionPath(vertices);
2635}
2636
2637/** This function returns the number of visible pixels of a
2638        bounding box representing the sun.
2639*/
2640int TestSunVisible()
2641{
2642        // assume sun is at a far away point along the light vector
2643        Vector3 sunPos = light->GetDirection() * -1e3f;
2644        sunPos += camera->GetPosition();
2645
2646        sunBox->GetTransform()->SetMatrix(TranslationMatrix(sunPos));
2647
2648        glBeginQueryARB(GL_SAMPLES_PASSED_ARB, sunQuery);
2649
2650        sunBox->Render(&renderState);
2651
2652        glEndQueryARB(GL_SAMPLES_PASSED_ARB);
2653
2654        GLuint sampleCount;
2655
2656        glGetQueryObjectuivARB(sunQuery, GL_QUERY_RESULT_ARB, &sampleCount);
2657
2658        return sampleCount;
2659}
2660
2661
2662static Technique GetVizTechnique()
2663{
2664        Technique tech;
2665        tech.Init();
2666
2667        tech.SetEmmisive(RgbaColor(1.0f, 1.0f, 1.0f, 1.0f));
2668        tech.SetDiffuse(RgbaColor(1.0f, 1.0f, 1.0f, 1.0f));
2669        tech.SetAmbient(RgbaColor(1.0f, 1.0f, 1.0f, 1.0f));
2670
2671        return tech;
2672}
2673
2674
2675void UpdatePvs(const Vector3 &pos)
2676{
2677        viewCell = viewCellsTree->GetViewCell(camera->GetPosition());
2678
2679        const float elapsedAlgorithmTime = applicationTimer.Elapsedms(false);
2680
2681        // assume 60 FPS, total time is in secs
2682        const float raysPerMs = 2.0f * pvsTotalSamples / (pvsTotalTime * 1000.0f);
2683        //shotRays = visibilitySolutionInitialState + elapsedAlgorithmTime * raysPerMs;
2684        //shotRays += 1000 * raysPerMs / 60.0f;
2685
2686        //cout << "totalt: " << pvsTotalTime << endl;
2687        //cout << "rays per ms: " << raysPerMs << endl;
2688
2689        SceneEntity::SetCurrentVisibleId(globalVisibleId);
2690
2691        for (int i = 0; i < viewCell->mPvs.GetSize(); ++ i)
2692        {
2693                PvsEntry entry = viewCell->mPvs.GetEntry(i);
2694#ifdef USE_TIMESTAMPS
2695                if (!((entry.mTimeStamp < 0.0f) || (entry.mTimeStamp <= shotRays)))
2696                        continue;
2697#endif
2698                entry.mEntity->SetVisibleId(globalVisibleId);
2699                //numTriangles += entry.mEntity->CountNumTriangles();
2700        }
2701
2702        ++ globalVisibleId;
2703}
2704
2705
2706void LoadVisibilitySolution()
2707{
2708        ///////////
2709        //-- load the visibility solution
2710
2711        const string vis_filename =
2712                string(model_path + visibilitySolution + ".vis");
2713
2714        VisibilitySolutionLoader visLoader;
2715
2716        viewCellsTree = visLoader.Load(vis_filename,
2717                                           bvh,
2718                                                                   pvsTotalSamples,
2719                                                                   pvsTotalTime,
2720                                                                   viewCellsScaleFactor);
2721
2722        if (!viewCellsTree)
2723        {
2724                cerr << "loading pvs failed" << endl;
2725                CleanUp();
2726                exit(0);
2727        }
2728}
2729
2730
2731void RenderViewCell()
2732{
2733        // render current view cell
2734        static Technique vcTechnique = GetVizTechnique();
2735
2736        vcTechnique.Render(&renderState);
2737        Visualization::RenderBoxForViz(viewCell->GetBox());
2738}
2739
2740
2741void LoadPompeiiFloor()
2742{
2743        AxisAlignedBox3 pompeiiBox =
2744                SceneEntity::ComputeBoundingBox(staticObjects);
2745
2746        // todo: dispose texture
2747        Texture *floorTex = new Texture(model_path + "stairs.c.01.tif");
2748
2749        floorTex->SetBoundaryModeS(Texture::REPEAT);
2750        floorTex->SetBoundaryModeT(Texture::REPEAT);
2751
2752        floorTex->Create();
2753        Material *mymat = resourceManager->CreateMaterial();
2754
2755        Technique *tech = mymat->GetDefaultTechnique();
2756        tech->SetDiffuse(RgbaColor(1, 1, 1, 1));
2757        tech->SetTexture(floorTex);
2758
2759        Technique *depthPass = new Technique(*tech);
2760        Technique *deferred = new Technique(*tech);
2761
2762        depthPass->SetColorWriteEnabled(false);
2763        depthPass->SetLightingEnabled(false);
2764
2765        ShaderProgram *defaultFragmentTexProgramMrt =
2766                ShaderManager::GetSingleton()->GetShaderProgram("defaultFragmentTexMrt");
2767        ShaderProgram *defaultVertexProgramMrt =
2768                ShaderManager::GetSingleton()->GetShaderProgram("defaultVertexMrt");
2769
2770        deferred->SetFragmentProgram(defaultFragmentTexProgramMrt);
2771        deferred->SetVertexProgram(defaultVertexProgramMrt);
2772
2773        deferred->GetFragmentProgramParameters()->SetViewMatrixParam(0);
2774        deferred->GetVertexProgramParameters()->SetModelMatrixParam(1);
2775        deferred->GetVertexProgramParameters()->SetOldModelMatrixParam(2);
2776
2777        deferred->SetTexture(floorTex);
2778       
2779        mymat->AddTechnique(deferred);
2780        mymat->AddTechnique(depthPass);
2781
2782
2783        //const Vector3 offs(1300.0f, -2500.0f, .0f);
2784        const Vector3 offs(pompeiiBox.Center(0), pompeiiBox.Center(1), 0);
2785        Matrix4x4 moffs = TranslationMatrix(offs);
2786
2787        Plane3 plane;
2788        Transform3 *mytrafo = resourceManager->CreateTransform(moffs);
2789
2790        SceneEntity *myplane =
2791                SceneEntityConverter().ConvertPlane(plane,
2792                                                    pompeiiBox.Size(0),
2793                                                                                        pompeiiBox.Size(1),
2794                                                                                        5,
2795                                                                                        5,
2796                                                                                        mymat,
2797                                                                                        mytrafo);
2798
2799        resourceManager->AddSceneEntity(myplane);
2800        staticObjects.push_back(myplane);
2801}
2802
2803
2804void LoadOrUpdatePVSs(const Vector3 &pos)
2805{
2806        if (!viewCellsTree)     
2807        {
2808                LoadVisibilitySolution();
2809                applicationTimer.Start();
2810                shotRays = visibilitySolutionInitialState;
2811        }
2812
2813        if (viewCellsTree) UpdatePvs(pos);
2814}
Note: See TracBrowser for help on using the repository browser.