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

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