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

# Content
1 #include <cstdlib>
2
3 #include <vector>
4
5 using namespace std;
6
7 #include "opengl.h"
8
9 #include "oct.h"
10 #include "view.h"
11 #include "entity.h"
12 #include "material.h" //DEBUG
13
14 struct oct_visibility : visibility_base
15 {
16 bool subvis, evis;
17 int occ_res;
18
19 void clear ()
20 {
21 occ_res = -1;
22 evis = true;
23 subvis = true;
24 }
25
26 oct_visibility (octant &oct)
27 {
28 clear ();
29 }
30 };
31
32 octant world(0, sector (0, 0, 0), MAXEXTENT);
33
34 octant::octant (octant *parent, const sector &orig, uoffs extent)
35 : parent(parent)
36 , orig(orig)
37 , extent(extent)
38 {
39 for (fill = 8; fill--; )
40 sub[fill] = 0;
41 }
42
43 visibility_base *octant::new_visibility ()
44 {
45 return new oct_visibility (*this);
46 }
47
48 void octant::clear_visibility (visibility_base *vs)
49 {
50 ((oct_visibility *)vs)->clear ();
51 }
52
53 octant::~octant ()
54 {
55 for (fill = 8; fill--; )
56 delete sub[fill];
57 }
58
59 static bool overlap (const sector &orig, uoffs extent, const sector &a, const sector &b)
60 {
61 sector size = (b - a + 1) >> 1;
62 sector center = a + size;
63
64 return abs (orig - center) <= extent + size;
65 }
66
67 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 }
75
76 void octant::add (entity *e)
77 {
78 const sector &a = e->a;
79 const sector &b = e->b;
80
81 uoffs size = max (abs (b - a));
82
83 if (size >= extent >> 4)
84 {
85 if (overlap (orig, extent, a, b))
86 {
87 push_back (e);
88 e->o.push_back (this);
89 }
90 }
91 else
92 {
93 uoffs extent2 = extent >> 1;
94
95 for (int i = 8; i--; )
96 {
97 sector s = offset (orig, i, extent2);
98
99 if (overlap (s, extent2, a, b))
100 {
101 if (!sub[i])
102 {
103 sub[i] = new octant (this, s, extent2);
104 fill++;
105 }
106
107 sub[i]->add (e);
108 }
109 }
110 }
111 }
112
113 void octant::remove (entity *e)
114 {
115 }
116
117 bool octant::detect_visibility (view &ctx) //, bool fully_visible)
118 {
119 sector centeri = orig - ctx.orig;
120 point centerf = point (centeri);
121
122 GLfloat rad = ctx.diagfact * extent;
123
124 if (!overlap (ctx.frustum.c, sphere (centerf, rad)))
125 return false;
126
127 oct_visibility &vs = *(oct_visibility *)get_visibility (ctx);
128
129 if (max (centeri) < extent)
130 {
131 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 }
143
144 #if 0
145 GLfloat fd = distance (ctx.frustum.f, centerf);
146
147 if (fd < -(ctx.c_far - ctx.z_far) -rad * 3.F)
148 return false;
149 #endif
150
151 // very important, optimize?
152 GLfloat z = length (ctx.p - centerf) + rad;
153 if (z < 0.F || ctx.perspfact * extent / z < 10.) // very crude "too small to see" check
154 {
155 vs.clear ();//D
156 return false;
157 }
158
159 #if 0
160 if (vs.state == PARTIAL || vs.state == FULL)
161 ctx.nc_far = max (ctx.nc_far, z);
162 #endif
163
164 if (vs.occ_res > 0)
165 vs.evis = true;
166 else if (!(vs.subvis || vs.evis))
167 {
168 ctx.postdepthlist.push_back (this);
169 return false;
170 }
171
172 bool subvis = false;
173
174 // 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
179 // bit-toggle to find next child for front-to-back order
180 static unsigned char toggle[8+1]
181 = { 0, 0^1, 1^2, 2^4, 4^3, 3^5, 5^6, 6^7, 0 };
182
183 unsigned char *next = toggle;
184 do
185 {
186 si ^= *next;
187
188 if (sub[si])
189 subvis = subvis | sub[si]->detect_visibility (ctx);
190 }
191 while (*++next);
192
193 vs.subvis = subvis;
194
195 if (subvis)
196 {
197 if (size ())
198 {
199 ctx.postdepthlist.push_back (this);
200 ctx.vislist.push_back (this);
201 }
202
203 return true;
204 }
205 else
206 {
207 ctx.postdepthlist.push_back (this);
208 ctx.vislist.push_back (this);
209
210 return vs.evis && vs.occ_res;
211 }
212 }
213
214 void octant::draw_depth (view &ctx)
215 {
216 oct_visibility &vs = *(oct_visibility *)get_visibility (ctx);
217
218 if (!vs.occ_res)
219 return;
220
221 for (int i = 0; i < size (); ++i)
222 {
223 entity *e = (*this)[i];
224
225 entity_visibility &evis = *(entity_visibility *)e->get_visibility (ctx);
226
227 if (evis.occ_res)
228 {
229 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 }
241 }
242 }
243
244 void octant::draw_postdepth (view &ctx)
245 {
246 oct_visibility &vs = *(oct_visibility *)get_visibility (ctx);
247
248 if (!vs.evis)
249 {
250 ctx.begin_occ_query (vs.occ_res);
251 sector s = orig - ctx.orig;
252 gl::draw_bbox (s - extent, s + extent);
253 ctx.end_occ_query ();
254 }
255 else
256 {
257 vs.evis = false;
258
259 for (int i = 0; i < size (); ++i)
260 {
261 entity *e = (*this)[i];
262 entity_visibility &evis = *(entity_visibility *)e->get_visibility (ctx);
263
264 if (evis.occ_res)
265 vs.evis = true;
266 else
267 {
268 if (!ctx.may_draw (e))
269 continue;
270
271 ctx.stat1++;
272 ctx.begin_occ_query (evis.occ_res);
273 gl::draw_bbox (e->a - ctx.orig, e->b - ctx.orig);
274 ctx.end_occ_query ();
275 }
276 }
277 }
278 }
279
280 void octant::draw_lighted (view &ctx)
281 {
282 oct_visibility &vs = *(oct_visibility *)get_visibility (ctx);
283
284 if (!vs.occ_res)
285 return;
286
287 #if 0
288 if (vs.state == FULL || vs.state == OCCLUDED)
289 {
290 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 }
297 #endif
298
299 for (int i = 0; i < size (); ++i)
300 {
301 entity *e = (*this)[i];
302 entity_visibility &evis = *(entity_visibility *)e->get_visibility (ctx);
303
304 if (evis.occ_res)
305 {
306 if (!ctx.may_draw (e))
307 continue;
308
309 sector center = ((e->a + e->b) >> 1) - ctx.orig;
310 GLfloat z = length (vec3 (center));
311 ctx.pixfact = ctx.perspfact / z;
312
313 if (!ctx.first_lighted
314 || evis.next > timer.now)
315 e->draw (ctx);
316 else
317 {
318 evis.next = timer.now + 0.2;
319 ctx.begin_occ_query (evis.occ_res);
320 e->draw (ctx);
321 ctx.end_occ_query ();
322 }
323 }
324 }
325 }
326