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

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