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

Revision 3371, 72.8 KB checked in by mattausch, 15 years ago (diff)

fehler tritt nicht auf!!

RevLine 
[2961]1// chcdemo.cpp : Defines the entry point for the console application.
[2642]2//
[3019]3
[3021]4
5#include "common.h"
6
[3019]7#ifdef _CRT_SET
8        #define _CRTDBG_MAP_ALLOC
9        #include <stdlib.h>
10        #include <crtdbg.h>
11
12        // redefine new operator
13        #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
14        #define new DEBUG_NEW
15#endif
16
[2746]17#include <math.h>
18#include <time.h>
[3019]19#include "glInterface.h"
20
21
[2642]22#include "RenderTraverser.h"
[2756]23#include "SceneEntity.h"
24#include "Vector3.h"
25#include "Matrix4x4.h"
[2795]26#include "ResourceManager.h"
[2756]27#include "Bvh.h"
28#include "Camera.h"
29#include "Geometry.h"
[2760]30#include "BvhLoader.h"
31#include "FrustumCullingTraverser.h"
[2763]32#include "StopAndWaitTraverser.h"
[2764]33#include "CHCTraverser.h"
[2767]34#include "CHCPlusPlusTraverser.h"
35#include "Visualization.h"
[2769]36#include "RenderState.h"
[2795]37#include "Timer/PerfTimer.h"
[2796]38#include "SceneQuery.h"
[2801]39#include "RenderQueue.h"
[2819]40#include "Material.h"
[2826]41#include "glfont2.h"
[2827]42#include "PerformanceGraph.h"
[2828]43#include "Environment.h"
[2837]44#include "Halton.h"
[2840]45#include "Transform3.h"
[2853]46#include "SampleGenerator.h"
[2857]47#include "FrameBufferObject.h"
[2896]48#include "DeferredRenderer.h"
[2887]49#include "ShadowMapping.h"
50#include "Light.h"
[2953]51#include "SceneEntityConverter.h"
[2957]52#include "SkyPreetham.h"
[2964]53#include "Texture.h"
[3057]54#include "ShaderManager.h"
[3078]55#include "MotionPath.h"
[3113]56#include "ShaderProgram.h"
57#include "Shape.h"
[3219]58#include "WalkThroughRecorder.h"
[3223]59#include "StatsWriter.h"
[3243]60#include "VisibilitySolutionLoader.h"
61#include "ViewCellsTree.h"
[3258]62#include "PvsCollectionRenderer.h"
[3260]63#include "ObjExporter.h"
64#include "BvhExporter.h"
[2642]65
[3066]66
[2756]67using namespace std;
[2776]68using namespace CHCDemoEngine;
[2642]69
70
[3068]71/// the environment for the program parameter
[2828]72static Environment env;
73
74
[2826]75GLuint fontTex;
[3068]76/// the fbo used for MRT
[3038]77FrameBufferObject *fbo = NULL;
[2756]78/// the renderable scene geometry
[3267]79SceneEntityContainer staticObjects;
[3214]80/// the dynamic objects in the scene
[3070]81SceneEntityContainer dynamicObjects;
[2756]82// traverses and renders the hierarchy
[2767]83RenderTraverser *traverser = NULL;
[2756]84/// the hierarchy
[2767]85Bvh *bvh = NULL;
[2793]86/// handles scene loading
[3059]87ResourceManager *resourceManager = NULL;
[3057]88/// handles scene loading
89ShaderManager *shaderManager = NULL;
[2756]90/// the scene camera
[3062]91PerspectiveCamera *camera = NULL;
[2795]92/// the scene camera
[3062]93PerspectiveCamera *visCamera = NULL;
[2767]94/// the visualization
95Visualization *visualization = NULL;
[3101]96/// the current render renderState
97RenderState renderState;
[2764]98/// the rendering algorithm
[2795]99int renderMode = RenderTraverser::CHCPLUSPLUS;
[3038]100/// eye near plane distance
[3068]101const float nearDist = 0.2f;
[3106]102//const float nearDist = 1.0f;
[3038]103/// eye far plane distance
[2927]104float farDist = 1e6f;
[2856]105/// the field of view
[3369]106//const float fov = 50.0f;
107const float fov = 90.0f;
[2764]108
[3279]109float skyDomeScaleFactor = 80.0f;
110
[2796]111SceneQuery *sceneQuery = NULL;
[2801]112RenderQueue *renderQueue = NULL;
[3068]113/// traverses and renders the hierarchy
[2897]114RenderTraverser *shadowTraverser = NULL;
[3068]115/// the skylight + skydome model
[2957]116SkyPreetham *preetham = NULL;
[2897]117
[3078]118MotionPath *motionPath = NULL;
[3189]119/// max depth where candidates for tighter bounds are searched
[3123]120int maxDepthForTestingChildren = 3;
[3246]121/// use full resolution for ssao or half
[3216]122bool ssaoUseFullResolution = false;
[3123]123
[3219]124/// store the frames as tga
125bool recordFrames = false;
126/// record the taken path
127bool recordPath = false;
128/// replays the recorded path
129bool replayPath = false;
[3223]130/// frame number for replay
[3219]131int currentReplayFrame = -1;
132
[3220]133string recordedFramesSuffix("frames");
[3223]134string statsFilename("stats");
[3220]135
[3238]136string filename("city");
[3271]137string bvhname("");
[3243]138string visibilitySolution("");
[3238]139
140
[3219]141/// the walkThroughRecorder
142WalkThroughRecorder *walkThroughRecorder = NULL;
143WalkThroughPlayer *walkThroughPlayer = NULL;
[3223]144StatsWriter *statsWriter = NULL;
[3219]145
[3225]146bool makeSnapShot = false;
[3219]147
[3244]148ViewCellsTree *viewCellsTree = NULL;
[3246]149ViewCell *viewCell = NULL;
[3225]150
[3247]151bool useSkylightForIllum = true;
[3273]152bool showFPS = true;
[3245]153static int globalVisibleId = 0;
[3284]154PerfTimer applicationTimer;
[3245]155
[3284]156float shotRays = .0f;
[3286]157/// the visibility solution is initialized at this number of rays shot that
158int visibilitySolutionInitialState = 0;
[3245]159
[3295]160Vector3 defaultAmbient(0.2f);
161Vector3 defaultDiffuse(1.0f);
[3284]162
[3295]163
[3068]164/// the technique used for rendering
165enum RenderTechnique
166{
167        FORWARD,
168        DEFERRED,
169        DEPTH_PASS
170};
171
172
[2994]173/// the used render type for this render pass
174enum RenderMethod
175{
[3043]176        RENDER_FORWARD,
[2994]177        RENDER_DEPTH_PASS,
178        RENDER_DEFERRED,
179        RENDER_DEPTH_PASS_DEFERRED,
180        RENDER_NUM_RENDER_TYPES
181};
[2957]182
[2994]183/// one of four possible render methods
[3043]184int renderMethod = RENDER_FORWARD;
[2994]185
[3059]186static int winWidth = 1024;
187static int winHeight = 768;
188static float winAspectRatio = 1.0f;
[2994]189
[2809]190/// these values get scaled with the frame rate
[2828]191static float keyForwardMotion = 30.0f;
192static float keyRotation = 1.5f;
[2801]193
[2826]194/// elapsed time in milliseconds
[3059]195double elapsedTime = 1000.0;
196double algTime = 1000.0;
197double accumulatedTime = 1000.0;
198float fps = 1e3f;
[3193]199float turbitity = 5.0f;
[2795]200
[3212]201// ssao parameters
202float ssaoKernelRadius = 1e-8f;
[3361]203float ssaoSampleIntensity = .2f;
[3305]204float ssaoFilterRadius = 3.0f;
[3212]205float ssaoTempCohFactor = 255.0;
206bool sortSamples = true;
207
[2945]208int shadowSize = 2048;
[3212]209
[3059]210/// the hud font
[2826]211glfont::GLFont myfont;
212
[2809]213// rendertexture
[3212]214int texWidth = 1024;
215int texHeight = 768;
[2866]216
[2770]217int renderedObjects = 0;
[2773]218int renderedNodes = 0;
219int renderedTriangles = 0;
220
[2770]221int issuedQueries = 0;
222int traversedNodes = 0;
223int frustumCulledNodes = 0;
224int queryCulledNodes = 0;
225int stateChanges = 0;
[2800]226int numBatches = 0;
[2770]227
[3101]228// mouse navigation renderState
[2809]229int xEyeBegin = 0;
230int yEyeBegin = 0;
231int yMotionBegin = 0;
232int verticalMotionBegin = 0;
233int horizontalMotionBegin = 0;
[2642]234
[2792]235bool leftKeyPressed = false;
236bool rightKeyPressed = false;
237bool upKeyPressed = false;
238bool downKeyPressed = false;
[2837]239bool descendKeyPressed = false;
240bool ascendKeyPressed = false;
[3105]241bool leftStrafeKeyPressed = false;
242bool rightStrafeKeyPressed = false;
243
[3054]244bool altKeyPressed = false;
245
[2994]246bool showHelp = false;
247bool showStatistics = false;
248bool showOptions = true;
249bool showBoundingVolumes = false;
250bool visMode = false;
251
252bool useOptimization = false;
[3074]253bool useTightBounds = true;
[2994]254bool useRenderQueue = true;
255bool useMultiQueries = true;
256bool flyMode = true;
257
[2875]258bool useGlobIllum = false;
259bool useTemporalCoherence = true;
[2994]260bool showAlgorithmTime = false;
[2875]261
[2994]262bool useFullScreen = false;
263bool useLODs = true;
264bool moveLight = false;
265
266bool useAdvancedShading = false;
267bool showShadowMap = false;
268bool renderLightView = false;
[3054]269bool useHDR = true;
[3175]270bool useAntiAliasing = true;
[3215]271bool useLenseFlare = true;
[2994]272
[3246]273bool usePvs = false;
274
275
[3054]276PerfTimer frameTimer, algTimer;
[3212]277/// the performance graph window
[3054]278PerformanceGraph *perfGraph = NULL;
[2994]279
[3189]280int sCurrentMrtSet = 0;
[3111]281static Matrix4x4 invTrafo = IdentityMatrix();
[3246]282float mouseMotion = 0.2f;
[3111]283
[3256]284float viewCellsScaleFactor = 1.0f;
[3246]285
[3316]286float maxConvergence = 2000.0f;
[3319]287float spatialWeight = 0.0001f;
[3256]288
[3316]289
[3068]290//////////////
[3246]291//-- chc++ algorithm parameters
[2827]292
[3068]293/// the pixel threshold where a node is still considered invisible
294/// (should be zero for conservative visibility)
295int threshold;
296int assumedVisibleFrames = 10;
297int maxBatchSize = 50;
298int trianglesPerVirtualLeaf = INITIAL_TRIANGLES_PER_VIRTUAL_LEAVES;
299
[3244]300
[3068]301//////////////
302
303enum {CAMERA_PASS = 0, LIGHT_PASS = 1};
304
305
[2948]306//DeferredRenderer::SAMPLING_METHOD samplingMethod = DeferredRenderer::SAMPLING_POISSON;
307DeferredRenderer::SAMPLING_METHOD samplingMethod = DeferredRenderer::SAMPLING_QUADRATIC;
[2865]308
[2894]309ShadowMap *shadowMap = NULL;
[2952]310DirectionalLight *light = NULL;
[3111]311DeferredRenderer *deferredShader = NULL;
[2834]312
[3175]313
[3059]314SceneEntity *buddha = NULL;
[2957]315SceneEntity *skyDome = NULL;
[3214]316SceneEntity *sunBox = NULL;
[2895]317
[3214]318GLuint sunQuery = 0;
[2952]319
[3271]320string walkThroughSuffix("frames");
[3214]321
[3271]322
[3059]323////////////////////
324//--- function forward declarations
[2991]325
[2759]326void InitExtensions();
[3059]327void InitGLstate();
328
[2756]329void DisplayVisualization();
[3059]330/// destroys all allocated resources
[2759]331void CleanUp();
332void SetupEyeView();
333void SetupLighting();
[2764]334void DisplayStats();
[3059]335/// draw the help screen
[2786]336void DrawHelpMessage();
[3059]337/// render the sky dome
[2796]338void RenderSky();
[3059]339/// render the objects found visible in the depth pass
[2801]340void RenderVisibleObjects();
[2756]341
[3215]342int TestSunVisible();
[3214]343
[2792]344void Begin2D();
345void End2D();
[3059]346/// the main loop
347void MainLoop();
348
[2792]349void KeyBoard(unsigned char c, int x, int y);
350void Special(int c, int x, int y);
351void KeyUp(unsigned char c, int x, int y);
352void SpecialKeyUp(int c, int x, int y);
353void Reshape(int w, int h);
[3101]354void Mouse(int button, int renderState, int x, int y);
[2792]355void LeftMotion(int x, int y);
356void RightMotion(int x, int y);
357void MiddleMotion(int x, int y);
[3059]358void KeyHorizontalMotion(float shift);
359void KeyVerticalMotion(float shift);
360/// returns the string representation of a number with the decimal points
[2792]361void CalcDecimalPoint(string &str, int d);
[3059]362/// Creates the traversal method (vfc, stopandwait, chc, chc++)
[3062]363RenderTraverser *CreateTraverser(PerspectiveCamera *cam);
[3059]364/// place the viewer on the floor plane
[2801]365void PlaceViewer(const Vector3 &oldPos);
[3019]366// initialise the frame buffer objects
[2809]367void InitFBO();
[3059]368/// changes the sunlight direction
[2954]369void RightMotionLight(int x, int y);
[3059]370/// render the shader map
[2951]371void RenderShadowMap(float newfar);
[3059]372/// function that touches each material once in order to accelarate render queue
373void PrepareRenderQueue();
374/// loads the specified model
[3237]375int LoadModel(const string &model, SceneEntityContainer &entities);
[2810]376
[3059]377inline float KeyRotationAngle() { return keyRotation * elapsedTime * 1e-3f; }
378inline float KeyShift() { return keyForwardMotion * elapsedTime * 1e-3f; }
[3054]379
[3316]380void CreateAnimation(const Vector3 &pos);
[3078]381
[3120]382SceneQuery *GetOrCreateSceneQuery();
[3078]383
[3246]384void LoadPvs();
[3120]385
[3246]386void LoadVisibilitySolution();
[3244]387
[3246]388void RenderViewCell();
389
[3279]390void LoadPompeiiFloor();
[3246]391
[3287]392void LoadOrUpdatePVSs(const Vector3 &pos);
393
[3316]394void CreateNewInstance(SceneEntity *parent, const Vector3 &pos);
395
396
397/////////////
398
[3292]399string envFileName = "default.env";
[3287]400
[3285]401float pvsTotalSamples = .0f;
402float pvsTotalTime = .0f;
[3276]403
[3285]404
[3120]405// new view projection matrix of the camera
[3005]406static Matrix4x4 viewProjMat = IdentityMatrix();
[3120]407// the old view projection matrix of the camera
[3005]408static Matrix4x4 oldViewProjMat = IdentityMatrix();
[2820]409
[2837]410
[2995]411
[2809]412static void PrintGLerror(char *msg)
413{
414        GLenum errCode;
415        const GLubyte *errStr;
416       
417        if ((errCode = glGetError()) != GL_NO_ERROR)
418        {
419                errStr = gluErrorString(errCode);
420                fprintf(stderr,"OpenGL ERROR: %s: %s\n", errStr, msg);
421        }
422}
423
424
[2642]425int main(int argc, char* argv[])
426{
[3019]427#ifdef _CRT_SET
428        //Now just call this function at the start of your program and if you're
429        //compiling in debug mode (F5), any leaks will be displayed in the Output
430        //window when the program shuts down. If you're not in debug mode this will
431        //be ignored. Use it as you will!
432        //note: from GDNet Direct [3.8.04 - 3.14.04] void detectMemoryLeaks() {
433
434        _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF|_CRTDBG_ALLOC_MEM_DF);
435        _CrtSetReportMode(_CRT_ASSERT,_CRTDBG_MODE_FILE);
436        _CrtSetReportFile(_CRT_ASSERT,_CRTDBG_FILE_STDERR);
437#endif
[3052]438
[3019]439
[2781]440        int returnCode = 0;
441
[2837]442        Vector3 camPos(.0f, .0f, .0f);
[2838]443        Vector3 camDir(.0f, 1.0f, .0f);
[2952]444        Vector3 lightDir(-0.8f, 1.0f, -0.7f);
[2837]445
[3292]446        if (argc > 1) envFileName = argv[1];
[2830]447
[3292]448        cout << "=== reading environment file " << envFileName << " ===" << endl << endl;
449
[2837]450        if (!env.Read(envFileName))
451        {
452                cerr << "loading environment " << envFileName << " failed!" << endl;
453        }
454        else
455        {
456                env.GetIntParam(string("assumedVisibleFrames"), assumedVisibleFrames);
457                env.GetIntParam(string("maxBatchSize"), maxBatchSize);
458                env.GetIntParam(string("trianglesPerVirtualLeaf"), trianglesPerVirtualLeaf);
[3123]459                env.GetIntParam(string("winWidth"), winWidth);
460                env.GetIntParam(string("winHeight"), winHeight);
461                env.GetIntParam(string("shadowSize"), shadowSize);
462                env.GetIntParam(string("maxDepthForTestingChildren"), maxDepthForTestingChildren);
[2828]463
[2837]464                env.GetFloatParam(string("keyForwardMotion"), keyForwardMotion);
465                env.GetFloatParam(string("keyRotation"), keyRotation);
[3246]466                env.GetFloatParam(string("mouseMotion"), mouseMotion);
[3123]467                env.GetFloatParam(string("tempCohFactor"), ssaoTempCohFactor);
[3193]468                env.GetFloatParam(string("turbitity"), turbitity);
[3123]469               
[2837]470                env.GetVectorParam(string("camPosition"), camPos);
[2838]471                env.GetVectorParam(string("camDirection"), camDir);
[2952]472                env.GetVectorParam(string("lightDirection"), lightDir);
[3295]473                env.GetVectorParam(string("defaultAmbient"), defaultAmbient);
474                env.GetVectorParam(string("defaultDiffuse"), defaultDiffuse);
[2865]475
[3117]476                env.GetBoolParam(string("useFullScreen"), useFullScreen);
477                env.GetBoolParam(string("useLODs"), useLODs);
[2994]478                env.GetBoolParam(string("useHDR"), useHDR);
[3175]479                env.GetBoolParam(string("useAA"), useAntiAliasing);
[3215]480                env.GetBoolParam(string("useLenseFlare"), useLenseFlare);
[3175]481                env.GetBoolParam(string("useAdvancedShading"), useAdvancedShading);
[2994]482
[3175]483                env.GetIntParam(string("renderMethod"), renderMethod);
[3117]484
[3212]485                env.GetFloatParam(string("ssaoKernelRadius"), ssaoKernelRadius);
486                env.GetFloatParam(string("ssaoSampleIntensity"), ssaoSampleIntensity);
[3216]487                env.GetBoolParam(string("ssaoUseFullResolution"), ssaoUseFullResolution);
488
[3220]489                env.GetStringParam(string("recordedFramesSuffix"), recordedFramesSuffix);
[3271]490                env.GetStringParam(string("walkThroughSuffix"), walkThroughSuffix);
[3223]491                env.GetStringParam(string("statsFilename"), statsFilename);
[3238]492                env.GetStringParam(string("filename"), filename);
[3271]493                env.GetStringParam(string("bvhname"), bvhname);
[3243]494                env.GetStringParam(string("visibilitySolution"), visibilitySolution);
[3220]495
[3246]496                env.GetBoolParam(string("usePvs"), usePvs);
[3247]497                env.GetBoolParam(string("useSkylightForIllum"), useSkylightForIllum);
[3256]498                env.GetFloatParam(string("viewCellsScaleFactor"), viewCellsScaleFactor);
[3279]499                env.GetFloatParam(string("skyDomeScaleFactor"), skyDomeScaleFactor);
[3286]500                env.GetIntParam(string("visibilitySolutionInitialState"), visibilitySolutionInitialState);
[3294]501                env.GetIntParam(string("renderMode"), renderMode);
[3279]502               
[2846]503                //env.GetStringParam(string("modelPath"), model_path);
[2838]504                //env.GetIntParam(string("numSssaoSamples"), numSsaoSamples);
505
[3212]506                texWidth = winWidth;
507                texHeight = winHeight;
508
[3251]509                cout << "assumed visible frames: " << assumedVisibleFrames << endl;
510                cout << "max batch size: " << maxBatchSize << endl;
511                cout << "triangles per virtual leaf: " << trianglesPerVirtualLeaf << endl;
[2828]512
[3271]513                cout << "static scene filename prefix: " << filename << endl;
514                cout << "bvh filename prefix: " << bvhname << endl;
515
[3251]516                cout << "key forward motion: " << keyForwardMotion << endl;
517                cout << "key rotation: " << keyRotation << endl;
518                cout << "win width: " << winWidth << endl;
519                cout << "win height: " << winHeight << endl;
520                cout << "use full screen: " << useFullScreen << endl;
521                cout << "use LODs: " << useLODs << endl;
522                cout << "camera position: " << camPos << endl;
[2945]523                cout << "shadow size: " << shadowSize << endl;
[3175]524                cout << "render method: " << renderMethod << endl;
525                cout << "use antialiasing: " << useAntiAliasing << endl;
[3215]526                cout << "use lense flare: " << useLenseFlare << endl;
[3175]527                cout << "use advanced shading: " << useAdvancedShading << endl;
[3193]528                cout << "turbitity: " << turbitity << endl;
[3251]529                cout << "temporal coherence factor: " << ssaoTempCohFactor << endl;
[3212]530                cout << "sample intensity: " << ssaoSampleIntensity << endl;
531                cout << "kernel radius: " << ssaoKernelRadius << endl;
[3251]532                cout << "use ssao full resolution: " << ssaoUseFullResolution << endl;
[3220]533                cout << "recorded frames suffix: " << recordedFramesSuffix << endl;
[3271]534                cout << "walkthrough suffix: " << walkThroughSuffix << endl;
[3223]535                cout << "stats filename: " << statsFilename << endl;
[3251]536                cout << "use PVSs: " << usePvs << endl;
537                cout << "visibility solution: " << visibilitySolution << endl;
[3256]538                cout << "view cells scale factor: " << viewCellsScaleFactor << endl;
[3251]539                cout << "use skylight for illumination: " << useSkylightForIllum << endl;
[3279]540                cout << "sky dome scale factor: " << skyDomeScaleFactor << endl;
[3294]541                cout << "rendermode: " << renderMode << endl;
[2873]542
[2846]543                //cout << "model path: " << model_path << endl;
[3294]544                cout << "==== end parameters ====" << endl << endl;
[2837]545        }
[2829]546
[2828]547        ///////////////////////////
548
[3062]549        camera = new PerspectiveCamera(winWidth / winHeight, fov);
[2795]550        camera->SetNear(nearDist);
[3360]551        camera->SetFar(1e6f);
[2888]552
[2838]553        camera->SetDirection(camDir);
[2829]554        camera->SetPosition(camPos);
555
[3062]556        visCamera = new PerspectiveCamera(winWidth / winHeight, fov);
[3353]557        visCamera->SetNear(.0f);
[2796]558        visCamera->Yaw(.5 * M_PI);
[2781]559
[2952]560        // create a new light
[2968]561        light = new DirectionalLight(lightDir, RgbaColor(1, 1, 1, 1), RgbaColor(1, 1, 1, 1));
[3061]562        // the render queue for material sorting
[3101]563        renderQueue = new RenderQueue(&renderState);
[2952]564
[2760]565        glutInitWindowSize(winWidth, winHeight);
[2756]566        glutInit(&argc, argv);
[2853]567        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_MULTISAMPLE);
568        //glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
[2850]569        //glutInitDisplayString("samples=2");
570
[2867]571        SceneEntity::SetUseLODs(useLODs);
572
[3256]573
[2828]574        if (!useFullScreen)
[2856]575        {
[2828]576                glutCreateWindow("FriendlyCulling");
[2856]577        }
[2828]578        else
579        {
580                glutGameModeString( "1024x768:32@75" );
581                glutEnterGameMode();
582        }
583
[3059]584        glutDisplayFunc(MainLoop);
[2792]585        glutKeyboardFunc(KeyBoard);
586        glutSpecialFunc(Special);
587        glutReshapeFunc(Reshape);
588        glutMouseFunc(Mouse);
[3059]589        glutIdleFunc(MainLoop);
[2792]590        glutKeyboardUpFunc(KeyUp);
591        glutSpecialUpFunc(SpecialKeyUp);
592        glutIgnoreKeyRepeat(true);
593
[2829]594        // initialise gl graphics
[2756]595        InitExtensions();
596        InitGLstate();
[2850]597
[2854]598        glEnable(GL_MULTISAMPLE_ARB);
599        glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST);
[2850]600
[2792]601        LeftMotion(0, 0);
602        MiddleMotion(0, 0);
[2756]603
[2829]604        perfGraph = new PerformanceGraph(1000);
[2756]605
[3059]606        resourceManager = ResourceManager::GetSingleton();
[3057]607        shaderManager = ShaderManager::GetSingleton();
[2793]608
[3220]609
[3059]610        ///////////
611        //-- load the static scene geometry
[2756]612
[3267]613        LoadModel(filename + ".dem", staticObjects);
[3059]614
[3074]615
[3072]616        //////////
617        //-- load some dynamic stuff
[3059]618
[3203]619        //resourceManager->mUseNormalMapping = true;
[3193]620        //resourceManager->mUseNormalMapping = false;
[3226]621        resourceManager->mUseSpecialColors = true;
622
[3203]623        //LoadModel("fisch.dem", dynamicObjects);
[3235]624
[3146]625        //LoadModel("venusm.dem", dynamicObjects);
[3153]626        //LoadModel("camel.dem", dynamicObjects);
[3146]627        //LoadModel("toyplane2.dem", dynamicObjects);
[3151]628        //LoadModel("elephal.dem", dynamicObjects);
[3128]629
[3369]630        if (1) LoadPompeiiFloor();
[3362]631
[3360]632#if 1
[3271]633
[3319]634#if 0
[3318]635        // vienna positions
[3316]636        VertexArray positions;
637        positions.push_back(Vector3(478.398f, 268.0f, 181.3));
638        positions.push_back(Vector3(470.461, 268.543, 181.7));
639        positions.push_back(Vector3(499.648, 264.358, 181.7));
640        positions.push_back(Vector3(487.913, 285.162, 181.7));
641
642#else
643
[3318]644        // sibenik positions
[3316]645        VertexArray positions;
[3369]646        //const float factor2 = 1.6f;
647        const float factor2 = 1.5f;
648
[3360]649        // for buddha (lowres)
[3362]650        positions.push_back(Vector3(6.07307, 8.20723, 6.62 - factor2));
651        positions.push_back(Vector3(-17.1935, 11.1687, 8.8781 - factor2));
652        //positions.push_back(Vector3(1.50032, 31.1943, 19.1f));
[3316]653
[3360]654        // for happy buddha
655        //positions.push_back(Vector3(6.07307, 8.20723, 4.6f));
656        //positions.push_back(Vector3(-17.1935, 11.1687, 6.8f));
657        //positions.push_back(Vector3(1.50032, 31.1943, 17.6f));
[3359]658
[3360]659        // for dragon
660        //positions.push_back(Vector3(6.07307, 8.20723, 5.0f));
[3362]661        //positions.push_back(Vector3(0, 0, -0.8f));
[3360]662
[3316]663#endif
664
[3261]665        //const Vector3 sceneCenter(470.398f, 240.364f, 180.3);
[3316]666        Matrix4x4 transl = TranslationMatrix(positions[0]);
[3362]667        //LoadModel("dragon.dem", dynamicObjects);
668
669#if 1
670
[3371]671        LoadModel("hbuddha.dem", dynamicObjects);
[3361]672        //LoadModel("horse.dem", dynamicObjects);
[3371]673        //LoadModel("happy2.dem", dynamicObjects);
[3341]674        //LoadModel("torus.dem", dynamicObjects);
[3325]675        //LoadModel("venusm.dem", dynamicObjects);
[3128]676
[3072]677        buddha = dynamicObjects.back();
678        buddha->GetTransform()->SetMatrix(transl);
679
[3316]680       
681        for (size_t i = 1; i < positions.size(); ++ i)
[3072]682        {
[3316]683                CreateNewInstance(buddha, positions[i]);
684        }
[3072]685
[3362]686
[3359]687        const float rotAngle = M_PI / 2.0f;
688        const Matrix4x4 rotMatrix = RotationXMatrix(rotAngle);
689        const Matrix4x4 scaleMatrix = ScaleMatrix(14, 14, 14);
690
[3353]691        // hack: second buddha
[3359]692        dynamicObjects[0]->GetTransform()->MultMatrix(rotMatrix);
[3362]693        //dynamicObjects[0]->GetTransform()->MultMatrix(scaleMatrix);
[3072]694
[3362]695        /*dynamicObjects[1]->GetTransform()->MultMatrix(rotMatrix);
[3361]696        dynamicObjects[1]->GetTransform()->MultMatrix(scaleMatrix);
[3360]697
[3361]698        dynamicObjects[2]->GetTransform()->MultMatrix(rotMatrix);
699        dynamicObjects[2]->GetTransform()->MultMatrix(scaleMatrix);
[3360]700
[3359]701        cout << "dynamic objects: " << (int)dynamicObjects.size() << endl;
[3361]702        */
[3360]703        CreateAnimation(positions[0]);
[3361]704
[3360]705#endif
[3362]706#endif
[3359]707        // hack
[3247]708        resourceManager->mUseNormalMapping = false;
709        resourceManager->mUseSpecialColors = false;
710
711
[3059]712        ///////////
713        //-- load the associated static bvh
714
[3266]715        BvhFactory bvhFactory;
[2795]716
[3271]717        if (bvhname != "")
[2795]718        {
[3271]719                cout << "loading bvh from disc" << endl;
720                const string bvh_fullpath = string(model_path + bvhname + ".bvh");
721                bvh = bvhFactory.Create(bvh_fullpath, staticObjects, dynamicObjects, maxDepthForTestingChildren);
722
723                if (!bvh)
724                {
725                        cerr << "loading bvh " << bvh_fullpath << " failed" << endl;
726                        CleanUp();
727                        exit(0);
728                }
[2795]729        }
[3271]730        else
731        {
732                cout << "creating new bvh" << endl;
733                bvh = bvhFactory.Create(staticObjects, dynamicObjects, maxDepthForTestingChildren);
734        }
[2795]735
[3059]736        /// set the depth of the bvh depending on the triangles per leaf node
737        bvh->SetVirtualLeaves(trianglesPerVirtualLeaf);
738
[2963]739        // set far plane based on scene extent
[3362]740        farDist = 10.0f * Magnitude(bvh->GetBox().Diagonal());
741        //farDist = 1000.0f;
[3059]742        camera->SetFar(farDist);
[2963]743
[2961]744
[3282]745        //ObjExporter().Export(model_path + "mytest.obj", bvh);
746        //BvhExporter().Export(model_path + "mytest.bv", bvh);
[3260]747
748
749
[3059]750        //////////////////
751        //-- setup the skydome model
[2964]752
[3267]753        LoadModel("sky.dem", staticObjects);
754        skyDome = staticObjects.back();
[2861]755
[3059]756        /// the turbitity of the sky (from clear to hazy, use <3 for clear sky)
[3193]757        preetham = new SkyPreetham(turbitity, skyDome);
[2961]758
[3059]759
[3214]760        //////////////////////////
[3219]761        //-- a bounding box representing the sun pos in order to test visibility
762
[3214]763        Transform3 *trafo = resourceManager->CreateTransform(IdentityMatrix());
[3078]764
[3214]765        // make it slightly bigger to simulate sun diameter
766        const float size = 25.0f;
767        AxisAlignedBox3 sbox(Vector3(-size), Vector3(size));
768
769        SceneEntityConverter conv;
770
[3245]771
772        //////////////////
773        //-- occlusion query for sun
774
[3215]775        Material *mat = resourceManager->CreateMaterial();
[3214]776
777        mat->GetTechnique(0)->SetDepthWriteEnabled(false);
778        mat->GetTechnique(0)->SetColorWriteEnabled(false);
779
780        sunBox = conv.ConvertBox(sbox, mat, trafo);
[3215]781        resourceManager->AddSceneEntity(sunBox);
782
783        /// create single occlusion query that handles sun visibility
[3214]784        glGenQueriesARB(1, &sunQuery);
785
786
[3059]787        //////////
788        //-- initialize the traversal algorithm
789
[2897]790        traverser = CreateTraverser(camera);
[3059]791       
792        // the bird-eye visualization
[3101]793        visualization = new Visualization(bvh, camera, NULL, &renderState);
[3054]794
[3059]795        // this function assign the render queue bucket ids of the materials in beforehand
[3227]796        // => probably less overhead for new parts of the scene that are not yet assigned
[3059]797        PrepareRenderQueue();
798        /// forward rendering is the default
[3101]799        renderState.SetRenderTechnique(FORWARD);
[2847]800        // frame time is restarted every frame
801        frameTimer.Start();
[3059]802
[3238]803        //Halton::TestHalton(7, 2);
804        //HaltonSequence::TestHalton(15, 2);
805        //Halton::TestPrime();
[3227]806
[2857]807        // the rendering loop
[2642]808        glutMainLoop();
[3059]809       
[2642]810        // clean up
[2756]811        CleanUp();
[3019]812       
[2642]813        return 0;
814}
815
[2756]816
[2809]817void InitFBO()
[2810]818{
[2949]819        PrintGLerror("fbo start");
[2980]820
[2857]821        // this fbo basicly stores the scene information we get from standard rendering of a frame
[3066]822        // we store diffuse colors, eye space depth and normals
[2884]823        fbo = new FrameBufferObject(texWidth, texHeight, FrameBufferObject::DEPTH_32);
[2857]824
[2859]825        // the diffuse color buffer
[3015]826        fbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR, ColorBufferObject::FILTER_NEAREST);
[3009]827        // the normals buffer
[3197]828        //fbo->AddColorBuffer(ColorBufferObject::RGB_FLOAT_16, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_NEAREST);
829        fbo->AddColorBuffer(ColorBufferObject::RGB_FLOAT_16, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
[3066]830        // a rgb buffer which could hold material properties
[3113]831        //fbo->AddColorBuffer(ColorBufferObject::RGB_UBYTE, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_NEAREST);
[3117]832        // buffer holding the difference vector to the old frame
[3367]833        fbo->AddColorBuffer(ColorBufferObject::RGB_FLOAT_16, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
[3361]834        //fbo->AddColorBuffer(ColorBufferObject::RGB_UBYTE, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
[2879]835        // another color buffer
[3015]836        fbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR, ColorBufferObject::FILTER_NEAREST);
[2879]837
[3371]838
[3117]839        for (int i = 0; i < 4; ++ i)
[3219]840        {
[3117]841                FrameBufferObject::InitBuffer(fbo, i);
[3219]842        }
843
[3117]844        PrintGLerror("init fbo");
[2809]845}
846
847
[2827]848bool InitFont(void)
[2642]849{
[2826]850        glEnable(GL_TEXTURE_2D);
851
852        glGenTextures(1, &fontTex);
853        glBindTexture(GL_TEXTURE_2D, fontTex);
[3019]854
[2829]855        if (!myfont.Create("data/fonts/verdana.glf", fontTex))
[2826]856                return false;
857
858        glDisable(GL_TEXTURE_2D);
[2827]859       
[2826]860        return true;
861}
862
863
864void InitGLstate()
865{
[3246]866        glClearColor(0.4f, 0.4f, 0.4f, 1e20f);
[2642]867       
868        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
869        glPixelStorei(GL_PACK_ALIGNMENT,1);
870       
871        glDepthFunc(GL_LESS);
[2762]872        glEnable(GL_DEPTH_TEST);
[2642]873
[2760]874        glColor3f(1.0f, 1.0f, 1.0f);
[2642]875        glShadeModel(GL_SMOOTH);
876       
877        glMaterialf(GL_FRONT, GL_SHININESS, 64);
878        glEnable(GL_NORMALIZE);
[2767]879               
880        glDisable(GL_ALPHA_TEST);
[2951]881        glAlphaFunc(GL_GEQUAL, 0.5f);
[2767]882
[2642]883        glFrontFace(GL_CCW);
884        glCullFace(GL_BACK);
[2851]885        glEnable(GL_CULL_FACE);
886
[2800]887        glDisable(GL_TEXTURE_2D);
[2762]888
[2959]889        GLfloat ambientColor[] = {0.2, 0.2, 0.2, 1.0};
[2756]890        GLfloat diffuseColor[] = {1.0, 0.0, 0.0, 1.0};
[2759]891        GLfloat specularColor[] = {0.0, 0.0, 0.0, 1.0};
[2642]892
[2756]893        glMaterialfv(GL_FRONT, GL_AMBIENT, ambientColor);
894        glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuseColor);
895        glMaterialfv(GL_FRONT, GL_SPECULAR, specularColor);
[2801]896
897        glDepthFunc(GL_LESS);
[2826]898
[2827]899        if (!InitFont())
[2826]900                cerr << "font creation failed" << endl;
901        else
902                cout << "successfully created font" << endl;
[2953]903
904
[2954]905        //////////////////////////////
906
[2959]907        //GLfloat lmodel_ambient[] = {1.0f, 1.0f, 1.0f, 1.0f};
908        GLfloat lmodel_ambient[] = {0.7f, 0.7f, 0.8f, 1.0f};
[2954]909
910        glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
[2959]911        //glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
912        glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
[2954]913        glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL_EXT, GL_SINGLE_COLOR_EXT);
[2642]914}
915
916
[2827]917void DrawHelpMessage()
[2826]918{
[2642]919        const char *message[] =
920        {
921                "Help information",
922                "",
923                "'F1'           - shows/dismisses this message",
[2795]924                "'F2'           - shows/hides bird eye view",
[2790]925                "'F3'           - shows/hides bounds (boxes or tight bounds)",
[2827]926                "'F4',          - shows/hides parameters",
927                "'F5'           - shows/hides statistics",
928                "'F6',          - toggles between fly/walkmode",
[2826]929                "'F7',          - cycles throw render modes",
930                "'F8',          - enables/disables ambient occlusion (only deferred)",
931                "'F9',          - shows pure algorithm render time (using glFinish)",
[2790]932                "'SPACE'        - cycles through occlusion culling algorithms",
[2642]933                "",
[2827]934                "'MOUSE LEFT'        - turn left/right, move forward/backward",
935                "'MOUSE RIGHT'       - turn left/right, move forward/backward",
936                "'MOUSE MIDDLE'      - move up/down, left/right",
937                "'CURSOR UP/DOWN'    - move forward/backward",
938                "'CURSOR LEFT/RIGHT' - turn left/right",
[2642]939                "",
[2827]940                "'-'/'+'        - decreases/increases max batch size",
[2837]941                "'1'/'2'        - downward/upward motion",
942                "'3'/'4'        - decreases/increases triangles per virtual bvh leaf (sets bvh depth)",
943                "'5'/'6'        - decreases/increases assumed visible frames",
[2776]944                "",
[2786]945                "'R'            - use render queue",
[2790]946                "'B'            - use tight bounds",
947                "'M'            - use multiqueries",
[2792]948                "'O'            - use CHC optimization (geometry queries for leaves)",
[2642]949                0,
950        };
951       
[2756]952       
[2827]953        glColor4f(0.0f, 1.0f , 0.0f, 0.2f); // 20% green.
[2756]954
[2827]955        glRecti(30, 30, winWidth - 30, winHeight - 30);
[2642]956
[2827]957        glEnd();
958
[2756]959        glColor3f(1.0f, 1.0f, 1.0f);
960       
[2829]961        glEnable(GL_TEXTURE_2D);
[2827]962        myfont.Begin();
963
964        int x = 40, y = 30;
965
966        for(int i = 0; message[i] != 0; ++ i)
[2756]967        {
968                if(message[i][0] == '\0')
969                {
[2786]970                        y += 15;
[2756]971                }
972                else
973                {
[2827]974                        myfont.DrawString(message[i], x, winHeight - y);
975                        y += 25;
[2642]976                }
977        }
[2829]978        glDisable(GL_TEXTURE_2D);
[2642]979}
980
981
[3062]982RenderTraverser *CreateTraverser(PerspectiveCamera *cam)
[2764]983{
[2897]984        RenderTraverser *tr;
985       
[2764]986        switch (renderMode)
987        {
988        case RenderTraverser::CULL_FRUSTUM:
[2897]989                tr = new FrustumCullingTraverser();
[2764]990                break;
991        case RenderTraverser::STOP_AND_WAIT:
[2897]992                tr = new StopAndWaitTraverser();
[2764]993                break;
994        case RenderTraverser::CHC:
[2897]995                tr = new CHCTraverser();
[2764]996                break;
[2767]997        case RenderTraverser::CHCPLUSPLUS:
[2897]998                tr = new CHCPlusPlusTraverser();
[2767]999                break;
[3284]1000        //case RenderTraverser::CULL_COLLECTOR:
1001        //      tr = new PvsCollectionRenderer();
1002        //      break;
[2764]1003        default:
[2897]1004                tr = new FrustumCullingTraverser();
[2764]1005        }
1006
[2897]1007        tr->SetCamera(cam);
1008        tr->SetHierarchy(bvh);
1009        tr->SetRenderQueue(renderQueue);
[3101]1010        tr->SetRenderState(&renderState);
[2897]1011        tr->SetUseOptimization(useOptimization);
1012        tr->SetUseRenderQueue(useRenderQueue);
1013        tr->SetVisibilityThreshold(threshold);
1014        tr->SetAssumedVisibleFrames(assumedVisibleFrames);
1015        tr->SetMaxBatchSize(maxBatchSize);
1016        tr->SetUseMultiQueries(useMultiQueries);
[3294]1017        tr->SetUseTightBounds((renderMode == RenderTraverser::CHCPLUSPLUS) && useTightBounds);
[2955]1018        tr->SetUseDepthPass((renderMethod == RENDER_DEPTH_PASS) || (renderMethod == RENDER_DEPTH_PASS_DEFERRED));
[2897]1019        tr->SetRenderQueue(renderQueue);
[3066]1020        tr->SetShowBounds(showBoundingVolumes);
[2897]1021
[3066]1022        bvh->ResetNodeClassifications();
1023
1024
[2897]1025        return tr;
[2764]1026}
1027
[3295]1028/** Setup lighting conditions
[3059]1029*/
[2759]1030void SetupLighting()
[2642]1031{
[2759]1032        glEnable(GL_LIGHT0);
[2959]1033        glDisable(GL_LIGHT1);
[2825]1034       
[2954]1035        Vector3 lightDir = -light->GetDirection();
1036
1037
[2945]1038        ///////////
1039        //-- first light: sunlight
1040
[2954]1041        GLfloat ambient[] = {0.25f, 0.25f, 0.3f, 1.0f};
1042        GLfloat diffuse[] = {1.0f, 0.95f, 0.85f, 1.0f};
1043        GLfloat specular[] = {1.0f, 1.0f, 1.0f, 1.0f};
[2982]1044       
[2759]1045
[3175]1046        const bool useHDRValues =
[3046]1047                ((renderMethod == RENDER_DEPTH_PASS_DEFERRED) ||
1048                 (renderMethod == RENDER_DEFERRED)) && useHDR;
[2982]1049
[3046]1050
[2954]1051        Vector3 sunAmbient;
1052        Vector3 sunDiffuse;
[2759]1053
[3247]1054        if (useSkylightForIllum)
1055        {
1056                preetham->ComputeSunColor(lightDir, sunAmbient, sunDiffuse, !useHDRValues);
[2945]1057
[3247]1058                ambient[0] = sunAmbient.x;
1059                ambient[1] = sunAmbient.y;
1060                ambient[2] = sunAmbient.z;
[2825]1061
[3247]1062                diffuse[0] = sunDiffuse.x;
1063                diffuse[1] = sunDiffuse.y;
1064                diffuse[2] = sunDiffuse.z;
1065        }
1066        else
1067        {
[3295]1068                ambient[0] = defaultAmbient.x;
1069                ambient[1] = defaultAmbient.y;
1070                ambient[2] = defaultAmbient.z;
[2945]1071
[3295]1072                diffuse[0] = defaultDiffuse.x;
1073                diffuse[1] = defaultDiffuse.y;
1074                diffuse[2] = defaultDiffuse.z;
[3247]1075        }
[3193]1076
[2954]1077        glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
1078        glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
1079        glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
[2825]1080
[2954]1081        GLfloat position[] = {lightDir.x, lightDir.y, lightDir.z, 0.0f};
1082        glLightfv(GL_LIGHT0, GL_POSITION, position);
[2642]1083}
1084
[2800]1085
[2795]1086void SetupEyeView()
[2642]1087{
[2861]1088        // store matrix of last frame
[3005]1089        oldViewProjMat = viewProjMat;
[2834]1090
[3061]1091        camera->SetupViewProjection();
[2759]1092
[3061]1093
[2864]1094        /////////////////
[3059]1095        //-- compute view projection matrix and store for later use
[2864]1096
[2894]1097        Matrix4x4 matViewing, matProjection;
[2864]1098
[2834]1099        camera->GetModelViewMatrix(matViewing);
1100        camera->GetProjectionMatrix(matProjection);
1101
[3005]1102        viewProjMat = matViewing * matProjection;
[2642]1103}
1104
1105
[2792]1106void KeyHorizontalMotion(float shift)
1107{
[2888]1108        Vector3 hvec = -camera->GetDirection();
[2792]1109        hvec.z = 0;
1110
1111        Vector3 pos = camera->GetPosition();
1112        pos += hvec * shift;
1113       
1114        camera->SetPosition(pos);
1115}
1116
1117
[2794]1118void KeyVerticalMotion(float shift)
1119{
1120        Vector3 uvec = Vector3(0, 0, shift);
1121
1122        Vector3 pos = camera->GetPosition();
1123        pos += uvec;
1124       
1125        camera->SetPosition(pos);
1126}
1127
1128
[3105]1129void KeyStrafe(float shift)
1130{
1131        Vector3 viewDir = camera->GetDirection();
1132        Vector3 pos = camera->GetPosition();
1133
1134        // the 90 degree rotated view vector
1135        // z zero so we don't move in the vertical
1136        Vector3 rVec(viewDir[0], viewDir[1], 0);
1137
1138        Matrix4x4 rot = RotationZMatrix(M_PI * 0.5f);
1139        rVec = rot * rVec;
1140        pos += rVec * shift;
1141
1142        camera->SetPosition(pos);
1143}
1144
1145
[3059]1146/** Initialize the deferred rendering pass.
1147*/
[2948]1148void InitDeferredRendering()
1149{
1150        if (!fbo) InitFBO();
1151        fbo->Bind();
1152
1153        // multisampling does not work with deferred shading
1154        glDisable(GL_MULTISAMPLE_ARB);
[3101]1155        renderState.SetRenderTechnique(DEFERRED);
[2948]1156
1157
[3175]1158        // draw to 3 render targets
[3118]1159        if (sCurrentMrtSet == 0)
1160        {
1161                DeferredRenderer::colorBufferIdx = 0;
1162                glDrawBuffers(3, mrt);
1163        }
1164        else
1165        {
1166                DeferredRenderer::colorBufferIdx = 3;
1167                glDrawBuffers(3, mrt2);
1168        }
[2985]1169
[2978]1170        sCurrentMrtSet = 1 - sCurrentMrtSet;
[2948]1171}
1172
1173
[3059]1174/** the main rendering loop
1175*/
1176void MainLoop()
[2801]1177{       
[3359]1178        for (size_t i = 0; i < dynamicObjects.size(); ++ i)
1179                dynamicObjects[i]->GetTransform()->InitFrame();
1180
[3361]1181        if (buddha)
[3120]1182        {
[3246]1183                Matrix4x4 oldTrafo = buddha->GetTransform()->GetMatrix();
1184                Vector3 buddhaPos = motionPath->GetCurrentPosition();
1185                Matrix4x4 trafo = TranslationMatrix(buddhaPos);
[3120]1186
[3246]1187                buddha->GetTransform()->SetMatrix(trafo);
1188
[3362]1189                const float rotAngle3 = M_PI / 2.0f;
1190                const Matrix4x4 rotMatrix3 = RotationZMatrix(rotAngle3);
1191
1192                // hack: second buddha
1193                buddha->GetTransform()->MultMatrix(rotMatrix3);
1194
[3246]1195#if TODO // drop objects on ground floor
1196                for (int i = 0; i < 10; ++ i)
[3120]1197                {
[3246]1198                        SceneEntity *ent = dynamicObjects[i];
1199                        Vector3 newPos = ent->GetWorldCenter();
1200
1201                        if (GetOrCreateSceneQuery()->CalcIntersection(newPos))
1202                        {
1203                                Matrix4x4 mat = TranslationMatrix(newPos - ent->GetCenter());
1204                                ent->GetTransform()->SetMatrix(mat);
1205                        }
[3120]1206                }
[3221]1207#endif
[3120]1208
[3246]1209                /////////////////////////
1210                //-- update animations
[3221]1211
[3362]1212
[3246]1213                //const float rotAngle = M_PI * 1e-3f;
[3368]1214                //const float rotAngle = 1.5f * M_PI / 180.0f;
1215                const float rotAngle = 0.6f * M_PI / 180.0f;
[3225]1216
[3246]1217                Matrix4x4 rotMatrix = RotationZMatrix(rotAngle);
[3316]1218                // hack: second buddha
[3291]1219                dynamicObjects[1]->GetTransform()->MultMatrix(rotMatrix);
[3125]1220
[3361]1221                // hack: second buddha
[3359]1222                const float rotAngle2 = 0.0033f * M_PI;
[3335]1223                Matrix4x4 rotMatrix2 = RotationZMatrix(rotAngle);
[3338]1224                //dynamicObjects[3]->GetTransform()->MultMatrix(rotMatrix2);
[3335]1225
[3316]1226                //const float moveSpeed = 5e-3f;
[3365]1227                const float moveSpeed = 5e-1f;
[3314]1228                motionPath->Move(moveSpeed);
[3246]1229        }
[3125]1230
[3113]1231
[3111]1232        /////////////
[3078]1233
[3219]1234        static Vector3 oldPos = camera->GetPosition();
1235        static Vector3 oldDir = camera->GetDirection();
[2800]1236
[2792]1237        if (leftKeyPressed)
[2795]1238                camera->Pitch(KeyRotationAngle());
[2792]1239        if (rightKeyPressed)
[2795]1240                camera->Pitch(-KeyRotationAngle());
[2792]1241        if (upKeyPressed)
[2887]1242                KeyHorizontalMotion(-KeyShift());
1243        if (downKeyPressed)
[2795]1244                KeyHorizontalMotion(KeyShift());
[2837]1245        if (ascendKeyPressed)
1246                KeyVerticalMotion(KeyShift());
1247        if (descendKeyPressed)
[2795]1248                KeyVerticalMotion(-KeyShift());
[3105]1249        if (leftStrafeKeyPressed)
1250                KeyStrafe(KeyShift());
1251        if (rightStrafeKeyPressed)
1252                KeyStrafe(-KeyShift());
[2792]1253
[3105]1254
[2801]1255        // place view on ground
1256        if (!flyMode) PlaceViewer(oldPos);
[2800]1257
[2826]1258        if (showAlgorithmTime)
1259        {
1260                glFinish();
1261                algTimer.Start();
1262        }
[2809]1263       
[3219]1264        // don't allow replay on record
1265        if (replayPath && !recordPath)
1266        {
1267                if (!walkThroughPlayer)
[3271]1268                        walkThroughPlayer = new WalkThroughPlayer(walkThroughSuffix + ".log");
[3219]1269               
1270                ++ currentReplayFrame;
[2895]1271
[3223]1272                // reset if end of walkthrough is reached
[3219]1273                if (!walkThroughPlayer->ReadNextFrame(camera))
1274                {
[3286]1275                        cout << "reached end of walkthrough" << endl;
[3219]1276                        currentReplayFrame = -1;
1277                        replayPath = false;
1278                }
1279        }
1280
[2931]1281        if ((!shadowMap || !shadowTraverser) && (showShadowMap || renderLightView))
1282        {
[3313]1283                if (!shadowMap)
1284                        shadowMap = new ShadowMap(light, shadowSize, bvh->GetBox(), camera);
1285
1286                if (!shadowTraverser)
1287                        shadowTraverser = CreateTraverser(shadowMap->GetShadowCamera());
1288
[2931]1289        }
[2951]1290       
1291        // bring eye modelview matrix up-to-date
1292        SetupEyeView();
[3219]1293       
[3287]1294
[3059]1295        // set frame related parameters for GPU programs
[3046]1296        GPUProgramParameters::InitFrame(camera, light);
[3045]1297
[3219]1298        if (recordPath)
1299        {
1300                if (!walkThroughRecorder)
[3286]1301                {
[3271]1302                        walkThroughRecorder = new WalkThroughRecorder(walkThroughSuffix + ".log");
[3286]1303                }
1304
1305                // question: check if player has moved more than a minimum distance?
1306
1307                if (0 ||
1308                        (Distance(oldPos, camera->GetPosition()) > 1e-6f) ||
[3219]1309                        (DotProd(oldDir, camera->GetDirection()) < 1.0f - 1e-6f))
1310                {
1311                        walkThroughRecorder->WriteFrame(camera);
1312                }
1313        }
1314
[3059]1315        // hack: store current rendering method and restore later
[2955]1316        int oldRenderMethod = renderMethod;
[3044]1317        // for rendering the light view, we use forward rendering
[3068]1318        if (renderLightView) renderMethod = FORWARD;
[2931]1319
[3059]1320        /// enable vbo vertex array
[2953]1321        glEnableClientState(GL_VERTEX_ARRAY);
[2931]1322
[3287]1323        if (usePvs) LoadOrUpdatePVSs(camera->GetPosition());
[3256]1324
[3246]1325
[2931]1326        // render with the specified method (forward rendering, forward + depth, deferred)
[2955]1327        switch (renderMethod)
[2825]1328        {
[3043]1329        case RENDER_FORWARD:
[2825]1330       
[2851]1331                glEnable(GL_MULTISAMPLE_ARB);
[3101]1332                renderState.SetRenderTechnique(FORWARD);
[3223]1333               
[2829]1334                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
[2953]1335                glEnableClientState(GL_NORMAL_ARRAY);
[2825]1336                break;
1337
[2955]1338        case RENDER_DEPTH_PASS_DEFERRED:
[2948]1339
[2950]1340                glDisable(GL_MULTISAMPLE_ARB);
[3101]1341                renderState.SetUseAlphaToCoverage(false);
1342                renderState.SetRenderTechnique(DEPTH_PASS);
[2949]1343
[3175]1344                if (!fbo) InitFBO();
1345                fbo->Bind();
[3223]1346                // render to single depth texture
[2948]1347                glDrawBuffers(1, mrt);
[3223]1348                // clear buffer once
[2951]1349                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
[2948]1350
[3068]1351                // the scene is rendered withouth any shading
[3101]1352                // (should be handled by render renderState)
[2948]1353                glShadeModel(GL_FLAT);
1354                break;
1355
[2955]1356        case RENDER_DEPTH_PASS:
[2851]1357
1358                glEnable(GL_MULTISAMPLE_ARB);
[3101]1359                renderState.SetRenderTechnique(DEPTH_PASS);
[2857]1360
[3067]1361                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1362
[3068]1363                // the scene is rendered withouth any shading
[3101]1364                // (should be handled by render renderState)
[2943]1365                glShadeModel(GL_FLAT);
[2825]1366                break;
1367       
[3048]1368        case RENDER_DEFERRED:
[2851]1369
[2948]1370                if (showShadowMap && !renderLightView)
[3295]1371                {
[2951]1372                        RenderShadowMap(camera->GetFar());
[3295]1373                }
[2951]1374
[2948]1375                //glPushAttrib(GL_VIEWPORT_BIT);
[2825]1376                glViewport(0, 0, texWidth, texHeight);
1377
[2948]1378                InitDeferredRendering();
[2951]1379               
[2953]1380                glEnableClientState(GL_NORMAL_ARRAY);
[2954]1381                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
[2825]1382                break;
1383        }
1384
[2801]1385        glDepthFunc(GL_LESS);
1386        glDisable(GL_TEXTURE_2D);
1387        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
[2825]1388               
[2801]1389
[3059]1390        // set proper lod levels for current frame using current eye point
[2847]1391        LODLevel::InitFrame(camera->GetPosition());
[3059]1392        // set up sunlight
[2954]1393        SetupLighting();
[2795]1394
[2801]1395
[2931]1396        if (renderLightView)
1397        {
[3101]1398                // change CHC++ set of renderState variables:
[3059]1399                // must be done for each change of camera because otherwise
1400                // the temporal coherency is broken
[3054]1401                BvhNode::SetCurrentState(LIGHT_PASS);
[3005]1402                shadowMap->RenderShadowView(shadowTraverser, viewProjMat);
[3054]1403                BvhNode::SetCurrentState(CAMERA_PASS);
[2931]1404        }
1405        else
[3079]1406        {
[3284]1407                //if (traverser->GetType() == RenderTraverser::CULL_COLLECTOR)
1408                //      ((PvsCollectionRenderer *)traverser)->SetViewCell(usePvs ? viewCell : NULL);
[3258]1409
[2931]1410                // actually render the scene geometry using the specified algorithm
[3245]1411                traverser->RenderScene();
[2948]1412        }
[2892]1413
[2931]1414
[2825]1415        /////////
[2809]1416        //-- do the rest of the rendering
[2893]1417       
[3244]1418        // return from depth pass and render visible objects
[2955]1419        if ((renderMethod == RENDER_DEPTH_PASS) ||
1420                (renderMethod == RENDER_DEPTH_PASS_DEFERRED))
[2801]1421        {
1422                RenderVisibleObjects();
1423        }
1424
[3215]1425        const bool useDeferred =
1426                ((renderMethod == RENDER_DEFERRED) || (renderMethod == RENDER_DEPTH_PASS_DEFERRED));
[3214]1427
[3215]1428        // if no lense flare => just set sun to invisible
[3221]1429        const int sunVisiblePixels = useLenseFlare  &&  useDeferred ? TestSunVisible() : 0;
[3214]1430
[3246]1431       
[3215]1432
[2796]1433        ///////////////
1434        //-- render sky
[2795]1435
[2894]1436        // q: should we render sky after deferred shading?
1437        // this would conveniently solves some issues (e.g, skys without shadows)
[2893]1438
[3051]1439        RenderSky();
[2801]1440
[2961]1441
[3221]1442        //////////////////////////////
1443
[3215]1444        if (useDeferred)
[2825]1445        {
[2881]1446                FrameBufferObject::Release();
[2810]1447
[3247]1448                if (!deferredShader)
1449                {
1450                        deferredShader =
1451                                new DeferredRenderer(texWidth, texHeight, camera, ssaoUseFullResolution);
1452
1453                        deferredShader->SetKernelRadius(ssaoKernelRadius);
1454                        deferredShader->SetSampleIntensity(ssaoSampleIntensity);
1455                }
1456
[2903]1457                DeferredRenderer::SHADING_METHOD shadingMethod;
1458
1459                if (useAdvancedShading)
1460                {
1461                        if (useGlobIllum)
1462                                shadingMethod = DeferredRenderer::GI;
1463                        else
1464                                shadingMethod = DeferredRenderer::SSAO;
1465                }
1466                else
[3216]1467                {
[2903]1468                        shadingMethod = DeferredRenderer::DEFAULT;
[3216]1469                }
[2903]1470
[3225]1471                static int snapShotIdx = 0;
1472
[3215]1473                deferredShader->SetSunVisiblePixels(sunVisiblePixels);
[3111]1474                deferredShader->SetShadingMethod(shadingMethod);
1475                deferredShader->SetSamplingMethod(samplingMethod);
[3247]1476               
[3111]1477                deferredShader->SetUseTemporalCoherence(useTemporalCoherence);
[3242]1478                //deferredShader->SetSortSamples(sortSamples);
1479                deferredShader->SetTemporalCoherenceFactorForSsao(ssaoTempCohFactor);
1480                deferredShader->SetUseToneMapping(useHDR);
1481                deferredShader->SetUseAntiAliasing(useAntiAliasing);
[3316]1482                deferredShader->SetMaxConvergence(maxConvergence);
[3319]1483                deferredShader->SetSpatialWeight(spatialWeight);
[2903]1484
[3242]1485
[3225]1486                if (recordFrames && replayPath)
[3269]1487                {
1488                        // record all frames of the walkthrough
[3225]1489                        deferredShader->SetSaveFrame(recordedFramesSuffix, currentReplayFrame);
[3269]1490                }
[3225]1491                else if (makeSnapShot)
[3269]1492                {
1493                        // make snap shot
1494                        deferredShader->SetSaveFrame("snap", snapShotIdx ++);
1495                }
[3225]1496                else
[3269]1497                {
1498                        // do nothing
[3225]1499                        deferredShader->SetSaveFrame("", -1);           
[3269]1500                }
[3276]1501               
[3362]1502                static int dummy = 0;
1503                if (makeSnapShot && (dummy ++ == 650)) makeSnapShot = false;
[3225]1504
[2895]1505                ShadowMap *sm = showShadowMap ? shadowMap : NULL;
[3242]1506                deferredShader->Render(fbo, light, sm);
[2825]1507        }
[2827]1508
[2893]1509
[3101]1510        renderState.SetRenderTechnique(FORWARD);
1511        renderState.Reset();
[2827]1512
[2893]1513        glDisableClientState(GL_VERTEX_ARRAY);
1514        glDisableClientState(GL_NORMAL_ARRAY);
[2931]1515       
[2955]1516        renderMethod = oldRenderMethod;
[2893]1517
1518
1519        ///////////
1520
1521
[2826]1522        if (showAlgorithmTime)
1523        {
1524                glFinish();
[2827]1525
[2826]1526                algTime = algTimer.Elapsedms();
[2827]1527                perfGraph->AddData(algTime);
[2828]1528
[2827]1529                perfGraph->Draw();
[2826]1530        }
[2827]1531        else
1532        {
1533                if (visMode) DisplayVisualization();
1534        }
[2825]1535
[2884]1536        glFlush();
[2847]1537
1538        const bool restart = true;
1539        elapsedTime = frameTimer.Elapsedms(restart);
1540
[3223]1541        // statistics
[2764]1542        DisplayStats();
[2767]1543
[2642]1544        glutSwapBuffers();
[3219]1545
1546        oldPos = camera->GetPosition();
1547        oldDir = camera->GetDirection();
[2642]1548}
1549
1550
[3219]1551#pragma warning(disable : 4100)
[2792]1552void KeyBoard(unsigned char c, int x, int y)
[2642]1553{
1554        switch(c)
1555        {
1556        case 27:
[3212]1557                // write out current position on exit
[3134]1558                Debug << "camPosition=" << camera->GetPosition().x << " " << camera->GetPosition().y << " " << camera->GetPosition().z << endl;
1559                Debug << "camDirection=" << camera->GetDirection().x << " " << camera->GetDirection().y << " " << camera->GetDirection().z << endl;
[3285]1560                Debug << "lightDirection=" << light->GetDirection().x << " " << light->GetDirection().y << " " << light->GetDirection().z << endl;
[3134]1561
[2792]1562                CleanUp();
[2642]1563                exit(0);
[2948]1564        case 32: // space
[2800]1565                renderMode = (renderMode + 1) % RenderTraverser::NUM_TRAVERSAL_TYPES;
[3258]1566                //renderMode = (renderMode + 1) % 4;
[2897]1567
1568                DEL_PTR(traverser);
1569                traverser = CreateTraverser(camera);
1570
[2931]1571                if (shadowTraverser)
[2897]1572                {
[2948]1573                        // shadow traverser has to be recomputed
[2897]1574                        DEL_PTR(shadowTraverser);
[2948]1575                        shadowTraverser = CreateTraverser(shadowMap->GetShadowCamera());
[2897]1576                }
1577
[2642]1578                break;
1579        case '+':
[2867]1580                if (maxBatchSize < 10)
1581                        maxBatchSize = 10;
1582                else
1583                        maxBatchSize += 10;
1584
[2776]1585                traverser->SetMaxBatchSize(maxBatchSize);
[2642]1586                break;
1587        case '-':
[2776]1588                maxBatchSize -= 10;
1589                if (maxBatchSize < 0) maxBatchSize = 1;
1590                traverser->SetMaxBatchSize(maxBatchSize);               
[2642]1591                break;
[2837]1592        case 'M':
1593        case 'm':
1594                useMultiQueries = !useMultiQueries;
1595                traverser->SetUseMultiQueries(useMultiQueries);
1596                break;
1597        case '1':
1598                descendKeyPressed = true;
1599                break;
1600        case '2':
1601                ascendKeyPressed = true;
1602                break;
1603        case '3':
[3212]1604                if (trianglesPerVirtualLeaf >= 100) trianglesPerVirtualLeaf -= 100;
[2837]1605                bvh->SetVirtualLeaves(trianglesPerVirtualLeaf);
1606                break;
1607        case '4':
1608                trianglesPerVirtualLeaf += 100;
1609                bvh->SetVirtualLeaves(trianglesPerVirtualLeaf);
1610                break;
1611        case '5':
[2776]1612                assumedVisibleFrames -= 1;
1613                if (assumedVisibleFrames < 1) assumedVisibleFrames = 1;
1614                traverser->SetAssumedVisibleFrames(assumedVisibleFrames);
1615                break;
[2837]1616        case '6':
[2776]1617                assumedVisibleFrames += 1;
1618                traverser->SetAssumedVisibleFrames(assumedVisibleFrames);               
1619                break;
[2837]1620        case '7':
[3227]1621                ssaoTempCohFactor *= 1.0f / 1.2f;
[3216]1622                cout << "new temporal coherence factor: " << ssaoTempCohFactor << endl;
[2776]1623                break;
[2767]1624        case '8':
[3227]1625                ssaoTempCohFactor *= 1.2f;
[3216]1626                cout << "new temporal coherence factor: " << ssaoTempCohFactor << endl;
[2837]1627                break;
[3212]1628        case '9':
[3360]1629                ssaoKernelRadius *= .8f;
[3216]1630                cout << "new ssao kernel radius: " << ssaoKernelRadius << endl;
[3247]1631                if (deferredShader) deferredShader->SetKernelRadius(ssaoKernelRadius);
[3212]1632                break;
1633        case '0':
[3360]1634                ssaoKernelRadius *= 1.0f / .8f;
[3247]1635                if (deferredShader) deferredShader->SetKernelRadius(ssaoKernelRadius);
[3216]1636                cout << "new ssao kernel radius: " << ssaoKernelRadius << endl;
[3212]1637                break;
1638        case 'n':
[3360]1639                ssaoSampleIntensity *= .9f;
[3247]1640                if (deferredShader) deferredShader->SetSampleIntensity(ssaoSampleIntensity);
[3216]1641                cout << "new ssao sample intensity: " << ssaoSampleIntensity << endl;
[3212]1642                break;
1643        case 'N':
[3360]1644                ssaoSampleIntensity *= 1.0f / .9f;
[3247]1645                if (deferredShader) deferredShader->SetSampleIntensity(ssaoSampleIntensity);
[3216]1646                cout << "new ssao sample intensity: " << ssaoSampleIntensity << endl;
[3212]1647                break;
[3219]1648        /*      case 'o':
1649        case 'O':
1650                useOptimization = !useOptimization;
1651                // chc optimization of using the objects instead of
1652                // the bounding boxes for querying previously visible nodes
1653                traverser->SetUseOptimization(useOptimization);
1654                break;*/
[3316]1655        case 'o':
[3319]1656                        spatialWeight /= 2.0f;
1657                        cout << "spatialWeight: " << spatialWeight << endl;
1658                        break;
[3316]1659        case 'O':
[3319]1660                        spatialWeight *= 2.0f;
1661                        cout << "spatialWeight: " << spatialWeight << endl;
1662                        break;
1663        /*case 'o':
1664        case 'O':
[3316]1665                if (maxConvergence > 100.0f)
1666                        maxConvergence = 1.0f;
1667                else
1668                        maxConvergence = 5000.0f;
1669                cout << "max convergence: " << maxConvergence << endl;
[3320]1670        */
[3316]1671                break;
[3175]1672        case 'l':
1673        case 'L':
[2865]1674                useLODs = !useLODs;
1675                SceneEntity::SetUseLODs(useLODs);
[3216]1676                cout << "using LODs: " << useLODs << endl;
[2865]1677                break;
[2887]1678        case 'P':
1679        case 'p':
[2930]1680                samplingMethod = DeferredRenderer::SAMPLING_METHOD((samplingMethod + 1) % 3);
1681                cout << "ssao sampling method: " << samplingMethod << endl;
[2887]1682                break;
[2895]1683        case 'Y':
1684        case 'y':
1685                showShadowMap = !showShadowMap;
1686                break;
[2875]1687        case 'g':
[2903]1688        case 'G':
1689                useGlobIllum = !useGlobIllum;
1690                break;
[2875]1691        case 't':
1692        case 'T':
1693                useTemporalCoherence = !useTemporalCoherence;
[3360]1694                cout << "using temporal coherence " << useTemporalCoherence << endl;
[2875]1695                break;
[2767]1696        case 'a':
1697        case 'A':
[2931]1698                leftKeyPressed = true;
[2767]1699                break;
1700        case 'd':
1701        case 'D':
[2931]1702                rightKeyPressed = true;
[2767]1703                break;
1704        case 'w':
1705        case 'W':
[2931]1706                upKeyPressed = true;
[2767]1707                break;
[2829]1708        case 's':
1709        case 'S':
[2931]1710                downKeyPressed = true;
[2767]1711                break;
[3105]1712        case 'j':
1713        case 'J':
1714                leftStrafeKeyPressed = true;
1715                break;
1716        case 'k':
1717        case 'K':
1718                rightStrafeKeyPressed = true;
1719                break;
[2767]1720        case 'r':
1721        case 'R':
[2931]1722                useRenderQueue = !useRenderQueue;
1723                traverser->SetUseRenderQueue(useRenderQueue);
[2790]1724                break;
[2786]1725        case 'b':
1726        case 'B':
[2931]1727                useTightBounds = !useTightBounds;
[3294]1728                traverser->SetUseTightBounds((renderMode == RenderTraverser::CHCPLUSPLUS) && useTightBounds);
[2790]1729                break;
[3175]1730        case 'v':
1731        case 'V':
[2931]1732                renderLightView = !renderLightView;
1733                break;
[2994]1734        case 'h':
1735        case 'H':
1736                useHDR = !useHDR;
1737                break;
[3175]1738        case 'i':
1739        case 'I':
1740                useAntiAliasing = !useAntiAliasing;
1741                break;
[3215]1742        case 'c':
1743        case 'C':
1744                useLenseFlare = !useLenseFlare;
[3189]1745                break;
[3219]1746        case 'u':
1747        case 'U':
[3220]1748                // move light source instead of camera tilt
[3219]1749                moveLight = !moveLight;
1750                break;
[3225]1751        case '#':
1752                // make a snapshot of the current frame
1753                makeSnapShot = true;
1754                break;
[3246]1755        case '.':
1756                // enable / disable view cells
1757                usePvs = !usePvs;
[3259]1758                if (!usePvs) SceneEntity::SetCurrentVisibleId(-1);
[3246]1759                break;
[3273]1760        case ',':
1761                // show / hide FPS
1762                showFPS = !showFPS;
1763                break;
1764       
[2642]1765        default:
1766                return;
1767        }
1768
1769        glutPostRedisplay();
1770}
1771
1772
[2792]1773void SpecialKeyUp(int c, int x, int y)
[2642]1774{
[2792]1775        switch (c)
1776        {
1777        case GLUT_KEY_LEFT:
1778                leftKeyPressed = false;
1779                break;
1780        case GLUT_KEY_RIGHT:
1781                rightKeyPressed = false;
1782                break;
1783        case GLUT_KEY_UP:
1784                upKeyPressed = false;
1785                break;
1786        case GLUT_KEY_DOWN:
1787                downKeyPressed = false;
1788                break;
[2953]1789        case GLUT_ACTIVE_ALT:
1790                altKeyPressed = false;
1791                break;
[2792]1792        default:
1793                return;
1794        }
1795}
1796
1797
1798void KeyUp(unsigned char c, int x, int y)
1799{
1800        switch (c)
1801        {
[2879]1802
[2792]1803        case 'A':
1804        case 'a':
1805                leftKeyPressed = false;
1806                break;
1807        case 'D':
1808        case 'd':
1809                rightKeyPressed = false;
1810                break;
1811        case 'W':
1812        case 'w':
1813                upKeyPressed = false;
1814                break;
[2829]1815        case 'S':
1816        case 's':
[2792]1817                downKeyPressed = false;
1818                break;
[2837]1819        case '1':
1820                descendKeyPressed = false;
[2794]1821                break;
[2837]1822        case '2':
1823                ascendKeyPressed = false;
[2794]1824                break;
[3105]1825        case 'j':
1826        case 'J':
1827                leftStrafeKeyPressed = false;
1828                break;
1829        case 'k':
1830        case 'K':
1831                rightStrafeKeyPressed = false;
1832                break;
[2792]1833        default:
1834                return;
1835        }
1836        //glutPostRedisplay();
1837}
1838
1839
1840void Special(int c, int x, int y)
1841{
[2642]1842        switch(c)
1843        {
1844        case GLUT_KEY_F1:
1845                showHelp = !showHelp;
1846                break;
[2790]1847        case GLUT_KEY_F2:
[2795]1848                visMode = !visMode;
[2790]1849                break;
1850        case GLUT_KEY_F3:
1851                showBoundingVolumes = !showBoundingVolumes;
1852                traverser->SetShowBounds(showBoundingVolumes);
1853                break;
1854        case GLUT_KEY_F4:
[2827]1855                showOptions = !showOptions;
[2790]1856                break;
1857        case GLUT_KEY_F5:
[2827]1858                showStatistics = !showStatistics;
[2790]1859                break;
[2800]1860        case GLUT_KEY_F6:
1861                flyMode = !flyMode;
1862                break;
[2801]1863        case GLUT_KEY_F7:
[2825]1864
[2955]1865                renderMethod = (renderMethod + 1) % 4;
1866
1867                traverser->SetUseDepthPass(
1868                        (renderMethod == RENDER_DEPTH_PASS) ||
1869                        (renderMethod == RENDER_DEPTH_PASS_DEFERRED)
1870                        );
[2801]1871                break;
[2803]1872        case GLUT_KEY_F8:
[2903]1873                useAdvancedShading = !useAdvancedShading;
[2821]1874                break;
[2826]1875        case GLUT_KEY_F9:
1876                showAlgorithmTime = !showAlgorithmTime;
1877                break;
[2954]1878        case GLUT_KEY_F10:
[3219]1879                replayPath = !replayPath;
1880
1881                if (replayPath)
1882                {
1883                        cout << "replaying path" << endl;
1884                        currentReplayFrame = -1;
[3285]1885
1886                        // hack: load pvs on replay (remove later!)
[3287]1887                        //usePvs = true;
[3219]1888                }
1889                else
1890                {
1891                        cout << "finished replaying path" << endl;
1892                }
[2954]1893                break;
[3219]1894        case GLUT_KEY_F11:
1895                recordPath = !recordPath;
1896               
1897                if (recordPath)
1898                {
1899                        cout << "recording path" << endl;
1900                }
1901                else
1902                {
1903                        cout << "finished recording path" << endl;
1904                        // start over with new frame recording next time
1905                        DEL_PTR(walkThroughRecorder);
1906                }
1907                break;
1908        case GLUT_KEY_F12:
1909                recordFrames = !recordFrames;
1910
1911                if (recordFrames)
1912                        cout << "recording frames on replaying" << endl;
1913                else
[3286]1914                        cout << "not recording frames on replaying" << endl;
[3219]1915                break;
[2642]1916        case GLUT_KEY_LEFT:
[2767]1917                {
[2792]1918                        leftKeyPressed = true;
[2795]1919                        camera->Pitch(KeyRotationAngle());
[2767]1920                }
[2642]1921                break;
1922        case GLUT_KEY_RIGHT:
[2767]1923                {
[2792]1924                        rightKeyPressed = true;
[2795]1925                        camera->Pitch(-KeyRotationAngle());
[2767]1926                }
[2642]1927                break;
1928        case GLUT_KEY_UP:
[2767]1929                {
[2792]1930                        upKeyPressed = true;
[2795]1931                        KeyHorizontalMotion(KeyShift());
[2767]1932                }
[2642]1933                break;
1934        case GLUT_KEY_DOWN:
[2767]1935                {
[2792]1936                        downKeyPressed = true;
[2795]1937                        KeyHorizontalMotion(-KeyShift());
[2767]1938                }
[2642]1939                break;
1940        default:
1941                return;
1942
1943        }
1944
1945        glutPostRedisplay();
1946}
[2767]1947
[2642]1948#pragma warning( default : 4100 )
1949
1950
[2792]1951void Reshape(int w, int h)
[2642]1952{
[2759]1953        winAspectRatio = 1.0f;
[2642]1954
1955        glViewport(0, 0, w, h);
1956       
1957        winWidth = w;
1958        winHeight = h;
1959
[2833]1960        if (w) winAspectRatio = (float) w / (float) h;
[2642]1961
[2758]1962        glMatrixMode(GL_PROJECTION);
1963        glLoadIdentity();
[2642]1964
[2927]1965        gluPerspective(fov, winAspectRatio, nearDist, farDist);
[2788]1966
[2758]1967        glMatrixMode(GL_MODELVIEW);
1968
[2642]1969        glutPostRedisplay();
1970}
1971
1972
[3101]1973void Mouse(int button, int renderState, int x, int y)
[2642]1974{
[3101]1975        if ((button == GLUT_LEFT_BUTTON) && (renderState == GLUT_DOWN))
[2642]1976        {
1977                xEyeBegin = x;
1978                yMotionBegin = y;
1979
[2792]1980                glutMotionFunc(LeftMotion);
[2642]1981        }
[3101]1982        else if ((button == GLUT_RIGHT_BUTTON) && (renderState == GLUT_DOWN))
[2642]1983        {
[2829]1984                xEyeBegin = x;
[2758]1985                yEyeBegin = y;
1986                yMotionBegin = y;
1987
[2954]1988                if (!moveLight)
1989                        glutMotionFunc(RightMotion);
1990                else
1991                        glutMotionFunc(RightMotionLight);
[2758]1992        }
[3101]1993        else if ((button == GLUT_MIDDLE_BUTTON) && (renderState == GLUT_DOWN))
[2758]1994        {
[2642]1995                horizontalMotionBegin = x;
1996                verticalMotionBegin = y;
[2792]1997                glutMotionFunc(MiddleMotion);
[2642]1998        }
1999
2000        glutPostRedisplay();
2001}
2002
[2758]2003
2004/**     rotation for left/right mouse drag
[2642]2005        motion for up/down mouse drag
2006*/
[2792]2007void LeftMotion(int x, int y)
[2642]2008{
[2758]2009        Vector3 viewDir = camera->GetDirection();
2010        Vector3 pos = camera->GetPosition();
2011
2012        // don't move in the vertical direction
[2764]2013        Vector3 horView(viewDir[0], viewDir[1], 0);
[2642]2014       
[2795]2015        float eyeXAngle = 0.2f *  M_PI * (xEyeBegin - x) / 180.0;
[2756]2016
[2795]2017        camera->Pitch(eyeXAngle);
[2787]2018
[3246]2019        pos += horView * (yMotionBegin - y) * mouseMotion;
[2795]2020       
[2758]2021        camera->SetPosition(pos);
[2642]2022       
2023        xEyeBegin = x;
2024        yMotionBegin = y;
[2758]2025
[2642]2026        glutPostRedisplay();
2027}
2028
[2758]2029
[2954]2030void RightMotionLight(int x, int y)
2031{
[3362]2032        const float theta = .2f * M_PI * (xEyeBegin - x) / 180.0f;
2033        const float phi   = .2f * M_PI * (yMotionBegin - y) / 180.0f;
[2954]2034       
2035        Vector3 lightDir = light->GetDirection();
2036
2037        Matrix4x4 roty = RotationYMatrix(theta);
2038        Matrix4x4 rotx = RotationXMatrix(phi);
2039
2040        lightDir = roty * lightDir;
2041        lightDir = rotx * lightDir;
2042
[2967]2043        // normalize to avoid accumulating errors
2044        lightDir.Normalize();
2045
[2954]2046        light->SetDirection(lightDir);
2047
2048        xEyeBegin = x;
2049        yMotionBegin = y;
2050
2051        glutPostRedisplay();
2052}
2053
2054
[2767]2055/**     rotation for left / right mouse drag
2056        motion for up / down mouse drag
[2758]2057*/
[2792]2058void RightMotion(int x, int y)
[2758]2059{
[2829]2060        float eyeXAngle = 0.2f *  M_PI * (xEyeBegin - x) / 180.0;
[2795]2061        float eyeYAngle = -0.2f *  M_PI * (yEyeBegin - y) / 180.0;
[2758]2062
[2795]2063        camera->Yaw(eyeYAngle);
[2829]2064        camera->Pitch(eyeXAngle);
[2780]2065
[2829]2066        xEyeBegin = x;
[2758]2067        yEyeBegin = y;
[2829]2068
[2758]2069        glutPostRedisplay();
2070}
2071
2072
[3105]2073/** strafe
2074*/
[2792]2075void MiddleMotion(int x, int y)
[2642]2076{
[2758]2077        Vector3 viewDir = camera->GetDirection();
2078        Vector3 pos = camera->GetPosition();
2079
[2642]2080        // the 90 degree rotated view vector
2081        // y zero so we don't move in the vertical
[2764]2082        Vector3 rVec(viewDir[0], viewDir[1], 0);
[2642]2083       
[3362]2084        Matrix4x4 rot = RotationZMatrix(M_PI * .5f);
[2758]2085        rVec = rot * rVec;
[2642]2086       
[3362]2087        pos    -= rVec * (x - horizontalMotionBegin) * mouseMotion;
[3246]2088        pos[2] += (verticalMotionBegin - y) * mouseMotion;
[2642]2089
[2758]2090        camera->SetPosition(pos);
2091
[2642]2092        horizontalMotionBegin = x;
2093        verticalMotionBegin = y;
[2758]2094
[2642]2095        glutPostRedisplay();
2096}
2097
2098
[2756]2099void InitExtensions(void)
[2642]2100{
2101        GLenum err = glewInit();
[2756]2102
[2642]2103        if (GLEW_OK != err)
2104        {
2105                // problem: glewInit failed, something is seriously wrong
2106                fprintf(stderr,"Error: %s\n", glewGetErrorString(err));
2107                exit(1);
2108        }
[2756]2109        if  (!GLEW_ARB_occlusion_query)
[2642]2110        {
[2756]2111                printf("I require the GL_ARB_occlusion_query to work.\n");
[2642]2112                exit(1);
2113        }
2114}
2115
2116
[2826]2117void Begin2D()
[2642]2118{
2119        glDisable(GL_LIGHTING);
2120        glDisable(GL_DEPTH_TEST);
2121
[2826]2122        glMatrixMode(GL_PROJECTION);
[2642]2123        glPushMatrix();
2124        glLoadIdentity();
[2834]2125
[2826]2126        gluOrtho2D(0, winWidth, 0, winHeight);
[2642]2127
[2826]2128        glMatrixMode(GL_MODELVIEW);
[2642]2129        glPushMatrix();
2130        glLoadIdentity();
2131}
2132
2133
[2826]2134void End2D()
[2642]2135{
[2834]2136        glMatrixMode(GL_PROJECTION);
[2642]2137        glPopMatrix();
[2834]2138
[2642]2139        glMatrixMode(GL_MODELVIEW);
2140        glPopMatrix();
2141
2142        glEnable(GL_LIGHTING);
2143        glEnable(GL_DEPTH_TEST);
2144}
2145
2146
[2787]2147// displays the visualisation of culling algorithm
2148void DisplayVisualization()
[2796]2149{
[3246]2150        // render current view cell
2151        if (usePvs) RenderViewCell();
2152       
2153        visualization->SetViewCell(usePvs ? viewCell : NULL);
[2787]2154        visualization->SetFrameId(traverser->GetCurrentFrameId());
[3246]2155       
[3245]2156
[2792]2157        Begin2D();
[2642]2158        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2159        glEnable(GL_BLEND);
[2827]2160        glColor4f(0.0f ,0.0f, 0.0f, 0.5f);
[2642]2161
[2827]2162        glRecti(winWidth - winWidth / 3, winHeight - winHeight / 3, winWidth, winHeight);
[2642]2163        glDisable(GL_BLEND);
[2792]2164        End2D();
[2788]2165       
2166       
2167        AxisAlignedBox3 box = bvh->GetBox();
2168
[2948]2169        const float offs = box.Size().x * 0.3f;
[2834]2170       
[2838]2171        Vector3 vizpos = Vector3(box.Min().x, box.Min().y  - box.Size().y * 0.35f, box.Min().z + box.Size().z * 50);
[2806]2172       
[2795]2173        visCamera->SetPosition(vizpos);
[2838]2174        visCamera->ResetPitchAndYaw();
[2892]2175       
[2834]2176        glPushAttrib(GL_VIEWPORT_BIT);
[2806]2177        glViewport(winWidth - winWidth / 3, winHeight - winHeight / 3, winWidth / 3, winHeight / 3);
[2796]2178
2179        glMatrixMode(GL_PROJECTION);
[2834]2180        glPushMatrix();
2181
[2787]2182        glLoadIdentity();
[2807]2183        glOrtho(-offs, offs, -offs, offs, 0.0f, box.Size().z * 100.0f);
[2787]2184
[2796]2185        glMatrixMode(GL_MODELVIEW);
[2834]2186        glPushMatrix();
[2787]2187
[2796]2188        visCamera->SetupCameraView();
[2806]2189
2190        Matrix4x4 rotZ = RotationZMatrix(-camera->GetPitch());
2191        glMultMatrixf((float *)rotZ.x);
2192
[2887]2193        // inverse translation in order to fix current position
[2838]2194        Vector3 pos = camera->GetPosition();
[2806]2195        glTranslatef(-pos.x, -pos.y, -pos.z);
2196
2197
[2788]2198        GLfloat position[] = {0.8f, 1.0f, 1.5f, 0.0f};
2199        glLightfv(GL_LIGHT0, GL_POSITION, position);
[2787]2200
[2788]2201        GLfloat position1[] = {bvh->GetBox().Center().x, bvh->GetBox().Max().y, bvh->GetBox().Center().z, 1.0f};
2202        glLightfv(GL_LIGHT1, GL_POSITION, position1);
[2787]2203
[2642]2204        glClear(GL_DEPTH_BUFFER_BIT);
2205
[2888]2206
[2767]2207        ////////////
[2787]2208        //-- visualization of the occlusion culling
2209
[3063]2210        visualization->Render(showShadowMap);
[2887]2211
[2767]2212       
[2834]2213        // reset previous settings
2214        glPopAttrib();
2215
2216        glMatrixMode(GL_PROJECTION);
2217        glPopMatrix();
2218        glMatrixMode(GL_MODELVIEW);
2219        glPopMatrix();
[2642]2220}
2221
[2767]2222
[2642]2223// cleanup routine after the main loop
[2756]2224void CleanUp()
[2642]2225{
[2756]2226        DEL_PTR(traverser);
[2796]2227        DEL_PTR(sceneQuery);
[2756]2228        DEL_PTR(bvh);
[2767]2229        DEL_PTR(visualization);
[2787]2230        DEL_PTR(camera);
[2801]2231        DEL_PTR(renderQueue);
[2827]2232        DEL_PTR(perfGraph);
[2879]2233        DEL_PTR(fbo);
[3111]2234        DEL_PTR(deferredShader);
[3019]2235        DEL_PTR(light);
2236        DEL_PTR(visCamera);
2237        DEL_PTR(preetham);
[3020]2238        DEL_PTR(shadowMap);
2239        DEL_PTR(shadowTraverser);
[3078]2240        DEL_PTR(motionPath);
[3219]2241        DEL_PTR(walkThroughRecorder);
2242        DEL_PTR(walkThroughPlayer);
[3223]2243        DEL_PTR(statsWriter);
[3244]2244        DEL_PTR(viewCellsTree);
[3052]2245
[3037]2246        ResourceManager::DelSingleton();
[3057]2247        ShaderManager::DelSingleton();
2248
[3059]2249        resourceManager = NULL;
[3057]2250        shaderManager = NULL;
[2642]2251}
2252
2253
2254// this function inserts a dezimal point after each 1000
[2829]2255void CalcDecimalPoint(string &str, int d, int len)
[2642]2256{
[2827]2257        static vector<int> numbers;
2258        numbers.clear();
2259
[2829]2260        static string shortStr;
2261        shortStr.clear();
[2642]2262
[2829]2263        static char hstr[100];
2264
[2642]2265        while (d != 0)
2266        {
2267                numbers.push_back(d % 1000);
2268                d /= 1000;
2269        }
2270
2271        // first element without leading zeros
2272        if (numbers.size() > 0)
2273        {
[2800]2274                sprintf(hstr, "%d", numbers.back());
[2829]2275                shortStr.append(hstr);
[2642]2276        }
2277       
[2764]2278        for (int i = (int)numbers.size() - 2; i >= 0; i--)
[2642]2279        {
[2800]2280                sprintf(hstr, ",%03d", numbers[i]);
[2829]2281                shortStr.append(hstr);
[2642]2282        }
[2829]2283
2284        int dif = len - (int)shortStr.size();
2285
2286        for (int i = 0; i < dif; ++ i)
2287        {
2288                str += " ";
2289        }
2290
2291        str.append(shortStr);
[2764]2292}
2293
2294
2295void DisplayStats()
2296{
[2826]2297        static char msg[9][300];
[2764]2298
[2826]2299        static double frameTime = elapsedTime;
2300        static double renderTime = algTime;
2301
[2818]2302        const float expFactor = 0.1f;
[2767]2303
[2802]2304        // if some strange render time spike happened in this frame => don't count
[2826]2305        if (elapsedTime < 500) frameTime = elapsedTime * expFactor + (1.0f - expFactor) * elapsedTime;
2306       
2307        static float rTime = 1000.0f;
[2764]2308
[3285]2309        // the render time is used only for the traversal algorithm using glfinish
2310        if (algTime < 500) renderTime = algTime * expFactor + (1.0f - expFactor) * renderTime;
2311       
[2802]2312
[2826]2313        accumulatedTime += elapsedTime;
2314
[2776]2315        if (accumulatedTime > 500) // update every fraction of a second
[2770]2316        {       
2317                accumulatedTime = 0;
2318
[2826]2319                if (frameTime) fps = 1e3f / (float)frameTime;
2320                rTime = renderTime;
[2773]2321
[2948]2322                if (renderLightView && shadowTraverser)
2323                {
2324                        renderedTriangles = shadowTraverser->GetStats().mNumRenderedTriangles;
2325                        renderedObjects = shadowTraverser->GetStats().mNumRenderedGeometry;
2326                        renderedNodes = shadowTraverser->GetStats().mNumRenderedNodes;
2327                }
2328                else if (showShadowMap && shadowTraverser)
2329                {
2330                        renderedNodes = traverser->GetStats().mNumRenderedNodes + shadowTraverser->GetStats().mNumRenderedNodes;
2331                        renderedObjects = traverser->GetStats().mNumRenderedGeometry + shadowTraverser->GetStats().mNumRenderedGeometry;
2332                        renderedTriangles = traverser->GetStats().mNumRenderedTriangles + shadowTraverser->GetStats().mNumRenderedTriangles;
2333                }
2334                else
2335                {
2336                        renderedTriangles = traverser->GetStats().mNumRenderedTriangles;
2337                        renderedObjects = traverser->GetStats().mNumRenderedGeometry;
2338                        renderedNodes = traverser->GetStats().mNumRenderedNodes;
2339                }
2340
[2770]2341                traversedNodes = traverser->GetStats().mNumTraversedNodes;
2342                frustumCulledNodes = traverser->GetStats().mNumFrustumCulledNodes;
2343                queryCulledNodes = traverser->GetStats().mNumQueryCulledNodes;
2344                issuedQueries = traverser->GetStats().mNumIssuedQueries;
2345                stateChanges = traverser->GetStats().mNumStateChanges;
[2800]2346                numBatches = traverser->GetStats().mNumBatches;
[2770]2347        }
2348
[2764]2349
[3223]2350        ////////////////
2351        //-- record stats on walkthrough
2352
2353        static float accTime = .0f;
2354        static float averageTime = .0f;
2355
2356        if (currentReplayFrame > -1)
2357        {
2358                accTime += frameTime;
2359                averageTime = accTime / (currentReplayFrame + 1);
2360
2361                if (!statsWriter)
[3279]2362                        statsWriter = new StatsWriter(statsFilename + ".log");
[3223]2363                       
2364                FrameStats frameStats;
2365                frameStats.mFrame = currentReplayFrame;
2366                frameStats.mFPS = 1e3f / (float)frameTime;
2367                frameStats.mTime = frameTime;
2368                frameStats.mNodes = renderedNodes;
2369                frameStats.mObjects = renderedObjects;
2370                frameStats.mTriangles = renderedTriangles;
2371
2372                statsWriter->WriteFrameStats(frameStats);
2373        }
2374        else if (statsWriter)
2375        {
2376                Debug << "average frame time " << averageTime << " for traversal algorithm " << renderMode << endl;
2377
2378                // reset average frame time
[3224]2379                averageTime = accTime = .0f;
[3223]2380
2381                DEL_PTR(statsWriter);
2382        }
2383
2384
[2826]2385        Begin2D();
[2808]2386
[2826]2387        glEnable(GL_BLEND);
2388        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
[2764]2389
[2826]2390        if (showHelp)
2391        {       
2392                DrawHelpMessage();
2393        }
2394        else
2395        {
[2829]2396                if (showOptions)
2397                {
2398                        glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
2399                        glRecti(5, winHeight - 95, winWidth * 2 / 3 - 5, winHeight - 5);
2400                }
2401
2402                if (showStatistics)
2403                {
2404                        glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
2405                        glRecti(5, winHeight - 165, winWidth * 2 / 3 - 5, winHeight - 100);
2406                }
2407
2408                glEnable(GL_TEXTURE_2D);
[2827]2409                myfont.Begin();
[2769]2410
[2826]2411                if (showOptions)
2412                {
[2829]2413                        glColor3f(0.0f, 1.0f, 0.0f);
[2826]2414                        int i = 0;
2415
[3065]2416                        static char *renderMethodStr[] =
2417                                {"forward", "depth pass + forward", "deferred shading", "depth pass + deferred"};
[2826]2418                        sprintf(msg[i ++], "multiqueries: %d, tight bounds: %d, render queue: %d",
[3294]2419                                        useMultiQueries, (renderMode == RenderTraverser::CHCPLUSPLUS) && useTightBounds, useRenderQueue);
[3246]2420                        sprintf(msg[i ++], "render technique: %s, use pvss: %d", renderMethodStr[renderMethod], usePvs);
[2826]2421                        sprintf(msg[i ++], "triangles per virtual leaf: %5d", trianglesPerVirtualLeaf);
2422                        sprintf(msg[i ++], "assumed visible frames: %4d, max batch size: %4d",
2423                                assumedVisibleFrames, maxBatchSize);
[2808]2424
[2826]2425                        for (int j = 0; j < 4; ++ j)
[2829]2426                                myfont.DrawString(msg[j], 10.0f, winHeight - 5 - j * 20);
[2826]2427                }
[2808]2428
[2786]2429                if (showStatistics)
[2764]2430                {
[2829]2431                        glColor3f(1.0f, 1.0f, 0.0f);
2432
[2948]2433                        string objStr, totalObjStr;
2434                        string triStr, totalTriStr;
[2826]2435
[2829]2436                        int len = 10;
[2948]2437                        CalcDecimalPoint(objStr, renderedObjects, len);
[3059]2438                        CalcDecimalPoint(totalObjStr, (int)resourceManager->GetNumEntities(), len);
[2826]2439
[2948]2440                        CalcDecimalPoint(triStr, renderedTriangles, len);
2441                        CalcDecimalPoint(totalTriStr, bvh->GetBvhStats().mTriangles, len);
2442
[2826]2443                        int i = 4;
2444
[3276]2445                        if (0) // q: show rendered objects or nodes (no space for both)
[2953]2446                        {
2447                                sprintf(msg[i ++], "rendered: %s of %s objects, %s of %s triangles",
2448                                        objStr.c_str(), totalObjStr.c_str(), triStr.c_str(), totalTriStr.c_str());
2449                        }
2450                        else
2451                        {
2452                                sprintf(msg[i ++], "rendered: %6d of %6d nodes, %s of %s triangles",
2453                                        renderedNodes, bvh->GetNumVirtualNodes(), triStr.c_str(), totalTriStr.c_str());
2454                        }
[2826]2455
[3276]2456                        sprintf(msg[i ++], "traversed: %5d, frustum culled: %5d, query culled: %5d nodes",
[2826]2457                                traversedNodes, frustumCulledNodes, queryCulledNodes);
[3251]2458                        sprintf(msg[i ++], "issued queries: %5d, state changes: %5d, render batches: %5d",
[2826]2459                                issuedQueries, stateChanges, numBatches);
2460
2461                        for (int j = 4; j < 7; ++ j)
[2829]2462                                myfont.DrawString(msg[j], 10.0f, winHeight - (j + 1) * 20);
[2764]2463                }
[2790]2464
[3286]2465                glColor3f(0.0f, 1.0f, 0.0f);
2466
[3258]2467                static char *alg_str[] = {
2468                        "Frustum Cull"
2469                        , "Stop and Wait"
2470                        , "CHC"
2471                        , "CHC ++"
[3285]2472            //, "Collector"
[3258]2473                };
[3284]2474       
[2827]2475                if (!showAlgorithmTime)
[3273]2476                {
2477                        if (showFPS)
[3276]2478                        {                       
2479                                sprintf(msg[7], "%s:  %6.1f fps", alg_str[renderMode], fps);           
[3292]2480                                myfont.DrawString(msg[7], 1.3f, winWidth - 330, winHeight - 10.0f);
[3288]2481
2482                                //int mrays = (int)shotRays / 1000000;
2483                                //sprintf(msg[7], "%s:  %04d M rays", alg_str[renderMode], mrays);     
[3292]2484                                //myfont.DrawString(msg[7], 1.3f, winWidth - 330, winHeight - 60.0f);           
[3276]2485                        }
[3273]2486                }
[2827]2487                else
[3276]2488                {
[2827]2489                        sprintf(msg[7], "%s:  %6.1f ms", alg_str[renderMode], rTime);
[3292]2490                        myfont.DrawString(msg[7], 1.3f, winWidth - 330, winHeight - 10.0f);
[3276]2491                }
[3286]2492
2493                glColor3f(1.0f, 1.0f, 1.0f);
[2764]2494        }
2495
[3286]2496        glColor3f(1, 1, 1);
[2826]2497        glDisable(GL_BLEND);
2498        glDisable(GL_TEXTURE_2D);
2499
[2792]2500        End2D();
[2764]2501}       
[2796]2502
2503
2504void RenderSky()
2505{
[2959]2506        if ((renderMethod == RENDER_DEFERRED) || (renderMethod == RENDER_DEPTH_PASS_DEFERRED))
[3101]2507                renderState.SetRenderTechnique(DEFERRED);
[2958]2508
[3036]2509        const bool useToneMapping =
2510                ((renderMethod == RENDER_DEPTH_PASS_DEFERRED) ||
2511                 (renderMethod == RENDER_DEFERRED)) && useHDR;
[3059]2512       
[3279]2513        preetham->RenderSkyDome(-light->GetDirection(), camera, &renderState, !useToneMapping, skyDomeScaleFactor);
[3212]2514
2515        /// once again reset the renderState just to make sure
[3101]2516        renderState.Reset();
[2801]2517}
[2796]2518
[2948]2519
[2895]2520// render visible object from depth pass
[2801]2521void RenderVisibleObjects()
2522{
[2955]2523        if (renderMethod == RENDER_DEPTH_PASS_DEFERRED)
[2948]2524        {
[2950]2525                if (showShadowMap && !renderLightView)
[2951]2526                {
[3068]2527                        // usethe maximal visible distance to focus shadow map
[3235]2528                        const float newFar = min(camera->GetFar(), traverser->GetMaxVisibleDistance());
2529                        RenderShadowMap(newFar);
[2951]2530                }
[3284]2531
[3068]2532                // initialize deferred rendering
[2948]2533                InitDeferredRendering();
2534        }
[2949]2535        else
[2950]2536        {
[3101]2537                renderState.SetRenderTechnique(FORWARD);
[2950]2538        }
[2948]2539
[3127]2540
[3068]2541        /////////////////
[3101]2542        //-- reset gl renderState before the final visible objects pass
[3068]2543
[3101]2544        renderState.Reset();
[3068]2545
[2953]2546        glEnableClientState(GL_NORMAL_ARRAY);
[3068]2547        /// switch back to smooth shading
[3067]2548        glShadeModel(GL_SMOOTH);
[3068]2549        /// reset alpha to coverage flag
[3101]2550        renderState.SetUseAlphaToCoverage(true);
[3067]2551        // clear color
2552        glClear(GL_COLOR_BUFFER_BIT);
[3039]2553       
[3068]2554        // draw only objects having exactly the same depth as the current sample
2555        glDepthFunc(GL_EQUAL);
[2951]2556
[2949]2557        //cout << "visible: " << (int)traverser->GetVisibleObjects().size() << endl;
2558
[3068]2559        SceneEntityContainer::const_iterator sit,
[2801]2560                sit_end = traverser->GetVisibleObjects().end();
2561
2562        for (sit = traverser->GetVisibleObjects().begin(); sit != sit_end; ++ sit)
[2948]2563        {
[2801]2564                renderQueue->Enqueue(*sit);
[2948]2565        }
[3258]2566
[3068]2567        /// now render out everything in one giant pass
[2801]2568        renderQueue->Apply();
2569
[3068]2570        // switch back to standard depth func
[2801]2571        glDepthFunc(GL_LESS);
[3101]2572        renderState.Reset();
[2949]2573
[3276]2574        PrintGLerror("visible objects");
[2801]2575}
2576
2577
[3120]2578SceneQuery *GetOrCreateSceneQuery()
[2801]2579{
[3037]2580        if (!sceneQuery)
[3258]2581        {
[3101]2582                sceneQuery = new SceneQuery(bvh->GetBox(), traverser, &renderState);
[3258]2583        }
[3037]2584
[3120]2585        return sceneQuery;
2586}
2587
2588
2589void PlaceViewer(const Vector3 &oldPos)
2590{
[2801]2591        Vector3 playerPos = camera->GetPosition();
[3120]2592        bool validIntersect = GetOrCreateSceneQuery()->CalcIntersection(playerPos);
[2801]2593
[2853]2594        if (validIntersect)
[3276]2595                //&& ((playerPos.z - oldPos.z) < bvh->GetBox().Size(2) * 1e-1f))
[2801]2596        {
2597                camera->SetPosition(playerPos);
2598        }
[2809]2599}
[2948]2600
2601
[2951]2602void RenderShadowMap(float newfar)
[2948]2603{
[2953]2604        glDisableClientState(GL_NORMAL_ARRAY);
[3101]2605        renderState.SetRenderTechnique(DEPTH_PASS);
[3038]2606       
2607        // hack: disable cull face because of alpha textured balconies
2608        glDisable(GL_CULL_FACE);
[3101]2609        renderState.LockCullFaceEnabled(true);
[3068]2610
2611        /// don't use alpha to coverage for the depth map (problems with fbo rendering)
[3101]2612        renderState.SetUseAlphaToCoverage(false);
[2948]2613
[3287]2614        const Vector3 lightPos = light->GetDirection() * -1e3f;
2615        if (usePvs) LoadOrUpdatePVSs(lightPos);
2616
2617
[3101]2618        // change CHC++ set of renderState variables
[2980]2619        // this must be done for each change of camera because
[2948]2620        // otherwise the temporal coherency is broken
[3054]2621        BvhNode::SetCurrentState(LIGHT_PASS);
[2948]2622        // hack: temporarily change camera far plane
[2951]2623        camera->SetFar(newfar);
[2948]2624        // the scene is rendered withouth any shading   
[3005]2625        shadowMap->ComputeShadowMap(shadowTraverser, viewProjMat);
[2948]2626
2627        camera->SetFar(farDist);
2628
[3101]2629        renderState.SetUseAlphaToCoverage(true);
2630        renderState.LockCullFaceEnabled(false);
[3102]2631        glEnable(GL_CULL_FACE);
[2948]2632
[2953]2633        glEnableClientState(GL_NORMAL_ARRAY);
[3101]2634        // change back renderState
[3054]2635        BvhNode::SetCurrentState(CAMERA_PASS);
[2952]2636}
[3059]2637
[3068]2638
[3110]2639/** Touch each material once in order to preload the render queue
[3059]2640        bucket id of each material
2641*/
2642void PrepareRenderQueue()
2643{
2644        for (int i = 0; i < 3; ++ i)
2645        {
[3101]2646                renderState.SetRenderTechnique(i);
[3059]2647
2648                // fill all shapes into the render queue        once so we can establish the buckets
2649                ShapeContainer::const_iterator sit, sit_end = (*resourceManager->GetShapes()).end();
2650
2651                for (sit = (*resourceManager->GetShapes()).begin(); sit != sit_end; ++ sit)
2652                {
[3071]2653                        static Transform3 dummy(IdentityMatrix());
[3110]2654                        renderQueue->Enqueue(*sit, NULL);
[3059]2655                }
2656       
2657                // just clear queue again
2658                renderQueue->Clear();
2659        }
2660}
2661
2662
[3237]2663int LoadModel(const string &model, SceneEntityContainer &entities)
[3059]2664{
2665        const string filename = string(model_path + model);
[3237]2666        int numEntities = 0;
2667
[3127]2668        cout << "\nloading model " << filename << endl;
[3237]2669
2670        if (numEntities = resourceManager->Load(filename, entities))
[3225]2671        {
[3127]2672                cout << "model " << filename << " successfully loaded" << endl;
[3225]2673        }
[3059]2674        else
2675        {
2676                cerr << "loading model " << filename << " failed" << endl;
[3225]2677
[3059]2678                CleanUp();
2679                exit(0);
2680        }
[3237]2681
2682        return numEntities;
[3078]2683}
2684
2685
[3316]2686void CreateAnimation(const Vector3 &pos)
[3078]2687{
[3316]2688        //const float b = 5.0f; const float a = 1.5f;
2689        const float a = 5.0f; const float b = 1.5f;
[3078]2690
2691        VertexArray vertices;
2692
[3316]2693        for (int i = 0; i < 360; ++ i)
[3078]2694        {
[3316]2695                const float angle = (float)i * M_PI / 180.0f;
[3078]2696
[3316]2697                Vector3 offs = Vector3(cos(angle) * a, sin(angle) * b, 0);
2698                vertices.push_back(pos + offs);
2699        }
[3080]2700
[3316]2701        /*for (int i = 0; i < 5; ++ i)
[3080]2702        {
2703                Vector3 offs = Vector3(i, 0, 0);
2704                vertices.push_back(center + offs);
[3078]2705        }
[3080]2706       
2707        for (int i = 0; i < 5; ++ i)
2708        {
[3316]2709                Vector3 offs = Vector3(4 - i, 0, 0);
[3080]2710                vertices.push_back(center + offs);
[3316]2711        }*/
[3080]2712
[3078]2713        motionPath = new MotionPath(vertices);
[3214]2714}
2715
[3316]2716
[3215]2717/** This function returns the number of visible pixels of a
2718        bounding box representing the sun.
2719*/
2720int TestSunVisible()
[3214]2721{
2722        // assume sun is at a far away point along the light vector
2723        Vector3 sunPos = light->GetDirection() * -1e3f;
2724        sunPos += camera->GetPosition();
2725
2726        sunBox->GetTransform()->SetMatrix(TranslationMatrix(sunPos));
2727
2728        glBeginQueryARB(GL_SAMPLES_PASSED_ARB, sunQuery);
2729
2730        sunBox->Render(&renderState);
2731
2732        glEndQueryARB(GL_SAMPLES_PASSED_ARB);
2733
2734        GLuint sampleCount;
2735
2736        glGetQueryObjectuivARB(sunQuery, GL_QUERY_RESULT_ARB, &sampleCount);
2737
[3215]2738        return sampleCount;
[3214]2739}
[3244]2740
2741
[3245]2742static Technique GetVizTechnique()
2743{
2744        Technique tech;
2745        tech.Init();
2746
2747        tech.SetEmmisive(RgbaColor(1.0f, 1.0f, 1.0f, 1.0f));
2748        tech.SetDiffuse(RgbaColor(1.0f, 1.0f, 1.0f, 1.0f));
2749        tech.SetAmbient(RgbaColor(1.0f, 1.0f, 1.0f, 1.0f));
2750
2751        return tech;
2752}
2753
2754
[3287]2755void UpdatePvs(const Vector3 &pos)
[3244]2756{
[3245]2757        viewCell = viewCellsTree->GetViewCell(camera->GetPosition());
[3244]2758
[3286]2759        const float elapsedAlgorithmTime = applicationTimer.Elapsedms(false);
[3245]2760
[3286]2761        // assume 60 FPS, total time is in secs
2762        const float raysPerMs = 2.0f * pvsTotalSamples / (pvsTotalTime * 1000.0f);
2763        //shotRays = visibilitySolutionInitialState + elapsedAlgorithmTime * raysPerMs;
2764        //shotRays += 1000 * raysPerMs / 60.0f;
[3285]2765
[3286]2766        //cout << "totalt: " << pvsTotalTime << endl;
2767        //cout << "rays per ms: " << raysPerMs << endl;
[3284]2768
[3259]2769        SceneEntity::SetCurrentVisibleId(globalVisibleId);
[3251]2770
[3259]2771        for (int i = 0; i < viewCell->mPvs.GetSize(); ++ i)
[3244]2772        {
[3284]2773                PvsEntry entry = viewCell->mPvs.GetEntry(i);
[3285]2774#ifdef USE_TIMESTAMPS
[3286]2775                if (!((entry.mTimeStamp < 0.0f) || (entry.mTimeStamp <= shotRays)))
2776                        continue;
[3285]2777#endif
[3286]2778                entry.mEntity->SetVisibleId(globalVisibleId);
2779                //numTriangles += entry.mEntity->CountNumTriangles();
[3244]2780        }
[3245]2781
[3251]2782        ++ globalVisibleId;
[3246]2783}
[3245]2784
[3246]2785
2786void LoadVisibilitySolution()
2787{
2788        ///////////
2789        //-- load the visibility solution
2790
2791        const string vis_filename =
2792                string(model_path + visibilitySolution + ".vis");
2793
2794        VisibilitySolutionLoader visLoader;
2795
[3285]2796        viewCellsTree = visLoader.Load(vis_filename,
2797                                           bvh,
2798                                                                   pvsTotalSamples,
2799                                                                   pvsTotalTime,
2800                                                                   viewCellsScaleFactor);
[3247]2801
2802        if (!viewCellsTree)
2803        {
2804                cerr << "loading pvs failed" << endl;
2805                CleanUp();
2806                exit(0);
2807        }
[3246]2808}
2809
2810
2811void RenderViewCell()
2812{
[3245]2813        // render current view cell
2814        static Technique vcTechnique = GetVizTechnique();
2815
2816        vcTechnique.Render(&renderState);
2817        Visualization::RenderBoxForViz(viewCell->GetBox());
[3276]2818}
2819
2820
[3279]2821void LoadPompeiiFloor()
[3276]2822{
[3284]2823        AxisAlignedBox3 pompeiiBox =
2824                SceneEntity::ComputeBoundingBox(staticObjects);
[3276]2825
2826        // todo: dispose texture
2827        Texture *floorTex = new Texture(model_path + "stairs.c.01.tif");
2828
2829        floorTex->SetBoundaryModeS(Texture::REPEAT);
2830        floorTex->SetBoundaryModeT(Texture::REPEAT);
2831
2832        floorTex->Create();
2833        Material *mymat = resourceManager->CreateMaterial();
2834
2835        Technique *tech = mymat->GetDefaultTechnique();
2836        tech->SetDiffuse(RgbaColor(1, 1, 1, 1));
2837        tech->SetTexture(floorTex);
2838
2839        Technique *depthPass = new Technique(*tech);
2840        Technique *deferred = new Technique(*tech);
2841
2842        depthPass->SetColorWriteEnabled(false);
2843        depthPass->SetLightingEnabled(false);
2844
[3284]2845        ShaderProgram *defaultFragmentTexProgramMrt =
2846                ShaderManager::GetSingleton()->GetShaderProgram("defaultFragmentTexMrt");
2847        ShaderProgram *defaultVertexProgramMrt =
2848                ShaderManager::GetSingleton()->GetShaderProgram("defaultVertexMrt");
[3276]2849
2850        deferred->SetFragmentProgram(defaultFragmentTexProgramMrt);
2851        deferred->SetVertexProgram(defaultVertexProgramMrt);
2852
2853        deferred->GetFragmentProgramParameters()->SetViewMatrixParam(0);
2854        deferred->GetVertexProgramParameters()->SetModelMatrixParam(1);
2855        deferred->GetVertexProgramParameters()->SetOldModelMatrixParam(2);
2856
2857        deferred->SetTexture(floorTex);
2858       
2859        mymat->AddTechnique(deferred);
2860        mymat->AddTechnique(depthPass);
2861
2862
2863        //const Vector3 offs(1300.0f, -2500.0f, .0f);
2864        const Vector3 offs(pompeiiBox.Center(0), pompeiiBox.Center(1), 0);
2865        Matrix4x4 moffs = TranslationMatrix(offs);
2866
2867        Plane3 plane;
2868        Transform3 *mytrafo = resourceManager->CreateTransform(moffs);
2869
2870        SceneEntity *myplane =
2871                SceneEntityConverter().ConvertPlane(plane,
2872                                                    pompeiiBox.Size(0),
2873                                                                                        pompeiiBox.Size(1),
2874                                                                                        5,
2875                                                                                        5,
2876                                                                                        mymat,
2877                                                                                        mytrafo);
2878
2879        resourceManager->AddSceneEntity(myplane);
2880        staticObjects.push_back(myplane);
[3287]2881}
2882
2883
2884void LoadOrUpdatePVSs(const Vector3 &pos)
2885{
2886        if (!viewCellsTree)     
2887        {
2888                LoadVisibilitySolution();
2889                applicationTimer.Start();
2890                shotRays = visibilitySolutionInitialState;
2891        }
2892
2893        if (viewCellsTree) UpdatePvs(pos);
[3316]2894}
2895
2896
2897void CreateNewInstance(SceneEntity *parent, const Vector3 &pos)
2898{
2899        SceneEntity *ent = new SceneEntity(*parent);
2900        resourceManager->AddSceneEntity(ent);
2901
2902        Matrix4x4 transl = TranslationMatrix(pos);
2903        Transform3 *transform = resourceManager->CreateTransform(transl);
2904
2905        ent->SetTransform(transform);
2906        dynamicObjects.push_back(ent);
2907        //Debug << "positions: " << newPos << endl;
[3246]2908}
Note: See TracBrowser for help on using the repository browser.