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

Revision 223, 7.3 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"
6#include "MutualVisibility.h"
7
8SamplingPreprocessor::SamplingPreprocessor()
9{
10  // this should increase coherence of the samples
11  environment->GetIntValue("Sampling.samplesPerPass", mSamplesPerPass);
12  environment->GetIntValue("Sampling.totalSamples", mTotalSamples);
13  mKdPvsDepth = 100;
14
15}
16
17void
18SamplingPreprocessor::SetupRay(Ray &ray, const Vector3 &point, const Vector3 &direction)
19{
20  ray.intersections.clear();
21  ray.leaves.clear();
22  ray.meshes.clear();
23  //  cout<<point<<" "<<direction<<endl;
24  ray.Init(point, direction, Ray::LOCAL_RAY);
25}
26
27KdNode *
28SamplingPreprocessor::GetNodeForPvs(KdLeaf *leaf)
29{
30  KdNode *node = leaf;
31  while (node->mParent && node->mDepth > mKdPvsDepth)
32    node = node->mParent;
33  return node;
34}
35
36int
37SamplingPreprocessor::AddNodeSamples(Intersectable *object,
38                                     const Ray &ray,
39                                     const int pass)
40{
41  int contributingSamples = 0;
42  int j;
43  for (j=0; j < ray.leaves.size(); j++) {
44    KdNode *node = GetNodeForPvs( ray.leaves[j] );
45    contributingSamples += object->mKdPvs.AddNodeSample(node);
46  }
47 
48  if (pass > 10)
49    for (j=1; j < ray.leaves.size() - 1; j++) {
50      ray.leaves[j]->AddPassingRay(ray, contributingSamples ? 1 : 0);
51    }
52 
53  return contributingSamples;
54}
55
56
57void
58SamplingPreprocessor::HoleSamplingPass()
59{
60  vector<KdLeaf *> leaves;
61  mKdTree->CollectLeaves(leaves);
62 
63  // go through all the leaves and evaluate their passing contribution
64  for (int i=0 ; i < leaves.size(); i++) {
65    KdLeaf *leaf = leaves[i];
66    cout<<leaf->mPassingRays<<endl;
67  }
68}
69
70bool
71SamplingPreprocessor::ComputeVisibility()
72{
73
74  // pickup an object
75  ObjectContainer objects;
76 
77  mSceneGraph->CollectObjects(&objects);
78
79  Vector3 point, normal, direction;
80  Ray ray;
81
82  long startTime = GetTime();
83 
84  int i;
85  int pass = 0;
86  int totalSamples = 0;
87
88  int pvsOut = Min((int)objects.size(), 10);
89 
90  vector<Ray> rays[10];
91 
92  while (totalSamples < mTotalSamples)
93    {
94      int passContributingSamples = 0;
95      int passSampleContributions = 0;
96      int passSamples = 0;
97      int index = 0;
98
99      for (i =0; i < objects.size(); i++) {
100        KdNode *nodeToSample = NULL;
101        Intersectable *object = objects[i];
102                 
103        int pvsSize = object->mKdPvs.GetSize();
104     
105        if (0 && pvsSize) {
106          // mail all nodes from the pvs
107          Intersectable::NewMail();
108          KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
109                         
110          for (; i != object->mKdPvs.mEntries.end(); i++) {
111            KdNode *node = (*i).first;
112            node->Mail();
113          }
114
115          int maxTries = 2*pvsSize;
116       
117          for (int tries = 0; tries < 10; tries++) {
118            index = RandomValue(0, pvsSize - 1);
119            KdPvsData data;
120            KdNode *node;
121            object->mKdPvs.GetData(index, node, data);
122            nodeToSample = mKdTree->FindRandomNeighbor(node, true);
123            if (nodeToSample)
124              break;
125          }
126        }
127
128       
129        if (pvsSize && pass == 50 ) {
130          // mail all nodes from the pvs
131          Intersectable::NewMail();
132          KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
133          for (; i != object->mKdPvs.mEntries.end(); i++) {
134            KdNode *node = (*i).first;
135            node->Mail();
136          }
137       
138          vector<KdNode *> invisibleNeighbors;
139          // get all neighbors of all PVS nodes
140          i = object->mKdPvs.mEntries.begin();
141          for (; i != object->mKdPvs.mEntries.end(); i++) {
142            KdNode *node = (*i).first;
143            mKdTree->FindNeighbors(node, invisibleNeighbors, true);
144            AxisAlignedBox3 box = object->GetBox();
145            for (int j=0; j < invisibleNeighbors.size(); j++) {
146              int visibility = ComputeBoxVisibility(mKdTree,
147                                                    box,
148                                                    mKdTree->GetBox(invisibleNeighbors[j]),
149                                                    1.0f);
150           
151            }
152            // now rank all the neighbors according to probability that a new
153            // sample creates some contribution
154          }
155        }
156
157     
158        for (int k=0; k < mSamplesPerPass; k++) {
159          object->GetRandomSurfacePoint(point, normal);
160       
161          if (nodeToSample) {
162            int maxTries = 5;
163         
164            for (int tries = 0; tries < maxTries; tries++) {
165              direction = mKdTree->GetBox(nodeToSample).GetRandomPoint() - point;
166           
167              if (DotProd(direction, normal) > Limits::Small)
168                break;
169            }
170         
171            if (tries == maxTries)
172              direction = UniformRandomVector(normal);
173          }
174          else
175            direction = UniformRandomVector(normal);
176       
177          // construct a ray
178          SetupRay(ray, point, direction);
179          mKdTree->CastRay(ray);
180
181          if (i < pvsOut)
182            rays[i].push_back(ray);
183       
184          int sampleContributions = 0;
185       
186                 
187          if (ray.leaves.size()) {
188            sampleContributions += AddNodeSamples(object, ray, pass);
189         
190            if (ray.intersections.size()) {
191              sampleContributions += AddNodeSamples(ray.intersections[0].mObject, ray, pass);
192              // check whether we can add this to the rays
193              for (int j = 0; j < pvsOut; j++) {
194                if (objects[j] == ray.intersections[0].mObject) {
195                  rays[j].push_back(ray);
196                }
197              }
198            }
199
200            passSamples++;
201                       
202            if (sampleContributions) {
203              passContributingSamples++;
204              passSampleContributions += sampleContributions;
205            }
206          }
207        }
208      }
209
210      totalSamples += passSamples;
211
212      //    if (pass>10)
213      //      HoleSamplingPass();
214   
215
216      pass++;
217   
218      int pvsSize = 0;
219      for (i=0; i < objects.size(); i++) {
220        Intersectable *object = objects[i];
221        pvsSize += object->mKdPvs.GetSize();
222      }
223   
224      cout << "pass " << pass<<" : t = " << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl;
225      cout << "#totalSamples=" << totalSamples/1000
226           << "k   #sampleContributions=" << passSampleContributions << " ("
227           << 100*passContributingSamples/(float)passSamples<<"%)" << " avgPVS="
228           << pvsSize/(float)objects.size() << endl
229           << "avg ray contrib=" << passSampleContributions/(float)passContributingSamples << endl;
230    }
231
232  int totalPvsSize = mKdTree->CollectLeafPvs();
233  cout << "#totalPvsSize=" << totalPvsSize << endl;
234 
235  //  HoleSamplingPass();
236  if (1) {
237    Exporter *exporter = Exporter::GetExporter("ray-density.x3d");
238    exporter->SetExportRayDensity(true);
239    exporter->ExportKdTree(*mKdTree);
240    delete exporter;
241  }
242 
243  bool exportRays = false;
244  if (exportRays) {
245    Exporter *exporter = NULL;
246    exporter = Exporter::GetExporter("sample-rays.x3d");
247    exporter->SetWireframe();
248    exporter->ExportKdTree(*mKdTree);
249
250    for (i=0; i < pvsOut; i++)
251      exporter->ExportRays(rays[i], 1000, RgbColor(1, 0, 0));
252    exporter->SetFilled();
253         
254    delete exporter;
255  }
256
257  if (1) {
258    for (int k=0; k < pvsOut; k++) {
259      Intersectable *object = objects[k];
260      char s[64];
261      sprintf(s, "sample-pvs%04d.x3d", k);
262      Exporter *exporter = Exporter::GetExporter(s);
263      exporter->SetWireframe();
264      KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
265                 
266      Intersectable::NewMail();
267                 
268      // avoid adding the object to the list
269      object->Mail();
270      ObjectContainer visibleObjects;
271      for (; i != object->mKdPvs.mEntries.end(); i++) {
272        KdNode *node = (*i).first;
273        exporter->ExportBox(mKdTree->GetBox(node));
274        mKdTree->CollectObjects(node, visibleObjects);
275      }
276     
277      exporter->ExportRays(rays[k], 1000, RgbColor(0, 1, 0));
278      exporter->SetFilled();
279
280      for (int j = 0; j < visibleObjects.size(); j++)
281        exporter->ExportIntersectable(visibleObjects[j]);
282       
283      Material m;
284      m.mDiffuseColor = RgbColor(1, 0, 0);
285      exporter->SetForcedMaterial(m);
286      exporter->ExportIntersectable(object);
287     
288      delete exporter;
289    }
290  }
291 
292  return true;
293}
294
295 
296
297   
Note: See TracBrowser for help on using the repository browser.