source: trunk/VUT/GtpVisibilityPreprocessor/src/Mesh.cpp @ 359

Revision 359, 10.4 KB checked in by bittner, 19 years ago (diff)

gnomi compilation

RevLine 
[167]1#include "Ray.h"
[162]2#include "Mesh.h"
[170]3#include "MeshKdTree.h"
[191]4#include "Triangle3.h"
[162]5
[339]6int Intersectable::sMailId = 21843194198;
[162]7
8void
9Mesh::Preprocess()
10{
[340]11        Cleanup();
12       
13        mBox.Initialize();
[162]14  VertexContainer::const_iterator vi = mVertices.begin();
15  for (; vi != mVertices.end(); vi++) {
[176]16    mBox.Include(*vi);
[162]17  }
18 
[176]19  /** true if it is a watertight convex mesh */
[162]20  mIsConvex = false;
[176]21 
22  if (mFaces.size() > MeshKdTree::mTermMinCost) {
[170]23    mKdTree = new MeshKdTree(this);
24    MeshKdLeaf *root = (MeshKdLeaf *)mKdTree->GetRoot();
25    for (int i = 0; i < mFaces.size(); i++)
26      root->mFaces.push_back(i);
27    cout<<"KD";
28    mKdTree->Construct();
[176]29
30    if (mKdTree->GetRoot()->IsLeaf()) {
31      cout<<"d";
32      delete mKdTree;
[258]33                        mKdTree = NULL;
[176]34    }
[170]35  }
[162]36}
37
[170]38AxisAlignedBox3
39Mesh::GetFaceBox(const int faceIndex)
40{
41  Face *face = mFaces[faceIndex];
42  AxisAlignedBox3 box;
43  box.SetMin( mVertices[face->mVertexIndices[0]] );
44  box.SetMax(box.Min());
45  for (int i = 1; i < face->mVertexIndices.size(); i++) {
46    box.Include(mVertices[face->mVertexIndices[i]]);
47  }
48  return box;
49}
[162]50
51int
[170]52Mesh::CastRayToFace(
[333]53                                                                                const int faceIndex,
54                                                                                Ray &ray,
55                                                                                float &nearestT,
56                                                                                int &nearestFace,
57                                                                                Intersectable *instance
58                                                                                )
[170]59{
60  float t;
61  int hit = 0;
62  if (RayFaceIntersection(faceIndex, ray, t, nearestT) == Ray::INTERSECTION) {
63    switch (ray.GetType()) {
64    case Ray::GLOBAL_RAY:
[191]65      ray.intersections.push_back(Ray::Intersection(t, instance, faceIndex));
[170]66      hit++;
67      break;
68    case Ray::LOCAL_RAY:
69      nearestT = t;
70      nearestFace = faceIndex;
71      hit++;
72      break;
[245]73    case Ray::LINE_SEGMENT:
74      if (t <= 1.0f) {
[333]75                                ray.intersections.push_back(Ray::Intersection(t, instance, faceIndex));
76                                hit++;
[245]77      }
78      break;
[170]79    }
80  }
81  return hit;
82}
83
84int
[162]85Mesh::CastRay(
[333]86                                                        Ray &ray,
87                                                        MeshInstance *instance
88                                                        )
[162]89{
[170]90  if (mKdTree) {
91    return mKdTree->CastRay(ray, instance);
92  }
93 
[162]94  int faceIndex = 0;
95  int hits = 0;
96  float nearestT = MAX_FLOAT;
[170]97  int nearestFace = -1;
98 
[162]99  if (ray.GetType() == Ray::LOCAL_RAY && ray.intersections.size())
100    nearestT = ray.intersections[0].mT;
101
102  for ( ;
[333]103                                faceIndex < mFaces.size();
104                                faceIndex++) {
[170]105    hits += CastRayToFace(faceIndex, ray, nearestT, nearestFace, instance);
106    if (mIsConvex && nearestFace != -1)
107      break;
[162]108  }
109 
110  if ( hits && ray.GetType() == Ray::LOCAL_RAY ) {
111    if (ray.intersections.size())
[191]112      ray.intersections[0] = Ray::Intersection(nearestT, instance, nearestFace);
[162]113    else
[191]114      ray.intersections.push_back(Ray::Intersection(nearestT, instance, nearestFace));
[162]115  }
116 
117  return hits;
118}
119
[170]120int
121Mesh::CastRayToSelectedFaces(
[333]122                                                                                                                 Ray &ray,
123                                                                                                                 const vector<int> &faces,
124                                                                                                                 Intersectable *instance
125                                                                                                                 )
[170]126{
127  vector<int>::const_iterator fi;
128  int faceIndex = 0;
129  int hits = 0;
130  float nearestT = MAX_FLOAT;
131  int nearestFace = -1;
[162]132
[170]133  if (ray.GetType() == Ray::LOCAL_RAY && ray.intersections.size())
134    nearestT = ray.intersections[0].mT;
135
136  for ( fi = faces.begin();
[333]137                                fi != faces.end();
138                                fi++) {
[170]139    hits += CastRayToFace(*fi, ray, nearestT, nearestFace, instance);
140    if (mIsConvex && nearestFace != -1)
141      break;
142  }
143 
144  if ( hits && ray.GetType() == Ray::LOCAL_RAY ) {
145    if (ray.intersections.size())
[191]146      ray.intersections[0] = Ray::Intersection(nearestT, instance, nearestFace);
[170]147    else
[191]148      ray.intersections.push_back(Ray::Intersection(nearestT, instance, nearestFace));
[170]149  }
150 
151  return hits;
152}
153
154
[162]155// int_lineseg returns 1 if the given line segment intersects a 2D
156// ray travelling in the positive X direction.  This is used in the
157// Jordan curve computation for polygon intersection.
158inline int
159int_lineseg(float px,
[333]160                                                float py,
161                                                float u1,
162                                                float v1,
163                                                float u2,
164                                                float v2)
[162]165{
166  float t;
167  float ydiff;
168
169  u1 -= px; u2 -= px;     // translate line
170  v1 -= py; v2 -= py;
171
172  if ((v1 > 0 && v2 > 0) ||
173      (v1 < 0 && v2 < 0) ||
174      (u1 < 0 && u2 < 0))
175    return 0;
176
177  if (u1 > 0 && u2 > 0)
178    return 1;
179
180  ydiff = v2 - v1;
181  if (fabs(ydiff) < Limits::Small) {      // denominator near 0
182    if (((fabs(v1) > Limits::Small) ||
[333]183                                 (u1 > 0) || (u2 > 0)))
[162]184      return 0;
185    return 1;
186  }
187
188  t = -v1 / ydiff;                // Compute parameter
189
190  return (u1 + t * (u2 - u1)) > 0;
191}
192
193
194
195// intersection with the polygonal face of the mesh
196int
197Mesh::RayFaceIntersection(const int faceIndex,
[333]198                                                                                                        const Ray &ray,
199                                                                                                        float &t,
200                                                                                                        const float nearestT
201                                                                                                        )
[162]202{
203  Face *face  = mFaces[faceIndex];
204
205  Plane3 plane = GetFacePlane(faceIndex);
206  float dot = DotProd(plane.mNormal, ray.GetDir());
207 
208  // Watch for near-zero denominator
209  // ONLY single sided polygons!!!!!
210  if (dot > -Limits::Small)
211    //  if (fabs(dot) < Limits::Small)
212    return Ray::NO_INTERSECTION;
213 
214  t = (-plane.mD - DotProd(plane.mNormal, ray.GetLoc())) / dot;
215 
216  if (t <= Limits::Small)
217    return Ray::INTERSECTION_OUT_OF_LIMITS;
218 
219  if (t >= nearestT) {
220    return Ray::INTERSECTION_OUT_OF_LIMITS; // no intersection was found
221  }
222 
223  int count = 0;
224  float u, v, u1, v1, u2, v2;
225  int i;
226
227  int paxis = plane.mNormal.DrivingAxis();
228
229  // Project the intersection point onto the coordinate plane
230  // specified by which.
231  ray.Extrap(t).ExtractVerts(&u, &v, paxis);
232
233
[170]234  int size = face->mVertexIndices.size();
235
236  mVertices[face->mVertexIndices[size - 1]].
[162]237    ExtractVerts(&u1, &v1, paxis );
[170]238 
239  if (0 && size <= 4) {
[162]240    // assume a convex face
[170]241    for (i = 0; i < size; i++) {
[162]242      mVertices[face->mVertexIndices[i]].ExtractVerts(&u2, &v2, paxis);
243      // line u1, v1, u2, v2
244      if ((v2 - v1)*(u1 - u) > (u2 - u1)*(v1 - v))
[333]245                                return Ray::NO_INTERSECTION;
[162]246      u1 = u2;
247      v1 = v2;
248    }
249   
250    return Ray::INTERSECTION;
251  }
252 
253  // We're stuck with the Jordan curve computation.  Count number
254  // of intersections between the line segments the polygon comprises
255  // with a ray originating at the point of intersection and
256  // travelling in the positive X direction.
[170]257  for (i = 0; i < size; i++) {
[162]258    mVertices[face->mVertexIndices[i]].ExtractVerts(&u2, &v2, paxis);
259    count += (int_lineseg(u, v, u1, v1, u2, v2) != 0);
260    u1 = u2;
261    v1 = v2;
262  }
263
264  // We hit polygon if number of intersections is odd.
265  return (count & 1) ? Ray::INTERSECTION : Ray::NO_INTERSECTION;
266}
267
[349]268int
[176]269Mesh::GetRandomSurfacePoint(Vector3 &point, Vector3 &normal)
270{
271  int faceIndex = RandomValue(0, mFaces.size()-1);
272 
273  // assume the face is convex and generate a convex combination
274  //
275  Face *face = mFaces[faceIndex];
276  point = Vector3(0,0,0);
277  float sum = 0.0f;
278  for (int i = 0; i < face->mVertexIndices.size(); i++) {
279    float r = RandomValue(0,1);
280    sum += r;
281    point += mVertices[face->mVertexIndices[i]]*r;
282  }
283  point *= 1.0f/sum;
[340]284       
285        normal = GetFacePlane(faceIndex).mNormal;
[349]286
287        return faceIndex;
[176]288}
289
[162]290int
[354]291Mesh::GetRandomVisibleSurfacePoint(Vector3 &point,
292                                                                                                                                         Vector3 &normal,
293                                                                                                                                         const Vector3 &viewpoint,
294                                                                                                                                         const int maxTries
295                                                                                                                                         )
296{
[359]297  Plane3 plane;
298  int faceIndex = RandomValue(0, mFaces.size()-1);
299        int tries;
300  for (tries = 0; tries < maxTries; tries++) {
301    Face *face = mFaces[faceIndex];
302    plane = GetFacePlane(faceIndex);
303   
304    if (plane.Side(viewpoint) > 0) {
305      point = Vector3(0,0,0);
306      float sum = 0.0f;
307      // pickup a point inside this triangle
308      for (int i = 0; i < face->mVertexIndices.size(); i++) {
[354]309                                float r = RandomValue(0,1);
310                                sum += r;
311                                point += mVertices[face->mVertexIndices[i]]*r;
[359]312      }
313      point *= 1.0f/sum;
314      break;
315    }
316  }
317 
318  normal = plane.mNormal;
319  return (tries < maxTries) ? faceIndex + 1 : 0;
[354]320}
321
322
323int
[162]324MeshInstance::CastRay(
[333]325                                                                                        Ray &ray
326                                                                                        )
[162]327{
328  int res = mMesh->CastRay(ray, this);
329  return res;
330}
331
[170]332int
333MeshInstance::CastRay(
[333]334                                                                                        Ray &ray,
335                                                                                        const vector<int> &faces
336                                                                                        )
[170]337{
338  return mMesh->CastRayToSelectedFaces(ray, faces, this);
339}
[162]340
[170]341
[176]342
[349]343int
[176]344MeshInstance::GetRandomSurfacePoint(Vector3 &point, Vector3 &normal)
345{
[349]346  return mMesh->GetRandomSurfacePoint(point, normal);
[176]347}
348
[349]349int
[354]350MeshInstance::GetRandomVisibleSurfacePoint(Vector3 &point,
351                                                                                                                                                                         Vector3 &normal,
352                                                                                                                                                                         const Vector3 &viewpoint,
353                                                                                                                                                                         const int maxTries
354                                                                                                                                                                         )
355{
356        return mMesh->GetRandomVisibleSurfacePoint(point, normal, viewpoint, maxTries);
357}
358
359
360int
[176]361TransformedMeshInstance::GetRandomSurfacePoint(Vector3 &point, Vector3 &normal)
362{
[349]363  int index = mMesh->GetRandomSurfacePoint(point, normal);
[176]364  point = mWorldTransform*point;
365  normal = TransformNormal(mWorldTransform, normal);
[349]366  return index;
[176]367}
368
[162]369Plane3
370Mesh::GetFacePlane(const int faceIndex)
371{
372  Face *face = mFaces[faceIndex];
[340]373        return Plane3(mVertices[face->mVertexIndices[0]],
[333]374                                                                mVertices[face->mVertexIndices[1]],
375                                                                mVertices[face->mVertexIndices[2]]);
[162]376}
377
[340]378bool
379Mesh::ValidateFace(const int i)
380{
381        Face *face = mFaces[i];
382
383        Plane3 plane = Plane3(mVertices[face->mVertexIndices[0]],
384                                                                                                mVertices[face->mVertexIndices[1]],
385                                                                                                mVertices[face->mVertexIndices[2]]);
386       
387        if (!eq(Magnitude(plane.mNormal), 1.0f))
388                return false;
[350]389
390        return true;
[340]391}
392
393void
394Mesh::Cleanup()
395{
396        int toRemove = 0;
397        FaceContainer newFaces;
398        for (int i=0; i < mFaces.size(); i++)
399                if (ValidateFace(i)) {
400                        newFaces.push_back(mFaces[i]);
401                } else {
402                        cout<<"d";
403                        delete mFaces[i];
404                        toRemove++;
405                }
406       
407        if (toRemove) {
408                mFaces = newFaces;
409        }
410       
411        // cleanup vertices??
412}
413
[162]414int
[176]415TransformedMeshInstance::CastRay(
[333]416                                                                                                                                 Ray &ray
417                                                                                                                                 )
[162]418{
419  ray.ApplyTransform(Invert(mWorldTransform));
420  int res = mMesh->CastRay(ray, this);
421  ray.ApplyTransform(mWorldTransform);
422 
423  return res;
424}
[170]425
[209]426
[191]427void
428Mesh::AddTriangle(const Triangle3 &triangle)
429{
430  int index = mVertices.size();
431
432  for (int i=0; i < 3; i++) {
433    mVertices.push_back(triangle.mVertices[i]);
434  }
435 
436  AddFace(new Face(index + 0, index + 1, index + 2) );
437}
[209]438
439void
440Mesh::AddRectangle(const Rectangle3 &rect)
441{
442  int index = mVertices.size();
443
444  for (int i=0; i < 4; i++) {
445    mVertices.push_back(rect.mVertices[i]);
446  }
447 
448  AddFace(new Face(index + 0, index + 1, index + 2, index + 3) );
449}
Note: See TracBrowser for help on using the repository browser.