1 // Copyright 2003, 2004, 2005 David Hilvert <dhilvert@auricle.dyndns.org>,
2 // <dhilvert@ugcs.caltech.edu>
4 /* This file is part of the Anti-Lamenessing Engine.
6 The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with the Anti-Lamenessing Engine; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * d3/space.h: Representation of 3D space.
34 * Structure to hold a subdivisible region of space.
37 struct node
*positive
;
38 struct node
*negative
;
50 static node
*root_node
;
54 static void init_root() {
59 * Space traversal and navigation class.
68 static int get_next_split(point min
, point max
) {
69 assert(min
[0] < max
[0]);
70 assert(min
[1] < max
[1]);
71 assert(min
[2] < max
[2]);
74 * Double-infinite case.
77 for (int d
= 0; d
< 3; d
++)
78 if (isinf(max
[d
]) && isinf(min
[d
]))
82 * Finite or single-infinite case
85 if (max
[0] - min
[0] >= max
[1] - min
[1]
86 && (max
[0] >= max
[1] || !isinf(min
[1]))
87 && (min
[0] <= min
[1] || !isinf(max
[1]))
88 && max
[0] - min
[0] >= max
[2] - min
[2]
89 && (max
[0] >= max
[2] || !isinf(min
[2]))
90 && (min
[0] <= min
[2] || !isinf(max
[2])))
93 if (max
[1] - min
[1] > max
[2] - min
[2]
94 && (max
[1] >= max
[2] || !isinf(min
[2]))
95 && (min
[1] <= min
[2] || !isinf(max
[2])))
101 static ale_pos
split_coordinate(int d
, point min
, point max
) {
102 if (isinf(max
[d
]) && isinf(min
[d
]))
106 return tan((atan(min
[d
]) + M_PI
/2) / 2);
109 return tan((atan(max
[d
]) - M_PI
/2) / 2);
111 return (min
[d
] + max
[d
]) / 2;
114 static int get_next_cells(int d
, point min
, point max
, point cells
[2][2]) {
120 ale_pos split_point
= split_coordinate(d
, min
, max
);
122 if (split_point
== min
[d
]
123 || split_point
== max
[d
]
124 || !finite(split_point
))
127 cells
[0][1][d
] = split_point
;
128 cells
[1][0][d
] = split_point
;
133 int get_next_split() {
134 return get_next_split(bounds
[0], bounds
[1]);
137 ale_pos
split_coordinate(int d
) {
138 return split_coordinate(d
, bounds
[0], bounds
[1]);
141 ale_pos
split_coordinate() {
142 int next_split
= get_next_split();
143 return split_coordinate(next_split
);
146 static traverse
root() {
150 result
.current
= root_node
;
151 result
.bounds
[0] = point::neginf();
152 result
.bounds
[1] = point::posinf();
154 assert(result
.current
);
159 int precision_wall() {
160 int next_split
= get_next_split();
161 ale_pos split_point
= split_coordinate(next_split
);
163 point
&min
= bounds
[0];
164 point
&max
= bounds
[1];
166 assert(split_point
<= max
[next_split
]);
167 assert(split_point
>= min
[next_split
]);
169 if (split_point
== min
[next_split
] || split_point
== max
[next_split
])
175 traverse
positive() {
179 int next_split
= get_next_split();
181 if (current
->positive
== NULL
) {
182 current
->positive
= new node
;
187 result
.current
= current
->positive
;
188 result
.bounds
[0] = bounds
[0];
189 result
.bounds
[1] = bounds
[1];
191 result
.bounds
[0][next_split
] = split_coordinate(next_split
);
193 assert(result
.current
);
198 traverse
negative() {
202 int next_split
= get_next_split();
204 if (current
->negative
== NULL
) {
205 current
->negative
= new node
;
210 result
.current
= current
->negative
;
211 result
.bounds
[0] = bounds
[0];
212 result
.bounds
[1] = bounds
[1];
214 result
.bounds
[1][next_split
] = split_coordinate(next_split
);
216 assert(result
.current
);
221 point
get_min() const {
225 point
get_max() const {
229 const point
*get_bounds() const {
233 point
get_centroid() const {
234 return (bounds
[0] + bounds
[1]) / 2;
237 int includes(point p
) {
239 for (int d
= 0; d
< 3; d
++) {
240 if (p
[d
] > bounds
[1][d
])
242 if (p
[d
] < bounds
[0][d
])
259 * Class to iterate through subspaces based on proximity to a camera.
263 std::stack
<traverse
> node_stack
;
267 iterate(point co
, traverse top
= traverse::root()) {
269 node_stack
.push(top
);
273 if (node_stack
.empty())
276 traverse st
= node_stack
.top();
278 int d
= st
.get_next_split();
280 ale_pos split_coordinate
= st
.split_coordinate();
282 node
*n
= st
.get_node()->negative
;
283 node
*p
= st
.get_node()->positive
;
285 if (camera_origin
[d
] > split_coordinate
) {
287 node_stack
.top() = st
.negative();
289 node_stack
.push(st
.positive());
292 node_stack
.top() = st
.positive();
298 node_stack
.top() = st
.positive();
300 node_stack
.push(st
.negative());
303 node_stack
.top() = st
.negative();
309 return (!node_stack
.empty());
313 assert (!node_stack
.empty());
315 iterate
result(camera_origin
, node_stack
.top());
323 return node_stack
.empty();
327 assert (!node_stack
.empty());
328 return node_stack
.top();