Subversion Repositories gelsvn

Rev

Rev 313 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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