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

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