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

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