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

Revision 1287, 17.3 KB checked in by mattausch, 18 years ago (diff)

implemented bv hierarchy

Line 
1#include "Ray.h"
2#include "Mesh.h"
3#include "MeshKdTree.h"
4#include "Triangle3.h"
5#include "ResourceManager.h"
6
7namespace GtpVisibilityPreprocessor {
8
9bool MeshDebug = false;
10
11int Intersectable::sMailId = 2147483647;
12int Intersectable::sReservedMailboxes = 1;
13
14struct SortableVertex {
15
16  Vector3 vertex;
17
18  int originalId;
19  int newId;
20  int finalPos;
21
22  SortableVertex() {}
23
24  SortableVertex(const Vector3 &v,
25                                 const int id):
26        vertex(v),
27        originalId(id),
28        newId(id)
29  {}
30 
31  friend bool operator<(const SortableVertex &a,
32                                                const SortableVertex &b)
33  {
34        if (a.vertex.x < b.vertex.x)
35          return true;
36        else
37          if (a.vertex.x > b.vertex.x)
38                return false;
39       
40        if (a.vertex.y < b.vertex.y)
41          return true;
42        else
43          if (a.vertex.y > b.vertex.y)
44                return false;
45       
46        if (a.vertex.z < b.vertex.z)
47          return true;
48        else
49          //      if (a.z > b.z)
50          return false;
51       
52        //      return false;
53  }
54
55};
56
57
58void
59Mesh::ComputeBoundingBox()
60{
61
62  mBox.Initialize();
63  VertexContainer::const_iterator vi = mVertices.begin();
64  for (; vi != mVertices.end(); vi++) {
65    mBox.Include(*vi);
66  }
67//mBox.Enlarge(1e-4f);
68}
69
70void
71Mesh::Preprocess()
72{
73        Cleanup();
74 
75        ComputeBoundingBox();
76 
77        /** true if it is a watertight convex mesh
78        */
79        mIsConvex = false;
80
81        if (mFaces.size() > MeshKdTree::mTermMinCost)
82        {
83                mKdTree = new MeshKdTree(this);
84                MeshKdLeaf *root = (MeshKdLeaf *)mKdTree->GetRoot();
85               
86                for (int i = 0; i < mFaces.size(); i++)
87                        root->mFaces.push_back(i);
88               
89                cout<<"KD";
90               
91                mKdTree->Construct();
92
93                if (mKdTree->GetRoot()->IsLeaf())
94                {
95                        cout<<"d";
96                        delete mKdTree;
97                        mKdTree = NULL;
98                }
99        }
100}
101
102
103void
104Mesh::IndexVertices()
105{
106  int i;
107  // check whether the vertices can be simplfied and reindexed
108  vector<SortableVertex> svertices(mVertices.size());
109
110  for (i=0; i < mVertices.size(); i++)
111        svertices[i] = SortableVertex(mVertices[i], i);
112
113  sort(svertices.begin(), svertices.end());
114
115  for (i=0; i < svertices.size() - 1; i++)
116        if (svertices[i].vertex == svertices[i+1].vertex)
117          svertices[i+1].newId = svertices[i].newId;
118
119  // remove the same vertices
120  int k = 0;
121  mVertices[0] = svertices[0].vertex;
122  svertices[0].finalPos = 0;
123 
124  for (i=1; i < svertices.size(); i++) {
125        if (svertices[i].newId != svertices[i-1].newId)
126          k++;
127       
128        mVertices[k] = svertices[i].vertex;
129        svertices[i].finalPos = k;
130  }
131
132  mVertices.resize(k + 1);
133 
134  vector<int> remapBuffer(svertices.size());
135  for (i = 0; i < svertices.size(); i++)
136        remapBuffer[svertices[i].originalId] = svertices[i].finalPos;
137 
138  // remap all faces
139 
140  for (int faceIndex = 0; faceIndex < mFaces.size(); faceIndex++) {
141        Face *face = mFaces[faceIndex];
142        for (int i = 0; i < face->mVertexIndices.size(); i++) {
143          face->mVertexIndices[i] = remapBuffer[face->mVertexIndices[i]];
144        }
145  }
146}
147
148AxisAlignedBox3
149Mesh::GetFaceBox(const int faceIndex)
150{
151  Face *face = mFaces[faceIndex];
152  AxisAlignedBox3 box;
153  box.SetMin( mVertices[face->mVertexIndices[0]] );
154  box.SetMax(box.Min());
155  for (int i = 1; i < face->mVertexIndices.size(); i++) {
156    box.Include(mVertices[face->mVertexIndices[i]]);
157  }
158  return box;
159}
160
161int
162Mesh::CastRayToFace(
163                                        const int faceIndex,
164                                        Ray &ray,
165                                        float &nearestT,
166                                        Vector3 &nearestNormal,
167                                        int &nearestFace,
168                                        Intersectable *instance
169                                        )
170{
171  float t;
172  int hit = 0;
173  Vector3 normal;
174  if (RayFaceIntersection(faceIndex, ray, t, normal, nearestT) == Ray::INTERSECTION) {
175    switch (ray.GetType()) {
176    case Ray::GLOBAL_RAY:
177      ray.intersections.push_back(Ray::Intersection(t, normal, instance, faceIndex));
178      hit++;
179      break;
180    case Ray::LOCAL_RAY:
181      nearestT = t;
182          nearestNormal = normal;
183      nearestFace = faceIndex;
184      hit++;
185      break;
186    case Ray::LINE_SEGMENT:
187      if (t <= 1.0f) {
188                ray.intersections.push_back(Ray::Intersection(t, normal, instance, faceIndex));
189                hit++;
190      }
191      break;
192    }
193  }
194  return hit;
195}
196
197int
198Mesh::CastRay(
199                          Ray &ray,
200                          MeshInstance *instance
201                          )
202{
203  if (mKdTree) {
204    return mKdTree->CastRay(ray, instance);
205  }
206 
207  int faceIndex = 0;
208  int hits = 0;
209  float nearestT = MAX_FLOAT;
210  Vector3 nearestNormal;
211  int nearestFace = -1;
212 
213  if (ray.GetType() == Ray::LOCAL_RAY && ray.intersections.size())
214    nearestT = ray.intersections[0].mT;
215
216       
217  for ( ;
218                faceIndex < mFaces.size();
219                faceIndex++) {
220    hits += CastRayToFace(faceIndex, ray, nearestT, nearestNormal, nearestFace, instance);
221    if (mIsConvex && nearestFace != -1)
222      break;
223  }
224 
225  if ( hits && ray.GetType() == Ray::LOCAL_RAY ) {
226    if (ray.intersections.size())
227      ray.intersections[0] = Ray::Intersection(nearestT, nearestNormal, instance, nearestFace);
228    else
229      ray.intersections.push_back(Ray::Intersection(nearestT, nearestNormal, instance, nearestFace));
230  }
231 
232  return hits;
233}
234
235int
236Mesh::CastRayToSelectedFaces(
237                                                         Ray &ray,
238                                                         const vector<int> &faces,
239                                                         Intersectable *instance
240                                                         )
241{
242  vector<int>::const_iterator fi;
243  int faceIndex = 0;
244  int hits = 0;
245  float nearestT = MAX_FLOAT;
246  Vector3 nearestNormal;
247  int nearestFace = -1;
248 
249  if (ray.GetType() == Ray::LOCAL_RAY && ray.intersections.size())
250    nearestT = ray.intersections[0].mT;
251
252  for ( fi = faces.begin();
253                fi != faces.end();
254                fi++) {
255    hits += CastRayToFace(*fi, ray, nearestT, nearestNormal, nearestFace, instance);
256    if (mIsConvex && nearestFace != -1)
257      break;
258  }
259 
260  if ( hits && ray.GetType() == Ray::LOCAL_RAY ) {
261    if (ray.intersections.size())
262      ray.intersections[0] = Ray::Intersection(nearestT, nearestNormal,instance, nearestFace);
263    else
264      ray.intersections.push_back(Ray::Intersection(nearestT, nearestNormal,instance, nearestFace));
265  }
266 
267  return hits;
268}
269
270
271// int_lineseg returns 1 if the given line segment intersects a 2D
272// ray travelling in the positive X direction.  This is used in the
273// Jordan curve computation for polygon intersection.
274inline int
275int_lineseg(float px,
276                        float py,
277                        float u1,
278                        float v1,
279                        float u2,
280                        float v2)
281{
282  float ydiff;
283
284  u1 -= px; u2 -= px;     // translate line
285  v1 -= py; v2 -= py;
286
287  if ((v1 > 0 && v2 > 0) ||
288      (v1 < 0 && v2 < 0) ||
289      (u1 < 0 && u2 < 0))
290    return 0;
291
292  if (u1 > 0 && u2 > 0)
293    return 1;
294
295  ydiff = v2 - v1;
296  if (fabs(ydiff) < Limits::Small) {      // denominator near 0
297    if (((fabs(v1) > Limits::Small) ||
298                 (u1 > 0) || (u2 > 0)))
299      return 0;
300    return 1;
301  }
302 
303  double t = -v1 / ydiff;                 // Compute parameter
304
305  double thresh;
306
307  if (ydiff < 0.0f)
308        thresh = -1e-20;
309  else
310        thresh = 1e-20;
311
312 
313  return (u1 + t * (u2 - u1)) > thresh; //-Limits::Small;
314}
315
316
317
318// intersection with the polygonal face of the mesh
319int
320Mesh::RayFaceIntersection(const int faceIndex,
321                                                  const Ray &ray,
322                                                  float &t,
323                                                  Vector3 &normal,
324                                                  const float nearestT
325                                                  )
326{
327  Face *face  = mFaces[faceIndex];
328
329  Plane3 plane = GetFacePlane(faceIndex);
330  float dot = DotProd(plane.mNormal, ray.GetDir());
331
332  if (MeshDebug) {
333        cout<<endl<<endl;
334        cout<<"normal="<<plane.mNormal<<endl;
335        cout<<"dot="<<dot<<endl;
336  }
337 
338       
339  // Watch for near-zero denominator
340  // ONLY single sided polygons!!!!!
341  if (ray.mFlags & Ray::CULL_BACKFACES) {
342        if (dot > -Limits::Small)
343          //  if (fabs(dot) < Limits::Small)
344          return Ray::NO_INTERSECTION;
345  } else {
346        if (fabs(dot) < Limits::Small)
347          return Ray::NO_INTERSECTION;
348  }
349 
350  normal = plane.mNormal;
351
352  t = (-plane.mD - DotProd(plane.mNormal, ray.GetLoc())) / dot;
353
354  if (MeshDebug)
355        cout<<"t="<<t<<endl;
356
357  if (t <= Limits::Small)
358    return Ray::INTERSECTION_OUT_OF_LIMITS;
359 
360  if (t >= nearestT) {
361    return Ray::INTERSECTION_OUT_OF_LIMITS; // no intersection was found
362  }
363 
364  int count = 0;
365  float u, v, u1, v1, u2, v2;
366  int i;
367
368  int paxis = plane.mNormal.DrivingAxis();
369
370 
371  // Project the intersection point onto the coordinate plane
372  // specified by which.
373  ray.Extrap(t).ExtractVerts(&u, &v, paxis);
374
375
376  int size = (int)face->mVertexIndices.size();
377
378  if (MeshDebug)
379        cout<<"size="<<size<<endl;
380 
381  mVertices[face->mVertexIndices[size - 1]].
382    ExtractVerts(&u1, &v1, paxis );
383 
384  //$$JB changed 12.4.2006 from 0 ^^
385  if (0 && size <= 4) {
386    // assume a convex face
387    for (i = 0; i < size; i++) {
388      mVertices[face->mVertexIndices[i]].ExtractVerts(&u2, &v2, paxis);
389      // line u1, v1, u2, v2
390      if ((v1 - v2)*(u - u1) + (u2 - u1)*(v - v1) > 0) {
391                if (MeshDebug)
392                  cout<<"exit on "<<i<<endl;
393                return Ray::NO_INTERSECTION;
394          }
395      u1 = u2;
396      v1 = v2;
397    }
398   
399    return Ray::INTERSECTION;
400  }
401 
402  // We're stuck with the Jordan curve computation.  Count number
403  // of intersections between the line segments the polygon comprises
404  // with a ray originating at the point of intersection and
405  // travelling in the positive X direction.
406  for (i = 0; i < size; i++) {
407    mVertices[face->mVertexIndices[i]].ExtractVerts(&u2, &v2, paxis);
408    count += (int_lineseg(u, v, u1, v1, u2, v2) != 0);
409    u1 = u2;
410    v1 = v2;
411  }
412
413  if (MeshDebug)
414        cout<<"count="<<count<<endl;
415
416  // We hit polygon if number of intersections is odd.
417  return (count & 1) ? Ray::INTERSECTION : Ray::NO_INTERSECTION;
418}
419
420int
421Mesh::GetRandomSurfacePoint(Vector3 &point, Vector3 &normal)
422{
423  const int faceIndex = (int)RandomValue(0, (Real)((int)mFaces.size()-1));
424 
425  // assume the face is convex and generate a convex combination
426  //
427  Face *face = mFaces[faceIndex];
428 
429  point = Vector3(0,0,0);
430  float sum = 0.0f;
431 
432  for (int i = 0; i < face->mVertexIndices.size(); i++) {
433    float r = RandomValue(0,1);
434    sum += r;
435    point += mVertices[face->mVertexIndices[i]]*r;
436  }
437  point *= 1.0f/sum;
438       
439        normal = GetFacePlane(faceIndex).mNormal;
440
441        return faceIndex;
442}
443
444int
445Mesh::GetRandomVisibleSurfacePoint(Vector3 &point,
446                                                                   Vector3 &normal,
447                                                                   const Vector3 &viewpoint,
448                                                                   const int maxTries)
449{
450  Plane3 plane;
451  int faceIndex = (int)RandomValue(0, (Real)((int)mFaces.size()-1));
452        int tries;
453  for (tries = 0; tries < maxTries; tries++) {
454    Face *face = mFaces[faceIndex];
455    plane = GetFacePlane(faceIndex);
456   
457    if (plane.Side(viewpoint) > 0) {
458      point = Vector3(0,0,0);
459      float sum = 0.0f;
460      // pickup a point inside this triangle
461      for (int i = 0; i < face->mVertexIndices.size(); i++) {
462                                float r = RandomValue(0,1);
463                                sum += r;
464                                point += mVertices[face->mVertexIndices[i]]*r;
465      }
466      point *= 1.0f/sum;
467      break;
468    }
469  }
470 
471  normal = plane.mNormal;
472  return (tries < maxTries) ? faceIndex + 1 : 0;
473}
474
475
476Plane3
477Mesh::GetFacePlane(const int faceIndex)
478{
479  Face *face = mFaces[faceIndex];
480        return Plane3(mVertices[face->mVertexIndices[0]],
481                                                                mVertices[face->mVertexIndices[1]],
482                                                                mVertices[face->mVertexIndices[2]]);
483}
484
485bool
486Mesh::ValidateFace(const int i)
487{
488        Face *face = mFaces[i];
489
490        Plane3 plane = Plane3(mVertices[face->mVertexIndices[0]],
491                                                  mVertices[face->mVertexIndices[1]],
492                                                  mVertices[face->mVertexIndices[2]]);
493       
494        if (!eq(Magnitude(plane.mNormal), 1.0f))
495                return false;
496
497        return true;
498}
499
500void
501Mesh::Cleanup()
502{
503        int toRemove = 0;
504        FaceContainer newFaces;
505        for (int i=0; i < mFaces.size(); i++)
506                if (ValidateFace(i)) {
507                        newFaces.push_back(mFaces[i]);
508                } else {
509                        cout<<"d";
510                        delete mFaces[i];
511                        toRemove++;
512                }
513       
514        if (toRemove) {
515                mFaces = newFaces;
516        }
517       
518        // cleanup vertices??
519}
520
521
522void
523Mesh::AddTriangle(const Triangle3 &triangle)
524{
525  int index = (int)mVertices.size();
526
527  for (int i=0; i < 3; i++) {
528    mVertices.push_back(triangle.mVertices[i]);
529  }
530 
531  AddFace(new Face(index + 0, index + 1, index + 2) );
532}
533
534void
535Mesh::AddRectangle(const Rectangle3 &rect)
536{
537  int index = (int)mVertices.size();
538
539  for (int i=0; i < 4; i++) {
540    mVertices.push_back(rect.mVertices[i]);
541  }
542 
543  AddFace(new Face(index + 0, index + 1, index + 2, index + 3) );
544}
545
546void
547Mesh::AssignRandomMaterial()
548
549        mMaterial = MaterialManager::GetSingleton()->CreateResource();
550 
551        Material randMat = RandomMaterial();
552
553        mMaterial->mDiffuseColor = randMat.mDiffuseColor;
554        mMaterial->mSpecularColor = randMat.mSpecularColor;
555        mMaterial->mAmbientColor = randMat.mAmbientColor;
556}
557
558
559Mesh *CreateMeshFromBox(const AxisAlignedBox3 &box)
560{
561        Mesh *mesh = MeshManager::GetSingleton()->CreateResource();
562
563        // add 8 vertices of the box
564        const int index = (int)mesh->mVertices.size();
565       
566        for (int i=0; i < 8; ++ i)
567        {
568        Vector3 v;
569                box.GetVertex(i, v);
570                mesh->mVertices.push_back(v);
571        }
572
573        mesh->AddFace(new Face(index + 0, index + 1, index + 3, index + 2) );
574        mesh->AddFace(new Face(index + 0, index + 2, index + 6, index + 4) );
575        mesh->AddFace(new Face(index + 4, index + 6, index + 7, index + 5) );
576 
577        mesh->AddFace(new Face(index + 3, index + 1, index + 5, index + 7) );
578        mesh->AddFace(new Face(index + 0, index + 4, index + 5, index + 1) );
579        mesh->AddFace(new Face(index + 2, index + 3, index + 7, index + 6) );
580 
581        return mesh;
582}
583
584
585Mesh::Mesh(const int id, const int vertices, const int faces):
586mFaces(),
587mMaterial(NULL),
588mKdTree(NULL),
589mVertices(),
590mIsConvex(false),
591mIsWatertight(false),
592mId(id)
593{
594    mVertices.reserve(vertices);
595    mFaces.reserve(faces);
596}
597
598
599Mesh::Mesh(const int id):
600mId(id), mVertices(), mFaces(), mMaterial(NULL), mKdTree(NULL)
601{}
602
603
604// apply transformation to each vertex
605void Mesh::ApplyTransformation(const Matrix4x4 &m)
606{
607        VertexContainer::iterator it, it_end = mVertices.end();
608
609        for (it = mVertices.begin(); it != it_end; ++ it)
610        {
611                (*it) = m * (*it);       
612        }
613}
614
615
616Mesh::Mesh(const Mesh &rhs):
617mKdTree(NULL)
618{
619        mVertices = rhs.mVertices;
620        mFaces.reserve(rhs.mFaces.size());
621        mId = rhs.mId;
622        mMaterial = rhs.mMaterial;
623       
624        FaceContainer::const_iterator it, it_end = rhs.mFaces.end();
625
626        for (it = rhs.mFaces.begin(); it != it_end; ++ it)
627        {
628                Face *face = *it;
629                mFaces.push_back(new Face(*face));
630        }
631}
632
633
634Mesh& Mesh::operator=(const Mesh& m)
635{
636    if (this == &m)
637                return *this;
638 
639        CLEAR_CONTAINER(mFaces);
640
641        mVertices = m.mVertices;
642        mFaces.reserve(m.mFaces.size());
643        mMaterial = m.mMaterial;
644        // note: we don't copy id on purpose
645        //mId = m.mId;
646       
647        FaceContainer::const_iterator it, it_end = m.mFaces.end();
648
649        for (it = m.mFaces.begin(); it != it_end; ++ it)
650        {
651                Face *face = *it;
652                mFaces.push_back(new Face(*face));
653        }
654
655        return *this;
656}
657
658
659Mesh::~Mesh()
660{
661        for (int i=0; i < mFaces.size(); ++ i)
662                delete mFaces[i];
663
664        DEL_PTR(mKdTree);
665}
666 
667
668void Mesh::Clear()
669{
670        mVertices.clear();
671        mFaces.clear();
672
673        DEL_PTR(mKdTree);
674}
675
676/********************************************************/
677/*                      MeshInstance implementation             */
678/********************************************************/
679
680int
681MeshInstance::CastRay(
682                                          Ray &ray
683                                          )
684{
685  int res = mMesh->CastRay(ray, this);
686  return res;
687}
688
689int
690MeshInstance::CastRay(
691                                          Ray &ray,
692                                          const vector<int> &faces
693                                          )
694{
695  return mMesh->CastRayToSelectedFaces(ray, faces, this);
696}
697
698
699
700int
701MeshInstance::GetRandomSurfacePoint(Vector3 &point, Vector3 &normal)
702{
703  return mMesh->GetRandomSurfacePoint(point, normal);
704}
705
706int
707MeshInstance::GetRandomVisibleSurfacePoint(Vector3 &point,
708                                                                                   Vector3 &normal,
709                                                                                   const Vector3 &viewpoint,
710                                                                                   const int maxTries)
711{
712        return mMesh->GetRandomVisibleSurfacePoint(point, normal, viewpoint, maxTries);
713}
714
715
716void MeshInstance::SetMaterial(Material *mat)
717{
718        mMaterial = mat;
719}
720
721Material *MeshInstance::GetMaterial() const
722{
723        return mMaterial;
724}
725
726
727/*************************************************************/
728/*           TransformedMeshInstance implementation          */
729/*************************************************************/
730
731TransformedMeshInstance::TransformedMeshInstance(Mesh *mesh):
732MeshInstance(mesh)
733{
734    mWorldTransform = IdentityMatrix();
735}
736
737
738int TransformedMeshInstance::GetRandomSurfacePoint(Vector3 &point, Vector3 &normal)
739{
740  int index = mMesh->GetRandomSurfacePoint(point, normal);
741  point = mWorldTransform*point;
742  normal = TransformNormal(mWorldTransform, normal);
743  return index;
744}
745
746
747int TransformedMeshInstance::CastRay(Ray &ray)
748{
749        ray.ApplyTransform(Invert(mWorldTransform));
750       
751        const int res = mMesh->CastRay(ray, this);
752        ray.ApplyTransform(mWorldTransform);
753
754    return res;
755}
756
757int TransformedMeshInstance::CastRay(Ray &ray, const vector<int> &faces)
758{
759        ray.ApplyTransform(Invert(mWorldTransform));
760
761        const int res = mMesh->CastRayToSelectedFaces(ray, faces, this);
762        ray.ApplyTransform(mWorldTransform);
763
764         return res;
765}
766
767
768void TransformedMeshInstance::ApplyWorldTransform(const Matrix4x4 &m)
769{
770        mWorldTransform = m * mWorldTransform;
771}
772
773
774void TransformedMeshInstance::LoadWorldTransform(const Matrix4x4 &m)
775{
776        mWorldTransform = m;
777}
778
779
780void TransformedMeshInstance::GetWorldTransform(Matrix4x4 &m) const
781{
782        m = mWorldTransform;
783}
784
785
786AxisAlignedBox3 TransformedMeshInstance::GetBox() const
787{
788    return Transform(mMesh->mBox, mWorldTransform);
789}
790
791
792void TransformedMeshInstance::GetTransformedMesh(Mesh &transformedMesh) const
793{
794        // copy mesh
795        transformedMesh = *mMesh;
796        transformedMesh.ApplyTransformation(mWorldTransform);
797}
798
799}
Note: See TracBrowser for help on using the repository browser.