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

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