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

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