ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libgender/oct.C
Revision: 1.96
Committed: Thu Aug 11 23:26:24 2005 UTC (18 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.95: +1 -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 root 1.91
5 root 1.8 using namespace std;
6    
7 root 1.48 #include "opengl.h"
8 root 1.8
9 root 1.1 #include "oct.h"
10 root 1.8 #include "view.h"
11 root 1.2 #include "entity.h"
12 root 1.89 #include "material.h" //DEBUG
13 root 1.2
14 root 1.52 struct oct_visibility : visibility_base
15     {
16 root 1.93 bool subvis, evis;
17     int occ_res;
18 root 1.52
19 root 1.93 void clear ()
20 root 1.79 {
21 root 1.93 occ_res = -1;
22     evis = true;
23     subvis = true;
24 root 1.79 }
25    
26 root 1.52 oct_visibility (octant &oct)
27     {
28 root 1.93 clear ();
29 root 1.52 }
30     };
31    
32 root 1.75 octant world(0, sector (0, 0, 0), MAXEXTENT);
33 root 1.8
34     octant::octant (octant *parent, const sector &orig, uoffs extent)
35 root 1.54 : parent(parent)
36     , orig(orig)
37     , extent(extent)
38 root 1.8 {
39     for (fill = 8; fill--; )
40     sub[fill] = 0;
41 root 1.2 }
42    
43 root 1.53 visibility_base *octant::new_visibility ()
44     {
45     return new oct_visibility (*this);
46     }
47    
48     void octant::clear_visibility (visibility_base *vs)
49     {
50 root 1.93 ((oct_visibility *)vs)->clear ();
51 root 1.53 }
52 root 1.65
53 root 1.2 octant::~octant ()
54     {
55     for (fill = 8; fill--; )
56     delete sub[fill];
57     }
58    
59 root 1.75 static bool overlap (const sector &orig, uoffs extent, const sector &a, const sector &b)
60 root 1.4 {
61 root 1.75 sector size = (b - a + 1) >> 1;
62     sector center = a + size;
63 root 1.4
64 root 1.75 return abs (orig - center) <= extent + size;
65     }
66 root 1.33
67 root 1.75 static sector offset (const sector &s, int subindex, uoffs extent)
68     {
69     return sector (
70     s.x + (subindex & 1 ? extent : -extent),
71     s.y + (subindex & 2 ? extent : -extent),
72     s.z + (subindex & 4 ? extent : -extent)
73     );
74 root 1.4 }
75    
76 root 1.32 void octant::add (entity *e)
77 root 1.2 {
78 root 1.32 const sector &a = e->a;
79     const sector &b = e->b;
80 root 1.7
81 root 1.80 uoffs size = max (abs (b - a));
82    
83     if (size >= extent >> 4)
84 root 1.4 {
85 root 1.80 if (overlap (orig, extent, a, b))
86 root 1.8 {
87     push_back (e);
88     e->o.push_back (this);
89     }
90 root 1.80 }
91     else
92     {
93     uoffs extent2 = extent >> 1;
94 root 1.5
95 root 1.8 for (int i = 8; i--; )
96 root 1.5 {
97 root 1.75 sector s = offset (orig, i, extent2);
98 root 1.32
99     if (overlap (s, extent2, a, b))
100 root 1.5 {
101 root 1.8 if (!sub[i])
102 root 1.50 {
103     sub[i] = new octant (this, s, extent2);
104     fill++;
105     }
106 root 1.8
107     sub[i]->add (e);
108 root 1.5 }
109 root 1.8 }
110 root 1.4 }
111 root 1.2 }
112 root 1.1
113 root 1.32 void octant::remove (entity *e)
114 root 1.1 {
115     }
116    
117 root 1.80 bool octant::detect_visibility (view &ctx) //, bool fully_visible)
118 root 1.1 {
119 root 1.75 sector centeri = orig - ctx.orig;
120     point centerf = point (centeri);
121 root 1.51
122 root 1.75 GLfloat rad = ctx.diagfact * extent;
123 root 1.43
124 root 1.59 if (!overlap (ctx.frustum.c, sphere (centerf, rad)))
125     return false;
126 root 1.65
127     oct_visibility &vs = *(oct_visibility *)get_visibility (ctx);
128 root 1.59
129 root 1.90 if (max (centeri) < extent)
130 root 1.10 {
131 root 1.93 vs.evis = true;
132     vs.occ_res = -1;
133     }
134     else if (distance (ctx.frustum.t, centerf) < -rad
135     || distance (ctx.frustum.b, centerf) < -rad
136     || distance (ctx.frustum.l, centerf) < -rad
137     || distance (ctx.frustum.r, centerf) < -rad
138     || distance (ctx.frustum.n, centerf) < -rad)
139     {
140     vs.clear ();
141     return false;
142 root 1.90 }
143 root 1.25
144 root 1.59 #if 0
145 root 1.91 GLfloat fd = distance (ctx.frustum.f, centerf);
146 root 1.25
147 root 1.91 if (fd < -(ctx.c_far - ctx.z_far) -rad * 3.F)
148     return false;
149 root 1.80 #endif
150 root 1.8
151 root 1.75 // very important, optimize?
152 root 1.85 GLfloat z = length (ctx.p - centerf) + rad;
153 root 1.86 if (z < 0.F || ctx.perspfact * extent / z < 10.) // very crude "too small to see" check
154 root 1.93 {
155     vs.clear ();//D
156     return false;
157     }
158 root 1.45
159 root 1.59 #if 0
160 root 1.56 if (vs.state == PARTIAL || vs.state == FULL)
161 root 1.45 ctx.nc_far = max (ctx.nc_far, z);
162 root 1.59 #endif
163 root 1.45
164 root 1.93 if (vs.occ_res > 0)
165 root 1.95 vs.evis = true;
166 root 1.94 else if (!(vs.subvis || vs.evis))
167 root 1.93 {
168 root 1.94 ctx.postdepthlist.push_back (this);
169     return false;
170 root 1.93 }
171 root 1.72
172 root 1.93 bool subvis = false;
173 root 1.74
174 root 1.51 // node to start with
175     unsigned char si = centeri.x > 0 ? 1 : 0
176     | centeri.y > 0 ? 2 : 0
177     | centeri.z > 0 ? 4 : 0;
178 root 1.19
179     // bit-toggle to find next child for front-to-back order
180 root 1.50 static unsigned char toggle[8+1]
181 root 1.51 = { 0, 0^1, 1^2, 2^4, 4^3, 3^5, 5^6, 6^7, 0 };
182 root 1.19
183 root 1.50 unsigned char *next = toggle;
184     do
185 root 1.19 {
186 root 1.51 si ^= *next;
187 root 1.19
188     if (sub[si])
189 root 1.93 subvis = subvis | sub[si]->detect_visibility (ctx);
190 root 1.19 }
191 root 1.51 while (*++next);
192    
193 root 1.93 vs.subvis = subvis;
194    
195     if (subvis)
196 root 1.71 {
197     if (size ())
198 root 1.91 {
199     ctx.postdepthlist.push_back (this);
200 root 1.93 ctx.vislist.push_back (this);
201 root 1.91 }
202    
203     return true;
204     }
205 root 1.93 else
206 root 1.81 {
207 root 1.93 ctx.postdepthlist.push_back (this);
208     ctx.vislist.push_back (this);
209 root 1.91
210 root 1.96 return vs.evis && vs.occ_res;
211 root 1.91 }
212 root 1.19 }
213    
214 root 1.75 void octant::draw_depth (view &ctx)
215 root 1.19 {
216 root 1.54 oct_visibility &vs = *(oct_visibility *)get_visibility (ctx);
217 root 1.8
218 root 1.95 if (!vs.occ_res)
219 root 1.75 return;
220    
221 root 1.79 for (int i = 0; i < size (); ++i)
222 root 1.50 {
223 root 1.79 entity *e = (*this)[i];
224 root 1.75
225 root 1.93 entity_visibility &evis = *(entity_visibility *)e->get_visibility (ctx);
226    
227     if (evis.occ_res)
228 root 1.54 {
229 root 1.75 if (!ctx.may_draw (e))
230     continue;
231    
232     sector center = ((e->a + e->b) >> 1) - ctx.orig;
233     GLfloat z = length (vec3 (center));
234     ctx.pixfact = ctx.perspfact / z;
235    
236     ctx.nz_far = max (ctx.nz_far, z + extent);
237     ctx.nz_near = min (ctx.nz_near, z - extent);
238    
239     e->draw (ctx);
240 root 1.56 }
241     }
242 root 1.75 }
243    
244     void octant::draw_postdepth (view &ctx)
245     {
246     oct_visibility &vs = *(oct_visibility *)get_visibility (ctx);
247    
248 root 1.94 if (!vs.evis)
249 root 1.75 {
250 root 1.93 ctx.begin_occ_query (vs.occ_res);
251 root 1.75 sector s = orig - ctx.orig;
252     gl::draw_bbox (s - extent, s + extent);
253     ctx.end_occ_query ();
254     }
255 root 1.56 else
256     {
257 root 1.93 vs.evis = false;
258 root 1.64
259 root 1.79 for (int i = 0; i < size (); ++i)
260 root 1.56 {
261 root 1.79 entity *e = (*this)[i];
262 root 1.93 entity_visibility &evis = *(entity_visibility *)e->get_visibility (ctx);
263 root 1.56
264 root 1.93 if (evis.occ_res)
265     vs.evis = true;
266     else
267 root 1.56 {
268 root 1.75 if (!ctx.may_draw (e))
269     continue;
270    
271 root 1.93 ctx.stat1++;
272     ctx.begin_occ_query (evis.occ_res);
273 root 1.75 gl::draw_bbox (e->a - ctx.orig, e->b - ctx.orig);
274     ctx.end_occ_query ();
275 root 1.56 }
276 root 1.75 }
277     }
278     }
279    
280     void octant::draw_lighted (view &ctx)
281     {
282     oct_visibility &vs = *(oct_visibility *)get_visibility (ctx);
283    
284 root 1.95 if (!vs.occ_res)
285     return;
286    
287 root 1.90 #if 0
288     if (vs.state == FULL || vs.state == OCCLUDED)
289 root 1.87 {
290 root 1.90 sector s = orig - ctx.orig;
291     debugmat->enable (ctx);
292     if (max (s) >= extent)
293     gl::draw_bbox (s - extent, s + extent);
294     debugmat->disable (ctx);
295     //printf ("DLP %ld %ld %ld (%ld)\n", orig.x, orig.y, orig.z, extent);//D
296 root 1.87 }
297     #endif
298    
299 root 1.79 for (int i = 0; i < size (); ++i)
300 root 1.75 {
301 root 1.79 entity *e = (*this)[i];
302 root 1.93 entity_visibility &evis = *(entity_visibility *)e->get_visibility (ctx);
303 root 1.75
304 root 1.93 if (evis.occ_res)
305 root 1.75 {
306 root 1.66 if (!ctx.may_draw (e))
307     continue;
308    
309 root 1.75 sector center = ((e->a + e->b) >> 1) - ctx.orig;
310     GLfloat z = length (vec3 (center));
311     ctx.pixfact = ctx.perspfact / z;
312    
313 root 1.91 if (!ctx.first_lighted
314 root 1.93 || evis.next > timer.now)
315 root 1.75 e->draw (ctx);
316     else
317     {
318 root 1.94 evis.next = timer.now + 0.2;
319 root 1.93 ctx.begin_occ_query (evis.occ_res);
320 root 1.75 e->draw (ctx);
321     ctx.end_occ_query ();
322 root 1.56 }
323 root 1.54 }
324 root 1.50 }
325 root 1.1 }
326 root 1.8