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

Revision 3251, 63.9 KB checked in by mattausch, 15 years ago (diff)

played around with pvs. now using pvs without vfc or anything. using function that allows to skip tree at some point

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