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

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