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

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