source: GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp @ 1740

Revision 1740, 29.5 KB checked in by mattausch, 18 years ago (diff)

exchanged pvs implementation: using vectors instead of maps

Line 
1#include "SceneGraph.h"
2#include "Exporter.h"
3#include "UnigraphicsParser.h"
4#include "X3dParser.h"
5#include "Preprocessor.h"
6#include "ViewCell.h"
7#include "Environment.h"
8#include "ViewCellsManager.h"
9#include "ViewCellBsp.h"
10#include "VspBspTree.h"
11#include "RenderSimulator.h"
12#include "GlRenderer.h"
13#include "PlyParser.h"
14#include "SamplingStrategy.h"
15#include "VspTree.h"
16#include "OspTree.h"
17#include "ObjParser.h"
18#include "BvHierarchy.h"
19#include "HierarchyManager.h"
20#include "VssRay.h"
21#include "IntelRayCaster.h"
22#include "InternalRayCaster.h"
23
24
25
26#define DEBUG_RAYCAST 0
27#define SHOW_RAYCAST_TIMING 1
28
29
30namespace GtpVisibilityPreprocessor {
31
32const static bool ADDITIONAL_GEOMETRY_HACK = false;
33
34
35// HACK: Artificially modify scene to watch rendercost changes
36static void AddGeometry(SceneGraph *scene)
37{
38        scene->GetRoot()->UpdateBox();
39
40        AxisAlignedBox3 sceneBox = scene->GetBox();
41
42        int n = 200;
43
44        if (0)
45        {
46                // form grid of boxes
47                for (int i = 0; i < n; ++ i)
48                {
49                        for (int j = 0; j < n; ++ j)
50                        {
51                                const Vector3 scale2((float)j * 0.8f / n + 0.1f,  0.05f, (float)i * 0.8f  / (float)n + 0.1f);
52
53                                const Vector3 pt2 = sceneBox.Min() + scale2 * (sceneBox.Max() - sceneBox.Min());
54
55                                const Vector3 boxSize = sceneBox.Size() * Vector3(0.0025f, 0.01f, 0.0025f);
56                                AxisAlignedBox3 box(pt2, pt2 + boxSize);
57                                Mesh *mesh = CreateMeshFromBox(box);
58
59                                mesh->Preprocess();
60
61                                MeshInstance *mi = new MeshInstance(mesh);
62                                scene->GetRoot()->mGeometry.push_back(mi);
63                        }
64                }
65
66                for (int i = 0; i < n; ++ i)
67                {
68                        for (int j = 0; j < n; ++ j)
69                        {
70                                const Vector3 scale2(0.15f, (float)j * 0.8f / n + 0.1f, (float)i * 0.8f  / (float)n + 0.1f);
71
72                                Vector3 pt2 = sceneBox.Min() + scale2 * (sceneBox.Max() - sceneBox.Min());
73
74                                Vector3 boxSize = sceneBox.Size() * Vector3(0.0025f, 0.01f, 0.0025f);
75                                AxisAlignedBox3 box(pt2, pt2 + boxSize);
76                                Mesh *mesh = CreateMeshFromBox(box);
77
78                                mesh->Preprocess();
79
80                                MeshInstance *mi = new MeshInstance(mesh);
81                                scene->GetRoot()->mGeometry.push_back(mi);
82                        }
83                }
84
85                for (int i = 0; i < n; ++ i)
86                {
87                        const Vector3 scale2(2, 0.2f, (float)i * 0.8f  / (float)n + 0.1f);
88
89                        Vector3 pt2 = sceneBox.Min() + scale2 * (sceneBox.Max() - sceneBox.Min());
90                        Vector3 boxSize = sceneBox.Size() * Vector3(0.005f, 0.02f, 0.005f);
91
92                        AxisAlignedBox3 box(pt2 + 0.1f, pt2 + boxSize);
93                        Mesh *mesh = CreateMeshFromBox(box);
94
95                        mesh->Preprocess();
96
97                        MeshInstance *mi = new MeshInstance(mesh);
98                        scene->GetRoot()->mGeometry.push_back(mi);
99                }
100
101                scene->GetRoot()->UpdateBox();
102        }
103
104        if (1)
105        {
106                // plane separating view space regions
107                const Vector3 scale(1.0f, 0.0, 0);
108
109                Vector3 pt = sceneBox.Min() + scale * (sceneBox.Max() - sceneBox.Min());
110
111                Plane3 cuttingPlane(Vector3(1, 0, 0), pt);
112                Mesh *planeMesh = new Mesh();
113
114                Polygon3 *poly = sceneBox.CrossSection(cuttingPlane);
115                IncludePolyInMesh(*poly, *planeMesh);
116
117                planeMesh->Preprocess();
118
119                MeshInstance *planeMi = new MeshInstance(planeMesh);
120                scene->GetRoot()->mGeometry.push_back(planeMi);
121        }       
122}
123
124
125Preprocessor::Preprocessor():
126mKdTree(NULL),
127mBspTree(NULL),
128mVspBspTree(NULL),
129mViewCellsManager(NULL),
130mRenderSimulator(NULL),
131mPass(0),
132mSceneGraph(NULL),
133mRayCaster(NULL),
134mStopComputation(false)
135{
136        Environment::GetSingleton()->GetBoolValue("Preprocessor.useGlRenderer", mUseGlRenderer);
137 
138        // renderer will be constructed when the scene graph and viewcell manager will be known
139        renderer = NULL;
140 
141        Environment::GetSingleton()->GetBoolValue("Preprocessor.delayVisibilityComputation",
142                                                                                          mDelayVisibilityComputation);
143       
144        Environment::GetSingleton()->GetBoolValue("Preprocessor.useGlDebugger", mUseGlDebugger);
145        Environment::GetSingleton()->GetBoolValue("Preprocessor.loadMeshes", mLoadMeshes);
146        Environment::GetSingleton()->GetBoolValue("Preprocessor.quitOnFinish", mQuitOnFinish);
147        Environment::GetSingleton()->GetBoolValue("Preprocessor.computeVisibility", mComputeVisibility);
148        Environment::GetSingleton()->GetBoolValue("Preprocessor.detectEmptyViewSpace", mDetectEmptyViewSpace);
149        Environment::GetSingleton()->GetBoolValue("Preprocessor.exportVisibility", mExportVisibility );
150       
151        char buffer[256];
152        Environment::GetSingleton()->GetStringValue("Preprocessor.visibilityFile",  buffer);
153   
154        mVisibilityFileName = buffer;
155        Environment::GetSingleton()->GetBoolValue("Preprocessor.applyVisibilityFilter", mApplyVisibilityFilter );
156        Environment::GetSingleton()->GetBoolValue("Preprocessor.applyVisibilitySpatialFilter",
157                                                                                          mApplyVisibilitySpatialFilter );
158        Environment::GetSingleton()->GetFloatValue("Preprocessor.visibilityFilterWidth", mVisibilityFilterWidth);
159
160        Environment::GetSingleton()->GetBoolValue("Preprocessor.exportObj", mExportObj);
161       
162        Environment::GetSingleton()->GetBoolValue("Preprocessor.useViewSpaceBox", mUseViewSpaceBox);
163
164        Debug << "******* Preprocessor Options **********" << endl;
165        Debug << "detect empty view space=" << mDetectEmptyViewSpace << endl;
166        Debug << "load meshes: " << mLoadMeshes << endl;
167        Debug << "load meshes: " << mLoadMeshes << endl;
168        Debug << "export obj: " << mExportObj << endl;
169        Debug << "use view space box: " << mUseViewSpaceBox << endl;
170}
171
172
173Preprocessor::~Preprocessor()
174{
175        cout << "cleaning up" << endl;
176
177        cout << "Deleting view cells manager ... \n";
178        DEL_PTR(mViewCellsManager);
179        cout << "done.\n";
180
181        cout << "Deleting bsp tree ... \n";
182        DEL_PTR(mBspTree);
183        cout << "done.\n";
184
185        cout << "Deleting kd tree...\n";
186        DEL_PTR(mKdTree);
187        cout << "done.\n";
188
189        cout << "Deleting vspbsp tree...\n";
190        DEL_PTR(mVspBspTree);
191        cout << "done.\n";
192
193        cout << "Deleting scene graph...\n";
194        DEL_PTR(mSceneGraph);
195        cout << "done.\n";
196
197        DEL_PTR(mRenderSimulator);
198        DEL_PTR(renderer);
199        DEL_PTR(mRayCaster);
200}
201
202
203GlRendererBuffer *Preprocessor::GetRenderer()
204{
205        return renderer;
206}
207
208
209static int SplitFilenames(const string str, vector<string> &filenames)
210{
211        int pos = 0;
212
213        while(1) {
214                int npos = (int)str.find(';', pos);
215               
216                if (npos < 0 || npos - pos < 1)
217                        break;
218                filenames.push_back(string(str, pos, npos - pos));
219                pos = npos + 1;
220        }
221       
222        filenames.push_back(string(str, pos, str.size() - pos));
223        return (int)filenames.size();
224}
225
226
227bool Preprocessor::LoadBinaryObj(const string filename,
228                                                                 SceneGraphNode *root,
229                                                                 vector<FaceParentInfo> *parents)
230{
231        //ifstream samplesIn(filename, ios::binary);
232        igzstream samplesIn(filename.c_str());
233       
234        if (!samplesIn.is_open())
235                return false;
236
237        cout << "binary obj dump available, loading " << filename.c_str() << endl;
238        // table associating indices with vectors
239        map<int, Vector3> hashTable;
240
241        // table for vertices
242        VertexContainer vertices;
243        FaceContainer faces;
244
245        while (1)
246        {
247                Triangle3 tri;
248               
249                samplesIn.read(reinterpret_cast<char *>(tri.mVertices + 0), sizeof(Vector3));
250                samplesIn.read(reinterpret_cast<char *>(tri.mVertices + 1), sizeof(Vector3));
251                samplesIn.read(reinterpret_cast<char *>(tri.mVertices + 2), sizeof(Vector3));
252               
253                // end of file reached
254                if (samplesIn.eof())
255                        break;
256
257                TriangleIntersectable *obj = new TriangleIntersectable(tri);
258                root->mGeometry.push_back(obj);
259
260                // matt: we don't really need to keep an additional data structure
261                // if working with triangles => remove this
262                if (parents)
263                {
264                        FaceParentInfo info(obj, 0);
265                        parents->push_back(info);
266                }       
267        }
268       
269        return true;
270}
271
272
273bool Preprocessor::ExportBinaryObj(const string filename, SceneGraphNode *root)
274{
275        //ifstream samplesIn(filename, ios::binary);
276        ogzstream samplesOut(filename.c_str());
277        if (!samplesOut.is_open())
278                return false;
279
280        ObjectContainer::const_iterator oit, oit_end = root->mGeometry.end();
281
282        for (oit = root->mGeometry.begin(); oit != oit_end; ++ oit)
283        {
284                Intersectable *obj = *oit;
285
286                if (obj->Type() == Intersectable::TRIANGLE_INTERSECTABLE)
287                {
288                        Triangle3 tri = dynamic_cast<TriangleIntersectable *>(obj)->GetItem();
289
290                        samplesOut.write(reinterpret_cast<char *>(tri.mVertices + 0), sizeof(Vector3));
291                        samplesOut.write(reinterpret_cast<char *>(tri.mVertices + 1), sizeof(Vector3));
292                        samplesOut.write(reinterpret_cast<char *>(tri.mVertices + 2), sizeof(Vector3));
293                }
294                else
295                {
296                        cout << "not implemented intersectable type " << obj->Type() << endl;
297                }
298        }
299
300        return true;
301}
302
303
304bool Preprocessor::ExportObj(const string filename, const ObjectContainer &objects)
305{
306        ofstream samplesOut(filename.c_str());
307
308        if (!samplesOut.is_open())
309                return false;
310
311        ObjectContainer::const_iterator oit, oit_end = objects.end();
312
313        AxisAlignedBox3 bbox = mSceneGraph->GetBox(); bbox.Enlarge(30.0);
314        for (oit = objects.begin(); oit != oit_end; ++ oit)
315        {
316                Intersectable *obj = *oit;
317
318                if (obj->Type() == Intersectable::TRIANGLE_INTERSECTABLE)
319                {
320                        Triangle3 tri = dynamic_cast<TriangleIntersectable *>(obj)->GetItem();
321                        //if (bbox.IsInside(tri.mVertices[0]) && bbox.IsInside(tri.mVertices[1]) && bbox.IsInside(tri.mVertices[2]))
322                        //{
323                                samplesOut << "v " << tri.mVertices[0].x << " " << tri.mVertices[0].y << " " << tri.mVertices[0].z << endl;
324                                samplesOut << "v " << tri.mVertices[1].x << " " << tri.mVertices[1].y << " " << tri.mVertices[1].z << endl;
325                                samplesOut << "v " << tri.mVertices[2].x << " " << tri.mVertices[2].y << " " << tri.mVertices[2].z << endl;
326                        //}
327                }
328                else
329                {
330                        cout << "not implemented intersectable type " << obj->Type() << endl;
331                }
332        }
333
334        // write faces
335        int i = 1;
336        for (oit = objects.begin(); oit != oit_end; ++ oit)
337        {
338                Intersectable *obj = *oit;
339                if (obj->Type() == Intersectable::TRIANGLE_INTERSECTABLE)
340                {
341                        //Triangle3 tri = dynamic_cast<TriangleIntersectable *>(obj)->GetItem();
342                        //if (bbox.IsInside(tri.mVertices[0]) && bbox.IsInside(tri.mVertices[1]) && bbox.IsInside(tri.mVertices[2]))
343                        //{
344                                Triangle3 tri = dynamic_cast<TriangleIntersectable *>(obj)->GetItem();
345                                samplesOut << "f " << i << " " << i + 1 << " " << i + 2 << endl;
346                                i += 3;
347                        //}
348                }
349                else
350                {
351                        cout << "not implemented intersectable type " << obj->Type() << endl;
352                }
353        }
354
355        return true;
356
357}
358
359static string ReplaceSuffix(string filename, string a, string b)
360{
361        string result = filename;
362
363        int pos = (int)filename.rfind(a, (int)filename.size() - 1);
364        if (pos == filename.size() - a.size()) {
365                result.replace(pos, a.size(), b);
366        }
367        return result;
368}
369
370
371bool
372Preprocessor::LoadScene(const string filename)
373{
374    // use leaf nodes of the original spatial hierarchy as occludees
375        mSceneGraph = new SceneGraph;
376 
377        Parser *parser;
378        vector<string> filenames;
379        const int files = SplitFilenames(filename, filenames);
380        cout << "number of input files: " << files << endl;
381        bool result = false;
382        bool isObj = false;
383
384        // root for different files
385        mSceneGraph->SetRoot(new SceneGraphNode());
386
387        // intel ray caster can only trace triangles
388        int rayCastMethod;
389        Environment::GetSingleton()->GetIntValue("Preprocessor.rayCastMethod", rayCastMethod);
390        vector<FaceParentInfo> *fi = (rayCastMethod == RayCaster::INTEL_RAYCASTER) ?
391                &mFaceParents : NULL;
392
393        if (files == 1)
394        {
395                if (strstr(filename.c_str(), ".x3d"))
396                {
397                        parser = new X3dParser;
398                       
399                        result = parser->ParseFile(filename,
400                                                                           mSceneGraph->GetRoot(),
401                                                                           mLoadMeshes,
402                                                                           fi);
403                        delete parser;
404                }
405                else if (strstr(filename.c_str(), ".ply") || strstr(filename.c_str(), ".plb"))
406                {
407                        parser = new PlyParser;
408
409                        result = parser->ParseFile(filename,
410                                                                           mSceneGraph->GetRoot(),
411                                                                           mLoadMeshes,
412                                                                           fi);
413                        delete parser;
414                }
415                else if (strstr(filename.c_str(), ".obj"))
416                {
417                        isObj = true;
418
419                        // hack: load binary dump
420                        string binFile = ReplaceSuffix(filename, ".obj", ".bin");
421
422                        if (!mLoadMeshes)
423                        {
424                                result = LoadBinaryObj(binFile, mSceneGraph->GetRoot(), fi);
425                        }
426
427                        if (!result)
428                        {
429                                cout << "no binary dump available or loading full meshes, parsing file" << endl;
430                                parser = new ObjParser;
431               
432                                result = parser->ParseFile(filename,
433                                                                   mSceneGraph->GetRoot(),
434                                                                   mLoadMeshes,
435                                                                   fi);
436                                               
437                                // only works for triangles
438                                if (!mLoadMeshes)
439                                {
440                                        cout << "exporting binary obj to " << binFile << "... " << endl;
441                                        ExportBinaryObj(binFile, mSceneGraph->GetRoot());
442                                        cout << "finished" << endl;
443                                }
444
445                                delete parser;
446                        }
447                        else if (0)
448                        {
449                                ExportBinaryObj("../data/test.bin", mSceneGraph->GetRoot());
450                        }
451                }
452                else
453                {
454                        parser = new UnigraphicsParser;
455                        result = parser->ParseFile(filename,
456                                                                           mSceneGraph->GetRoot(),
457                                                                           mLoadMeshes,                                                           
458                                                                           fi);
459                        delete parser;
460                }
461               
462                cout << filename << endl;
463        }
464        else
465        {
466                vector<string>::const_iterator fit, fit_end = filenames.end();
467               
468                for (fit = filenames.begin(); fit != fit_end; ++ fit)
469                {
470                        const string filename = *fit;
471
472                        cout << "parsing file " << filename.c_str() << endl;
473                        if (strstr(filename.c_str(), ".x3d"))
474                                parser = new X3dParser;
475                        else
476                                parser = new UnigraphicsParser;
477
478                        SceneGraphNode *node = new SceneGraphNode();
479                        const bool success =
480                                parser->ParseFile(filename, node, mLoadMeshes, fi);
481
482                        if (success)
483                        {
484                                mSceneGraph->GetRoot()->mChildren.push_back(node);
485                                result = true; // at least one file parsed
486                        }
487
488                        // temporare hack
489                        //if (!strstr(filename.c_str(), "plane")) mSceneGraph->GetRoot()->UpdateBox();
490
491                        delete parser;
492                }
493        }
494       
495        if (result)
496        {
497                // HACK
498                if (ADDITIONAL_GEOMETRY_HACK)
499                        AddGeometry(mSceneGraph);
500
501                mSceneGraph->AssignObjectIds();
502 
503                int intersectables, faces;
504                mSceneGraph->GetStatistics(intersectables, faces);
505 
506                cout<<filename<<" parsed successfully."<<endl;
507                cout<<"#NUM_OBJECTS (Total numner of objects)\n"<<intersectables<<endl;
508                cout<<"#NUM_FACES (Total numner of faces)\n"<<faces<<endl;
509               
510                mObjects.reserve(intersectables);
511                mSceneGraph->CollectObjects(&mObjects);
512               
513                // temp hack
514                //ExportObj("cropped_vienna.obj", mObjects);
515                mSceneGraph->GetRoot()->UpdateBox();
516                               
517                cout << "finished loading" << endl;
518        }
519
520        return result;
521}
522
523bool
524Preprocessor::ExportPreprocessedData(const string filename)
525{
526        mViewCellsManager->ExportViewCells(filename, true, mObjects);
527        return true;
528}
529
530
531bool
532Preprocessor::PostProcessVisibility()
533{
534 
535  if (mApplyVisibilityFilter || mApplyVisibilitySpatialFilter) {
536        cout<<"Applying visibility filter ...";
537        cout<<"filter width = " << mVisibilityFilterWidth << endl;
538       
539        if (!mViewCellsManager)
540          return false;
541       
542        mViewCellsManager->ApplyFilter(mKdTree,
543                                                                   mApplyVisibilityFilter ? mVisibilityFilterWidth : -1.0f,
544                                                                   mApplyVisibilitySpatialFilter ? mVisibilityFilterWidth : -1.0f);
545        cout << "done." << endl;
546  }
547 
548  // export the preprocessed information to a file
549  if (mExportVisibility)
550  {
551          ExportPreprocessedData(mVisibilityFileName);
552  }
553
554  return true;
555}
556
557
558bool
559Preprocessor::BuildKdTree()
560{
561  mKdTree = new KdTree;
562
563  // add mesh instances of the scene graph to the root of the tree
564  KdLeaf *root = (KdLeaf *)mKdTree->GetRoot();
565       
566  mSceneGraph->CollectObjects(&root->mObjects);
567 
568  const long startTime = GetTime();
569  cout << "building kd tree ... " << endl;
570
571  mKdTree->Construct();
572
573  cout << "finished kd tree construction in " << TimeDiff(startTime, GetTime()) * 1e-3
574           << " secs " << endl;
575
576  return true;
577}
578
579
580void
581Preprocessor::KdTreeStatistics(ostream &s)
582{
583  s<<mKdTree->GetStatistics();
584}
585
586void
587Preprocessor::BspTreeStatistics(ostream &s)
588{
589        s << mBspTree->GetStatistics();
590}
591
592bool
593Preprocessor::Export( const string filename,
594                                          const bool scene,
595                                          const bool kdtree
596                                          )
597{
598  Exporter *exporter = Exporter::GetExporter(filename);
599       
600  if (exporter) {
601    if (2 && scene)
602      exporter->ExportScene(mSceneGraph->GetRoot());
603
604    if (1 && kdtree) {
605      exporter->SetWireframe();
606      exporter->ExportKdTree(*mKdTree);
607    }
608
609    delete exporter;
610    return true;
611  }
612
613  return false;
614}
615
616
617bool Preprocessor::PrepareViewCells()
618{
619        ///////
620        //-- parse view cells construction method
621
622        Environment::GetSingleton()->GetBoolValue("ViewCells.loadFromFile", mLoadViewCells);
623        char buf[100];
624
625        if (mLoadViewCells)
626        {       
627                Environment::GetSingleton()->GetStringValue("ViewCells.filename", buf);
628                cout << "loading view cells from " << buf << endl<<flush;
629
630                mViewCellsManager = ViewCellsManager::LoadViewCells(buf, &mObjects, true, NULL);
631
632                cout << "view cells loaded." << endl<<flush;
633
634                if (!mViewCellsManager)
635                {
636                        return false;
637                }
638        }
639        else
640        {
641                // parse type of view cell container
642                Environment::GetSingleton()->GetStringValue("ViewCells.type", buf);             
643                mViewCellsManager = CreateViewCellsManager(buf);
644
645                // default view space is the extent of the scene
646                AxisAlignedBox3 viewSpaceBox;
647
648                if (mUseViewSpaceBox)
649                {
650                        viewSpaceBox = mSceneGraph->GetBox();
651
652                        // use a small box outside of the scene
653                        viewSpaceBox.Scale(Vector3(0.15f, 0.3f, 0.5f));
654                        //viewSpaceBox.Translate(Vector3(Magnitude(mSceneGraph->GetBox().Size()) * 0.5f, 0, 0));
655                        viewSpaceBox.Translate(Vector3(Magnitude(mSceneGraph->GetBox().Size()) * 0.3f, 0, 0));
656                        mViewCellsManager->SetViewSpaceBox(viewSpaceBox);
657                }
658                else
659                {
660                        viewSpaceBox = mSceneGraph->GetBox();
661                        mViewCellsManager->SetViewSpaceBox(viewSpaceBox);
662                }
663
664                bool loadVcGeometry;
665                Environment::GetSingleton()->GetBoolValue("ViewCells.loadGeometry", loadVcGeometry);
666
667                bool extrudeBaseTriangles;
668                Environment::GetSingleton()->GetBoolValue("ViewCells.useBaseTrianglesAsGeometry", extrudeBaseTriangles);
669
670                char vcGeomFilename[100];
671                Environment::GetSingleton()->GetStringValue("ViewCells.geometryFilename", vcGeomFilename);
672
673                if (loadVcGeometry)
674                {
675                        if (mViewCellsManager->GetType() == ViewCellsManager::BSP)
676                        {
677                                if (!mViewCellsManager->LoadViewCellsGeometry(vcGeomFilename, extrudeBaseTriangles))
678                                {
679                                        cerr << "loading view cells geometry failed" << endl;
680                                }
681                        }
682                        else
683                        {
684                                cerr << "loading view cells geometry is not implemented for this manager" << endl;
685                        }
686                }
687        }
688
689        ////////
690        //-- evaluation of render cost heuristics
691        float objRenderCost = 0, vcOverhead = 0, moveSpeed = 0;
692
693        Environment::GetSingleton()->GetFloatValue("Simulation.objRenderCost",objRenderCost);
694        Environment::GetSingleton()->GetFloatValue("Simulation.vcOverhead", vcOverhead);
695        Environment::GetSingleton()->GetFloatValue("Simulation.moveSpeed", moveSpeed);
696
697        mRenderSimulator =
698                new RenderSimulator(mViewCellsManager, objRenderCost, vcOverhead, moveSpeed);
699
700        mViewCellsManager->SetRenderer(mRenderSimulator);
701
702        if (mUseGlRenderer || mUseGlDebugger)
703        {
704                // NOTE: render texture should be power of 2 and square
705                // renderer must be initialised
706                // $$matt
707                //              renderer = new GlRendererBuffer(1024, 768, mSceneGraph, mViewCellsManager, mKdTree);
708                //              renderer->makeCurrent();
709
710        }
711
712        mViewCellsManager->SetPreprocessor(this);
713        return true;
714}
715
716 
717bool Preprocessor::ConstructViewCells()
718{
719        // construct view cells using it's own set of samples
720        mViewCellsManager->Construct(this);
721
722        // visualizations and statistics
723        Debug << "finished view cells:" << endl;
724        mViewCellsManager->PrintStatistics(Debug);
725
726        return true;
727}
728
729
730ViewCellsManager *Preprocessor::CreateViewCellsManager(const char *name)
731{
732        ViewCellsTree *vcTree = new ViewCellsTree;
733
734        if (strcmp(name, "kdTree") == 0)
735        {
736                mViewCellsManager = new KdViewCellsManager(vcTree, mKdTree);
737        }
738        else if (strcmp(name, "bspTree") == 0)
739        {
740                Debug << "view cell type: Bsp" << endl;
741
742                mBspTree = new BspTree();
743                mViewCellsManager = new BspViewCellsManager(vcTree, mBspTree);
744        }
745        else if (strcmp(name, "vspBspTree") == 0)
746        {
747                Debug << "view cell type: VspBsp" << endl;
748
749                mVspBspTree = new VspBspTree();
750                mViewCellsManager = new VspBspViewCellsManager(vcTree, mVspBspTree);
751        }
752        else if (strcmp(name, "vspOspTree") == 0)
753        {
754                Debug << "view cell type: VspOsp" << endl;
755                char buf[100];         
756                Environment::GetSingleton()->GetStringValue("Hierarchy.type", buf);     
757
758                mViewCellsManager = new VspOspViewCellsManager(vcTree, buf);
759        }
760        else if (strcmp(name, "sceneDependent") == 0) //TODO
761        {
762                Debug << "view cell type: Bsp" << endl;
763               
764                mBspTree = new BspTree();
765                mViewCellsManager = new BspViewCellsManager(vcTree, mBspTree);
766        }
767        else
768        {
769                cerr << "Wrong view cells type " << name << "!!!" << endl;
770                exit(1);
771        }
772
773        return mViewCellsManager;
774}
775
776
777// use ascii format to store rays
778#define USE_ASCII 0
779
780
781static inline bool ilt(Intersectable *obj1, Intersectable *obj2)
782{
783        return obj1->mId < obj2->mId;
784}
785
786
787bool Preprocessor::LoadKdTree(const string filename)
788{
789        mKdTree = new KdTree();
790
791        return mKdTree->LoadBinTree(filename.c_str(), mObjects);
792}
793
794
795bool Preprocessor::ExportKdTree(const string filename)
796{
797        return mKdTree->ExportBinTree(filename.c_str());
798}
799
800
801bool Preprocessor::LoadSamples(VssRayContainer &samples,
802                                                           ObjectContainer &objects) const
803{
804        std::stable_sort(objects.begin(), objects.end(), ilt);
805        char fileName[100];
806        Environment::GetSingleton()->GetStringValue("Preprocessor.samplesFilename", fileName);
807       
808    Vector3 origin, termination;
809        // HACK: needed only for lower_bound algorithm to find the
810        // intersected objects
811        MeshInstance sObj(NULL);
812        MeshInstance tObj(NULL);
813
814#if USE_ASCII
815        ifstream samplesIn(fileName);
816        if (!samplesIn.is_open())
817                return false;
818
819        string buf;
820        while (!(getline(samplesIn, buf)).eof())
821        {
822                sscanf(buf.c_str(), "%f %f %f %f %f %f %d %d",
823                           &origin.x, &origin.y, &origin.z,
824                           &termination.x, &termination.y, &termination.z,
825                           &(sObj.mId), &(tObj.mId));
826               
827                Intersectable *sourceObj = NULL;
828                Intersectable *termObj = NULL;
829               
830                if (sObj.mId >= 0)
831                {
832                        ObjectContainer::iterator oit =
833                                lower_bound(objects.begin(), objects.end(), &sObj, ilt);
834                        sourceObj = *oit;
835                }
836               
837                if (tObj.mId >= 0)
838                {
839                        ObjectContainer::iterator oit =
840                                lower_bound(objects.begin(), objects.end(), &tObj, ilt);
841                        termObj = *oit;
842                }
843
844                samples.push_back(new VssRay(origin, termination, sourceObj, termObj));
845        }
846#else
847        ifstream samplesIn(fileName, ios::binary);
848        if (!samplesIn.is_open())
849                return false;
850
851        while (1)
852        {
853                 samplesIn.read(reinterpret_cast<char *>(&origin), sizeof(Vector3));
854                 samplesIn.read(reinterpret_cast<char *>(&termination), sizeof(Vector3));
855                 samplesIn.read(reinterpret_cast<char *>(&(sObj.mId)), sizeof(int));
856                 samplesIn.read(reinterpret_cast<char *>(&(tObj.mId)), sizeof(int));
857               
858                 if (samplesIn.eof())
859                        break;
860
861                Intersectable *sourceObj = NULL;
862                Intersectable *termObj = NULL;
863               
864                if (sObj.mId >= 0)
865                {
866                        ObjectContainer::iterator oit =
867                                lower_bound(objects.begin(), objects.end(), &sObj, ilt);
868                        sourceObj = *oit;
869                }
870               
871                if (tObj.mId >= 0)
872                {
873                        ObjectContainer::iterator oit =
874                                lower_bound(objects.begin(), objects.end(), &tObj, ilt);
875                        termObj = *oit;
876                }
877
878                samples.push_back(new VssRay(origin, termination, sourceObj, termObj));
879        }
880
881#endif
882        samplesIn.close();
883
884        return true;
885}
886
887
888bool Preprocessor::ExportSamples(const VssRayContainer &samples) const
889{
890        char fileName[100];
891        Environment::GetSingleton()->GetStringValue("Preprocessor.samplesFilename", fileName);
892       
893
894        VssRayContainer::const_iterator it, it_end = samples.end();
895       
896#if USE_ASCII
897        ofstream samplesOut(fileName);
898        if (!samplesOut.is_open())
899                return false;
900
901        for (it = samples.begin(); it != it_end; ++ it)
902        {
903                VssRay *ray = *it;
904                int sourceid = ray->mOriginObject ? ray->mOriginObject->mId : -1;               
905                int termid = ray->mTerminationObject ? ray->mTerminationObject->mId : -1;       
906
907                samplesOut << ray->GetOrigin().x << " " << ray->GetOrigin().y << " " << ray->GetOrigin().z << " "
908                                   << ray->GetTermination().x << " " << ray->GetTermination().y << " " << ray->GetTermination().z << " "
909                                   << sourceid << " " << termid << "\n";
910        }
911#else
912        ofstream samplesOut(fileName, ios::binary);
913        if (!samplesOut.is_open())
914                return false;
915
916        for (it = samples.begin(); it != it_end; ++ it)
917        {       
918                VssRay *ray = *it;
919                Vector3 origin(ray->GetOrigin());
920                Vector3 termination(ray->GetTermination());
921               
922                int sourceid = ray->mOriginObject ? ray->mOriginObject->mId : -1;               
923                int termid = ray->mTerminationObject ? ray->mTerminationObject->mId : -1;               
924
925                samplesOut.write(reinterpret_cast<char *>(&origin), sizeof(Vector3));
926                samplesOut.write(reinterpret_cast<char *>(&termination), sizeof(Vector3));
927                samplesOut.write(reinterpret_cast<char *>(&sourceid), sizeof(int));
928                samplesOut.write(reinterpret_cast<char *>(&termid), sizeof(int));
929    }
930#endif
931        samplesOut.close();
932
933        return true;
934}
935
936bool Preprocessor::GenerateRays(const int number,
937                                                                const int sampleType,
938                                                                SimpleRayContainer &rays)
939{
940        const int startSize = (int)rays.size();
941        SamplingStrategy *strategy = GenerateSamplingStrategy(sampleType);
942
943        if (!strategy)
944        {
945                return false;
946        }
947
948        for (int i=0; (int)rays.size() - startSize < number; ++ i)
949        {
950                SimpleRay newRay;
951
952                if (strategy->GenerateSample(newRay))
953                {
954#if 1
955                        rays.AddRay(newRay);
956#else
957                        GenerateRayBundle(rays, newRay, 16, 0);
958#endif
959                }       
960        }
961
962        delete strategy;
963    return true;
964}
965
966
967SamplingStrategy *Preprocessor::GenerateSamplingStrategy(const int strategyId) const
968{
969        switch (strategyId)
970        {
971        case SamplingStrategy::OBJECT_BASED_DISTRIBUTION:
972                return new ObjectBasedDistribution(*this);
973        case SamplingStrategy::OBJECT_DIRECTION_BASED_DISTRIBUTION:
974                return new ObjectDirectionBasedDistribution(*this);
975        case SamplingStrategy::DIRECTION_BASED_DISTRIBUTION:
976                return new DirectionBasedDistribution(*this);
977        case SamplingStrategy::DIRECTION_BOX_BASED_DISTRIBUTION:
978                return new DirectionBoxBasedDistribution(*this);
979        case SamplingStrategy::SPATIAL_BOX_BASED_DISTRIBUTION:
980                return new SpatialBoxBasedDistribution(*this);
981        case SamplingStrategy::REVERSE_OBJECT_BASED_DISTRIBUTION:
982                return new ReverseObjectBasedDistribution(*this);
983        //case OBJECTS_INTERIOR_DISTRIBUTION:
984        //      return new ObjectsInteriorDistribution(*this);
985        default: // no valid strategy
986                Debug << "warning: no valid sampling strategy" << endl;
987                return NULL;
988        }
989
990        return NULL; // should never come here
991}
992
993
994bool Preprocessor::InitRayCast(const string externKdTree, const string internKdTree)
995{
996        // always try to load the kd tree
997        cout << "loading kd tree file " << internKdTree << " ... " << endl;
998
999        if (!LoadKdTree(internKdTree))
1000        {
1001                cout << "error loading kd tree with filename " << internKdTree << ", rebuilding it instead ... " << endl;
1002                // build new kd tree from scene geometry
1003                BuildKdTree();
1004
1005                // export kd tree?
1006                const long startTime = GetTime();
1007                cout << "exporting kd tree ... ";
1008
1009                if (!ExportKdTree(internKdTree))
1010                {
1011                        cout << " error exporting kd tree with filename " << internKdTree << endl;
1012                }
1013                else
1014                {
1015                        cout << "finished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
1016                }
1017        }
1018       
1019        KdTreeStatistics(cout);
1020        cout << mKdTree->GetBox() << endl;
1021
1022        if (0)
1023        {
1024                Exporter *exporter = Exporter::GetExporter("dummykd.x3d");
1025                       
1026                if (exporter)
1027                {
1028                        exporter->ExportKdTree(*mKdTree, true);
1029                        delete exporter;
1030                }
1031        }
1032
1033        int rayCastMethod;
1034        Environment::GetSingleton()->GetIntValue("Preprocessor.rayCastMethod", rayCastMethod);
1035
1036        if (rayCastMethod == 0)
1037        {
1038                mRayCaster = new InternalRayCaster(*this, mKdTree);
1039                cout << "ray cast method: internal" << endl;
1040        }
1041        else
1042        {
1043#ifdef GTP_INTERNAL
1044                mRayCaster = new IntelRayCaster(*this, externKdTree);
1045                cout << "ray cast method: intel" << endl;
1046#endif
1047        }
1048
1049        return true;
1050}
1051
1052
1053void
1054Preprocessor::CastRays(
1055                                           SimpleRayContainer &rays,
1056                                           VssRayContainer &vssRays,
1057                                           const bool castDoubleRays,
1058                                           const bool pruneInvalidRays
1059                                           )
1060{
1061        const long t1 = GetTime();
1062
1063        for (int i = 0; i < (int)rays.size();)
1064        {
1065                if (i + 16 < (int)rays.size())
1066                {
1067                        mRayCaster->CastRays16(
1068                                                                   i,
1069                                                                   rays,                               
1070                                                                   vssRays,
1071                                                                   mViewCellsManager->GetViewSpaceBox(),
1072                                                                   castDoubleRays,
1073                                                                   pruneInvalidRays);
1074                        i += 16;
1075                }
1076                else
1077                  {
1078                        mRayCaster->CastRay(
1079                                                                rays[i],
1080                                                                vssRays,
1081                                                                mViewCellsManager->GetViewSpaceBox(),
1082                                                                castDoubleRays,
1083                                                                pruneInvalidRays);
1084                        i ++;
1085                  }
1086                if (i % 10000 == 0)
1087                  cout<<"\r"<<i<<"/"<<(int)rays.size()<<"\r";
1088        }
1089        cout<<endl;
1090       
1091        long t2 = GetTime();
1092
1093#if SHOW_RAYCAST_TIMING
1094        if (castDoubleRays)
1095                cout << 2 * rays.size() / (1e3f * TimeDiff(t1, t2)) << "M rays/s" << endl;
1096        else
1097                cout << rays.size() / (1e3f * TimeDiff(t1, t2)) << "M rays/s" << endl;
1098#endif 
1099}
1100
1101
1102bool Preprocessor::GenerateRayBundle(SimpleRayContainer &rayBundle,                                                                     
1103                                                                         const SimpleRay &mainRay,
1104                                                                         const int number,
1105                                                                         const int pertubType) const
1106{
1107        rayBundle.push_back(mainRay);
1108
1109        const float pertubOrigin = 0.0f;
1110        const float pertubDir = 0.2f;
1111
1112        for (int i = 0; i < number - 1; ++ i)
1113        {
1114                Vector3 pertub;
1115
1116                pertub.x = RandomValue(0.0f, pertubDir);
1117                pertub.y = RandomValue(0.0f, pertubDir);
1118                pertub.z = RandomValue(0.0f, pertubDir);
1119
1120                const Vector3 newDir = mainRay.mDirection + pertub;
1121                //const Vector3 newDir = mainRay.mDirection;
1122
1123                pertub.x = RandomValue(0.0f, pertubOrigin);
1124                pertub.y = RandomValue(0.0f, pertubOrigin);
1125                pertub.z = RandomValue(0.0f, pertubOrigin);
1126
1127                const Vector3 newOrigin = mainRay.mOrigin + pertub;
1128                //const Vector3 newOrigin = mainRay.mOrigin;
1129
1130                rayBundle.push_back(SimpleRay(newOrigin, newDir, 0));
1131        }
1132
1133        return true;
1134}
1135
1136
1137void Preprocessor::SetupRay(Ray &ray,
1138                                                        const Vector3 &point,
1139                                                        const Vector3 &direction) const
1140{
1141        ray.Clear();
1142        // do not store anything else then intersections at the ray
1143        ray.Init(point, direction, Ray::LOCAL_RAY);     
1144}
1145
1146
1147}
Note: See TracBrowser for help on using the repository browser.