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

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

global lines support

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