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

Revision 2614, 20.2 KB checked in by mattausch, 17 years ago (diff)

worked on dynamic objects

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