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

Revision 1715, 30.3 KB checked in by bittner, 18 years ago (diff)

new visibility filter support

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