Subversion Repositories gelsvn

Rev

Rev 290 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
208 jrf 1
#pragma warning (disable: 4786)
2
// Created by Bent Dalgaard Larsen, Nov, 2003
3
 
4
#include "Ray.h"
5
#include "BBox.h"
6
 
7
using namespace std;
8
using namespace CGLA;
9
using namespace BRender;
10
 
11
#define my_min(x,y) (x<y?x:y)
12
#define my_max(x,y) (x>y?x:y)
13
 
14
namespace TriMeshTrace 
15
{
16
  void BBox::intersect_min_max(Ray &ray, double &t_min, double &t_max) const 
17
  {
18
    double tx1 = (min_corner[0]-ray.origin[0])/ray.direction[0];
19
    double ty1 = (min_corner[1]-ray.origin[1])/ray.direction[1];
20
    double tz1 = (min_corner[2]-ray.origin[2])/ray.direction[2];
21
 
22
    double tx2 = (max_corner[0]-ray.origin[0])/ray.direction[0];
23
    double ty2 = (max_corner[1]-ray.origin[1])/ray.direction[1];
24
    double tz2 = (max_corner[2]-ray.origin[2])/ray.direction[2];
25
 
26
    t_min = my_max(my_min(tx1, tx2), my_max(my_min(ty1, ty2), my_min(tz1,tz2)));
27
    t_max = my_min(my_max(tx1, tx2), my_min(my_max(ty1, ty2), my_max(tz1,tz2)));
28
  }
29
 
30
  bool BBox::intersect(Ray &ray) 
31
  {
32
    double t_min, t_max;
33
    intersect_min_max(ray, t_min, t_max);
34
 
35
    if(t_min <= t_max && t_min < ray.dist && t_min > f_eps) 
36
      return true;
37
    else
38
      return false;
39
  }
40
 
41
  bool BBox::ray_triangle(Vec3f &ray_start, Vec3f &ray_end, ISectTri &tri) 
42
  {
43
    Vec3f origin = ray_start;
44
    Vec3f direction = ray_end - ray_start;
45
    double dist = direction.length();
46
    direction.normalize();
47
 
48
    Vec3f p;
49
    Vec3f q;
50
    Vec3f s;
51
    double a, f, u, v, t;
52
 
53
    p = cross(direction, Vec3f(tri.edge1));
54
    a = dot(Vec3f(tri.edge0),p);
55
    if (a>-f_eps && a<f_eps)
56
      return false;
57
    f = 1/a;
58
    s = origin - Vec3f(tri.point0);
59
    u = f*dot(s,p);
60
    if (u<0.0 || u>1.0)
61
      return false;
62
    q = cross(s, Vec3f(tri.edge0));
63
    v = f * dot(direction, q);  
64
    if (v<0.0 || u+v>1.0)
65
      return false;
66
    t = f*dot(Vec3f(tri.edge1), q);
67
    if (t<0)
68
      return false;
69
//	if (t<eps)
70
//		return false;
71
    if (t>dist)
72
      return false;
73
 
74
    return true;
75
  }
76
 
77
 
78
  bool BBox::intersect_edge_box(Vec3f &ray_start, Vec3f &ray_end) 
79
  {
80
    Ray test_ray;
81
    test_ray.origin = ray_start;
82
    test_ray.direction = ray_end - ray_start;
83
    test_ray.dist = test_ray.direction.length();
84
    test_ray.direction.normalize();
85
    return intersect(test_ray);
86
  }
87
 
88
  bool BBox::in_interval(double min_limit, double test_value, double max_limit) 
89
  {
90
    if (min_limit<=test_value && test_value<=max_limit)
91
      return true;
92
    return false;
93
  }
94
/*
95
 
96
bool BBox::intersect_triangle_left(ISectTri &tri, double plane, int axis) {
97
	if (tri.point0[axis]<=plane)
98
		return true;
99
	if (tri.point1[axis]<=plane)
100
		return true;
101
	if (tri.point2[axis]<=plane)
102
		return true;
103
	return false;
104
}
105
 
106
bool BBox::intersect_triangle_right(ISectTri &tri, double plane, int axis) {
107
	if (tri.point0[axis]>=plane)
108
		return true;
109
	if (tri.point1[axis]>=plane)
110
		return true;
111
	if (tri.point2[axis]>=plane)
112
		return true;
113
	return false;
114
}
115
*/
116
  bool BBox::intersect_triangle(ISectTri &tri) 
117
  {
118
    Vec3f tmin_corner = min_corner - Vec3f(0.01f,0.01f,0.01f);
119
    Vec3f tmax_corner = max_corner + Vec3f(0.01f,0.01f,0.01f);
120
 
121
    // Vertex in box test:
122
    // If any of the triangle vertices are inside the box then 
123
    // the triangle intersects the box
124
    if (in_interval(tmin_corner[0],tri.point0[0],tmax_corner[0]) && in_interval(tmin_corner[1],tri.point0[1],tmax_corner[1]) && in_interval(tmin_corner[2],tri.point0[2],tmax_corner[2]))
125
      return true;
126
    if (in_interval(tmin_corner[0],tri.point1[0],tmax_corner[0]) && in_interval(tmin_corner[1],tri.point1[1],tmax_corner[1]) && in_interval(tmin_corner[2],tri.point1[2],tmax_corner[2]))
127
      return true;
128
    if (in_interval(tmin_corner[0],tri.point2[0],tmax_corner[0]) && in_interval(tmin_corner[1],tri.point2[1],tmax_corner[1]) && in_interval(tmin_corner[2],tri.point2[2],tmax_corner[2]))
129
      return true;
130
 
131
    // Triangle outside box test:
132
    // If all of the triangle vertices are outside one of the planes 
133
    // defining the sides of the box then the triangle can be trivially
134
    // rejected as outside
135
    int i;
136
    for(i=0;i<3;i++)
137
      if (tri.point0[i]<tmin_corner[i] && tri.point1[i]<tmin_corner[i] && tri.point2[i]<tmin_corner[i])
138
	return false;
139
 
140
    for(i=0;i<3;i++)
141
      if (tri.point0[i]>tmax_corner[i] && tri.point1[i]>tmax_corner[i] && tri.point2[i]>tmax_corner[i])
142
	return false;
143
 
144
    // Triangle edges - box intersection test
145
    if (intersect_edge_box(Vec3f(tri.point0), Vec3f(tri.point1)))
146
      return true;
147
 
148
    if (intersect_edge_box(Vec3f(tri.point1), Vec3f(tri.point2)))
149
      return true;
150
 
151
    if (intersect_edge_box(Vec3f(tri.point2), Vec3f(tri.point0)))
152
      return true;
153
 
154
    // Box diagonal - triangle intersection test, 4 tests in total
155
    Vec3f corner0;
156
    Vec3f corner1;
157
 
158
    Vec3f tmin_corner_e = tmin_corner;
159
    Vec3f tmax_corner_e = tmax_corner;
160
 
161
    corner0.set(tmin_corner_e[0],tmin_corner_e[1],tmin_corner_e[2]);
162
    corner1.set(tmax_corner_e[0],tmax_corner_e[1],tmax_corner_e[2]);
163
    if (ray_triangle(corner0, corner1, tri))
164
      return true;
165
 
166
    corner0.set(tmax_corner_e[0],tmin_corner_e[1],tmin_corner_e[2]);
167
    corner1.set(tmin_corner_e[0],tmax_corner_e[1],tmax_corner_e[2]);
168
    if (ray_triangle(corner0, corner1, tri))
169
      return true;
170
 
171
    corner0.set(tmin_corner_e[0],tmax_corner_e[1],tmin_corner_e[2]);
172
    corner1.set(tmax_corner_e[0],tmin_corner_e[1],tmax_corner_e[2]);
173
    if (ray_triangle(corner0, corner1, tri))
174
      return true;
175
 
176
    corner0.set(tmin_corner_e[0],tmin_corner_e[1],tmax_corner_e[2]);
177
    corner1.set(tmax_corner_e[0],tmax_corner_e[1],tmin_corner_e[2]);
178
    if (ray_triangle(corner0, corner1, tri))
179
      return true;
180
 
181
    // None succeded 
182
    return false;
183
  }
184
 
185
  void BBox::compute_bbox(vector<ISectTri> &isectmesh) 
186
  {
187
    min_corner.set(CGLA::BIG,CGLA::BIG,CGLA::BIG);
188
    max_corner.set(-CGLA::BIG,-CGLA::BIG,-CGLA::BIG);
189
 
190
    for(unsigned int i=0;i<isectmesh.size(); ++i) 
191
    {
192
      const ISectTri& tri = isectmesh[i];
193
      for(int j=0;j<3;j++) {
194
	if (min_corner[j]>tri.point0[j])
195
	  min_corner[j]=tri.point0[j];
196
	if (min_corner[j]>tri.point1[j])
197
	  min_corner[j]=tri.point1[j];
198
	if (min_corner[j]>tri.point2[j])
199
	  min_corner[j]=tri.point2[j];
200
	if (max_corner[j]<tri.point0[j])
201
	  max_corner[j]=tri.point0[j];
202
	if (max_corner[j]<tri.point1[j])
203
	  max_corner[j]=tri.point1[j];
204
	if (max_corner[j]<tri.point2[j])
205
	  max_corner[j]=tri.point2[j];
206
      }
207
    }
208
  }
209
 
210
  double BBox::area() 
211
  {
212
    Vec3f size = max_corner - min_corner;
213
    return size[0]*size[1]*2 + 
214
      size[1]*size[2]*2 + 
215
      size[0]*size[2]*2; 
216
  }
217
}