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

Revision 2957, 48.3 KB checked in by mattausch, 16 years ago (diff)

preetham working

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