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

Revision 811, 13.3 KB checked in by bittner, 19 years ago (diff)

first merge after the svn server crash

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