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

Revision 1291, 31.2 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        {
45                // form grid of boxes
46                for (int i = 0; i < n; ++ i)
47                {
48                        for (int j = 0; j < n; ++ j)
49                        {
50                                const Vector3 scale2((float)j * 0.8f / n + 0.1f,  0.05f, (float)i * 0.8f  / (float)n + 0.1f);
51
52                                const Vector3 pt2 = sceneBox.Min() + scale2 * (sceneBox.Max() - sceneBox.Min());
53
54                                const Vector3 boxSize = sceneBox.Size() * Vector3(0.0025f, 0.01f, 0.0025f);
55                                AxisAlignedBox3 box(pt2, pt2 + boxSize);
56                                Mesh *mesh = CreateMeshFromBox(box);
57
58                                mesh->Preprocess();
59
60                                MeshInstance *mi = new MeshInstance(mesh);
61                                scene->mRoot->mGeometry.push_back(mi);
62                        }
63                }
64
65                for (int i = 0; i < n; ++ i)
66                {
67                        for (int j = 0; j < n; ++ j)
68                        {
69                                const Vector3 scale2(0.15f, (float)j * 0.8f / n + 0.1f, (float)i * 0.8f  / (float)n + 0.1f);
70
71                                Vector3 pt2 = sceneBox.Min() + scale2 * (sceneBox.Max() - sceneBox.Min());
72
73                                Vector3 boxSize = sceneBox.Size() * Vector3(0.0025f, 0.01f, 0.0025f);
74                                AxisAlignedBox3 box(pt2, pt2 + boxSize);
75                                Mesh *mesh = CreateMeshFromBox(box);
76
77                                mesh->Preprocess();
78
79                                MeshInstance *mi = new MeshInstance(mesh);
80                                scene->mRoot->mGeometry.push_back(mi);
81                        }
82                }
83
84                for (int i = 0; i < n; ++ i)
85                {
86                        const Vector3 scale2(2, 0.2f, (float)i * 0.8f  / (float)n + 0.1f);
87
88                        Vector3 pt2 = sceneBox.Min() + scale2 * (sceneBox.Max() - sceneBox.Min());
89
90                        //Vector3 boxSize = sceneBox.Size() * Vector3(0.0025, 0.01, 0.0025);
91                        Vector3 boxSize = sceneBox.Size() * Vector3(0.005f, 0.02f, 0.005f);
92
93                        AxisAlignedBox3 box(pt2 + 0.1f, pt2 + boxSize);
94                        Mesh *mesh = CreateMeshFromBox(box);
95
96                        mesh->Preprocess();
97
98                        MeshInstance *mi = new MeshInstance(mesh);
99                        scene->mRoot->mGeometry.push_back(mi);
100                }
101
102                scene->mRoot->UpdateBox();
103        }
104
105        if (1)
106        {
107                // plane separating view space regions
108                const Vector3 scale(1.0f, 0.0, 0);
109
110                Vector3 pt = sceneBox.Min() + scale * (sceneBox.Max() - sceneBox.Min());
111
112                Plane3 cuttingPlane(Vector3(1, 0, 0), pt);
113                Mesh *planeMesh = new Mesh();
114
115                Polygon3 *poly = sceneBox.CrossSection(cuttingPlane);
116                IncludePolyInMesh(*poly, *planeMesh);
117
118                planeMesh->Preprocess();
119
120                MeshInstance *planeMi = new MeshInstance(planeMesh);
121                scene->mRoot->mGeometry.push_back(planeMi);
122        }       
123}
124
125
126Preprocessor::Preprocessor():
127mKdTree(NULL),
128mBspTree(NULL),
129mVspBspTree(NULL),
130mVspTree(NULL),
131mHierarchyManager(NULL),
132mViewCellsManager(NULL),
133mRenderSimulator(NULL),
134mPass(0),
135mRayCastMethod(0)
136{
137        Environment::GetSingleton()->GetBoolValue("Preprocessor.useGlRenderer", mUseGlRenderer);
138 
139        // renderer will be constructed when the scene graph and viewcell manager will be known
140        renderer = NULL;
141 
142        Environment::GetSingleton()->GetBoolValue("Preprocessor.useGlDebugger", mUseGlDebugger);
143        Environment::GetSingleton()->GetBoolValue("Preprocessor.loadPolygonsAsMeshes", mLoadPolygonsAsMeshes);
144        Environment::GetSingleton()->GetBoolValue("Preprocessor.quitOnFinish", mQuitOnFinish);
145        Environment::GetSingleton()->GetBoolValue("Preprocessor.computeVisibility", mComputeVisibility);
146        Environment::GetSingleton()->GetBoolValue("Preprocessor.detectEmptyViewSpace", mDetectEmptyViewSpace);
147        Environment::GetSingleton()->GetBoolValue("Preprocessor.exportVisibility", mExportVisibility );
148        Environment::GetSingleton()->GetIntValue("Preprocessor.rayCastMethod", mRayCastMethod);
149
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                Debug << "hierarchy manager: osp" << endl;
464                // HACK for testing if per kd evaluation works!!
465                const bool ishack = true;
466                if (ishack)
467                        hierarchyManager = new HierarchyManager(mVspTree, mKdTree);
468                else
469                        hierarchyManager = new HierarchyManager(mVspTree, HierarchyManager::KD_BASED_OBJ_SUBDIV);
470        }
471        else if (strcmp(name, "bvh") == 0)
472        {
473                Debug << "hierarchy manager: bvh" << endl;
474                hierarchyManager = new HierarchyManager(mVspTree, HierarchyManager::BV_BASED_OBJ_SUBDIV);
475        }
476        else // only view space partition
477        {
478                Debug << "hierarchy manager: obj" << endl;
479                hierarchyManager = new HierarchyManager(mVspTree, HierarchyManager::NO_OBJ_SUBDIV);
480        }
481
482        return hierarchyManager;
483}
484
485
486ViewCellsManager *Preprocessor::CreateViewCellsManager(const char *name)
487{
488        ViewCellsTree *vcTree = new ViewCellsTree;
489
490        if (strcmp(name, "kdTree") == 0)
491        {
492                mViewCellsManager = new KdViewCellsManager(vcTree, mKdTree);
493        }
494        else if (strcmp(name, "bspTree") == 0)
495        {
496                Debug << "view cell type: Bsp" << endl;
497
498                mBspTree = new BspTree();
499                mViewCellsManager = new BspViewCellsManager(vcTree, mBspTree);
500        }
501        else if (strcmp(name, "vspBspTree") == 0)
502        {
503                Debug << "view cell type: VspBsp" << endl;
504
505                mVspBspTree = new VspBspTree();
506                mViewCellsManager = new VspBspViewCellsManager(vcTree, mVspBspTree);
507        }
508        else if (strcmp(name, "vspOspTree") == 0)
509        {
510                mVspTree = new VspTree();
511                char buf[100];         
512                Environment::GetSingleton()->GetStringValue("Hierarchy.type", buf);     
513
514                HierarchyManager *mHierarchyManager = CreateHierarchyManager(buf);
515                mViewCellsManager = new VspOspViewCellsManager(vcTree, mHierarchyManager);
516        }
517        else if (strcmp(name, "sceneDependent") == 0)
518        {
519                Debug << "view cell type: Bsp" << endl;
520
521                //TODO
522                mBspTree = new BspTree();
523                mViewCellsManager = new BspViewCellsManager(vcTree, mBspTree);
524        }
525        else
526        {
527                cerr << "Wrong view cells type " << name << "!!!" << endl;
528                exit(1);
529        }
530
531        return mViewCellsManager;
532}
533
534
535// use ascii format to store rays
536#define USE_ASCII 0
537
538
539static inline bool ilt(Intersectable *obj1, Intersectable *obj2)
540{
541        return obj1->mId < obj2->mId;
542}
543
544
545bool Preprocessor::LoadKdTree()
546{
547        return true;
548}
549
550bool Preprocessor::ExportKdTree()
551{
552        return true;
553}
554
555
556bool Preprocessor::LoadSamples(VssRayContainer &samples,
557                                                           ObjectContainer &objects) const
558{
559        std::stable_sort(objects.begin(), objects.end(), ilt);
560        char fileName[100];
561        Environment::GetSingleton()->GetStringValue("Preprocessor.samplesFilename", fileName);
562       
563    Vector3 origin, termination;
564        // HACK: needed only for lower_bound algorithm to find the
565        // intersected objects
566        MeshInstance sObj(NULL);
567        MeshInstance tObj(NULL);
568
569#if USE_ASCII
570        ifstream samplesIn(fileName);
571        if (!samplesIn.is_open())
572                return false;
573
574        string buf;
575        while (!(getline(samplesIn, buf)).eof())
576        {
577                sscanf(buf.c_str(), "%f %f %f %f %f %f %d %d",
578                           &origin.x, &origin.y, &origin.z,
579                           &termination.x, &termination.y, &termination.z,
580                           &(sObj.mId), &(tObj.mId));
581               
582                Intersectable *sourceObj = NULL;
583                Intersectable *termObj = NULL;
584               
585                if (sObj.mId >= 0)
586                {
587                        ObjectContainer::iterator oit =
588                                lower_bound(objects.begin(), objects.end(), &sObj, ilt);
589                        sourceObj = *oit;
590                }
591               
592                if (tObj.mId >= 0)
593                {
594                        ObjectContainer::iterator oit =
595                                lower_bound(objects.begin(), objects.end(), &tObj, ilt);
596                        termObj = *oit;
597                }
598
599                samples.push_back(new VssRay(origin, termination, sourceObj, termObj));
600        }
601#else
602        ifstream samplesIn(fileName, ios::binary);
603        if (!samplesIn.is_open())
604                return false;
605
606        while (1)
607        {
608                 samplesIn.read(reinterpret_cast<char *>(&origin), sizeof(Vector3));
609                 samplesIn.read(reinterpret_cast<char *>(&termination), sizeof(Vector3));
610                 samplesIn.read(reinterpret_cast<char *>(&(sObj.mId)), sizeof(int));
611                 samplesIn.read(reinterpret_cast<char *>(&(tObj.mId)), sizeof(int));
612               
613                 if (samplesIn.eof())
614                        break;
615
616                Intersectable *sourceObj = NULL;
617                Intersectable *termObj = NULL;
618               
619                if (sObj.mId >= 0)
620                {
621                        ObjectContainer::iterator oit =
622                                lower_bound(objects.begin(), objects.end(), &sObj, ilt);
623                        sourceObj = *oit;
624                }
625               
626                if (tObj.mId >= 0)
627                {
628                        ObjectContainer::iterator oit =
629                                lower_bound(objects.begin(), objects.end(), &tObj, ilt);
630                        termObj = *oit;
631                }
632
633                samples.push_back(new VssRay(origin, termination, sourceObj, termObj));
634        }
635
636#endif
637        samplesIn.close();
638
639        return true;
640}
641
642
643bool Preprocessor::ExportSamples(const VssRayContainer &samples) const
644{
645        char fileName[100];
646        Environment::GetSingleton()->GetStringValue("Preprocessor.samplesFilename", fileName);
647       
648
649        VssRayContainer::const_iterator it, it_end = samples.end();
650       
651#if USE_ASCII
652        ofstream samplesOut(fileName);
653        if (!samplesOut.is_open())
654                return false;
655
656        for (it = samples.begin(); it != it_end; ++ it)
657        {
658                VssRay *ray = *it;
659                int sourceid = ray->mOriginObject ? ray->mOriginObject->mId : -1;               
660                int termid = ray->mTerminationObject ? ray->mTerminationObject->mId : -1;       
661
662                samplesOut << ray->GetOrigin().x << " " << ray->GetOrigin().y << " " << ray->GetOrigin().z << " "
663                                   << ray->GetTermination().x << " " << ray->GetTermination().y << " " << ray->GetTermination().z << " "
664                                   << sourceid << " " << termid << "\n";
665        }
666#else
667        ofstream samplesOut(fileName, ios::binary);
668        if (!samplesOut.is_open())
669                return false;
670
671        for (it = samples.begin(); it != it_end; ++ it)
672        {       
673                VssRay *ray = *it;
674                Vector3 origin(ray->GetOrigin());
675                Vector3 termination(ray->GetTermination());
676               
677                int sourceid = ray->mOriginObject ? ray->mOriginObject->mId : -1;               
678                int termid = ray->mTerminationObject ? ray->mTerminationObject->mId : -1;               
679
680                samplesOut.write(reinterpret_cast<char *>(&origin), sizeof(Vector3));
681                samplesOut.write(reinterpret_cast<char *>(&termination), sizeof(Vector3));
682                samplesOut.write(reinterpret_cast<char *>(&sourceid), sizeof(int));
683                samplesOut.write(reinterpret_cast<char *>(&termid), sizeof(int));
684    }
685#endif
686        samplesOut.close();
687
688        return true;
689}
690
691#if 0 // matt: implemented interface samplestrategy
692bool
693Preprocessor::GenerateRays(
694                                                   const int number,
695                                                   const int sampleType,
696                                                   SimpleRayContainer &rays
697                                                   )
698{
699  Vector3 origin, direction;
700  int startSize = (int)rays.size();
701  for (int i=0; (int)rays.size() - startSize  < number; i ++) {
702        // now get the direction
703        switch (sampleType) {
704        case OBJECT_BASED_DISTRIBUTION: {
705          mViewCellsManager->GetViewPoint(origin);
706          Vector3 point;
707          Vector3 normal;
708          int i = RandomValue(0, mObjects.size() - 1);
709          Intersectable *object = mObjects[i];
710          object->GetRandomSurfacePoint(point, normal);
711          direction = point - origin;
712        }
713          break;
714        case OBJECT_DIRECTION_BASED_DISTRIBUTION: {
715          int i = RandomValue(0, mObjects.size() - 1);
716          Intersectable *object = mObjects[i];
717          Vector3 normal;
718          object->GetRandomSurfacePoint(origin, normal);
719          direction = UniformRandomVector(normal);
720          origin += 0.1f*direction;
721        }
722          break;
723        case DIRECTION_BASED_DISTRIBUTION:
724          mViewCellsManager->GetViewPoint(origin);
725          direction = UniformRandomVector();
726          break;
727        case DIRECTION_BOX_BASED_DISTRIBUTION: {
728          mViewCellsManager->GetViewPoint(origin);
729          float alpha = RandomValue(0.0f, 2*M_PI);
730          float beta = RandomValue(-M_PI/2, M_PI/2);
731          direction = VssRay::GetDirection(alpha, beta);
732          break;
733        }
734        case SPATIAL_BOX_BASED_DISTRIBUTION:
735          mViewCellsManager->GetViewPoint(origin);
736          direction = mKdTree->GetBox().GetRandomPoint() - origin;
737          break;
738        default:
739          // unsuported distribution type
740          return false;
741        }
742        // $$ jb the pdf is yet not correct for all sampling methods!
743        float pdf = 1.0f;
744        float c = Magnitude(direction);
745        if (c > Limits::Small) {
746          direction*=1.0f/c;
747          rays.AddRay(SimpleRay(origin, direction, pdf));
748        }
749  }
750  return true;
751}
752#endif
753bool Preprocessor::GenerateRays(const int number,
754                                                                const int sampleType,
755                                                                SimpleRayContainer &rays)
756{
757        Vector3 origin, direction;
758       
759        const int startSize = (int)rays.size();
760        SamplingStrategy *strategy = GenerateSamplingStrategy(sampleType);
761
762        if (!strategy)
763                return false;
764
765        for (int i=0; (int)rays.size() - startSize < number; ++ i)
766        {
767                SimpleRay newRay;
768                bool success = strategy->GenerateSample(newRay);
769
770                if (success)
771                        rays.AddRay(newRay);
772        }
773
774        delete strategy;
775
776    return true;
777}
778
779
780SamplingStrategy *Preprocessor::GenerateSamplingStrategy(const int strategyId) const
781{
782        switch (strategyId)
783        {
784        case OBJECT_BASED_DISTRIBUTION:
785                return new ObjectBasedDistribution(*this);
786        case OBJECT_DIRECTION_BASED_DISTRIBUTION:
787                return new ObjectDirectionBasedDistribution(*this);
788        case DIRECTION_BASED_DISTRIBUTION:
789                return new DirectionBasedDistribution(*this);
790        case DIRECTION_BOX_BASED_DISTRIBUTION:
791                return new DirectionBoxBasedDistribution(*this);
792        case SPATIAL_BOX_BASED_DISTRIBUTION:
793                return new SpatialBoxBasedDistribution(*this);
794        //case OBJECTS_INTERIOR_DISTRIBUTION:
795        //      return new ObjectsInteriorDistribution(*this);
796        default: // no valid strategy
797                Debug << "warning: no valid sampling strategy" << endl;
798                return NULL;
799        }
800
801        // should never come here
802        return NULL;
803}
804
805
806bool Preprocessor::InitRayCast(const string externKdTree)
807{
808        switch (mRayCastMethod) // use intel ray tracing
809        {
810        case INTEL_RAYCASTER:
811#ifdef GTP_INTERNAL
812          cout<<"Ray Cast file: "<<externKdTree<<endl;
813          return mlrtaLoadAS(externKdTree.c_str());
814#endif
815        case INTERNAL_RAYCASTER:
816        default:
817                break;
818        }
819
820        return true;
821}
822
823
824int Preprocessor::CastIntelDoubleRay(
825                                                                         const Vector3 &viewPoint,
826                                                                         const Vector3 &direction,
827                                                                         const float probability,
828                                                                         VssRayContainer &vssRays,
829                                                                         const AxisAlignedBox3 &box
830                                                                         )
831{
832        VssRay *vssRay  = NULL;
833        int hits = 0;
834
835        Vector3 pointA, pointB;
836       
837        Intersectable *objectA =
838                CastIntelSingleRay(viewPoint, direction, pointA, box);
839       
840        // cast ray into other direction
841        Intersectable *objectB =
842                CastIntelSingleRay(viewPoint, -direction, pointB, box);
843
844        const bool validSample = (objectA != objectB);
845       
846        if (validSample)
847        {       
848                if (objectA)
849                {
850                        vssRay = new VssRay(pointB,
851                                                                pointA,
852                                                                objectB,
853                                                                objectA,
854                                                                mPass,
855                                                                probability
856                                                                );
857
858                        vssRays.push_back(vssRay);
859                        hits ++;
860                }
861
862                if (objectB)
863                {
864                        vssRay = new VssRay(pointA,
865                                                                pointB,
866                                                                objectA,
867                                                                objectB,
868                                                                mPass,
869                                                                probability
870                                                                );
871
872                        vssRays.push_back(vssRay);
873                        hits ++;
874                }
875                //Debug << "intel ray: " << *vssRay << endl;
876        }
877
878        //cout << "a";
879        return hits;
880}
881
882
883Intersectable *Preprocessor::CastIntelSingleRay(const Vector3 &viewPoint,
884                                                                                                const Vector3 &direction,
885                                                                                                //const float probability,
886                                                                                                Vector3 &tPoint,
887                                                                                                const AxisAlignedBox3 &box
888                                                                                                )
889{
890        AxisAlignedBox3 sbox = box;
891        sbox.Enlarge(Vector3(-Limits::Small));
892
893        if (!sbox.IsInside(viewPoint))
894                return 0;
895       
896        float pforg[3];
897        float pfdir[3];
898        double pfnorm[3];
899
900        pforg[0] = viewPoint[0]; pforg[1] = viewPoint[1]; pforg[2] = viewPoint[2];
901        pfdir[0] = direction[0]; pfdir[1] = direction[1]; pfdir[2] = direction[2];
902
903        float dist = 0;
904#ifdef GTP_INTERNAL
905        const int hittriangle = mlrtaIntersectAS(pforg, pfdir, pfnorm, dist);
906#else
907        const int hittriangle = -1;
908#endif
909
910        if (hittriangle == -1)
911        {
912                static Ray ray;
913                SetupRay(ray, viewPoint, direction);
914
915                float tmin = 0, tmax;
916                if (box.ComputeMinMaxT(ray, &tmin, &tmax) && tmin < tmax)
917                {
918                        tPoint = ray.Extrap(tmax);
919                }
920
921                return NULL;
922        }
923        else
924        {
925                tPoint[0] = pforg[0] + pfdir[0] * dist;
926                tPoint[1] = pforg[1] + pfdir[1] * dist;
927                tPoint[2] = pforg[2] + pfdir[2] * dist;
928
929                return mFaceParents[hittriangle].mObject;
930        }
931}
932
933
934int Preprocessor::CastInternalRay(
935                                                                  const Vector3 &viewPoint,
936                                                                  const Vector3 &direction,
937                                                                  const float probability,
938                                                                  VssRayContainer &vssRays,
939                                                                  const AxisAlignedBox3 &box
940                                                                  )
941{
942
943  int hits = 0;
944  static Ray ray;
945  Intersectable *objectA, *objectB;
946  Vector3 pointA, pointB;
947
948  //  AxisAlignedBox3 box = Union(mKdTree->GetBox(), mViewCellsManager->GetViewSpaceBox());
949 
950
951  AxisAlignedBox3 sbox = box;
952  sbox.Enlarge(Vector3(-Limits::Small));
953  if (!sbox.IsInside(viewPoint))
954        return 0;
955       
956  SetupRay(ray, viewPoint, direction);
957  ray.mFlags &= ~Ray::CULL_BACKFACES;
958
959  // cast ray to KD tree to find intersection with other objects
960  float bsize = Magnitude(box.Size());
961 
962 
963  if (mKdTree->CastRay(ray)) {
964        objectA = ray.intersections[0].mObject;
965        pointA = 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       
972  } else {
973        objectA = NULL;
974        // compute intersection with the scene bounding box
975        float tmin, tmax;
976        if (box.ComputeMinMaxT(ray, &tmin, &tmax) && tmin < tmax)
977          pointA = ray.Extrap(tmax);
978        else
979          return 0;
980  }
981
982 
983  SetupRay(ray, viewPoint, -direction);
984  ray.mFlags &= ~Ray::CULL_BACKFACES;
985 
986  if (mKdTree->CastRay(ray)) {
987        objectB = ray.intersections[0].mObject;
988        pointB = ray.Extrap(ray.intersections[0].mT);
989        if (mDetectEmptyViewSpace)
990          if (DotProd(ray.intersections[0].mNormal, direction) <= 0) {
991                // discard the sample
992                return 0;
993          }
994  } else {
995        objectB = NULL;
996        float tmin, tmax;
997        if (box.ComputeMinMaxT(ray, &tmin, &tmax) && tmin < tmax)
998          pointB = ray.Extrap(tmax);
999        else
1000          return 0;
1001  }
1002 
1003 
1004  VssRay *vssRay  = NULL;
1005  bool validSample = (objectA != objectB);
1006  if (validSample) {
1007        if (objectA) {
1008          vssRay = new VssRay(pointB,
1009                                                  pointA,
1010                                                  objectB,
1011                                                  objectA,
1012                                                  mPass,
1013                                                  probability
1014                                                  );
1015          vssRays.push_back(vssRay);
1016          hits ++;
1017        }
1018       
1019        if (objectB) {
1020          vssRay = new VssRay(pointA,
1021                                                  pointB,
1022                                                  objectA,
1023                                                  objectB,
1024                                                  mPass,
1025                                                  probability
1026                                                  );
1027          vssRays.push_back(vssRay);
1028          hits ++;
1029        }
1030  }
1031 
1032  return hits;
1033}
1034
1035
1036int
1037Preprocessor::ProcessRay(
1038                                                 const Vector3 &viewPoint,
1039                                                 const Vector3 &direction,
1040                                                 Intersectable *objectA,
1041                                                 Vector3 &pointA,
1042                                                 const Vector3 &normalA,
1043                                                 Intersectable *objectB,
1044                                                 Vector3 &pointB,
1045                                                 const Vector3 &normalB,
1046                                                 const float probability,
1047                                                 VssRayContainer &vssRays,
1048                                                 const AxisAlignedBox3 &box
1049                                                 )
1050{
1051  int hits=0;
1052
1053  if (objectA == NULL && objectB == NULL)
1054        return 0;
1055
1056  AxisAlignedBox3 sbox = box;
1057  sbox.Enlarge(Vector3(-Limits::Small));
1058
1059  if (!sbox.IsInside(viewPoint))
1060        return 0;
1061
1062  if (objectA == NULL) {
1063        // compute intersection with the scene bounding box
1064        static Ray ray;
1065        SetupRay(ray, viewPoint, direction);
1066       
1067        float tmin, tmax;
1068        if (box.ComputeMinMaxT(ray, &tmin, &tmax) && tmin < tmax)
1069          pointA = ray.Extrap(tmax);
1070        else
1071          return 0;
1072  } else {
1073        if (mDetectEmptyViewSpace)
1074          if (DotProd(normalA, direction) >= 0) {
1075                // discard the sample
1076                return 0;
1077          }
1078  }
1079
1080  if (objectB == NULL) {
1081        // compute intersection with the scene bounding box
1082        static Ray ray;
1083        SetupRay(ray, viewPoint, -direction);
1084
1085        float tmin, tmax;
1086        if (box.ComputeMinMaxT(ray, &tmin, &tmax) && tmin < tmax)
1087          pointB = ray.Extrap(tmax);
1088        else
1089          return 0;
1090  } else {
1091        if (mDetectEmptyViewSpace)
1092          if (DotProd(normalB, direction) <= 0) {
1093                // discard the sample
1094                return 0;
1095          }
1096  }
1097 
1098  VssRay *vssRay  = NULL;
1099  bool validSample = (objectA != objectB);
1100  if (validSample) {
1101        if (objectA) {
1102          vssRay = new VssRay(pointB,
1103                                                  pointA,
1104                                                  objectB,
1105                                                  objectA,
1106                                                  mPass,
1107                                                  probability
1108                                                  );
1109          vssRays.push_back(vssRay);
1110          hits ++;
1111        }
1112       
1113        if (objectB) {
1114          vssRay = new VssRay(pointA,
1115                                                  pointB,
1116                                                  objectA,
1117                                                  objectB,
1118                                                  mPass,
1119                                                  probability
1120                                                  );
1121          vssRays.push_back(vssRay);
1122          hits ++;
1123        }
1124  }
1125 
1126  return hits;
1127}
1128
1129void
1130Preprocessor::CastRays16(const int index,
1131                                                 SimpleRayContainer &rays,
1132                                                 VssRayContainer &vssRays,
1133                                                 const AxisAlignedBox3 &sbox)
1134{
1135  int i;
1136  int num = 16;
1137 
1138  if (mRayCastMethod == INTEL_RAYCASTER) {
1139#ifdef GTP_INTERNAL
1140
1141  int forward_hit_triangles[16];
1142  float forward_dist[16];
1143
1144  int backward_hit_triangles[16];
1145  float backward_dist[16];
1146 
1147  Vector3 min = sbox.Min();
1148  Vector3 max = sbox.Max();
1149 
1150  for (i=0; i < num; i++) {
1151        mlrtaStoreRayAS16(&rays[index + i].mOrigin.x,
1152                                          &rays[index + i].mDirection.x,
1153                                          i);
1154  }
1155 
1156 
1157  mlrtaTraverseGroupAS16(&min.x,
1158                                                 &max.x,
1159                                                 forward_hit_triangles,
1160                                                 forward_dist);
1161
1162  for (i=0; i < num; i++) {
1163        Vector3 dir = -rays[index+i].mDirection;
1164        mlrtaStoreRayAS16(&rays[index+i].mOrigin.x,
1165                                          &dir.x,
1166                                          i);
1167  }
1168 
1169 
1170  mlrtaTraverseGroupAS16(&min.x,
1171                                                 &max.x,
1172                                                 backward_hit_triangles,
1173                                                 backward_dist);
1174 
1175
1176  for (i=0; i < num; i++) {
1177        Intersectable *objectA = NULL, *objectB = NULL;
1178        Vector3 pointA, pointB;
1179        Vector3 normalA, normalB;
1180        if (forward_hit_triangles[i] !=-1 ) {
1181          objectA = mFaceParents[forward_hit_triangles[i]].mObject;
1182          // Get the normal of that face
1183          Mesh *mesh = ((MeshInstance *)objectA)->GetMesh();
1184          normalA = mesh->GetFacePlane(mFaceParents[forward_hit_triangles[i]].mFaceIndex).mNormal;
1185          //-rays[index+i].mDirection; // $$ temporary
1186          pointA = rays[index+i].Extrap(forward_dist[i]);
1187        }
1188       
1189        if (backward_hit_triangles[i]!=-1) {
1190          objectB = mFaceParents[backward_hit_triangles[i]].mObject;
1191          Mesh *mesh = ((MeshInstance *)objectB)->GetMesh();
1192
1193          normalB = mesh->GetFacePlane(mFaceParents[backward_hit_triangles[i]].mFaceIndex).mNormal;
1194         
1195          //      normalB = rays[index+i].mDirection; // $$ temporary
1196          pointB = rays[index+i].Extrap(-backward_dist[i]);
1197        }
1198       
1199        ProcessRay(rays[index+i].mOrigin,
1200                           rays[index+i].mDirection,
1201                           objectA, pointA, normalA,
1202                           objectB, pointB, normalB,
1203                           rays[index+i].mPdf,
1204                           vssRays,
1205                           sbox
1206                           );
1207  }
1208#endif
1209  } else {
1210
1211        for (i=index; i < index + num; i++) {
1212          CastRay(rays[i].mOrigin,
1213                          rays[i].mDirection,
1214                          rays[i].mPdf,
1215                          vssRays,
1216                          sbox);
1217        }
1218  }
1219 
1220}
1221
1222void
1223Preprocessor::CastRays(
1224                                           SimpleRayContainer &rays,
1225                                           VssRayContainer &vssRays
1226                                           )
1227{
1228  long t1 = GetTime();
1229  for (int i=0; i < rays.size(); ) {
1230        if (i + 16 < rays.size()) {
1231          CastRays16(
1232                                 i,
1233                                 rays,
1234                                 vssRays,
1235                                 mViewCellsManager->GetViewSpaceBox());
1236          i += 16;
1237        } else {
1238          CastRay(rays[i].mOrigin,
1239                          rays[i].mDirection,
1240                          rays[i].mPdf,
1241                          vssRays,
1242                          mViewCellsManager->GetViewSpaceBox());
1243          i++;
1244        }
1245        if (i % 10000 == 0)
1246          cout<<".";
1247  }
1248
1249  long t2 = GetTime();
1250 
1251  cout<<2*rays.size()/(1e3*TimeDiff(t1, t2))<<"M rays/s"<<endl;
1252}
1253
1254
1255int Preprocessor::CastRay(
1256                                                  const Vector3 &viewPoint,
1257                                                  const Vector3 &direction,
1258                                                  const float probability,
1259                                                  VssRayContainer &vssRays,
1260                                                  const AxisAlignedBox3 &box
1261                                                  )
1262{
1263        switch (mRayCastMethod)
1264        {
1265        case INTEL_RAYCASTER:
1266                return CastIntelDoubleRay(viewPoint, direction, probability, vssRays, box);
1267        case INTERNAL_RAYCASTER:
1268        default:
1269                return CastInternalRay(viewPoint, direction, probability, vssRays, box);
1270        }
1271}
1272
1273
1274void Preprocessor::SetupRay(Ray &ray,
1275                                                        const Vector3 &point,
1276                                                        const Vector3 &direction
1277                                                        )
1278{
1279        ray.Clear();
1280        // do not store anything else then intersections at the ray
1281        ray.Init(point, direction, Ray::LOCAL_RAY);
1282}
1283
1284}
Note: See TracBrowser for help on using the repository browser.