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

Revision 333, 8.5 KB checked in by bittner, 19 years ago (diff)

code merge

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