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

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