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

Revision 258, 8.4 KB checked in by bittner, 19 years ago (diff)

mesh kdtree bug fixed

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