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

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