source: trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.cpp @ 177

Revision 177, 6.1 KB checked in by bittner, 19 years ago (diff)
Line 
1#include "SceneGraph.h"
2#include "KdTree.h"
3#include "SamplingPreprocessor.h"
4#include "X3dExporter.h"
5#include "Environment.h"
6SamplingPreprocessor::SamplingPreprocessor()
7{
8  // this should increase coherence of the samples
9  environment->GetIntValue("Sampling.samplesPerPass", mSamplesPerPass);
10  environment->GetIntValue("Sampling.totalSamples", mTotalSamples);
11  mKdPvsDepth = 100;
12
13}
14
15void
16SamplingPreprocessor::SetupRay(Ray &ray, const Vector3 &point, const Vector3 &direction)
17{
18  ray.intersections.clear();
19  ray.leaves.clear();
20  ray.meshes.clear();
21  //  cout<<point<<" "<<direction<<endl;
22  ray.Init(point, direction, Ray::LOCAL_RAY);
23}
24
25KdNode *
26SamplingPreprocessor::GetNodeForPvs(KdLeaf *leaf)
27{
28  KdNode *node = leaf;
29  while (node->mParent && node->mDepth > mKdPvsDepth)
30    node = node->mParent;
31  return node;
32}
33
34int
35SamplingPreprocessor::AddNodeSamples(Intersectable *object, const Ray &ray)
36{
37  int contributingSamples = 0;
38
39  for (int j=0; j < ray.leaves.size(); j++) {
40    KdNode *node = GetNodeForPvs( ray.leaves[j] );
41    contributingSamples += object->mKdPvs.AddNodeSample(node);
42  }
43 
44  return contributingSamples;
45}
46
47bool
48SamplingPreprocessor::ComputeVisibility()
49{
50
51  // pickup an object
52  ObjectContainer objects;
53 
54  mSceneGraph->CollectObjects(&objects);
55
56  Vector3 point, normal, direction;
57  Ray ray;
58
59  long startTime = GetTime();
60 
61  int i;
62  int pass = 0;
63  int totalSamples = 0;
64
65
66  int pvsOut = Min((int)objects.size(), 10);
67 
68  vector<Ray> rays[10];
69 
70  while (totalSamples < mTotalSamples) {
71
72    int passContributingSamples = 0;
73    int passSampleContributions = 0;
74    int passSamples = 0;
75   
76    for (i =0; i < objects.size(); i++) {
77      KdNode *nodeToSample = NULL;
78      Intersectable *object = objects[i];
79
80      int pvsSize = object->mKdPvs.GetSize();
81     
82      if (0 && pvsSize) {
83        // mail all nodes from the pvs
84        Intersectable::NewMail();
85        KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
86        for (; i != object->mKdPvs.mEntries.end(); i++) {
87          KdNode *node = (*i).first;
88          node->Mail();
89        }
90        int maxTries = 2*pvsSize;
91        for (int tries = 0; tries < 10; tries++) {
92          int index = RandomValue(0, pvsSize - 1);
93          KdPvsData data;
94          KdNode *visibleNode;
95          object->mKdPvs.GetData(index, visibleNode, data);
96          nodeToSample = mKdTree->FindRandomNeighbor(visibleNode, true);
97          if (nodeToSample)
98            break;
99        }
100      }
101
102      if (pvsSize) {
103        // mail all nodes from the pvs
104        Intersectable::NewMail();
105        KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
106        for (; i != object->mKdPvs.mEntries.end(); i++) {
107          KdNode *node = (*i).first;
108          node->Mail();
109        }
110        vector<KdNode *> invisibleNeighbors;
111        // get all neighbors of all PVS nodes
112        KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
113        for (; i != object->mKdPvs.mEntries.end(); i++) {
114          KdNode *node = (*i).first;
115          mKdTree->FindNeighbors(visibleNode, invisibleNeighbors, true);
116        }
117
118        KdPvsData data;
119        KdNode *visibleNode;
120        object->mKdPvs.GetData(index, visibleNode, data);
121        nodeToSample = mKdTree->FindRandomNeighbor(visibleNode, true);
122        if (nodeToSample)
123          break;
124      }
125     
126
127      for (int k=0; k < mSamplesPerPass; k++) {
128        object->GetRandomSurfacePoint(point, normal);
129        if (nodeToSample) {
130          int maxTries = 5;
131          for (int tries = 0; tries < maxTries; tries++) {
132            direction = mKdTree->GetBox(nodeToSample).GetRandomPoint() - point;
133            if (DotProd(direction, normal) > Limits::Small)
134              break;
135          }
136          if (tries == maxTries)
137            direction = UniformRandomVector(normal);
138        } else
139          direction = UniformRandomVector(normal);
140       
141        // construct a ray
142        SetupRay(ray, point, direction);
143        mKdTree->CastRay(ray);
144
145        if (i < pvsOut)
146          rays[i].push_back(ray);
147       
148        int sampleContributions = 0;
149       
150        if (ray.leaves.size()) {
151          sampleContributions += AddNodeSamples(object, ray);
152         
153          if (ray.intersections.size()) {
154            sampleContributions += AddNodeSamples(ray.intersections[0].mObject, ray);
155            // check whether we can add this to the rays
156            for (int j = 0; j < pvsOut; j++) {
157              if (objects[j] == ray.intersections[0].mObject) {
158                rays[j].push_back(ray);
159              }
160            }
161          }
162          passSamples++;
163          if (sampleContributions) {
164            passContributingSamples++;
165            passSampleContributions += sampleContributions;
166          }
167        }
168      }
169    }
170    totalSamples += passSamples;
171    pass++;
172   
173    int pvsSize = 0;
174    for (i=0; i < objects.size(); i++) {
175      Intersectable *object = objects[i];
176      pvsSize += object->mKdPvs.GetSize();
177    }
178   
179    cout<<"pass "<<pass<<" : t = "<<TimeDiff(startTime, GetTime())*1e-3<<"s"<<endl;
180    cout<<"#totalSamples="<<totalSamples/1000<<
181      "k   #sampleContributions="<<passSampleContributions<<
182      " ("<<100*passContributingSamples/(float)passSamples<<"%)"<<
183      " avgPVS="<<pvsSize/(float)objects.size()<<endl<<
184      "avg ray contrib="<<passSampleContributions/(float)passContributingSamples<<
185      endl;
186  }
187  bool exportRays = false;
188  if (exportRays) {
189    Exporter *exporter = NULL;
190    exporter = Exporter::GetExporter("sample-rays.x3d");
191    exporter->SetWireframe();
192    exporter->ExportKdTree(*mKdTree);
193    for (i=0; i < pvsOut; i++)
194      exporter->ExportRays(rays[i], 1000, RgbColor(1, 0, 0));
195    exporter->SetFilled();
196    delete exporter;
197  }
198
199  if (1) {
200    for (int k=0; k < pvsOut; k++) {
201      Intersectable *object = objects[k];
202      char s[64];
203      sprintf(s, "sample-pvs%04d.x3d", k);
204      Exporter *exporter = Exporter::GetExporter(s);
205      exporter->SetWireframe();
206      KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
207      Intersectable::NewMail();
208        // avoid adding the object to the list
209      object->Mail();
210      ObjectContainer visibleObjects;
211      for (; i != object->mKdPvs.mEntries.end(); i++) {
212        KdNode *node = (*i).first;
213        exporter->ExportBox(mKdTree->GetBox(node));
214        mKdTree->CollectObjects(node, visibleObjects);
215      }
216     
217      exporter->ExportRays(rays[k], 1000, RgbColor(0, 1, 0));
218      exporter->SetFilled();
219
220      for (int j = 0; j < visibleObjects.size(); j++)
221        exporter->ExportIntersectable(visibleObjects[j]);
222       
223      Material m;
224      m.mDiffuseColor = RgbColor(1, 0, 0);
225      exporter->SetForcedMaterial(m);
226      exporter->ExportIntersectable(object);
227     
228      delete exporter;
229    }
230   
231  }
232 
233  return true;
234}
235
236 
237
238   
Note: See TracBrowser for help on using the repository browser.