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

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