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

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