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

Revision 3282, 67.7 KB checked in by mattausch, 15 years ago (diff)

probably found export error

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