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

Revision 3089, 49.0 KB checked in by mattausch, 16 years ago (diff)

working better but stil not fully there

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