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

Revision 1779, 30.5 KB checked in by mattausch, 18 years ago (diff)

warning: this version contains bugs!!

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