ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libgender/oct.C
(Generate patch)

Comparing libgender/oct.C (file contents):
Revision 1.4 by root, Sun Oct 3 05:10:45 2004 UTC vs.
Revision 1.87 by root, Thu Jan 6 03:09:24 2005 UTC

1#include <cstdlib> 1#include <cstdlib>
2 2
3#include <vector>
4using namespace std;
5
6#include "opengl.h"
7
3#include "oct.h" 8#include "oct.h"
9#include "view.h"
4#include "entity.h" 10#include "entity.h"
5 11
6octant world(0, 0); 12enum visibility_state { FULL, PARTIAL, OCCLUDED };
7 13
8octant::octant (octant *parent, int subindex) 14struct evis {
15 entity *e;
16 visibility_state state;
17 double last; // time of last check
18
19 void clear ()
20 {
21 last = 0.;
22 state = FULL;
23 }
24
25 evis ()
26 {
27 clear ();
28 }
29};
30
31struct oct_visibility : visibility_base
32{
33 vector<evis> vismap;
34
35 visibility_state state;
36
37 evis &get_visibility (int i, entity *e)
38 {
39 evis &evs = vismap [i];
40
41 if (evs.e != e)
42 {
43 evs.clear ();
44 evs.e = e;
45 }
46
47 return evs;
48 }
49
50 oct_visibility (octant &oct)
51 : state(FULL)
52 {
53 }
54};
55
56octant world(0, sector (0, 0, 0), MAXEXTENT);
57
58octant::octant (octant *parent, const sector &orig, uoffs extent)
9: parent(parent) 59: parent(parent)
60, orig(orig)
61, extent(extent)
10{ 62{
11 for (fill = 8; fill--; ) 63 for (fill = 8; fill--; )
12 sub[fill] = 0; 64 sub[fill] = 0;
65}
13 66
14 if (parent) 67visibility_base *octant::new_visibility ()
15 { 68{
16 extent = (parent->extent + 1) >> 1; 69 return new oct_visibility (*this);
17 orig = parent->orig; 70}
18 orig.offset (subindex, extent); 71
19 } 72void octant::clear_visibility (visibility_base *vs)
20 else 73{
21 { 74 ((oct_visibility *)vs)->vismap.clear ();
22 extent = MAXEXTENT; 75 ((oct_visibility *)vs)->state = FULL;
23 orig.x = orig.y = orig.z = SOFFS_MIN;
24 }
25} 76}
26 77
27octant::~octant () 78octant::~octant ()
28{ 79{
29 for (fill = 8; fill--; ) 80 for (fill = 8; fill--; )
30 delete sub[fill]; 81 delete sub[fill];
31} 82}
32 83
33static bool overlap (const sector &o1, uoffs ea, const sector &o2, const box &bbox) 84static bool overlap (const sector &orig, uoffs extent, const sector &a, const sector &b)
34{ 85{
35 sector a2; 86 sector size = (b - a + 1) >> 1;
87 sector center = a + size;
36 88
37 ea /= 2; 89 return abs (orig - center) <= extent + size;
38
39 a2.x = o1.x + ea;
40 a2.y = o1.y + ea;
41 a2.z = o1.z + ea;
42
43 sector b2;
44 sector eb;
45
46 b2.x = o2.x + (soffs)bbox.a.x;
47 b2.y = o2.y + (soffs)bbox.a.y;
48 b2.z = o2.z + (soffs)bbox.a.z;
49
50 eb.x = (soffs)(bbox.b.x - bbox.a.x) / 2;
51 eb.y = (soffs)(bbox.b.y - bbox.a.y) / 2;
52 eb.z = (soffs)(bbox.b.z - bbox.a.z) / 2;
53
54 b2.x += eb.x;
55 b2.y += eb.y;
56 b2.z += eb.z;
57
58 return abs (a2.x - b2.x) <= ea + eb.x
59 && abs (a2.y - b2.y) <= ea + eb.y
60 && abs (a2.z - b2.z) <= ea + eb.z;
61} 90}
62 91
63void octant::add (const sector &sec, entity_base *e) 92static sector offset (const sector &s, int subindex, uoffs extent)
64{ 93{
65 printf ("OCTANT %d,%d,%d+%d\n", orig.x, orig.y, orig.z, extent); 94 return sector (
95 s.x + (subindex & 1 ? extent : -extent),
96 s.y + (subindex & 2 ? extent : -extent),
97 s.z + (subindex & 4 ? extent : -extent)
98 );
99}
66 100
101void octant::add (entity *e)
102{
103 const sector &a = e->a;
104 const sector &b = e->b;
105
106 uoffs size = max (abs (b - a));
107
108 if (size >= extent >> 4)
109 {
67 if (overlap (orig, extent, sec, e->bbox)) 110 if (overlap (orig, extent, a, b))
68 { 111 {
69 printf ("overlap, add\n");
70 push_back (e); 112 push_back (e);
71 e->o.push_back (this); 113 e->o.push_back (this);
114 }
72 } 115 }
73 else 116 else
74 printf ("no overlap\n"); 117 {
75} 118 uoffs extent2 = extent >> 1;
76 119
120 for (int i = 8; i--; )
121 {
122 sector s = offset (orig, i, extent2);
123
124 if (overlap (s, extent2, a, b))
125 {
126 if (!sub[i])
127 {
128 sub[i] = new octant (this, s, extent2);
129 fill++;
130 }
131
132 sub[i]->add (e);
133 }
134 }
135 }
136}
137
77void octant::remove (entity_base *e) 138void octant::remove (entity *e)
78{ 139{
79} 140}
80 141
81void octant::draw (draw_context &ctx) 142bool octant::detect_visibility (view &ctx) //, bool fully_visible)
82{ 143{
83 for (iterator i = end (); i-- != begin (); ) 144 ctx.stat1++;//D
84 (*i)->try_draw (ctx);
85}
86 145
146 sector centeri = orig - ctx.orig;
147 point centerf = point (centeri);
148
149 GLfloat rad = ctx.diagfact * extent;
150
151 if (!overlap (ctx.frustum.c, sphere (centerf, rad)))
152 return false;
153
154 oct_visibility &vs = *(oct_visibility *)get_visibility (ctx);
155
156 //vs.state = FULL;//D
157
158#if 0
159 if (max (abs (centeri)) <= extent)
160 ;
161 else
162 {
163#endif
164
165 //if (distance (ctx.frustum.t, centerf) < -rad) return false;
166 //if (distance (ctx.frustum.b, centerf) < -rad) return false;
167 //if (distance (ctx.frustum.l, centerf) < -rad) return false;
168 //if (distance (ctx.frustum.r, centerf) < -rad) return false;
169 ////if (distance (ctx.frustum.n, centerf) < -rad) return false;
170
171#if 0
172 GLfloat fd = distance (ctx.frustum.f, centerf);
173
174 if (fd < -(ctx.c_far - ctx.z_far) -rad * 3.F)
175 return false;
176#endif
177
178 // very important, optimize?
179 GLfloat z = length (ctx.p - centerf) + rad;
180 if (z < 0.F || ctx.perspfact * extent / z < 10.) // very crude "too small to see" check
181 return false;
182
183#if 0
184 if (vs.state == PARTIAL || vs.state == FULL)
185 ctx.nc_far = max (ctx.nc_far, z);
186#endif
187
188 if (vs.state == OCCLUDED)
189 {
190#if 0
191 if (extent < ctx.z_far)
192 {
193#endif
194 ctx.postdepthlist.push_back (this);
195 return false;
196#if 0
197 }
198 else
199 vs.state == PARTIAL;
200#endif
201 }
202
203 bool visible = size () && vs.state == FULL;
204
205 // node to start with
206 unsigned char si = centeri.x > 0 ? 1 : 0
207 | centeri.y > 0 ? 2 : 0
208 | centeri.z > 0 ? 4 : 0;
209
210 // bit-toggle to find next child for front-to-back order
211 static unsigned char toggle[8+1]
212 = { 0, 0^1, 1^2, 2^4, 4^3, 3^5, 5^6, 6^7, 0 };
213
214 unsigned char *next = toggle;
215 do
216 {
217 si ^= *next;
218
219 if (sub[si])
220 visible = visible | sub[si]->detect_visibility (ctx);
221 }
222 while (*++next);
223
224 if (visible)
225 {
226 if (size ())
227 ctx.vislist.push_back (this);
228
229 ctx.postdepthlist.push_back (this);
230 }
231 else
232 {
233 //vs.state = OCCLUDED;
234 ctx.postdepthlist.push_back (this);
235 }
236
237 return visible;
238}
239
240void octant::draw_depth (view &ctx)
241{
242 oct_visibility &vs = *(oct_visibility *)get_visibility (ctx);
243
244 vs.vismap.resize (size ());
245
246 if (vs.state == PARTIAL || vs.state == OCCLUDED)
247 return;
248
249 for (int i = 0; i < size (); ++i)
250 {
251 entity *e = (*this)[i];
252 const evis &evs = vs.get_visibility (i, e);
253
254 if (evs.state != OCCLUDED)
255 {
256 if (!ctx.may_draw (e))
257 continue;
258
259 sector center = ((e->a + e->b) >> 1) - ctx.orig;
260 GLfloat z = length (vec3 (center));
261 ctx.pixfact = ctx.perspfact / z;
262
263 ctx.nz_far = max (ctx.nz_far, z + extent);
264 ctx.nz_near = min (ctx.nz_near, z - extent);
265
266 e->draw (ctx);
267 }
268 }
269}
270
271void octant::draw_postdepth (view &ctx)
272{
273 oct_visibility &vs = *(oct_visibility *)get_visibility (ctx);
274
275 if (vs.state == PARTIAL || vs.state == OCCLUDED)
276 {
277 ctx.begin_occ_query (*this, 0);
278 sector s = orig - ctx.orig;
279 gl::draw_bbox (s - extent, s + extent);
280 ctx.end_occ_query ();
281 }
282 else
283 {
284 int nvis = 0;
285
286 for (int i = 0; i < size (); ++i)
287 {
288 entity *e = (*this)[i];
289 const evis &evs = vs.get_visibility (i, e);
290
291 if (evs.state == OCCLUDED)
292 {
293 if (!ctx.may_draw (e))
294 continue;
295
296 ctx.begin_occ_query (*this, e);
297 gl::draw_bbox (e->a - ctx.orig, e->b - ctx.orig);
298 ctx.end_occ_query ();
299 }
300 else
301 nvis++;
302 }
303
304#if 0
305 if (nvis == 0 && size ())
306 vs.state = PARTIAL;
307#endif
308 }
309}
310
311void octant::draw_lighted (view &ctx)
312{
313 oct_visibility &vs = *(oct_visibility *)get_visibility (ctx);
314
315#if 0
316 if (vs.state == PARTIAL || vs.state == OCCLUDED)
317 {
318 sector s = orig - ctx.orig;
319 gl::draw_bbox (s - extent, s + extent);
320 printf ("DLP %p\n", this);//D
321 }
322#endif
323
324 if (vs.state == PARTIAL || vs.state == OCCLUDED)
325 return;
326
327#if 0
328 {
329 static vertex_buffer vb;
330 static index_buffer ib;
331
332 sector s = orig - ctx.orig;
333 sector a = s - extent, b = s + extent;
334
335 vertex_v3f vd[] = {
336 point (a.x, a.y, a.z),
337 point (b.x, a.y, a.z),
338 point (a.x, b.y, a.z),
339 point (b.x, b.y, a.z),
340 point (a.x, a.y, b.z),
341 point (b.x, a.y, b.z),
342 point (a.x, b.y, b.z),
343 point (b.x, b.y, b.z),
344 };
345
346 if (!ib)
347 {
348 static GLushort verts[4*6] = {
349 0, 4, 6, 2, // -x
350 1, 3, 7, 5, // +x
351 0, 1, 5, 4, // -y
352 7, 3, 2, 6, // +y
353 0, 2, 3, 1, // -z
354 4, 5, 7, 6, // +z
355 };
356
357 ib.set (verts, 4*6, GL_STATIC_DRAW_ARB);
358 }
359
360 vb.set (vd, 8, GL_STREAM_DRAW_ARB);
361 vb.bind ();
362 for (int i = 0; i < 6; i++)
363 ib.draw (GL_LINE_LOOP, i*4, 4);
364
365 }
366#endif
367
368 for (int i = 0; i < size (); ++i)
369 {
370 entity *e = (*this)[i];
371 evis &evs = vs.get_visibility (i, e);
372
373 if (evs.state != OCCLUDED)
374 {
375 if (!ctx.may_draw (e))
376 continue;
377
378 sector center = ((e->a + e->b) >> 1) - ctx.orig;
379 GLfloat z = length (vec3 (center));
380 ctx.pixfact = ctx.perspfact / z;
381
382 if (ctx.pass->type != LIGHTED
383 || !ctx.first_lighted
384 || evs.last + 1. > timer.now)
385 e->draw (ctx);
386 else
387 {
388 evs.last = timer.now;
389 ctx.begin_occ_query (*this, e);
390 e->draw (ctx);
391 ctx.end_occ_query ();
392 }
393 }
394 }
395}
396
397void octant::event (occ_query &ev)
398{
399 oct_visibility &vs = *(oct_visibility *)get_visibility (ev.ctx);
400 entity *e = (entity *)ev.id;
401
402 if (e)
403 {
404 for (vector<evis>::iterator i = vs.vismap.begin ();
405 i != vs.vismap.end ();
406 ++i)
407 if (i->e == e)
408 {
409 i->state = ev.count ? FULL : OCCLUDED;
410 return;
411 }
412 }
413 else
414 vs.state = ev.count ? (vs.state == PARTIAL ? PARTIAL : FULL) : OCCLUDED;
415}
416
417

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines