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

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