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

Revision 3146, 51.9 KB checked in by mattausch, 16 years ago (diff)

normal mapping hack not working yet. found problems with ssao if the geometry is not tesselated enough (especially with smoothed
normals: one can see the underlying tesselation!

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