… | |
… | |
9 | #include "oct.h" |
9 | #include "oct.h" |
10 | #include "view.h" |
10 | #include "view.h" |
11 | #include "entity.h" |
11 | #include "entity.h" |
12 | #include "material.h" //DEBUG |
12 | #include "material.h" //DEBUG |
13 | |
13 | |
14 | enum visibility_state { |
14 | struct oct_visibility : visibility_base |
15 | PARTIAL, // surrounding the viewpoint |
15 | { |
16 | FULL, // in frustum |
16 | bool subvis, evis; |
17 | OCCLUDED, // in frustom, but occluded |
17 | int occ_res; |
18 | }; |
|
|
19 | |
|
|
20 | struct evis { |
|
|
21 | entity *e; |
|
|
22 | visibility_state state; |
|
|
23 | double next; // time of next check |
|
|
24 | |
18 | |
25 | void clear () |
19 | void clear () |
26 | { |
20 | { |
27 | next = 0.; |
21 | occ_res = -1; |
28 | state = FULL; |
22 | evis = true; |
|
|
23 | subvis = true; |
29 | } |
24 | } |
30 | |
25 | |
31 | evis () |
26 | oct_visibility (octant &oct) |
32 | { |
27 | { |
33 | clear (); |
28 | clear (); |
34 | } |
29 | } |
35 | }; |
30 | }; |
36 | |
31 | |
37 | struct oct_visibility : visibility_base |
|
|
38 | { |
|
|
39 | vector<evis> vismap; |
|
|
40 | |
|
|
41 | visibility_state state; |
|
|
42 | bool vis; |
|
|
43 | |
|
|
44 | evis &get_visibility (int i, entity *e) |
|
|
45 | { |
|
|
46 | evis &evs = vismap [i]; |
|
|
47 | |
|
|
48 | if (evs.e != e) |
|
|
49 | { |
|
|
50 | evs.clear (); |
|
|
51 | evs.e = e; |
|
|
52 | } |
|
|
53 | |
|
|
54 | return evs; |
|
|
55 | } |
|
|
56 | |
|
|
57 | oct_visibility (octant &oct) |
|
|
58 | : state (FULL), vis (true) |
|
|
59 | { |
|
|
60 | } |
|
|
61 | }; |
|
|
62 | |
|
|
63 | octant world(0, sector (0, 0, 0), MAXEXTENT); |
32 | octant world(0, sector (0, 0, 0), MAXEXTENT); |
64 | |
33 | |
65 | octant::octant (octant *parent, const sector &orig, uoffs extent) |
34 | octant::octant (octant *parent, const sector &orig, uoffs extent) |
66 | : parent(parent) |
35 | : parent(parent) |
67 | , orig(orig) |
36 | , orig(orig) |
… | |
… | |
76 | return new oct_visibility (*this); |
45 | return new oct_visibility (*this); |
77 | } |
46 | } |
78 | |
47 | |
79 | void octant::clear_visibility (visibility_base *vs) |
48 | void octant::clear_visibility (visibility_base *vs) |
80 | { |
49 | { |
81 | ((oct_visibility *)vs)->vismap.clear (); |
50 | ((oct_visibility *)vs)->clear (); |
82 | ((oct_visibility *)vs)->state = FULL; |
|
|
83 | } |
51 | } |
84 | |
52 | |
85 | octant::~octant () |
53 | octant::~octant () |
86 | { |
54 | { |
87 | for (fill = 8; fill--; ) |
55 | for (fill = 8; fill--; ) |
… | |
… | |
157 | return false; |
125 | return false; |
158 | |
126 | |
159 | oct_visibility &vs = *(oct_visibility *)get_visibility (ctx); |
127 | oct_visibility &vs = *(oct_visibility *)get_visibility (ctx); |
160 | |
128 | |
161 | if (max (centeri) < extent) |
129 | if (max (centeri) < extent) |
162 | vs.state = PARTIAL; |
130 | { |
163 | else |
131 | vs.evis = true; |
|
|
132 | vs.occ_res = -1; |
164 | { |
133 | } |
165 | if (distance (ctx.frustum.t, centerf) < -rad) return false; |
134 | else if (distance (ctx.frustum.t, centerf) < -rad |
166 | if (distance (ctx.frustum.b, centerf) < -rad) return false; |
135 | || distance (ctx.frustum.b, centerf) < -rad |
167 | if (distance (ctx.frustum.l, centerf) < -rad) return false; |
136 | || distance (ctx.frustum.l, centerf) < -rad |
168 | if (distance (ctx.frustum.r, centerf) < -rad) return false; |
137 | || distance (ctx.frustum.r, centerf) < -rad |
169 | if (distance (ctx.frustum.n, centerf) < -rad) return false; |
138 | || distance (ctx.frustum.n, centerf) < -rad) |
|
|
139 | { |
|
|
140 | vs.clear (); |
|
|
141 | return false; |
170 | } |
142 | } |
171 | |
143 | |
172 | #if 0 |
144 | #if 0 |
173 | GLfloat fd = distance (ctx.frustum.f, centerf); |
145 | GLfloat fd = distance (ctx.frustum.f, centerf); |
174 | |
146 | |
… | |
… | |
177 | #endif |
149 | #endif |
178 | |
150 | |
179 | // very important, optimize? |
151 | // very important, optimize? |
180 | GLfloat z = length (ctx.p - centerf) + rad; |
152 | GLfloat z = length (ctx.p - centerf) + rad; |
181 | if (z < 0.F || ctx.perspfact * extent / z < 10.) // very crude "too small to see" check |
153 | if (z < 0.F || ctx.perspfact * extent / z < 10.) // very crude "too small to see" check |
|
|
154 | { |
|
|
155 | vs.clear ();//D |
182 | return false; |
156 | return false; |
|
|
157 | } |
183 | |
158 | |
184 | #if 0 |
159 | #if 0 |
185 | if (vs.state == PARTIAL || vs.state == FULL) |
160 | if (vs.state == PARTIAL || vs.state == FULL) |
186 | ctx.nc_far = max (ctx.nc_far, z); |
161 | ctx.nc_far = max (ctx.nc_far, z); |
187 | #endif |
162 | #endif |
188 | |
163 | |
189 | if (vs.state == OCCLUDED) |
164 | if (vs.occ_res > 0) |
|
|
165 | { |
|
|
166 | vs.evis = true; |
|
|
167 | vs.occ_res = -1; |
|
|
168 | } |
|
|
169 | |
|
|
170 | if (!(vs.subvis || vs.evis)) |
190 | { |
171 | { |
191 | ctx.postdepthlist.push_back (this); |
172 | ctx.postdepthlist.push_back (this); |
192 | |
|
|
193 | return false; |
173 | return false; |
194 | } |
174 | } |
195 | |
175 | |
196 | //bool visible = size () && vs.state != OCCLUDED; |
|
|
197 | bool visible = false; |
176 | bool subvis = false; |
198 | |
177 | |
199 | // node to start with |
178 | // node to start with |
200 | unsigned char si = centeri.x > 0 ? 1 : 0 |
179 | unsigned char si = centeri.x > 0 ? 1 : 0 |
201 | | centeri.y > 0 ? 2 : 0 |
180 | | centeri.y > 0 ? 2 : 0 |
202 | | centeri.z > 0 ? 4 : 0; |
181 | | centeri.z > 0 ? 4 : 0; |
… | |
… | |
209 | do |
188 | do |
210 | { |
189 | { |
211 | si ^= *next; |
190 | si ^= *next; |
212 | |
191 | |
213 | if (sub[si]) |
192 | if (sub[si]) |
214 | visible = visible | sub[si]->detect_visibility (ctx); |
193 | subvis = subvis | sub[si]->detect_visibility (ctx); |
215 | } |
194 | } |
216 | while (*++next); |
195 | while (*++next); |
217 | |
196 | |
218 | if (visible) |
197 | vs.subvis = subvis; |
|
|
198 | |
|
|
199 | if (subvis) |
219 | { |
200 | { |
220 | if (size ()) |
201 | if (size ()) |
221 | { |
|
|
222 | ctx.postdepthlist.push_back (this); |
|
|
223 | if (vs.vis) |
|
|
224 | ctx.vislist.push_back (this); |
|
|
225 | } |
|
|
226 | |
|
|
227 | vs.state = FULL; |
|
|
228 | |
|
|
229 | return true; |
|
|
230 | } |
|
|
231 | else if (vs.state == OCCLUDED) |
|
|
232 | { |
|
|
233 | ctx.postdepthlist.push_back (this); |
|
|
234 | |
|
|
235 | return false; |
|
|
236 | } |
|
|
237 | else if (size()) |
|
|
238 | { |
|
|
239 | if (vs.vis) |
|
|
240 | { |
202 | { |
241 | ctx.postdepthlist.push_back (this); |
203 | ctx.postdepthlist.push_back (this); |
242 | ctx.vislist.push_back (this); |
204 | ctx.vislist.push_back (this); |
243 | } |
205 | } |
244 | else |
|
|
245 | vs.state = OCCLUDED; |
|
|
246 | |
206 | |
247 | return true; |
207 | return true; |
248 | } |
208 | } |
|
|
209 | else if (!vs.evis) |
|
|
210 | { |
|
|
211 | ctx.postdepthlist.push_back (this); |
|
|
212 | ctx.vislist.push_back (this); |
|
|
213 | |
|
|
214 | return false; |
|
|
215 | } |
249 | else |
216 | else |
250 | { |
217 | { |
251 | return vs.state != PARTIAL; |
218 | ctx.postdepthlist.push_back (this); |
|
|
219 | ctx.vislist.push_back (this); |
|
|
220 | |
|
|
221 | return true; |
252 | } |
222 | } |
253 | } |
223 | } |
254 | |
224 | |
255 | void octant::draw_depth (view &ctx) |
225 | void octant::draw_depth (view &ctx) |
256 | { |
226 | { |
257 | oct_visibility &vs = *(oct_visibility *)get_visibility (ctx); |
227 | oct_visibility &vs = *(oct_visibility *)get_visibility (ctx); |
258 | |
228 | |
259 | vs.vismap.resize (size ()); |
229 | if (!(vs.subvis || vs.evis)) |
260 | |
|
|
261 | if (vs.state == OCCLUDED) |
|
|
262 | return; |
230 | return; |
263 | |
231 | |
264 | for (int i = 0; i < size (); ++i) |
232 | for (int i = 0; i < size (); ++i) |
265 | { |
233 | { |
266 | entity *e = (*this)[i]; |
234 | entity *e = (*this)[i]; |
267 | const evis &evs = vs.get_visibility (i, e); |
|
|
268 | |
235 | |
269 | if (evs.state != OCCLUDED) |
236 | entity_visibility &evis = *(entity_visibility *)e->get_visibility (ctx); |
|
|
237 | |
|
|
238 | if (evis.occ_res) |
270 | { |
239 | { |
271 | if (!ctx.may_draw (e)) |
240 | if (!ctx.may_draw (e)) |
272 | continue; |
241 | continue; |
273 | |
242 | |
274 | sector center = ((e->a + e->b) >> 1) - ctx.orig; |
243 | sector center = ((e->a + e->b) >> 1) - ctx.orig; |
… | |
… | |
285 | |
254 | |
286 | void octant::draw_postdepth (view &ctx) |
255 | void octant::draw_postdepth (view &ctx) |
287 | { |
256 | { |
288 | oct_visibility &vs = *(oct_visibility *)get_visibility (ctx); |
257 | oct_visibility &vs = *(oct_visibility *)get_visibility (ctx); |
289 | |
258 | |
290 | if (vs.state == OCCLUDED || !vs.vis) |
259 | if (!(vs.subvis || vs.evis)) |
291 | { |
260 | { |
292 | ctx.begin_occ_query (*this, 0); |
261 | ctx.begin_occ_query (vs.occ_res); |
293 | sector s = orig - ctx.orig; |
262 | sector s = orig - ctx.orig; |
294 | gl::draw_bbox (s - extent, s + extent); |
263 | gl::draw_bbox (s - extent, s + extent); |
295 | ctx.end_occ_query (); |
264 | ctx.end_occ_query (); |
296 | } |
265 | } |
297 | else |
266 | else |
298 | { |
267 | { |
299 | vs.vis = false; |
268 | vs.evis = false; |
300 | |
269 | |
301 | for (int i = 0; i < size (); ++i) |
270 | for (int i = 0; i < size (); ++i) |
302 | { |
271 | { |
303 | entity *e = (*this)[i]; |
272 | entity *e = (*this)[i]; |
304 | const evis &evs = vs.get_visibility (i, e); |
273 | entity_visibility &evis = *(entity_visibility *)e->get_visibility (ctx); |
305 | |
274 | |
306 | if (evs.state == OCCLUDED) |
275 | if (evis.occ_res) |
|
|
276 | vs.evis = true; |
|
|
277 | else |
307 | { |
278 | { |
308 | if (!ctx.may_draw (e)) |
279 | if (!ctx.may_draw (e)) |
309 | continue; |
280 | continue; |
310 | |
281 | |
|
|
282 | ctx.stat1++; |
311 | ctx.begin_occ_query (*this, e); |
283 | ctx.begin_occ_query (evis.occ_res); |
312 | gl::draw_bbox (e->a - ctx.orig, e->b - ctx.orig); |
284 | gl::draw_bbox (e->a - ctx.orig, e->b - ctx.orig); |
313 | ctx.end_occ_query (); |
285 | ctx.end_occ_query (); |
314 | } |
286 | } |
315 | else |
|
|
316 | vs.vis = true; |
|
|
317 | } |
287 | } |
318 | } |
288 | } |
319 | } |
289 | } |
320 | |
290 | |
321 | void octant::draw_lighted (view &ctx) |
291 | void octant::draw_lighted (view &ctx) |
… | |
… | |
332 | debugmat->disable (ctx); |
302 | debugmat->disable (ctx); |
333 | //printf ("DLP %ld %ld %ld (%ld)\n", orig.x, orig.y, orig.z, extent);//D |
303 | //printf ("DLP %ld %ld %ld (%ld)\n", orig.x, orig.y, orig.z, extent);//D |
334 | } |
304 | } |
335 | #endif |
305 | #endif |
336 | |
306 | |
337 | if (vs.state == OCCLUDED) |
|
|
338 | return; |
|
|
339 | |
|
|
340 | for (int i = 0; i < size (); ++i) |
307 | for (int i = 0; i < size (); ++i) |
341 | { |
308 | { |
342 | entity *e = (*this)[i]; |
309 | entity *e = (*this)[i]; |
343 | evis &evs = vs.get_visibility (i, e); |
310 | entity_visibility &evis = *(entity_visibility *)e->get_visibility (ctx); |
344 | |
311 | |
345 | if (evs.state != OCCLUDED) |
312 | if (evis.occ_res) |
346 | { |
313 | { |
347 | if (!ctx.may_draw (e)) |
314 | if (!ctx.may_draw (e)) |
348 | continue; |
315 | continue; |
349 | |
316 | |
350 | sector center = ((e->a + e->b) >> 1) - ctx.orig; |
317 | sector center = ((e->a + e->b) >> 1) - ctx.orig; |
351 | GLfloat z = length (vec3 (center)); |
318 | GLfloat z = length (vec3 (center)); |
352 | ctx.pixfact = ctx.perspfact / z; |
319 | ctx.pixfact = ctx.perspfact / z; |
353 | |
320 | |
354 | if (!ctx.first_lighted |
321 | if (!ctx.first_lighted |
355 | || evs.next > timer.now) |
322 | || evis.next > timer.now) |
356 | e->draw (ctx); |
323 | e->draw (ctx); |
357 | else |
324 | else |
358 | { |
325 | { |
|
|
326 | ctx.stat2++;//D |
359 | evs.next = timer.now + 0.2; |
327 | evis.next = timer.now + 0.2 + 1e6; |
360 | ctx.begin_occ_query (*this, e); |
328 | ctx.begin_occ_query (evis.occ_res); |
361 | e->draw (ctx); |
329 | e->draw (ctx); |
362 | ctx.end_occ_query (); |
330 | ctx.end_occ_query (); |
363 | } |
331 | } |
364 | } |
332 | } |
365 | } |
333 | } |
366 | } |
334 | } |
367 | |
335 | |
368 | void octant::event (occ_query &ev) |
|
|
369 | { |
|
|
370 | oct_visibility &vs = *(oct_visibility *)get_visibility (ev.ctx); |
|
|
371 | entity *e = (entity *)ev.id; |
|
|
372 | |
|
|
373 | if (e) |
|
|
374 | { |
|
|
375 | #if 1 |
|
|
376 | for (vector<evis>::iterator i = vs.vismap.begin (); |
|
|
377 | i != vs.vismap.end (); |
|
|
378 | ++i) |
|
|
379 | if (i->e == e) |
|
|
380 | { |
|
|
381 | i->state = ev.count ? FULL : OCCLUDED; |
|
|
382 | return; |
|
|
383 | } |
|
|
384 | #endif |
|
|
385 | } |
|
|
386 | else |
|
|
387 | { |
|
|
388 | vs.state = ev.count ? FULL : OCCLUDED; |
|
|
389 | vs.vis = ev.count ? true : false; |
|
|
390 | } |
|
|
391 | } |
|
|
392 | |
|
|
393 | |
|
|