… | |
… | |
7 | |
7 | |
8 | #include "oct.h" |
8 | #include "oct.h" |
9 | #include "view.h" |
9 | #include "view.h" |
10 | #include "entity.h" |
10 | #include "entity.h" |
11 | |
11 | |
12 | enum visibility_state { FULL, PARTIAL, SMALL, OCCLUDED, SUBTREE_OCCLUDED }; |
12 | enum visibility_state { FULL, PARTIAL, OCCLUDED }; |
13 | |
13 | |
14 | struct evis { |
14 | struct evis { |
15 | entity *e; |
15 | entity *e; |
16 | visibility_state state; |
16 | visibility_state state; |
17 | double last; // time of last check |
17 | double last; // time of last check |
… | |
… | |
71 | |
71 | |
72 | void octant::clear_visibility (visibility_base *vs) |
72 | void octant::clear_visibility (visibility_base *vs) |
73 | { |
73 | { |
74 | ((oct_visibility *)vs)->vismap.clear (); |
74 | ((oct_visibility *)vs)->vismap.clear (); |
75 | ((oct_visibility *)vs)->state = FULL; |
75 | ((oct_visibility *)vs)->state = FULL; |
76 | ((oct_visibility *)vs)->state = OCCLUDED;//D |
|
|
77 | } |
76 | } |
78 | |
77 | |
79 | octant::~octant () |
78 | octant::~octant () |
80 | { |
79 | { |
81 | for (fill = 8; fill--; ) |
80 | for (fill = 8; fill--; ) |
… | |
… | |
102 | void octant::add (entity *e) |
101 | void octant::add (entity *e) |
103 | { |
102 | { |
104 | const sector &a = e->a; |
103 | const sector &a = e->a; |
105 | const sector &b = e->b; |
104 | const sector &b = e->b; |
106 | |
105 | |
|
|
106 | uoffs size = max (abs (b - a)); |
|
|
107 | |
|
|
108 | if (size >= extent >> 4) |
|
|
109 | { |
107 | if (overlap (orig, extent, a, b)) |
110 | if (overlap (orig, extent, a, b)) |
108 | { |
|
|
109 | uoffs extent2 = extent >> 1; |
|
|
110 | uoffs size = max (abs (b - a)); |
|
|
111 | |
|
|
112 | if (size >= extent2) |
|
|
113 | { |
111 | { |
114 | push_back (e); |
112 | push_back (e); |
115 | e->o.push_back (this); |
113 | e->o.push_back (this); |
116 | return; |
|
|
117 | } |
114 | } |
|
|
115 | } |
|
|
116 | else |
|
|
117 | { |
|
|
118 | uoffs extent2 = extent >> 1; |
118 | |
119 | |
119 | for (int i = 8; i--; ) |
120 | for (int i = 8; i--; ) |
120 | { |
121 | { |
121 | sector s = offset (orig, i, extent2); |
122 | sector s = offset (orig, i, extent2); |
122 | |
123 | |
… | |
… | |
136 | |
137 | |
137 | void octant::remove (entity *e) |
138 | void octant::remove (entity *e) |
138 | { |
139 | { |
139 | } |
140 | } |
140 | |
141 | |
141 | bool octant::detect_visibility (view &ctx) |
142 | bool octant::detect_visibility (view &ctx) //, bool fully_visible) |
142 | { |
143 | { |
143 | ctx.stat1++;//D |
144 | ctx.stat1++;//D |
144 | |
145 | |
145 | sector centeri = orig - ctx.orig; |
146 | sector centeri = orig - ctx.orig; |
146 | point centerf = point (centeri); |
147 | point centerf = point (centeri); |
… | |
… | |
150 | if (!overlap (ctx.frustum.c, sphere (centerf, rad))) |
151 | if (!overlap (ctx.frustum.c, sphere (centerf, rad))) |
151 | return false; |
152 | return false; |
152 | |
153 | |
153 | oct_visibility &vs = *(oct_visibility *)get_visibility (ctx); |
154 | oct_visibility &vs = *(oct_visibility *)get_visibility (ctx); |
154 | |
155 | |
|
|
156 | #if 0 |
155 | if (max (abs (centeri)) <= extent) |
157 | if (max (abs (centeri)) <= extent) |
156 | vs.state = PARTIAL; |
158 | ; |
157 | else |
159 | else |
158 | { |
160 | { |
159 | if (distance (ctx.frustum.t, centerf) < -rad) return false; |
161 | if (distance (ctx.frustum.t, centerf) < -rad) return false; |
160 | if (distance (ctx.frustum.b, centerf) < -rad) return false; |
162 | if (distance (ctx.frustum.b, centerf) < -rad) return false; |
161 | if (distance (ctx.frustum.l, centerf) < -rad) return false; |
163 | if (distance (ctx.frustum.l, centerf) < -rad) return false; |
… | |
… | |
167 | |
169 | |
168 | if (fd < -(ctx.c_far - ctx.z_far) -rad * 3.F) |
170 | if (fd < -(ctx.c_far - ctx.z_far) -rad * 3.F) |
169 | return false; |
171 | return false; |
170 | #endif |
172 | #endif |
171 | } |
173 | } |
|
|
174 | #endif |
172 | |
175 | |
173 | // very important, optimize? |
176 | // very important, optimize? |
174 | GLfloat z = ctx.z_near + distance (ctx.frustum.n, centerf) + rad; |
177 | GLfloat z = ctx.z_near + distance (ctx.frustum.n, centerf) + rad; |
175 | if (ctx.perspfact * extent / z < 1.) // very crude "too small to see" check |
178 | if (ctx.perspfact * extent / z < 10.) // very crude "too small to see" check |
176 | return false; |
179 | return false; |
177 | |
180 | |
178 | #if 0 |
181 | #if 0 |
179 | if (vs.state == PARTIAL || vs.state == FULL) |
182 | if (vs.state == PARTIAL || vs.state == FULL) |
180 | ctx.nc_far = max (ctx.nc_far, z); |
183 | ctx.nc_far = max (ctx.nc_far, z); |
181 | #endif |
184 | #endif |
182 | |
185 | |
183 | if (vs.state == SUBTREE_OCCLUDED) |
186 | if (vs.state == OCCLUDED) |
184 | { |
187 | { |
185 | ctx.vislist.push_back (this); |
188 | ctx.postdepthlist.push_back (this); |
186 | return false; |
189 | return false; |
187 | } |
190 | } |
188 | |
191 | |
189 | bool visible = size () && (vs.state == PARTIAL || vs.state == FULL); |
192 | bool visible = size () && (vs.state == PARTIAL || vs.state == FULL); |
190 | |
193 | |
… | |
… | |
209 | |
212 | |
210 | if (visible) |
213 | if (visible) |
211 | { |
214 | { |
212 | if (size ()) |
215 | if (size ()) |
213 | ctx.vislist.push_back (this); |
216 | ctx.vislist.push_back (this); |
|
|
217 | |
|
|
218 | ctx.postdepthlist.push_back (this); |
214 | } |
219 | } |
215 | else |
220 | else |
216 | vs.state = SUBTREE_OCCLUDED; |
221 | vs.state = OCCLUDED; |
217 | |
222 | |
218 | return visible; |
223 | return visible; |
219 | } |
224 | } |
220 | |
225 | |
221 | void octant::draw_depth (view &ctx) |
226 | void octant::draw_depth (view &ctx) |
222 | { |
227 | { |
223 | oct_visibility &vs = *(oct_visibility *)get_visibility (ctx); |
228 | oct_visibility &vs = *(oct_visibility *)get_visibility (ctx); |
224 | |
229 | |
225 | vs.vismap.resize (size ()); |
230 | vs.vismap.resize (size ()); |
226 | |
231 | |
227 | if (vs.state == OCCLUDED || vs.state == SUBTREE_OCCLUDED) |
232 | if (vs.state == PARTIAL || vs.state == OCCLUDED) |
228 | return; |
233 | return; |
229 | |
234 | |
230 | for (int i = 0; i < size (); ++i) |
235 | for (int i = 0; i < size (); ++i) |
231 | { |
236 | { |
232 | entity *e = (*this)[i]; |
237 | entity *e = (*this)[i]; |
… | |
… | |
251 | |
256 | |
252 | void octant::draw_postdepth (view &ctx) |
257 | void octant::draw_postdepth (view &ctx) |
253 | { |
258 | { |
254 | oct_visibility &vs = *(oct_visibility *)get_visibility (ctx); |
259 | oct_visibility &vs = *(oct_visibility *)get_visibility (ctx); |
255 | |
260 | |
256 | if (vs.state == OCCLUDED || vs.state == SUBTREE_OCCLUDED) |
261 | if (vs.state == PARTIAL || vs.state == OCCLUDED) |
257 | { |
262 | { |
258 | ctx.begin_occ_query (*this, 0); |
263 | ctx.begin_occ_query (*this, 0); |
259 | sector s = orig - ctx.orig; |
264 | sector s = orig - ctx.orig; |
260 | gl::draw_bbox (s - extent, s + extent); |
265 | gl::draw_bbox (s - extent, s + extent); |
261 | ctx.end_occ_query (); |
266 | ctx.end_occ_query (); |
… | |
… | |
281 | else |
286 | else |
282 | nvis++; |
287 | nvis++; |
283 | } |
288 | } |
284 | |
289 | |
285 | if (nvis == 0 && size ()) |
290 | if (nvis == 0 && size ()) |
286 | vs.state = OCCLUDED; |
291 | vs.state = PARTIAL; |
287 | } |
292 | } |
288 | } |
293 | } |
289 | |
294 | |
290 | void octant::draw_lighted (view &ctx) |
295 | void octant::draw_lighted (view &ctx) |
291 | { |
296 | { |
292 | oct_visibility &vs = *(oct_visibility *)get_visibility (ctx); |
297 | oct_visibility &vs = *(oct_visibility *)get_visibility (ctx); |
293 | |
298 | |
294 | if (vs.state == OCCLUDED || vs.state == SUBTREE_OCCLUDED) |
299 | if (vs.state == PARTIAL || vs.state == OCCLUDED) |
295 | return; |
300 | return; |
|
|
301 | |
|
|
302 | #if 1 |
|
|
303 | { |
|
|
304 | static vertex_buffer vb; |
|
|
305 | static index_buffer ib; |
|
|
306 | |
|
|
307 | sector s = orig - ctx.orig; |
|
|
308 | sector a = s - extent, b = s + extent; |
|
|
309 | |
|
|
310 | vertex_v3f vd[] = { |
|
|
311 | point (a.x, a.y, a.z), |
|
|
312 | point (b.x, a.y, a.z), |
|
|
313 | point (a.x, b.y, a.z), |
|
|
314 | point (b.x, b.y, a.z), |
|
|
315 | point (a.x, a.y, b.z), |
|
|
316 | point (b.x, a.y, b.z), |
|
|
317 | point (a.x, b.y, b.z), |
|
|
318 | point (b.x, b.y, b.z), |
|
|
319 | }; |
|
|
320 | |
|
|
321 | if (!ib) |
|
|
322 | { |
|
|
323 | static GLushort verts[4*6] = { |
|
|
324 | 0, 4, 6, 2, // -x |
|
|
325 | 1, 3, 7, 5, // +x |
|
|
326 | 0, 1, 5, 4, // -y |
|
|
327 | 7, 3, 2, 6, // +y |
|
|
328 | 0, 2, 3, 1, // -z |
|
|
329 | 4, 5, 7, 6, // +z |
|
|
330 | }; |
|
|
331 | |
|
|
332 | ib.set (verts, 4*6, GL_STATIC_DRAW_ARB); |
|
|
333 | } |
|
|
334 | |
|
|
335 | vb.set (vd, 8, GL_STREAM_DRAW_ARB); |
|
|
336 | vb.bind (); |
|
|
337 | for (int i = 0; i < 6; i++) |
|
|
338 | ib.draw (GL_LINES, i*4, 4); |
|
|
339 | } |
|
|
340 | #endif |
296 | |
341 | |
297 | for (int i = 0; i < size (); ++i) |
342 | for (int i = 0; i < size (); ++i) |
298 | { |
343 | { |
299 | entity *e = (*this)[i]; |
344 | entity *e = (*this)[i]; |
300 | evis &evs = vs.get_visibility (i, e); |
345 | evis &evs = vs.get_visibility (i, e); |
… | |
… | |
338 | i->state = ev.count ? FULL : OCCLUDED; |
383 | i->state = ev.count ? FULL : OCCLUDED; |
339 | return; |
384 | return; |
340 | } |
385 | } |
341 | } |
386 | } |
342 | else |
387 | else |
343 | vs.state = ev.count ? FULL : OCCLUDED; |
388 | vs.state = ev.count ? (vs.state == PARTIAL ? PARTIAL : FULL) : OCCLUDED; |
344 | } |
389 | } |
345 | |
390 | |
346 | |
391 | |