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

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