source: GTP/trunk/Lib/Vis/Preprocessing/src/Mesh.cpp @ 859

Revision 859, 13.4 KB checked in by bittner, 18 years ago (diff)

apply filter routine for working modules

Line 
1#include "Ray.h"
2#include "Mesh.h"
3#include "MeshKdTree.h"
4#include "Triangle3.h"
5
6int Intersectable::sMailId = 21843194198;
7int Intersectable::sReservedMailboxes = 1;
8
9struct SortableVertex {
10
11  Vector3 vertex;
12
13  int originalId;
14  int newId;
15  int finalPos;
16
17  SortableVertex() {}
18
19  SortableVertex(const Vector3 &v,
20                                 const int id):
21        vertex(v),
22        originalId(id),
23        newId(id)
24  {}
25 
26  friend bool operator<(const SortableVertex &a,
27                                                const SortableVertex &b)
28  {
29        if (a.vertex.x < b.vertex.x)
30          return true;
31        else
32          if (a.vertex.x > b.vertex.x)
33                return false;
34       
35        if (a.vertex.y < b.vertex.y)
36          return true;
37        else
38          if (a.vertex.y > b.vertex.y)
39                return false;
40       
41        if (a.vertex.z < b.vertex.z)
42          return true;
43        else
44          //      if (a.z > b.z)
45          return false;
46       
47        //      return false;
48  }
49
50};
51
52
53void
54Mesh::ComputeBoundingBox()
55{
56
57  mBox.Initialize();
58  VertexContainer::const_iterator vi = mVertices.begin();
59  for (; vi != mVertices.end(); vi++) {
60    mBox.Include(*vi);
61  }
62
63}
64
65void
66Mesh::Preprocess()
67{
68 Cleanup();
69   
70   ComputeBoundingBox();
71   
72  /** true if it is a watertight convex mesh */
73  mIsConvex = false;
74 
75  if (mFaces.size() > MeshKdTree::mTermMinCost) {
76    mKdTree = new MeshKdTree(this);
77    MeshKdLeaf *root = (MeshKdLeaf *)mKdTree->GetRoot();
78    for (int i = 0; i < mFaces.size(); i++)
79      root->mFaces.push_back(i);
80    cout<<"KD";
81    mKdTree->Construct();
82       
83    if (mKdTree->GetRoot()->IsLeaf()) {
84      cout<<"d";
85      delete mKdTree;
86          mKdTree = NULL;
87    }
88  }
89}
90
91
92void
93Mesh::IndexVertices()
94{
95  int i;
96  // check whether the vertices can be simplfied and reindexed
97  vector<SortableVertex> svertices(mVertices.size());
98
99  for (i=0; i < mVertices.size(); i++)
100        svertices[i] = SortableVertex(mVertices[i], i);
101
102  sort(svertices.begin(), svertices.end());
103
104  for (i=0; i < svertices.size() - 1; i++)
105        if (svertices[i].vertex == svertices[i+1].vertex)
106          svertices[i+1].newId = svertices[i].newId;
107
108  // remove the same vertices
109  int k = 0;
110  mVertices[0] = svertices[0].vertex;
111  svertices[0].finalPos = 0;
112 
113  for (i=1; i < svertices.size(); i++) {
114        if (svertices[i].newId != svertices[i-1].newId)
115          k++;
116       
117        mVertices[k] = svertices[i].vertex;
118        svertices[i].finalPos = k;
119  }
120
121  mVertices.resize(k + 1);
122 
123  vector<int> remapBuffer(svertices.size());
124  for (i = 0; i < svertices.size(); i++)
125        remapBuffer[svertices[i].originalId] = svertices[i].finalPos;
126 
127  // remap all faces
128 
129  for (int faceIndex = 0; faceIndex < mFaces.size(); faceIndex++) {
130        Face *face = mFaces[faceIndex];
131        for (int i = 0; i < face->mVertexIndices.size(); i++) {
132          face->mVertexIndices[i] = remapBuffer[face->mVertexIndices[i]];
133        }
134  }
135}
136
137AxisAlignedBox3
138Mesh::GetFaceBox(const int faceIndex)
139{
140  Face *face = mFaces[faceIndex];
141  AxisAlignedBox3 box;
142  box.SetMin( mVertices[face->mVertexIndices[0]] );
143  box.SetMax(box.Min());
144  for (int i = 1; i < face->mVertexIndices.size(); i++) {
145    box.Include(mVertices[face->mVertexIndices[i]]);
146  }
147  return box;
148}
149
150int
151Mesh::CastRayToFace(
152                                                                                const int faceIndex,
153                                                                                Ray &ray,
154                                                                                float &nearestT,
155                                                                                int &nearestFace,
156                                                                                Intersectable *instance
157                                                                                )
158{
159  float t;
160  int hit = 0;
161  if (RayFaceIntersection(faceIndex, ray, t, nearestT) == Ray::INTERSECTION) {
162    switch (ray.GetType()) {
163    case Ray::GLOBAL_RAY:
164      ray.intersections.push_back(Ray::Intersection(t, instance, faceIndex));
165      hit++;
166      break;
167    case Ray::LOCAL_RAY:
168      nearestT = t;
169      nearestFace = faceIndex;
170      hit++;
171      break;
172    case Ray::LINE_SEGMENT:
173      if (t <= 1.0f) {
174                                ray.intersections.push_back(Ray::Intersection(t, instance, faceIndex));
175                                hit++;
176      }
177      break;
178    }
179  }
180  return hit;
181}
182
183int
184Mesh::CastRay(
185                          Ray &ray,
186                          MeshInstance *instance
187                          )
188{
189  if (mKdTree) {
190    return mKdTree->CastRay(ray, instance);
191  }
192 
193  int faceIndex = 0;
194  int hits = 0;
195  float nearestT = MAX_FLOAT;
196  int nearestFace = -1;
197 
198  if (ray.GetType() == Ray::LOCAL_RAY && ray.intersections.size())
199    nearestT = ray.intersections[0].mT;
200
201       
202  for ( ;
203                faceIndex < mFaces.size();
204                faceIndex++) {
205    hits += CastRayToFace(faceIndex, ray, nearestT, nearestFace, instance);
206    if (mIsConvex && nearestFace != -1)
207      break;
208  }
209 
210  if ( hits && ray.GetType() == Ray::LOCAL_RAY ) {
211    if (ray.intersections.size())
212      ray.intersections[0] = Ray::Intersection(nearestT, instance, nearestFace);
213    else
214      ray.intersections.push_back(Ray::Intersection(nearestT, instance, nearestFace));
215  }
216 
217  return hits;
218}
219
220int
221Mesh::CastRayToSelectedFaces(
222                                                         Ray &ray,
223                                                         const vector<int> &faces,
224                                                         Intersectable *instance
225                                                         )
226{
227  vector<int>::const_iterator fi;
228  int faceIndex = 0;
229  int hits = 0;
230  float nearestT = MAX_FLOAT;
231  int nearestFace = -1;
232
233  if (ray.GetType() == Ray::LOCAL_RAY && ray.intersections.size())
234    nearestT = ray.intersections[0].mT;
235
236  for ( fi = faces.begin();
237                                fi != faces.end();
238                                fi++) {
239    hits += CastRayToFace(*fi, ray, nearestT, nearestFace, instance);
240    if (mIsConvex && nearestFace != -1)
241      break;
242  }
243 
244  if ( hits && ray.GetType() == Ray::LOCAL_RAY ) {
245    if (ray.intersections.size())
246      ray.intersections[0] = Ray::Intersection(nearestT, instance, nearestFace);
247    else
248      ray.intersections.push_back(Ray::Intersection(nearestT, instance, nearestFace));
249  }
250 
251  return hits;
252}
253
254
255// int_lineseg returns 1 if the given line segment intersects a 2D
256// ray travelling in the positive X direction.  This is used in the
257// Jordan curve computation for polygon intersection.
258inline int
259int_lineseg(float px,
260                        float py,
261                        float u1,
262                        float v1,
263                        float u2,
264                        float v2)
265{
266  float ydiff;
267
268  u1 -= px; u2 -= px;     // translate line
269  v1 -= py; v2 -= py;
270
271  if ((v1 > 0 && v2 > 0) ||
272      (v1 < 0 && v2 < 0) ||
273      (u1 < 0 && u2 < 0))
274    return 0;
275
276  if (u1 > 0 && u2 > 0)
277    return 1;
278
279  ydiff = v2 - v1;
280  if (fabs(ydiff) < Limits::Small) {      // denominator near 0
281    if (((fabs(v1) > Limits::Small) ||
282                 (u1 > 0) || (u2 > 0)))
283      return 0;
284    return 1;
285  }
286 
287  double t = -v1 / ydiff;                 // Compute parameter
288
289  double thresh;
290  if (ydiff < 0.0f)
291        thresh = -1e20;
292  else
293        thresh = 1e20;
294
295 
296  return (u1 + t * (u2 - u1)) > thresh; //-Limits::Small;
297}
298
299
300
301// intersection with the polygonal face of the mesh
302int
303Mesh::RayFaceIntersection(const int faceIndex,
304                                                  const Ray &ray,
305                                                  float &t,
306                                                  const float nearestT
307                                                  )
308{
309  Face *face  = mFaces[faceIndex];
310
311  Plane3 plane = GetFacePlane(faceIndex);
312  float dot = DotProd(plane.mNormal, ray.GetDir());
313 
314  // Watch for near-zero denominator
315  // ONLY single sided polygons!!!!!
316  if (ray.mFlags & Ray::CULL_BACKFACES) {
317        if (dot > -Limits::Small)
318          //  if (fabs(dot) < Limits::Small)
319          return Ray::NO_INTERSECTION;
320  } else {
321        if (fabs(dot) < Limits::Small)
322          return Ray::NO_INTERSECTION;
323  }
324 
325  t = (-plane.mD - DotProd(plane.mNormal, ray.GetLoc())) / dot;
326 
327  if (t <= Limits::Small)
328    return Ray::INTERSECTION_OUT_OF_LIMITS;
329 
330  if (t >= nearestT) {
331    return Ray::INTERSECTION_OUT_OF_LIMITS; // no intersection was found
332  }
333 
334  int count = 0;
335  float u, v, u1, v1, u2, v2;
336  int i;
337
338  int paxis = plane.mNormal.DrivingAxis();
339
340  // Project the intersection point onto the coordinate plane
341  // specified by which.
342  ray.Extrap(t).ExtractVerts(&u, &v, paxis);
343
344
345  int size = (int)face->mVertexIndices.size();
346
347  mVertices[face->mVertexIndices[size - 1]].
348    ExtractVerts(&u1, &v1, paxis );
349 
350  //$$JB changed 12.4.2006 from 0 ^^
351  if (0 && size <= 4) {
352    // assume a convex face
353    for (i = 0; i < size; i++) {
354      mVertices[face->mVertexIndices[i]].ExtractVerts(&u2, &v2, paxis);
355      // line u1, v1, u2, v2
356      if ((v1 - v2)*(u - u1) + (u2 - u1)*(v - v1) > 0)
357                return Ray::NO_INTERSECTION;
358      u1 = u2;
359      v1 = v2;
360    }
361   
362    return Ray::INTERSECTION;
363  }
364 
365  // We're stuck with the Jordan curve computation.  Count number
366  // of intersections between the line segments the polygon comprises
367  // with a ray originating at the point of intersection and
368  // travelling in the positive X direction.
369  for (i = 0; i < size; i++) {
370    mVertices[face->mVertexIndices[i]].ExtractVerts(&u2, &v2, paxis);
371    count += (int_lineseg(u, v, u1, v1, u2, v2) != 0);
372    u1 = u2;
373    v1 = v2;
374  }
375
376  // We hit polygon if number of intersections is odd.
377  return (count & 1) ? Ray::INTERSECTION : Ray::NO_INTERSECTION;
378}
379
380int
381Mesh::GetRandomSurfacePoint(Vector3 &point, Vector3 &normal)
382{
383  int faceIndex = (int)RandomValue(0, (Real)((int)mFaces.size()-1));
384 
385  // assume the face is convex and generate a convex combination
386  //
387  Face *face = mFaces[faceIndex];
388  point = Vector3(0,0,0);
389  float sum = 0.0f;
390  for (int i = 0; i < face->mVertexIndices.size(); i++) {
391    float r = RandomValue(0,1);
392    sum += r;
393    point += mVertices[face->mVertexIndices[i]]*r;
394  }
395  point *= 1.0f/sum;
396       
397        normal = GetFacePlane(faceIndex).mNormal;
398
399        return faceIndex;
400}
401
402int
403Mesh::GetRandomVisibleSurfacePoint(Vector3 &point,
404                                                                                                                                         Vector3 &normal,
405                                                                                                                                         const Vector3 &viewpoint,
406                                                                                                                                         const int maxTries
407                                                                                                                                         )
408{
409  Plane3 plane;
410  int faceIndex = (int)RandomValue(0, (Real)((int)mFaces.size()-1));
411        int tries;
412  for (tries = 0; tries < maxTries; tries++) {
413    Face *face = mFaces[faceIndex];
414    plane = GetFacePlane(faceIndex);
415   
416    if (plane.Side(viewpoint) > 0) {
417      point = Vector3(0,0,0);
418      float sum = 0.0f;
419      // pickup a point inside this triangle
420      for (int i = 0; i < face->mVertexIndices.size(); i++) {
421                                float r = RandomValue(0,1);
422                                sum += r;
423                                point += mVertices[face->mVertexIndices[i]]*r;
424      }
425      point *= 1.0f/sum;
426      break;
427    }
428  }
429 
430  normal = plane.mNormal;
431  return (tries < maxTries) ? faceIndex + 1 : 0;
432}
433
434
435int
436MeshInstance::CastRay(
437                                          Ray &ray
438                                          )
439{
440  int res = mMesh->CastRay(ray, this);
441  return res;
442}
443
444int
445MeshInstance::CastRay(
446                                          Ray &ray,
447                                          const vector<int> &faces
448                                          )
449{
450  return mMesh->CastRayToSelectedFaces(ray, faces, this);
451}
452
453
454
455int
456MeshInstance::GetRandomSurfacePoint(Vector3 &point, Vector3 &normal)
457{
458  return mMesh->GetRandomSurfacePoint(point, normal);
459}
460
461int
462MeshInstance::GetRandomVisibleSurfacePoint(Vector3 &point,
463                                                                                                                                                                         Vector3 &normal,
464                                                                                                                                                                         const Vector3 &viewpoint,
465                                                                                                                                                                         const int maxTries
466                                                                                                                                                                         )
467{
468        return mMesh->GetRandomVisibleSurfacePoint(point, normal, viewpoint, maxTries);
469}
470
471
472int
473TransformedMeshInstance::GetRandomSurfacePoint(Vector3 &point, Vector3 &normal)
474{
475  int index = mMesh->GetRandomSurfacePoint(point, normal);
476  point = mWorldTransform*point;
477  normal = TransformNormal(mWorldTransform, normal);
478  return index;
479}
480
481Plane3
482Mesh::GetFacePlane(const int faceIndex)
483{
484  Face *face = mFaces[faceIndex];
485        return Plane3(mVertices[face->mVertexIndices[0]],
486                                                                mVertices[face->mVertexIndices[1]],
487                                                                mVertices[face->mVertexIndices[2]]);
488}
489
490bool
491Mesh::ValidateFace(const int i)
492{
493        Face *face = mFaces[i];
494
495        Plane3 plane = Plane3(mVertices[face->mVertexIndices[0]],
496                                                                                                mVertices[face->mVertexIndices[1]],
497                                                                                                mVertices[face->mVertexIndices[2]]);
498       
499        if (!eq(Magnitude(plane.mNormal), 1.0f))
500                return false;
501
502        return true;
503}
504
505void
506Mesh::Cleanup()
507{
508        int toRemove = 0;
509        FaceContainer newFaces;
510        for (int i=0; i < mFaces.size(); i++)
511                if (ValidateFace(i)) {
512                        newFaces.push_back(mFaces[i]);
513                } else {
514                        cout<<"d";
515                        delete mFaces[i];
516                        toRemove++;
517                }
518       
519        if (toRemove) {
520                mFaces = newFaces;
521        }
522       
523        // cleanup vertices??
524}
525
526int
527TransformedMeshInstance::CastRay(
528                                                                 Ray &ray
529                                                                 )
530{
531  ray.ApplyTransform(Invert(mWorldTransform));
532  int res = mMesh->CastRay(ray, this);
533  ray.ApplyTransform(mWorldTransform);
534 
535  return res;
536}
537
538
539void
540Mesh::AddTriangle(const Triangle3 &triangle)
541{
542  int index = (int)mVertices.size();
543
544  for (int i=0; i < 3; i++) {
545    mVertices.push_back(triangle.mVertices[i]);
546  }
547 
548  AddFace(new Face(index + 0, index + 1, index + 2) );
549}
550
551void
552Mesh::AddRectangle(const Rectangle3 &rect)
553{
554  int index = (int)mVertices.size();
555
556  for (int i=0; i < 4; i++) {
557    mVertices.push_back(rect.mVertices[i]);
558  }
559 
560  AddFace(new Face(index + 0, index + 1, index + 2, index + 3) );
561}
562
563void
564Mesh::AssignRandomMaterial()
565{
566  if (!mMaterial)
567        mMaterial = new Material;
568  *mMaterial = RandomMaterial();
569
570}
571
572
573Mesh *CreateBox(const AxisAlignedBox3 &box)
574{
575        Mesh *mesh = new Mesh;
576  // add 8 vertices of the box
577  int index = (int)mesh->mVertices.size();
578  for (int i=0; i < 8; i++) {
579    Vector3 v;
580    box.GetVertex(i, v);
581    mesh->mVertices.push_back(v);
582  }
583 
584  mesh->AddFace(new Face(index + 0, index + 1, index + 3, index + 2) );
585  mesh->AddFace(new Face(index + 0, index + 2, index + 6, index + 4) );
586  mesh->AddFace(new Face(index + 4, index + 6, index + 7, index + 5) );
587 
588  mesh->AddFace(new Face(index + 3, index + 1, index + 5, index + 7) );
589  mesh->AddFace(new Face(index + 0, index + 4, index + 5, index + 1) );
590  mesh->AddFace(new Face(index + 2, index + 3, index + 7, index + 6) );
591 
592  return mesh;
593}
Note: See TracBrowser for help on using the repository browser.