Subversion Repositories gelsvn

Rev

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

Rev 61 Rev 67
1
#ifndef __THREEDDDA_H
1
#ifndef __THREEDDDA_H
2
#define __THREEDDDA_H
2
#define __THREEDDDA_H
3
 
3
 
4
#include "CGLA/Vec3f.h"
4
#include "CGLA/Vec3f.h"
5
#include "CGLA/Vec3i.h"
5
#include "CGLA/Vec3i.h"
6
 
6
 
7
namespace Geometry
7
namespace Geometry
8
{
8
{
9
 
9
 
10
 
10
 
11
	/** A ThreeDDDA is a class for traversing a grid of cells. We wish to 
11
	/** A ThreeDDDA is a class for traversing a grid of cells. We wish to 
12
			enumerate all cells pierced by the ray going from a point p0 to a 
12
			enumerate all cells pierced by the ray going from a point p0 to a 
13
			point p1. It is dangerous to use floating point arithmetic since rounding
13
			point p1. It is dangerous to use floating point arithmetic since rounding
14
			errors may accumulate entailing that the 3ddda misses the cell containing
14
			errors may accumulate entailing that the 3ddda misses the cell containing
15
			the end point of the ray.
15
			the end point of the ray.
16
		
16
		
17
			Daniel Cohen-Or devised a technique for exact ray traversal using only 
17
			Daniel Cohen-Or devised a technique for exact ray traversal using only 
18
			integer arithmetic. Using integer arithmetic, the computations are
18
			integer arithmetic. Using integer arithmetic, the computations are
19
			exact, but the ray must start and terminate exactly at grid points.
19
			exact, but the ray must start and terminate exactly at grid points.
20
			I.e. the ray must start and terminate in cell corners.
20
			I.e. the ray must start and terminate in cell corners.
21
 
21
 
22
			To overcome this issue, I have implemented a scheme where the ray
22
			To overcome this issue, I have implemented a scheme where the ray
23
			starts and terminates on a grid that is finer than the cell grid.
23
			starts and terminates on a grid that is finer than the cell grid.
24
			This means that we have fast and exact computations, and the ray can
24
			This means that we have fast and exact computations, and the ray can
25
			travel between two almost arbitrary points.
25
			travel between two almost arbitrary points.
26
 
26
 
27
			A central problem with this scheme was that - in order to simplify
27
			A central problem with this scheme was that - in order to simplify
28
			things during the iterative traversal - the ray direction vector
28
			things during the iterative traversal - the ray direction vector
29
			is always mirrored into the first octant (+x +y +z).  If the fine
29
			is always mirrored into the first octant (+x +y +z).  If the fine
30
			grid used for the ray start and end points is a superset of the
30
			grid used for the ray start and end points is a superset of the
31
			grid points of the cell grid, this mirroring is almost impossible
31
			grid points of the cell grid, this mirroring is almost impossible
32
			to implement correctly. This is due to the fact that the first
32
			to implement correctly. This is due to the fact that the first
33
			cell on the right side of the y axis is called 0,y whereas the
33
			cell on the right side of the y axis is called 0,y whereas the
34
			first cell on the left is called -1,y. This lack of symmetry makes
34
			first cell on the left is called -1,y. This lack of symmetry makes
35
			things very difficult, but by ensuring that the endpoints of a ray
35
			things very difficult, but by ensuring that the endpoints of a ray
36
			can never lie on an a corner, edge, or face of the cell grid, we
36
			can never lie on an a corner, edge, or face of the cell grid, we
37
			can make the problems go away.
37
			can make the problems go away.
38
 
38
 
39
			Hence, in this implementation, the fine grid is obtained by dividing 
39
			Hence, in this implementation, the fine grid is obtained by dividing 
40
			the cell into NxNxN subcells, but the grid points	of the fine grid lie 
40
			the cell into NxNxN subcells, but the grid points	of the fine grid lie 
41
			at the CENTRES of these subcells.  
41
			at the CENTRES of these subcells.  
42
		
42
		
43
	*/
43
	*/
44
 
44
 
45
	class ThreeDDDA
45
	class ThreeDDDA
46
	{
46
	{
47
		/** Resolution of the grid. This number indicates how many subcells
47
		/** Resolution of the grid. This number indicates how many subcells
48
				(along each axis) a cell is divided into. */
48
				(along each axis) a cell is divided into. */
49
		const int PRECISION;
49
		const int PRECISION;
50
 
50
 
51
		/// Sign indicates which octant contains the direction vector.
51
		/// Sign indicates which octant contains the direction vector.
52
		const CGLA::Vec3i sgn;
52
		const CGLA::Vec3i sgn;
53
 
53
 
54
		/// Fine grid position where the ray begins
54
		/// Fine grid position where the ray begins
55
		const CGLA::Vec3i p0_int;
55
		const CGLA::Vec3i p0_int;
56
 
56
 
57
		// Fine grid position where the ray ends.
57
		// Fine grid position where the ray ends.
58
		const CGLA::Vec3i p1_int;
58
		const CGLA::Vec3i p1_int;
59
 
59
 
60
		/// The direction of the ray 
60
		/// The direction of the ray 
61
		const CGLA::Vec3i dir;
61
		const CGLA::Vec3i dir;
62
 
62
 
63
		/// The cell containing the initial point on the ray.
63
		/// The cell containing the initial point on the ray.
64
		const CGLA::Vec3i first_cell;
64
		const CGLA::Vec3i first_cell;
65
 
65
 
66
		/// The cell containing the last point on the ray.
66
		/// The cell containing the last point on the ray.
67
		const CGLA::Vec3i last_cell;
67
		const CGLA::Vec3i last_cell;
68
 
68
 
69
		/** Number of steps. We can compute the number of steps that the
69
		/** Number of steps. We can compute the number of steps that the
70
				ray will take in advance. */
70
				ray will take in advance. */
71
		const int no_steps; 
71
		const int no_steps; 
72
 
72
 
73
		/** The direction vector, premultiplied by the step length.
73
		/** The direction vector, premultiplied by the step length.
74
				This constant is used to update the equations governing the
74
				This constant is used to update the equations governing the
75
				traversal. */
75
				traversal. */
76
		const CGLA::Vec3i dir_pre_mul;
76
		const CGLA::Vec3i dir_pre_mul;
77
 
77
 
78
		/** Discriminators. These values are delta[i]*dir[j] where delta[i]
78
		/** Discriminators. These values are delta[i]*dir[j] where delta[i]
79
				is the distance from the origin of the ray to the current position
79
				is the distance from the origin of the ray to the current position
80
				along the i axis multiplied by two). dir[j] is the direction vector
80
				along the i axis multiplied by two). dir[j] is the direction vector
81
				coordinate j. */
81
				coordinate j. */
82
	
82
	
83
		long long int disc[3][3];
83
		long long int disc[3][3];
84
 
84
 
85
		/** The current cell containing the ray. This value along with the 
85
		/** The current cell containing the ray. This value along with the 
86
				discriminators mentioned above represent the state of a ThreeDDDA. */
86
				discriminators mentioned above represent the state of a ThreeDDDA. */
87
		CGLA::Vec3i cell;
87
		CGLA::Vec3i cell;
88
 
88
 
89
 
89
 
90
		/** Return the position on the fine grid of a vector v. 
90
		/** Return the position on the fine grid of a vector v. 
91
				We simply multiply by the precision and round down. Note that 
91
				We simply multiply by the precision and round down. Note that 
92
				it is necessary to use floor since simply clamping the value
92
				it is necessary to use floor since simply clamping the value
93
				will always round toward zero.
93
				will always round toward zero.
94
		*/
94
		*/
95
		const CGLA::Vec3i grid_pos(const CGLA::Vec3f& v) const;
95
		const CGLA::Vec3i grid_pos(const CGLA::Vec3f& v) const;
96
	
96
	
97
		/// Compute the cell containing a given fine grid position.
97
		/// Compute the cell containing a given fine grid position.
98
		CGLA::Vec3i get_cell(const CGLA::Vec3i& v) const;
98
		CGLA::Vec3i get_cell(const CGLA::Vec3i& v) const;
99
	
99
	
100
		/// Mirror a fine grid position
100
		/// Mirror a fine grid position
101
		CGLA::Vec3i mirror(const CGLA::Vec3i& v) const;
101
		CGLA::Vec3i mirror(const CGLA::Vec3i& v) const;
102
 
102
 
103
 
103
 
104
	public:
104
	public:
105
 
105
 
106
		/** Create a 3DDDA based on the two end-points of the ray. An optional
106
		/** Create a 3DDDA based on the two end-points of the ray. An optional
107
				last argument indicates the resolution of the grid. */
107
				last argument indicates the resolution of the grid. */
108
		ThreeDDDA(const CGLA::Vec3f& p0, const CGLA::Vec3f& p1, 
108
		ThreeDDDA(const CGLA::Vec3f& p0, const CGLA::Vec3f& p1, 
109
							int _PRECISION = 0x100);
109
							int _PRECISION = 0x100);
110
	
110
	
111
		/// Return the total number of steps the ray will traverse.
111
		/// Return the total number of steps the ray will traverse.
112
		int get_no_steps() const
112
		int get_no_steps() const
113
		{
113
		{
114
			return no_steps;
114
			return no_steps;
115
		}
115
		}
116
 
116
 
117
		/// Yields the current cell containing the ray.
117
		/// Yields the current cell containing the ray.
118
		const CGLA::Vec3i& get_current_cell() const
118
		const CGLA::Vec3i& get_current_cell() const
119
		{
119
		{
120
			return cell;
120
			return cell;
121
		}
121
		}
122
 
122
 
123
		/// Get the initial cell containing the ray.
123
		/// Get the initial cell containing the ray.
124
		const CGLA::Vec3i& get_first_cell() const
124
		const CGLA::Vec3i& get_first_cell() const
125
		{
125
		{
126
			return first_cell;
126
			return first_cell;
127
		}
127
		}
128
 
128
 
129
		/// Get the last cell containing the ray.
129
		/// Get the last cell containing the ray.
130
		const CGLA::Vec3i& get_last_cell() const
130
		const CGLA::Vec3i& get_last_cell() const
131
		{
131
		{
132
			return last_cell;
132
			return last_cell;
133
		}
133
		}
134
 
134
 
135
		/// Get the initial point containing the ray.
135
		/// Get the initial point containing the ray.
136
		const CGLA::Vec3f get_first_point() const
136
		const CGLA::Vec3f get_first_point() const
137
		{
137
		{
138
			return (CGLA::Vec3f(p0_int)+CGLA::Vec3f(0.5))/PRECISION;
138
			return (CGLA::Vec3f(p0_int)+CGLA::Vec3f(0.5))/PRECISION;
139
		}
139
		}
140
 
140
 
141
 
141
 
142
		/// Get the last cell containing the ray.
142
		/// Get the last cell containing the ray.
143
		const CGLA::Vec3f get_last_point() const
143
		const CGLA::Vec3f get_last_point() const
144
		{
144
		{
145
			return (CGLA::Vec3f(p1_int)+CGLA::Vec3f(0.5))/PRECISION;
145
			return (CGLA::Vec3f(p1_int)+CGLA::Vec3f(0.5))/PRECISION;
146
		}
146
		}
147
	
147
	
148
		/// Returns true if we have reached the last cell.
148
		/// Returns true if we have reached the last cell.
149
		bool at_end() const
149
		bool at_end() const
150
		{
150
		{
151
			return cell == last_cell;
151
			return cell == last_cell;
152
		}
152
		}
153
 
153
 
154
		/// Take a step along the ray.
154
		/// Take a step along the ray.
155
		void operator++()
155
		void operator++()
156
		{
156
		{
157
			int step_dir;
157
			int step_dir;
158
			if(disc[1][0] > disc[0][1])
158
			if(disc[1][0] > disc[0][1])
159
				if(disc[2][0] > disc[0][2])
159
				if(disc[2][0] > disc[0][2])
160
					step_dir = 0;
160
					step_dir = 0;
161
				else
161
				else
162
					step_dir = 2;
162
					step_dir = 2;
163
			else
163
			else
164
				if(disc[2][1] > disc[1][2])
164
				if(disc[2][1] > disc[1][2])
165
					step_dir = 1;
165
					step_dir = 1;
166
				else
166
				else
167
					step_dir = 2;
167
					step_dir = 2;
168
				
168
				
169
			const int k1 = (step_dir + 1) % 3;
169
			const int k1 = (step_dir + 1) % 3;
170
			const int k2 = (step_dir + 2) % 3;
170
			const int k2 = (step_dir + 2) % 3;
171
			cell[step_dir] += sgn[step_dir];
171
			cell[step_dir] += sgn[step_dir];
172
			disc[step_dir][k1] += dir_pre_mul[k1];
172
			disc[step_dir][k1] += dir_pre_mul[k1];
173
			disc[step_dir][k2] += dir_pre_mul[k2];
173
			disc[step_dir][k2] += dir_pre_mul[k2];
174
		}
174
		}
175
 
175
 
176
		/// Get the initial point containing the ray.
176
		/// Get the initial point containing the ray.
177
			const CGLA::Vec3f step();
177
			const CGLA::Vec3f step();
178
 
178
 
179
 
179
 
180
	};
180
	};
181
}
181
}
182
 
182
 
183
#endif
183
#endif
184
 
184