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

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