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

Revision 1867, 31.2 KB checked in by bittner, 18 years ago (diff)

merge, global lines, rss sampling updates

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