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

Revision 245, 8.3 KB checked in by bittner, 19 years ago (diff)

Merged sources with ViewCellBsp?

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