ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libgender/oct.C
Revision: 1.89
Committed: Mon Jul 18 01:40:01 2005 UTC (18 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.88: +4 -1 lines
Log Message:
*** empty log message ***

File Contents

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