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

Revision 1076, 17.0 KB checked in by mattausch, 18 years ago (diff)

version for performance testing

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