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

Revision 3120, 51.2 KB checked in by mattausch, 16 years ago (diff)

worked on filtering now trying to reduce flickering (have to reorder ssao function quite much

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