source: trunk/VUT/GtpVisibilityPreprocessor/src/Mesh.cpp @ 176

Revision 176, 7.7 KB checked in by bittner, 19 years ago (diff)

cosine sampling bug fixed

Line 
1#include "Ray.h"
2#include "Mesh.h"
3#include "MeshKdTree.h"
4
5int MeshInstance::mailID = 21843194198;
6
7void
8Mesh::Preprocess()
9{
10  mBox.Initialize();
11
12  VertexContainer::const_iterator vi = mVertices.begin();
13  for (; vi != mVertices.end(); vi++) {
14    mBox.Include(*vi);
15  }
16 
17  /** true if it is a watertight convex mesh */
18  mIsConvex = false;
19 
20  if (mFaces.size() > MeshKdTree::mTermMinCost) {
21    mKdTree = new MeshKdTree(this);
22    MeshKdLeaf *root = (MeshKdLeaf *)mKdTree->GetRoot();
23    for (int i = 0; i < mFaces.size(); i++)
24      root->mFaces.push_back(i);
25    cout<<"KD";
26    mKdTree->Construct();
27
28    if (mKdTree->GetRoot()->IsLeaf()) {
29      cout<<"d";
30      delete mKdTree;
31    }
32  }
33}
34
35AxisAlignedBox3
36Mesh::GetFaceBox(const int faceIndex)
37{
38  Face *face = mFaces[faceIndex];
39  AxisAlignedBox3 box;
40  box.SetMin( mVertices[face->mVertexIndices[0]] );
41  box.SetMax(box.Min());
42  for (int i = 1; i < face->mVertexIndices.size(); i++) {
43    box.Include(mVertices[face->mVertexIndices[i]]);
44  }
45  return box;
46}
47
48int
49Mesh::CastRayToFace(
50                    const int faceIndex,
51                    Ray &ray,
52                    float &nearestT,
53                    int &nearestFace,
54                    MeshInstance *instance
55                    )
56{
57  float t;
58  int hit = 0;
59  if (RayFaceIntersection(faceIndex, ray, t, nearestT) == Ray::INTERSECTION) {
60    switch (ray.GetType()) {
61    case Ray::GLOBAL_RAY:
62      ray.intersections.push_back(Ray::RayIntersection(t, instance, faceIndex));
63      hit++;
64      break;
65    case Ray::LOCAL_RAY:
66      nearestT = t;
67      nearestFace = faceIndex;
68      hit++;
69      break;
70    }
71  }
72  return hit;
73}
74
75int
76Mesh::CastRay(
77              Ray &ray,
78              MeshInstance *instance
79              )
80{
81  if (mKdTree) {
82    return mKdTree->CastRay(ray, instance);
83  }
84 
85  int faceIndex = 0;
86  int hits = 0;
87  float nearestT = MAX_FLOAT;
88  int nearestFace = -1;
89 
90  if (ray.GetType() == Ray::LOCAL_RAY && ray.intersections.size())
91    nearestT = ray.intersections[0].mT;
92
93  for ( ;
94        faceIndex < mFaces.size();
95        faceIndex++) {
96    hits += CastRayToFace(faceIndex, ray, nearestT, nearestFace, instance);
97    if (mIsConvex && nearestFace != -1)
98      break;
99  }
100 
101  if ( hits && ray.GetType() == Ray::LOCAL_RAY ) {
102    if (ray.intersections.size())
103      ray.intersections[0] = Ray::RayIntersection(nearestT, instance, nearestFace);
104    else
105      ray.intersections.push_back(Ray::RayIntersection(nearestT, instance, nearestFace));
106  }
107 
108  return hits;
109}
110
111int
112Mesh::CastRayToSelectedFaces(
113                             Ray &ray,
114                             const vector<int> &faces,
115                             MeshInstance *instance
116                             )
117{
118  vector<int>::const_iterator fi;
119  int faceIndex = 0;
120  int hits = 0;
121  float nearestT = MAX_FLOAT;
122  int nearestFace = -1;
123
124  if (ray.GetType() == Ray::LOCAL_RAY && ray.intersections.size())
125    nearestT = ray.intersections[0].mT;
126
127  for ( fi = faces.begin();
128        fi != faces.end();
129        fi++) {
130    hits += CastRayToFace(*fi, ray, nearestT, nearestFace, instance);
131    if (mIsConvex && nearestFace != -1)
132      break;
133  }
134 
135  if ( hits && ray.GetType() == Ray::LOCAL_RAY ) {
136    if (ray.intersections.size())
137      ray.intersections[0] = Ray::RayIntersection(nearestT, instance, nearestFace);
138    else
139      ray.intersections.push_back(Ray::RayIntersection(nearestT, instance, nearestFace));
140  }
141 
142  return hits;
143}
144
145
146// int_lineseg returns 1 if the given line segment intersects a 2D
147// ray travelling in the positive X direction.  This is used in the
148// Jordan curve computation for polygon intersection.
149inline int
150int_lineseg(float px,
151            float py,
152            float u1,
153            float v1,
154            float u2,
155            float v2)
156{
157  float t;
158  float ydiff;
159
160  u1 -= px; u2 -= px;     // translate line
161  v1 -= py; v2 -= py;
162
163  if ((v1 > 0 && v2 > 0) ||
164      (v1 < 0 && v2 < 0) ||
165      (u1 < 0 && u2 < 0))
166    return 0;
167
168  if (u1 > 0 && u2 > 0)
169    return 1;
170
171  ydiff = v2 - v1;
172  if (fabs(ydiff) < Limits::Small) {      // denominator near 0
173    if (((fabs(v1) > Limits::Small) ||
174         (u1 > 0) || (u2 > 0)))
175      return 0;
176    return 1;
177  }
178
179  t = -v1 / ydiff;                // Compute parameter
180
181  return (u1 + t * (u2 - u1)) > 0;
182}
183
184
185
186// intersection with the polygonal face of the mesh
187int
188Mesh::RayFaceIntersection(const int faceIndex,
189                          const Ray &ray,
190                          float &t,
191                          const float nearestT
192                          )
193{
194  Face *face  = mFaces[faceIndex];
195
196  Plane3 plane = GetFacePlane(faceIndex);
197  float dot = DotProd(plane.mNormal, ray.GetDir());
198 
199  // Watch for near-zero denominator
200  // ONLY single sided polygons!!!!!
201  if (dot > -Limits::Small)
202    //  if (fabs(dot) < Limits::Small)
203    return Ray::NO_INTERSECTION;
204 
205  t = (-plane.mD - DotProd(plane.mNormal, ray.GetLoc())) / dot;
206 
207  if (t <= Limits::Small)
208    return Ray::INTERSECTION_OUT_OF_LIMITS;
209 
210  if (t >= nearestT) {
211    return Ray::INTERSECTION_OUT_OF_LIMITS; // no intersection was found
212  }
213 
214  int count = 0;
215  float u, v, u1, v1, u2, v2;
216  int i;
217
218  int paxis = plane.mNormal.DrivingAxis();
219
220  // Project the intersection point onto the coordinate plane
221  // specified by which.
222  ray.Extrap(t).ExtractVerts(&u, &v, paxis);
223
224
225  int size = face->mVertexIndices.size();
226
227  mVertices[face->mVertexIndices[size - 1]].
228    ExtractVerts(&u1, &v1, paxis );
229 
230  if (0 && size <= 4) {
231    // assume a convex face
232    for (i = 0; i < size; i++) {
233      mVertices[face->mVertexIndices[i]].ExtractVerts(&u2, &v2, paxis);
234      // line u1, v1, u2, v2
235      if ((v2 - v1)*(u1 - u) > (u2 - u1)*(v1 - v))
236        return Ray::NO_INTERSECTION;
237      u1 = u2;
238      v1 = v2;
239    }
240   
241    return Ray::INTERSECTION;
242  }
243 
244  // We're stuck with the Jordan curve computation.  Count number
245  // of intersections between the line segments the polygon comprises
246  // with a ray originating at the point of intersection and
247  // travelling in the positive X direction.
248  for (i = 0; i < size; i++) {
249    mVertices[face->mVertexIndices[i]].ExtractVerts(&u2, &v2, paxis);
250    count += (int_lineseg(u, v, u1, v1, u2, v2) != 0);
251    u1 = u2;
252    v1 = v2;
253  }
254
255  // We hit polygon if number of intersections is odd.
256  return (count & 1) ? Ray::INTERSECTION : Ray::NO_INTERSECTION;
257}
258
259
260void
261Mesh::GetRandomSurfacePoint(Vector3 &point, Vector3 &normal)
262{
263  int faceIndex = RandomValue(0, mFaces.size()-1);
264 
265  // assume the face is convex and generate a convex combination
266  //
267  Face *face = mFaces[faceIndex];
268  point = Vector3(0,0,0);
269  float sum = 0.0f;
270  for (int i = 0; i < face->mVertexIndices.size(); i++) {
271    float r = RandomValue(0,1);
272    sum += r;
273    point += mVertices[face->mVertexIndices[i]]*r;
274  }
275  point *= 1.0f/sum;
276  normal = GetFacePlane(faceIndex).mNormal;
277}
278
279
280int
281MeshInstance::CastRay(
282                      Ray &ray
283                      )
284{
285  int res = mMesh->CastRay(ray, this);
286  return res;
287}
288
289int
290MeshInstance::CastRay(
291                      Ray &ray,
292                      const vector<int> &faces
293                      )
294{
295  return mMesh->CastRayToSelectedFaces(ray, faces, this);
296}
297
298
299
300void
301MeshInstance::GetRandomSurfacePoint(Vector3 &point, Vector3 &normal)
302{
303  mMesh->GetRandomSurfacePoint(point, normal);
304}
305
306void
307TransformedMeshInstance::GetRandomSurfacePoint(Vector3 &point, Vector3 &normal)
308{
309  mMesh->GetRandomSurfacePoint(point, normal);
310  point = mWorldTransform*point;
311  normal = TransformNormal(mWorldTransform, normal);
312}
313
314Plane3
315Mesh::GetFacePlane(const int faceIndex)
316{
317  Face *face = mFaces[faceIndex];
318  return Plane3(mVertices[face->mVertexIndices[0]],
319                mVertices[face->mVertexIndices[1]],
320                mVertices[face->mVertexIndices[2]]);
321}
322
323int
324TransformedMeshInstance::CastRay(
325                                 Ray &ray
326                                 )
327{
328  ray.ApplyTransform(Invert(mWorldTransform));
329  int res = mMesh->CastRay(ray, this);
330  ray.ApplyTransform(mWorldTransform);
331 
332  return res;
333}
334
Note: See TracBrowser for help on using the repository browser.