Subversion Repositories gelsvn

Rev

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

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