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

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

new visibility filter support

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