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

Revision 1785, 30.2 KB checked in by bittner, 18 years ago (diff)

merge, filter update, renderebuffer made functional

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