Subversion Repositories gelsvn

Rev

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

Rev Author Line No. Line
61 jab 1
#ifndef __THREEDDDA_H
2
#define __THREEDDDA_H
3
 
4
#include "CGLA/Vec3f.h"
5
#include "CGLA/Vec3i.h"
6
 
7
namespace Geometry
8
{
9
 
10
 
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 
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
15
			the end point of the ray.
16
 
17
			Daniel Cohen-Or devised a technique for exact ray traversal using only 
18
			integer arithmetic. Using integer arithmetic, the computations are
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.
21
 
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.
24
			This means that we have fast and exact computations, and the ray can
25
			travel between two almost arbitrary points.
26
 
27
			A central problem with this scheme was that - in order to simplify
28
			things during the iterative traversal - the ray direction vector
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
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
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
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
37
			can make the problems go away.
38
 
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 
41
			at the CENTRES of these subcells.  
42
 
43
	*/
44
 
45
	class ThreeDDDA
46
	{
47
		/** Resolution of the grid. This number indicates how many subcells
48
				(along each axis) a cell is divided into. */
49
		const int PRECISION;
50
 
51
		/// Sign indicates which octant contains the direction vector.
52
		const CGLA::Vec3i sgn;
53
 
54
		/// Fine grid position where the ray begins
55
		const CGLA::Vec3i p0_int;
56
 
57
		// Fine grid position where the ray ends.
58
		const CGLA::Vec3i p1_int;
59
 
60
		/// The direction of the ray 
61
		const CGLA::Vec3i dir;
62
 
63
		/// The cell containing the initial point on the ray.
64
		const CGLA::Vec3i first_cell;
65
 
66
		/// The cell containing the last point on the ray.
67
		const CGLA::Vec3i last_cell;
68
 
69
		/** Number of steps. We can compute the number of steps that the
70
				ray will take in advance. */
71
		const int no_steps; 
72
 
73
		/** The direction vector, premultiplied by the step length.
74
				This constant is used to update the equations governing the
75
				traversal. */
76
		const CGLA::Vec3i dir_pre_mul;
77
 
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
80
				along the i axis multiplied by two). dir[j] is the direction vector
81
				coordinate j. */
82
 
83
		long long int disc[3][3];
84
 
85
		/** The current cell containing the ray. This value along with the 
86
				discriminators mentioned above represent the state of a ThreeDDDA. */
87
		CGLA::Vec3i cell;
88
 
89
 
90
		/** Return the position on the fine grid of a vector v. 
91
				We simply multiply by the precision and round down. Note that 
92
				it is necessary to use floor since simply clamping the value
93
				will always round toward zero.
94
		*/
95
		const CGLA::Vec3i grid_pos(const CGLA::Vec3f& v) const;
96
 
97
		/// Compute the cell containing a given fine grid position.
98
		CGLA::Vec3i get_cell(const CGLA::Vec3i& v) const;
99
 
100
		/// Mirror a fine grid position
101
		CGLA::Vec3i mirror(const CGLA::Vec3i& v) const;
102
 
103
 
104
	public:
105
 
106
		/** Create a 3DDDA based on the two end-points of the ray. An optional
107
				last argument indicates the resolution of the grid. */
108
		ThreeDDDA(const CGLA::Vec3f& p0, const CGLA::Vec3f& p1, 
109
							int _PRECISION = 0x100);
110
 
111
		/// Return the total number of steps the ray will traverse.
112
		int get_no_steps() const
113
		{
114
			return no_steps;
115
		}
116
 
117
		/// Yields the current cell containing the ray.
118
		const CGLA::Vec3i& get_current_cell() const
119
		{
120
			return cell;
121
		}
122
 
123
		/// Get the initial cell containing the ray.
124
		const CGLA::Vec3i& get_first_cell() const
125
		{
126
			return first_cell;
127
		}
128
 
129
		/// Get the last cell containing the ray.
130
		const CGLA::Vec3i& get_last_cell() const
131
		{
132
			return last_cell;
133
		}
134
 
135
		/// Get the initial point containing the ray.
136
		const CGLA::Vec3f get_first_point() const
137
		{
138
			return (CGLA::Vec3f(p0_int)+CGLA::Vec3f(0.5))/PRECISION;
139
		}
140
 
141
 
142
		/// Get the last cell containing the ray.
143
		const CGLA::Vec3f get_last_point() const
144
		{
145
			return (CGLA::Vec3f(p1_int)+CGLA::Vec3f(0.5))/PRECISION;
146
		}
147
 
148
		/// Returns true if we have reached the last cell.
149
		bool at_end() const
150
		{
151
			return cell == last_cell;
152
		}
153
 
154
		/// Take a step along the ray.
155
		void operator++()
156
		{
157
			int step_dir;
158
			if(disc[1][0] > disc[0][1])
159
				if(disc[2][0] > disc[0][2])
160
					step_dir = 0;
161
				else
162
					step_dir = 2;
163
			else
164
				if(disc[2][1] > disc[1][2])
165
					step_dir = 1;
166
				else
167
					step_dir = 2;
168
 
169
			const int k1 = (step_dir + 1) % 3;
170
			const int k2 = (step_dir + 2) % 3;
171
			cell[step_dir] += sgn[step_dir];
172
			disc[step_dir][k1] += dir_pre_mul[k1];
173
			disc[step_dir][k2] += dir_pre_mul[k2];
174
		}
175
 
176
		/// Get the initial point containing the ray.
177
			const CGLA::Vec3f step();
178
 
179
 
180
	};
181
}
182
 
183
#endif