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

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