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

Revision 162, 4.7 KB checked in by bittner, 19 years ago (diff)

functional raycasting version

Line 
1#include "ray.h"
2#include "Mesh.h"
3
4int MeshInstance::mailID = 21843194198;
5
6void
7Mesh::Preprocess()
8{
9  mBoundingBox.Initialize();
10
11  VertexContainer::const_iterator vi = mVertices.begin();
12  for (; vi != mVertices.end(); vi++) {
13    mBoundingBox.Include(*vi);
14  }
15 
16  mIsConvex = false;
17}
18
19
20int
21Mesh::CastRay(
22              Ray &ray,
23              MeshInstance *instance
24              )
25{
26  FaceContainer::const_iterator fi;
27  int faceIndex = 0;
28  int hits = 0;
29  float nearestT = MAX_FLOAT;
30  float nearestFace;
31
32  if (ray.GetType() == Ray::LOCAL_RAY && ray.intersections.size())
33    nearestT = ray.intersections[0].mT;
34
35 
36  for ( ;
37        faceIndex < mFaces.size();
38        faceIndex++) {
39    float t;
40    if (RayFaceIntersection(faceIndex, ray, t, nearestT) == Ray::INTERSECTION) {
41      switch (ray.GetType()) {
42      case Ray::GLOBAL_RAY:
43        ray.intersections.push_back(Ray::RayIntersection(t, instance, faceIndex));
44        hits++;
45        break;
46      case Ray::LOCAL_RAY:
47        hits++;
48        nearestT = t;
49        nearestFace = faceIndex;
50        break;
51      }
52    }
53  }
54 
55  if ( hits && ray.GetType() == Ray::LOCAL_RAY ) {
56    if (ray.intersections.size())
57      ray.intersections[0] = Ray::RayIntersection(nearestT, instance, nearestFace);
58    else
59      ray.intersections.push_back(Ray::RayIntersection(nearestT, instance, nearestFace));
60  }
61 
62  return hits;
63}
64
65
66// int_lineseg returns 1 if the given line segment intersects a 2D
67// ray travelling in the positive X direction.  This is used in the
68// Jordan curve computation for polygon intersection.
69inline int
70int_lineseg(float px,
71            float py,
72            float u1,
73            float v1,
74            float u2,
75            float v2)
76{
77  float t;
78  float ydiff;
79
80  u1 -= px; u2 -= px;     // translate line
81  v1 -= py; v2 -= py;
82
83  if ((v1 > 0 && v2 > 0) ||
84      (v1 < 0 && v2 < 0) ||
85      (u1 < 0 && u2 < 0))
86    return 0;
87
88  if (u1 > 0 && u2 > 0)
89    return 1;
90
91  ydiff = v2 - v1;
92  if (fabs(ydiff) < Limits::Small) {      // denominator near 0
93    if (((fabs(v1) > Limits::Small) ||
94         (u1 > 0) || (u2 > 0)))
95      return 0;
96    return 1;
97  }
98
99  t = -v1 / ydiff;                // Compute parameter
100
101  return (u1 + t * (u2 - u1)) > 0;
102}
103
104
105
106// intersection with the polygonal face of the mesh
107int
108Mesh::RayFaceIntersection(const int faceIndex,
109                          const Ray &ray,
110                          float &t,
111                          const float nearestT
112                          )
113{
114  Face *face  = mFaces[faceIndex];
115
116  Plane3 plane = GetFacePlane(faceIndex);
117  float dot = DotProd(plane.mNormal, ray.GetDir());
118 
119  // Watch for near-zero denominator
120  // ONLY single sided polygons!!!!!
121  if (dot > -Limits::Small)
122    //  if (fabs(dot) < Limits::Small)
123    return Ray::NO_INTERSECTION;
124 
125  t = (-plane.mD - DotProd(plane.mNormal, ray.GetLoc())) / dot;
126 
127  if (t <= Limits::Small)
128    return Ray::INTERSECTION_OUT_OF_LIMITS;
129 
130  if (t >= nearestT) {
131    return Ray::INTERSECTION_OUT_OF_LIMITS; // no intersection was found
132  }
133 
134  int count = 0;
135  float u, v, u1, v1, u2, v2;
136  int i;
137
138  int paxis = plane.mNormal.DrivingAxis();
139
140  // Project the intersection point onto the coordinate plane
141  // specified by which.
142  ray.Extrap(t).ExtractVerts(&u, &v, paxis);
143
144
145  mVertices[face->mVertexIndices[face->mVertexIndices.size() - 1]].
146    ExtractVerts(&u1, &v1, paxis );
147
148  if (mIsConvex) {
149    // assume a convex face
150    for (i = 0; i < face->mVertexIndices.size(); i++) {
151      mVertices[face->mVertexIndices[i]].ExtractVerts(&u2, &v2, paxis);
152      // line u1, v1, u2, v2
153      if ((v2 - v1)*(u1 - u) > (u2 - u1)*(v1 - v))
154        return Ray::NO_INTERSECTION;
155      u1 = u2;
156      v1 = v2;
157    }
158   
159    return Ray::INTERSECTION;
160  }
161 
162  // We're stuck with the Jordan curve computation.  Count number
163  // of intersections between the line segments the polygon comprises
164  // with a ray originating at the point of intersection and
165  // travelling in the positive X direction.
166  for (i = 0; i < face->mVertexIndices.size(); i++) {
167    mVertices[face->mVertexIndices[i]].ExtractVerts(&u2, &v2, paxis);
168    count += (int_lineseg(u, v, u1, v1, u2, v2) != 0);
169    u1 = u2;
170    v1 = v2;
171  }
172
173  // We hit polygon if number of intersections is odd.
174  return (count & 1) ? Ray::INTERSECTION : Ray::NO_INTERSECTION;
175}
176
177
178int
179MeshInstance::CastRay(
180                      Ray &ray
181                      )
182{
183  int res = mMesh->CastRay(ray, this);
184  return res;
185}
186
187
188Plane3
189Mesh::GetFacePlane(const int faceIndex)
190{
191  Face *face = mFaces[faceIndex];
192  return Plane3(mVertices[face->mVertexIndices[0]],
193                mVertices[face->mVertexIndices[1]],
194                mVertices[face->mVertexIndices[2]]);
195}
196
197int
198MeshTransformedInstance::CastRay(
199                                 Ray &ray
200                                 )
201{
202  ray.ApplyTransform(Invert(mWorldTransform));
203  int res = mMesh->CastRay(ray, this);
204  ray.ApplyTransform(mWorldTransform);
205 
206  return res;
207}
Note: See TracBrowser for help on using the repository browser.