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

Revision 170, 6.7 KB checked in by bittner, 19 years ago (diff)

mesh kd tree added

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