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

Revision 3316, 70.5 KB checked in by mattausch, 15 years ago (diff)

surpressed blur, worked on object placing in sibenik (why performance worse than vienna??)

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