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

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