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

Revision 1288, 31.0 KB checked in by mattausch, 18 years ago (diff)
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
22
23#ifdef GTP_INTERNAL
24#include "ArchModeler2MLRT.hxx"
25#endif
26
27namespace GtpVisibilityPreprocessor {
28
29const static bool ADDITIONAL_GEOMETRY_HACK = false;
30
31//Preprocessor *preprocessor;
32
33
34// HACK: Artificially modify scene to watch rendercost changes
35static void AddGeometry(SceneGraph *scene)
36{
37        scene->mRoot->UpdateBox();
38
39        AxisAlignedBox3 sceneBox = scene->GetBox();
40
41        int n = 200;
42
43        if (0){
44        // form grid of boxes
45        for (int i = 0; i < n; ++ i)
46        {
47                for (int j = 0; j < n; ++ j)
48                {
49                        const Vector3 scale2((float)j * 0.8f / n + 0.1f,  0.05f, (float)i * 0.8f  / (float)n + 0.1f);
50               
51                        const Vector3 pt2 = sceneBox.Min() + scale2 * (sceneBox.Max() - sceneBox.Min());
52               
53                        const Vector3 boxSize = sceneBox.Size() * Vector3(0.0025f, 0.01f, 0.0025f);
54                        AxisAlignedBox3 box(pt2, pt2 + boxSize);
55                        Mesh *mesh = CreateMeshFromBox(box);
56
57                        mesh->Preprocess();
58               
59                        MeshInstance *mi = new MeshInstance(mesh);
60                        scene->mRoot->mGeometry.push_back(mi);
61                }
62        }
63
64        for (int i = 0; i < n; ++ i)
65        {
66                for (int j = 0; j < n; ++ j)
67                {
68                        const Vector3 scale2(0.15f, (float)j * 0.8f / n + 0.1f, (float)i * 0.8f  / (float)n + 0.1f);
69               
70                        Vector3 pt2 = sceneBox.Min() + scale2 * (sceneBox.Max() - sceneBox.Min());
71               
72                        Vector3 boxSize = sceneBox.Size() * Vector3(0.0025f, 0.01f, 0.0025f);
73                        AxisAlignedBox3 box(pt2, pt2 + boxSize);
74                        Mesh *mesh = CreateMeshFromBox(box);
75
76                        mesh->Preprocess();
77               
78                        MeshInstance *mi = new MeshInstance(mesh);
79                        scene->mRoot->mGeometry.push_back(mi);
80                }
81        }
82
83        for (int i = 0; i < n; ++ i)
84        {
85                const Vector3 scale2(2, 0.2f, (float)i * 0.8f  / (float)n + 0.1f);
86               
87                Vector3 pt2 = sceneBox.Min() + scale2 * (sceneBox.Max() - sceneBox.Min());
88               
89                //Vector3 boxSize = sceneBox.Size() * Vector3(0.0025, 0.01, 0.0025);
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->mRoot->mGeometry.push_back(mi);
99        }
100       
101        scene->mRoot->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->mRoot->mGeometry.push_back(planeMi);
121        }       
122}
123
124
125Preprocessor::Preprocessor():
126mKdTree(NULL),
127mBspTree(NULL),
128mVspBspTree(NULL),
129mVspTree(NULL),
130mHierarchyManager(NULL),
131mViewCellsManager(NULL),
132mRenderSimulator(NULL),
133mPass(0),
134mRayCastMethod(0)
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.useGlDebugger", mUseGlDebugger);
142        Environment::GetSingleton()->GetBoolValue("Preprocessor.loadPolygonsAsMeshes", mLoadPolygonsAsMeshes);
143        Environment::GetSingleton()->GetBoolValue("Preprocessor.quitOnFinish", mQuitOnFinish);
144        Environment::GetSingleton()->GetBoolValue("Preprocessor.computeVisibility", mComputeVisibility);
145        Environment::GetSingleton()->GetBoolValue("Preprocessor.detectEmptyViewSpace", mDetectEmptyViewSpace);
146        Environment::GetSingleton()->GetBoolValue("Preprocessor.exportVisibility", mExportVisibility );
147//#if GTP_INTERNAL // choose other ray cast method
148        Environment::GetSingleton()->GetIntValue("Preprocessor.rayCastMethod", mRayCastMethod);
149//#endif
150        char buffer[256];
151        Environment::GetSingleton()->GetStringValue("Preprocessor.visibilityFile",  buffer);
152        mVisibilityFileName = buffer;
153        Environment::GetSingleton()->GetBoolValue("Preprocessor.applyVisibilityFilter", mApplyVisibilityFilter );
154        Environment::GetSingleton()->GetBoolValue("Preprocessor.applyVisibilitySpatialFilter",
155                                                          mApplyVisibilitySpatialFilter );
156        Environment::GetSingleton()->GetFloatValue("Preprocessor.visibilityFilterWidth", mVisibilityFilterWidth);
157
158        Debug << "detect empty view space=" << mDetectEmptyViewSpace << endl;
159        Debug << "load polygons as meshes: " << mLoadPolygonsAsMeshes << endl;
160}
161
162
163Preprocessor::~Preprocessor()
164{
165  cout << "cleaning up" << endl;
166
167  cout << "Deleting view cells manager ... \n";
168  DEL_PTR(mViewCellsManager);
169  cout << "done.\n";
170
171  cout << "Deleting bsp tree ... \n";
172  DEL_PTR(mBspTree);
173  cout << "done.\n";
174
175  cout << "Deleting kd tree...\n";
176  DEL_PTR(mKdTree);
177  cout << "done.\n";
178 
179  cout << "Deleting vsp tree...\n";
180  DEL_PTR(mVspTree);
181  cout << "done.\n";
182
183  cout << "Deleting hierarchy manager...\n";
184  DEL_PTR(mHierarchyManager);
185  cout << "done.\n";
186
187  cout << "Deleting vspbsp tree...\n";
188  DEL_PTR(mVspBspTree);
189  cout << "done.\n";
190
191   cout << "Deleting scene graph...\n";
192  DEL_PTR(mSceneGraph);
193  cout << "done.\n";
194
195  DEL_PTR(mRenderSimulator);
196  DEL_PTR(renderer);
197}
198
199int
200SplitFilenames(const string str, vector<string> &filenames)
201{
202        int pos = 0;
203
204        while(1) {
205                int npos = (int)str.find(';', pos);
206               
207                if (npos < 0 || npos - pos < 1)
208                        break;
209                filenames.push_back(string(str, pos, npos - pos));
210                pos = npos + 1;
211        }
212       
213        filenames.push_back(string(str, pos, str.size() - pos));
214        return (int)filenames.size();
215}
216
217
218bool
219Preprocessor::LoadScene(const string filename)
220{
221        // use leaf nodes of the original spatial hierarchy as occludees
222        mSceneGraph = new SceneGraph;
223 
224        Parser *parser;
225        vector<string> filenames;
226        int files = SplitFilenames(filename, filenames);
227        cout << "number of input files: " << files << endl;
228        bool result = false;
229        if (files == 1) {
230               
231                if (strstr(filename.c_str(), ".x3d"))
232                  parser = new X3dParser;
233                else
234                  if (strstr(filename.c_str(), ".ply") || strstr(filename.c_str(), ".plb"))
235                        parser = new PlyParser;
236                  else if (strstr(filename.c_str(), ".obj"))
237                          parser = new ObjParser;
238                  else
239                          parser = new UnigraphicsParser;
240
241                cout<<filename<<endl;
242
243                if (mRayCastMethod == Preprocessor::INTEL_RAYCASTER)
244                  result = parser->ParseFile(filename, &mSceneGraph->mRoot,
245                                                                         mLoadPolygonsAsMeshes,
246                                                                         &mFaceParents);
247                else
248                  result = parser->ParseFile(filename, &mSceneGraph->mRoot, mLoadPolygonsAsMeshes);
249               
250                delete parser;
251
252        } else {
253                // root for different files
254                mSceneGraph->mRoot = new SceneGraphNode;
255                for (int i= 0; i < filenames.size(); i++) {
256                  if (strstr(filenames[i].c_str(), ".x3d"))
257                        parser = new X3dParser;
258                  else
259                        parser = new UnigraphicsParser;
260                 
261                  SceneGraphNode *node;
262                  bool success;
263                 
264                  if (mRayCastMethod == Preprocessor::INTEL_RAYCASTER)
265                        success = parser->ParseFile(filename, &node,
266                                                                                mLoadPolygonsAsMeshes,
267                                                                                &mFaceParents);
268                  else
269                        success = parser->ParseFile(filename, &node, mLoadPolygonsAsMeshes);
270                 
271                  if (success) {
272                        mSceneGraph->mRoot->mChildren.push_back(node);
273                        // at least one file parsed
274                        result = true;
275                  }
276                 
277                  delete parser;
278                }
279        }
280       
281       
282        if (result)
283          {
284                // HACK
285                if (ADDITIONAL_GEOMETRY_HACK)
286                        AddGeometry(mSceneGraph);
287               
288                mSceneGraph->AssignObjectIds();
289       
290                int intersectables, faces;
291                mSceneGraph->GetStatistics(intersectables, faces);
292       
293                cout<<filename<<" parsed successfully."<<endl;
294                cout<<"#NUM_OBJECTS (Total numner of objects)\n"<<intersectables<<endl;
295                cout<<"#NUM_FACES (Total numner of faces)\n"<<faces<<endl;
296                mSceneGraph->CollectObjects(&mObjects);
297                mSceneGraph->mRoot->UpdateBox();
298
299                if (0)
300                {
301                        Exporter *exporter = Exporter::GetExporter("testload.x3d");
302
303                        if (exporter)
304                        {
305                                exporter->ExportGeometry(mObjects);
306                                delete exporter;
307                        }
308                }
309        }
310       
311       
312        return result;
313}
314
315bool
316Preprocessor::ExportPreprocessedData(const string filename)
317{
318 
319  mViewCellsManager->ExportViewCells(filename, true, mObjects);
320 
321  return true;
322}
323
324bool
325Preprocessor::PostProcessVisibility()
326{
327 
328  if (mApplyVisibilityFilter || mApplyVisibilitySpatialFilter) {
329        cout<<"Applying visibility filter ...";
330        cout<<"filter width = " << mVisibilityFilterWidth << endl;
331       
332        if (!mViewCellsManager)
333          return false;
334       
335        mViewCellsManager->ApplyFilter(mKdTree,
336                                                                   mApplyVisibilityFilter ? mVisibilityFilterWidth : -1.0f,
337                                                                   mApplyVisibilitySpatialFilter ? mVisibilityFilterWidth : -1.0f);
338        cout << "done." << endl;
339  }
340 
341  // export the preprocessed information to a file
342  if (mExportVisibility)
343        ExportPreprocessedData(mVisibilityFileName);
344 
345  return true;
346}
347
348
349bool
350Preprocessor::BuildKdTree()
351{
352  mKdTree = new KdTree;
353  // add mesh instances of the scene graph to the root of the tree
354  KdLeaf *root = (KdLeaf *)mKdTree->GetRoot();
355  mSceneGraph->CollectObjects(&root->mObjects);
356 
357  long startTime = GetTime();
358
359  cout << "building kd tree ... " << endl;
360  mKdTree->Construct();
361  cout << "construction finished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs " << endl;
362  return true;
363}
364
365void
366Preprocessor::KdTreeStatistics(ostream &s)
367{
368  s<<mKdTree->GetStatistics();
369}
370
371void
372Preprocessor::BspTreeStatistics(ostream &s)
373{
374        s << mBspTree->GetStatistics();
375}
376
377bool
378Preprocessor::Export( const string filename,
379                                          const bool scene,
380                                          const bool kdtree,
381                                          const bool bsptree
382                                          )
383{
384  Exporter *exporter = Exporter::GetExporter(filename);
385       
386  if (exporter) {
387    if (scene)
388      exporter->ExportScene(mSceneGraph->mRoot);
389
390    if (kdtree) {
391      exporter->SetWireframe();
392      exporter->ExportKdTree(*mKdTree);
393    }
394
395        if (bsptree) {
396                //exporter->SetWireframe();
397                exporter->ExportBspTree(*mBspTree);
398        }
399
400    delete exporter;
401    return true;
402  }
403
404  return false;
405}
406
407
408bool Preprocessor::PrepareViewCells()
409{
410        //-- parse view cells construction method
411        Environment::GetSingleton()->GetBoolValue("ViewCells.loadFromFile", mLoadViewCells);
412        char buf[100];
413       
414        if (mLoadViewCells)
415        {       
416                Environment::GetSingleton()->GetStringValue("ViewCells.filename", buf);
417                cout << "loading view cells from " << buf << endl;
418                mViewCellsManager = ViewCellsManager::LoadViewCells(buf, &mObjects, true);
419        }
420        else
421        {
422                // parse type of view cell container
423                Environment::GetSingleton()->GetStringValue("ViewCells.type", buf);             
424            mViewCellsManager = CreateViewCellsManager(buf);
425
426                // default view space is the extent of the scene
427                mViewCellsManager->SetViewSpaceBox(mSceneGraph->GetBox());
428        }
429       
430        //-- parameters for render heuristics evaluation
431        float objRenderCost = 0, vcOverhead = 0, moveSpeed = 0;
432
433        Environment::GetSingleton()->GetFloatValue("Simulation.objRenderCost",objRenderCost);
434        Environment::GetSingleton()->GetFloatValue("Simulation.vcOverhead", vcOverhead);
435        Environment::GetSingleton()->GetFloatValue("Simulation.moveSpeed", moveSpeed);
436       
437        mRenderSimulator =
438                new RenderSimulator(mViewCellsManager, objRenderCost, vcOverhead, moveSpeed);
439
440        mViewCellsManager->SetRenderer(mRenderSimulator);
441
442
443        if (mUseGlRenderer || mUseGlDebugger)
444        {
445                // NOTE: render texture should be power of 2 and square
446                // renderer must be initialised
447                // $$matt
448//              renderer = new GlRendererBuffer(1024, 768, mSceneGraph, mViewCellsManager, mKdTree);
449                //              renderer->makeCurrent();
450               
451        }
452       
453        return true;
454}
455
456
457HierarchyManager *Preprocessor::CreateHierarchyManager(const char *name)
458{
459        HierarchyManager *hierarchyManager;
460
461        if (strcmp(name, "osp") == 0)
462        {
463                // HACK for testing if per kd evaluation works!!
464                const bool ishack = true;
465                if (ishack)
466                        hierarchyManager = new HierarchyManager(mVspTree, mKdTree);
467                else
468                        hierarchyManager = new HierarchyManager(mVspTree, HierarchyManager::KD_BASED_OBJ_SUBDIV);
469        }
470        else if (strcmp(name, "bvh") == 0)
471        {
472                hierarchyManager = new HierarchyManager(mVspTree, HierarchyManager::BV_BASED_OBJ_SUBDIV);
473        }
474
475        return hierarchyManager;
476}
477
478
479ViewCellsManager *Preprocessor::CreateViewCellsManager(const char *name)
480{
481        ViewCellsTree *vcTree = new ViewCellsTree;
482
483        if (strcmp(name, "kdTree") == 0)
484        {
485                mViewCellsManager = new KdViewCellsManager(vcTree, mKdTree);
486        }
487        else if (strcmp(name, "bspTree") == 0)
488        {
489                Debug << "view cell type: Bsp" << endl;
490
491                mBspTree = new BspTree();
492                mViewCellsManager = new BspViewCellsManager(vcTree, mBspTree);
493        }
494        else if (strcmp(name, "vspBspTree") == 0)
495        {
496                Debug << "view cell type: VspBsp" << endl;
497
498                mVspBspTree = new VspBspTree();
499                mViewCellsManager = new VspBspViewCellsManager(vcTree, mVspBspTree);
500        }
501        else if (strcmp(name, "vspOspTree") == 0)
502        {
503                mVspTree = new VspTree();
504                char buf[100];         
505                Environment::GetSingleton()->GetStringValue("Hierarchy.type", buf);     
506
507                HierarchyManager *mHierarchyManager = CreateHierarchyManager(buf);
508                mViewCellsManager = new VspOspViewCellsManager(vcTree, mHierarchyManager);
509        }
510        else if (strcmp(name, "sceneDependent") == 0)
511        {
512                Debug << "view cell type: Bsp" << endl;
513
514                //TODO
515                mBspTree = new BspTree();
516                mViewCellsManager = new BspViewCellsManager(vcTree, mBspTree);
517        }
518        else
519        {
520                cerr << "Wrong view cells type " << name << "!!!" << endl;
521                exit(1);
522        }
523
524        return mViewCellsManager;
525}
526
527
528// use ascii format to store rays
529#define USE_ASCII 0
530
531
532static inline bool ilt(Intersectable *obj1, Intersectable *obj2)
533{
534        return obj1->mId < obj2->mId;
535}
536
537
538bool Preprocessor::LoadKdTree()
539{
540        return true;
541}
542
543bool Preprocessor::ExportKdTree()
544{
545        return true;
546}
547
548
549bool Preprocessor::LoadSamples(VssRayContainer &samples,
550                                                           ObjectContainer &objects) const
551{
552        std::stable_sort(objects.begin(), objects.end(), ilt);
553        char fileName[100];
554        Environment::GetSingleton()->GetStringValue("Preprocessor.samplesFilename", fileName);
555       
556    Vector3 origin, termination;
557        // HACK: needed only for lower_bound algorithm to find the
558        // intersected objects
559        MeshInstance sObj(NULL);
560        MeshInstance tObj(NULL);
561
562#if USE_ASCII
563        ifstream samplesIn(fileName);
564        if (!samplesIn.is_open())
565                return false;
566
567        string buf;
568        while (!(getline(samplesIn, buf)).eof())
569        {
570                sscanf(buf.c_str(), "%f %f %f %f %f %f %d %d",
571                           &origin.x, &origin.y, &origin.z,
572                           &termination.x, &termination.y, &termination.z,
573                           &(sObj.mId), &(tObj.mId));
574               
575                Intersectable *sourceObj = NULL;
576                Intersectable *termObj = NULL;
577               
578                if (sObj.mId >= 0)
579                {
580                        ObjectContainer::iterator oit =
581                                lower_bound(objects.begin(), objects.end(), &sObj, ilt);
582                        sourceObj = *oit;
583                }
584               
585                if (tObj.mId >= 0)
586                {
587                        ObjectContainer::iterator oit =
588                                lower_bound(objects.begin(), objects.end(), &tObj, ilt);
589                        termObj = *oit;
590                }
591
592                samples.push_back(new VssRay(origin, termination, sourceObj, termObj));
593        }
594#else
595        ifstream samplesIn(fileName, ios::binary);
596        if (!samplesIn.is_open())
597                return false;
598
599        while (1)
600        {
601                 samplesIn.read(reinterpret_cast<char *>(&origin), sizeof(Vector3));
602                 samplesIn.read(reinterpret_cast<char *>(&termination), sizeof(Vector3));
603                 samplesIn.read(reinterpret_cast<char *>(&(sObj.mId)), sizeof(int));
604                 samplesIn.read(reinterpret_cast<char *>(&(tObj.mId)), sizeof(int));
605               
606                 if (samplesIn.eof())
607                        break;
608
609                Intersectable *sourceObj = NULL;
610                Intersectable *termObj = NULL;
611               
612                if (sObj.mId >= 0)
613                {
614                        ObjectContainer::iterator oit =
615                                lower_bound(objects.begin(), objects.end(), &sObj, ilt);
616                        sourceObj = *oit;
617                }
618               
619                if (tObj.mId >= 0)
620                {
621                        ObjectContainer::iterator oit =
622                                lower_bound(objects.begin(), objects.end(), &tObj, ilt);
623                        termObj = *oit;
624                }
625
626                samples.push_back(new VssRay(origin, termination, sourceObj, termObj));
627        }
628
629#endif
630        samplesIn.close();
631
632        return true;
633}
634
635
636bool Preprocessor::ExportSamples(const VssRayContainer &samples) const
637{
638        char fileName[100];
639        Environment::GetSingleton()->GetStringValue("Preprocessor.samplesFilename", fileName);
640       
641
642        VssRayContainer::const_iterator it, it_end = samples.end();
643       
644#if USE_ASCII
645        ofstream samplesOut(fileName);
646        if (!samplesOut.is_open())
647                return false;
648
649        for (it = samples.begin(); it != it_end; ++ it)
650        {
651                VssRay *ray = *it;
652                int sourceid = ray->mOriginObject ? ray->mOriginObject->mId : -1;               
653                int termid = ray->mTerminationObject ? ray->mTerminationObject->mId : -1;       
654
655                samplesOut << ray->GetOrigin().x << " " << ray->GetOrigin().y << " " << ray->GetOrigin().z << " "
656                                   << ray->GetTermination().x << " " << ray->GetTermination().y << " " << ray->GetTermination().z << " "
657                                   << sourceid << " " << termid << "\n";
658        }
659#else
660        ofstream samplesOut(fileName, ios::binary);
661        if (!samplesOut.is_open())
662                return false;
663
664        for (it = samples.begin(); it != it_end; ++ it)
665        {       
666                VssRay *ray = *it;
667                Vector3 origin(ray->GetOrigin());
668                Vector3 termination(ray->GetTermination());
669               
670                int sourceid = ray->mOriginObject ? ray->mOriginObject->mId : -1;               
671                int termid = ray->mTerminationObject ? ray->mTerminationObject->mId : -1;               
672
673                samplesOut.write(reinterpret_cast<char *>(&origin), sizeof(Vector3));
674                samplesOut.write(reinterpret_cast<char *>(&termination), sizeof(Vector3));
675                samplesOut.write(reinterpret_cast<char *>(&sourceid), sizeof(int));
676                samplesOut.write(reinterpret_cast<char *>(&termid), sizeof(int));
677    }
678#endif
679        samplesOut.close();
680
681        return true;
682}
683
684#if 0 // matt: implemented interface samplestrategy
685bool
686Preprocessor::GenerateRays(
687                                                   const int number,
688                                                   const int sampleType,
689                                                   SimpleRayContainer &rays
690                                                   )
691{
692  Vector3 origin, direction;
693  int startSize = (int)rays.size();
694  for (int i=0; (int)rays.size() - startSize  < number; i ++) {
695        // now get the direction
696        switch (sampleType) {
697        case OBJECT_BASED_DISTRIBUTION: {
698          mViewCellsManager->GetViewPoint(origin);
699          Vector3 point;
700          Vector3 normal;
701          int i = RandomValue(0, mObjects.size() - 1);
702          Intersectable *object = mObjects[i];
703          object->GetRandomSurfacePoint(point, normal);
704          direction = point - origin;
705        }
706          break;
707        case OBJECT_DIRECTION_BASED_DISTRIBUTION: {
708          int i = RandomValue(0, mObjects.size() - 1);
709          Intersectable *object = mObjects[i];
710          Vector3 normal;
711          object->GetRandomSurfacePoint(origin, normal);
712          direction = UniformRandomVector(normal);
713          origin += 0.1f*direction;
714        }
715          break;
716        case DIRECTION_BASED_DISTRIBUTION:
717          mViewCellsManager->GetViewPoint(origin);
718          direction = UniformRandomVector();
719          break;
720        case DIRECTION_BOX_BASED_DISTRIBUTION: {
721          mViewCellsManager->GetViewPoint(origin);
722          float alpha = RandomValue(0.0f, 2*M_PI);
723          float beta = RandomValue(-M_PI/2, M_PI/2);
724          direction = VssRay::GetDirection(alpha, beta);
725          break;
726        }
727        case SPATIAL_BOX_BASED_DISTRIBUTION:
728          mViewCellsManager->GetViewPoint(origin);
729          direction = mKdTree->GetBox().GetRandomPoint() - origin;
730          break;
731        default:
732          // unsuported distribution type
733          return false;
734        }
735        // $$ jb the pdf is yet not correct for all sampling methods!
736        float pdf = 1.0f;
737        float c = Magnitude(direction);
738        if (c > Limits::Small) {
739          direction*=1.0f/c;
740          rays.AddRay(SimpleRay(origin, direction, pdf));
741        }
742  }
743  return true;
744}
745#endif
746bool Preprocessor::GenerateRays(const int number,
747                                                                const int sampleType,
748                                                                SimpleRayContainer &rays)
749{
750        Vector3 origin, direction;
751       
752        const int startSize = (int)rays.size();
753        SamplingStrategy *strategy = GenerateSamplingStrategy(sampleType);
754
755        if (!strategy)
756                return false;
757
758        for (int i=0; (int)rays.size() - startSize < number; ++ i)
759        {
760                SimpleRay newRay;
761                bool success = strategy->GenerateSample(newRay);
762
763                if (success)
764                        rays.AddRay(newRay);
765        }
766
767        delete strategy;
768
769    return true;
770}
771
772
773SamplingStrategy *Preprocessor::GenerateSamplingStrategy(const int strategyId) const
774{
775        switch (strategyId)
776        {
777        case OBJECT_BASED_DISTRIBUTION:
778                return new ObjectBasedDistribution(*this);
779        case OBJECT_DIRECTION_BASED_DISTRIBUTION:
780                return new ObjectDirectionBasedDistribution(*this);
781        case DIRECTION_BASED_DISTRIBUTION:
782                return new DirectionBasedDistribution(*this);
783        case DIRECTION_BOX_BASED_DISTRIBUTION:
784                return new DirectionBoxBasedDistribution(*this);
785        case SPATIAL_BOX_BASED_DISTRIBUTION:
786                return new SpatialBoxBasedDistribution(*this);
787        //case OBJECTS_INTERIOR_DISTRIBUTION:
788        //      return new ObjectsInteriorDistribution(*this);
789        default: // no valid strategy
790                Debug << "warning: no valid sampling strategy" << endl;
791                return NULL;
792        }
793
794        // should never come here
795        return NULL;
796}
797
798
799bool Preprocessor::InitRayCast(const string externKdTree)
800{
801        switch (mRayCastMethod) // use intel ray tracing
802        {
803        case INTEL_RAYCASTER:
804#ifdef GTP_INTERNAL
805          cout<<"Ray Cast file: "<<externKdTree<<endl;
806          return mlrtaLoadAS(externKdTree.c_str());
807#endif
808        case INTERNAL_RAYCASTER:
809        default:
810                break;
811        }
812
813        return true;
814}
815
816
817int Preprocessor::CastIntelDoubleRay(
818                                                                         const Vector3 &viewPoint,
819                                                                         const Vector3 &direction,
820                                                                         const float probability,
821                                                                         VssRayContainer &vssRays,
822                                                                         const AxisAlignedBox3 &box
823                                                                         )
824{
825        VssRay *vssRay  = NULL;
826        int hits = 0;
827
828        Vector3 pointA, pointB;
829       
830        Intersectable *objectA =
831                CastIntelSingleRay(viewPoint, direction, pointA, box);
832       
833        // cast ray into other direction
834        Intersectable *objectB =
835                CastIntelSingleRay(viewPoint, -direction, pointB, box);
836
837        const bool validSample = (objectA != objectB);
838       
839        if (validSample)
840        {       
841                if (objectA)
842                {
843                        vssRay = new VssRay(pointB,
844                                                                pointA,
845                                                                objectB,
846                                                                objectA,
847                                                                mPass,
848                                                                probability
849                                                                );
850
851                        vssRays.push_back(vssRay);
852                        hits ++;
853                }
854
855                if (objectB)
856                {
857                        vssRay = new VssRay(pointA,
858                                                                pointB,
859                                                                objectA,
860                                                                objectB,
861                                                                mPass,
862                                                                probability
863                                                                );
864
865                        vssRays.push_back(vssRay);
866                        hits ++;
867                }
868                //Debug << "intel ray: " << *vssRay << endl;
869        }
870
871        //cout << "a";
872        return hits;
873}
874
875
876Intersectable *Preprocessor::CastIntelSingleRay(const Vector3 &viewPoint,
877                                                                                                const Vector3 &direction,
878                                                                                                //const float probability,
879                                                                                                Vector3 &tPoint,
880                                                                                                const AxisAlignedBox3 &box
881                                                                                                )
882{
883        AxisAlignedBox3 sbox = box;
884        sbox.Enlarge(Vector3(-Limits::Small));
885
886        if (!sbox.IsInside(viewPoint))
887                return 0;
888       
889        float pforg[3];
890        float pfdir[3];
891        double pfnorm[3];
892
893        pforg[0] = viewPoint[0]; pforg[1] = viewPoint[1]; pforg[2] = viewPoint[2];
894        pfdir[0] = direction[0]; pfdir[1] = direction[1]; pfdir[2] = direction[2];
895
896        float dist = 0;
897#ifdef GTP_INTERNAL
898        const int hittriangle = mlrtaIntersectAS(pforg, pfdir, pfnorm, dist);
899#else
900        const int hittriangle = -1;
901#endif
902
903        if (hittriangle == -1)
904        {
905                static Ray ray;
906                SetupRay(ray, viewPoint, direction);
907
908                float tmin = 0, tmax;
909                if (box.ComputeMinMaxT(ray, &tmin, &tmax) && tmin < tmax)
910                {
911                        tPoint = ray.Extrap(tmax);
912                }
913
914                return NULL;
915        }
916        else
917        {
918                tPoint[0] = pforg[0] + pfdir[0] * dist;
919                tPoint[1] = pforg[1] + pfdir[1] * dist;
920                tPoint[2] = pforg[2] + pfdir[2] * dist;
921
922                return mFaceParents[hittriangle].mObject;
923        }
924}
925
926
927int Preprocessor::CastInternalRay(
928                                                                  const Vector3 &viewPoint,
929                                                                  const Vector3 &direction,
930                                                                  const float probability,
931                                                                  VssRayContainer &vssRays,
932                                                                  const AxisAlignedBox3 &box
933                                                                  )
934{
935
936  int hits = 0;
937  static Ray ray;
938  Intersectable *objectA, *objectB;
939  Vector3 pointA, pointB;
940
941  //  AxisAlignedBox3 box = Union(mKdTree->GetBox(), mViewCellsManager->GetViewSpaceBox());
942 
943
944  AxisAlignedBox3 sbox = box;
945  sbox.Enlarge(Vector3(-Limits::Small));
946  if (!sbox.IsInside(viewPoint))
947        return 0;
948       
949  SetupRay(ray, viewPoint, direction);
950  ray.mFlags &= ~Ray::CULL_BACKFACES;
951
952  // cast ray to KD tree to find intersection with other objects
953  float bsize = Magnitude(box.Size());
954 
955 
956  if (mKdTree->CastRay(ray)) {
957        objectA = ray.intersections[0].mObject;
958        pointA = ray.Extrap(ray.intersections[0].mT);
959        if (mDetectEmptyViewSpace)
960          if (DotProd(ray.intersections[0].mNormal, direction) >= 0) {
961                // discard the sample
962                return 0;
963          }
964       
965  } else {
966        objectA = NULL;
967        // compute intersection with the scene bounding box
968        float tmin, tmax;
969        if (box.ComputeMinMaxT(ray, &tmin, &tmax) && tmin < tmax)
970          pointA = ray.Extrap(tmax);
971        else
972          return 0;
973  }
974
975 
976  SetupRay(ray, viewPoint, -direction);
977  ray.mFlags &= ~Ray::CULL_BACKFACES;
978 
979  if (mKdTree->CastRay(ray)) {
980        objectB = ray.intersections[0].mObject;
981        pointB = ray.Extrap(ray.intersections[0].mT);
982        if (mDetectEmptyViewSpace)
983          if (DotProd(ray.intersections[0].mNormal, direction) <= 0) {
984                // discard the sample
985                return 0;
986          }
987  } else {
988        objectB = NULL;
989        float tmin, tmax;
990        if (box.ComputeMinMaxT(ray, &tmin, &tmax) && tmin < tmax)
991          pointB = ray.Extrap(tmax);
992        else
993          return 0;
994  }
995 
996 
997  VssRay *vssRay  = NULL;
998  bool validSample = (objectA != objectB);
999  if (validSample) {
1000        if (objectA) {
1001          vssRay = new VssRay(pointB,
1002                                                  pointA,
1003                                                  objectB,
1004                                                  objectA,
1005                                                  mPass,
1006                                                  probability
1007                                                  );
1008          vssRays.push_back(vssRay);
1009          hits ++;
1010        }
1011       
1012        if (objectB) {
1013          vssRay = new VssRay(pointA,
1014                                                  pointB,
1015                                                  objectA,
1016                                                  objectB,
1017                                                  mPass,
1018                                                  probability
1019                                                  );
1020          vssRays.push_back(vssRay);
1021          hits ++;
1022        }
1023  }
1024 
1025  return hits;
1026}
1027
1028
1029int
1030Preprocessor::ProcessRay(
1031                                                 const Vector3 &viewPoint,
1032                                                 const Vector3 &direction,
1033                                                 Intersectable *objectA,
1034                                                 Vector3 &pointA,
1035                                                 const Vector3 &normalA,
1036                                                 Intersectable *objectB,
1037                                                 Vector3 &pointB,
1038                                                 const Vector3 &normalB,
1039                                                 const float probability,
1040                                                 VssRayContainer &vssRays,
1041                                                 const AxisAlignedBox3 &box
1042                                                 )
1043{
1044  int hits=0;
1045
1046  if (objectA == NULL && objectB == NULL)
1047        return 0;
1048
1049  AxisAlignedBox3 sbox = box;
1050  sbox.Enlarge(Vector3(-Limits::Small));
1051
1052  if (!sbox.IsInside(viewPoint))
1053        return 0;
1054
1055  if (objectA == NULL) {
1056        // compute intersection with the scene bounding box
1057        static Ray ray;
1058        SetupRay(ray, viewPoint, direction);
1059       
1060        float tmin, tmax;
1061        if (box.ComputeMinMaxT(ray, &tmin, &tmax) && tmin < tmax)
1062          pointA = ray.Extrap(tmax);
1063        else
1064          return 0;
1065  } else {
1066        if (mDetectEmptyViewSpace)
1067          if (DotProd(normalA, direction) >= 0) {
1068                // discard the sample
1069                return 0;
1070          }
1071  }
1072
1073  if (objectB == NULL) {
1074        // compute intersection with the scene bounding box
1075        static Ray ray;
1076        SetupRay(ray, viewPoint, -direction);
1077
1078        float tmin, tmax;
1079        if (box.ComputeMinMaxT(ray, &tmin, &tmax) && tmin < tmax)
1080          pointB = ray.Extrap(tmax);
1081        else
1082          return 0;
1083  } else {
1084        if (mDetectEmptyViewSpace)
1085          if (DotProd(normalB, direction) <= 0) {
1086                // discard the sample
1087                return 0;
1088          }
1089  }
1090 
1091  VssRay *vssRay  = NULL;
1092  bool validSample = (objectA != objectB);
1093  if (validSample) {
1094        if (objectA) {
1095          vssRay = new VssRay(pointB,
1096                                                  pointA,
1097                                                  objectB,
1098                                                  objectA,
1099                                                  mPass,
1100                                                  probability
1101                                                  );
1102          vssRays.push_back(vssRay);
1103          hits ++;
1104        }
1105       
1106        if (objectB) {
1107          vssRay = new VssRay(pointA,
1108                                                  pointB,
1109                                                  objectA,
1110                                                  objectB,
1111                                                  mPass,
1112                                                  probability
1113                                                  );
1114          vssRays.push_back(vssRay);
1115          hits ++;
1116        }
1117  }
1118 
1119  return hits;
1120}
1121
1122void
1123Preprocessor::CastRays16(const int index,
1124                                                 SimpleRayContainer &rays,
1125                                                 VssRayContainer &vssRays,
1126                                                 const AxisAlignedBox3 &sbox)
1127{
1128  int i;
1129  int num = 16;
1130 
1131  if (mRayCastMethod == INTEL_RAYCASTER) {
1132#ifdef GTP_INTERNAL
1133
1134  int forward_hit_triangles[16];
1135  float forward_dist[16];
1136
1137  int backward_hit_triangles[16];
1138  float backward_dist[16];
1139 
1140  Vector3 min = sbox.Min();
1141  Vector3 max = sbox.Max();
1142 
1143  for (i=0; i < num; i++) {
1144        mlrtaStoreRayAS16(&rays[index + i].mOrigin.x,
1145                                          &rays[index + i].mDirection.x,
1146                                          i);
1147  }
1148 
1149 
1150  mlrtaTraverseGroupAS16(&min.x,
1151                                                 &max.x,
1152                                                 forward_hit_triangles,
1153                                                 forward_dist);
1154
1155  for (i=0; i < num; i++) {
1156        Vector3 dir = -rays[index+i].mDirection;
1157        mlrtaStoreRayAS16(&rays[index+i].mOrigin.x,
1158                                          &dir.x,
1159                                          i);
1160  }
1161 
1162 
1163  mlrtaTraverseGroupAS16(&min.x,
1164                                                 &max.x,
1165                                                 backward_hit_triangles,
1166                                                 backward_dist);
1167 
1168
1169  for (i=0; i < num; i++) {
1170        Intersectable *objectA = NULL, *objectB = NULL;
1171        Vector3 pointA, pointB;
1172        Vector3 normalA, normalB;
1173        if (forward_hit_triangles[i] !=-1 ) {
1174          objectA = mFaceParents[forward_hit_triangles[i]].mObject;
1175          // Get the normal of that face
1176          Mesh *mesh = ((MeshInstance *)objectA)->GetMesh();
1177          normalA = mesh->GetFacePlane(mFaceParents[forward_hit_triangles[i]].mFaceIndex).mNormal;
1178          //-rays[index+i].mDirection; // $$ temporary
1179          pointA = rays[index+i].Extrap(forward_dist[i]);
1180        }
1181       
1182        if (backward_hit_triangles[i]!=-1) {
1183          objectB = mFaceParents[backward_hit_triangles[i]].mObject;
1184          Mesh *mesh = ((MeshInstance *)objectB)->GetMesh();
1185
1186          normalB = mesh->GetFacePlane(mFaceParents[backward_hit_triangles[i]].mFaceIndex).mNormal;
1187         
1188          //      normalB = rays[index+i].mDirection; // $$ temporary
1189          pointB = rays[index+i].Extrap(-backward_dist[i]);
1190        }
1191       
1192        ProcessRay(rays[index+i].mOrigin,
1193                           rays[index+i].mDirection,
1194                           objectA, pointA, normalA,
1195                           objectB, pointB, normalB,
1196                           rays[index+i].mPdf,
1197                           vssRays,
1198                           sbox
1199                           );
1200  }
1201#endif
1202  } else {
1203
1204        for (i=index; i < index + num; i++) {
1205          CastRay(rays[i].mOrigin,
1206                          rays[i].mDirection,
1207                          rays[i].mPdf,
1208                          vssRays,
1209                          sbox);
1210        }
1211  }
1212 
1213}
1214
1215void
1216Preprocessor::CastRays(
1217                                           SimpleRayContainer &rays,
1218                                           VssRayContainer &vssRays
1219                                           )
1220{
1221  long t1 = GetTime();
1222  for (int i=0; i < rays.size(); ) {
1223        if (i + 16 < rays.size()) {
1224          CastRays16(
1225                                 i,
1226                                 rays,
1227                                 vssRays,
1228                                 mViewCellsManager->GetViewSpaceBox());
1229          i += 16;
1230        } else {
1231          CastRay(rays[i].mOrigin,
1232                          rays[i].mDirection,
1233                          rays[i].mPdf,
1234                          vssRays,
1235                          mViewCellsManager->GetViewSpaceBox());
1236          i++;
1237        }
1238        if (i % 10000 == 0)
1239          cout<<".";
1240  }
1241
1242  long t2 = GetTime();
1243 
1244  cout<<2*rays.size()/(1e3*TimeDiff(t1, t2))<<"M rays/s"<<endl;
1245}
1246
1247
1248int Preprocessor::CastRay(
1249                                                  const Vector3 &viewPoint,
1250                                                  const Vector3 &direction,
1251                                                  const float probability,
1252                                                  VssRayContainer &vssRays,
1253                                                  const AxisAlignedBox3 &box
1254                                                  )
1255{
1256        switch (mRayCastMethod)
1257        {
1258        case INTEL_RAYCASTER:
1259                return CastIntelDoubleRay(viewPoint, direction, probability, vssRays, box);
1260        case INTERNAL_RAYCASTER:
1261        default:
1262                return CastInternalRay(viewPoint, direction, probability, vssRays, box);
1263        }
1264}
1265
1266
1267void Preprocessor::SetupRay(Ray &ray,
1268                                                        const Vector3 &point,
1269                                                        const Vector3 &direction
1270                                                        )
1271{
1272        ray.Clear();
1273        // do not store anything else then intersections at the ray
1274        ray.Init(point, direction, Ray::LOCAL_RAY);
1275}
1276
1277}
Note: See TracBrowser for help on using the repository browser.