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

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