--- libgender/oct.C 2005/01/06 03:09:24 1.87 +++ libgender/oct.C 2005/08/11 20:42:19 1.95 @@ -1,6 +1,7 @@ #include #include + using namespace std; #include "opengl.h" @@ -8,48 +9,23 @@ #include "oct.h" #include "view.h" #include "entity.h" - -enum visibility_state { FULL, PARTIAL, OCCLUDED }; - -struct evis { - entity *e; - visibility_state state; - double last; // time of last check - - void clear () - { - last = 0.; - state = FULL; - } - - evis () - { - clear (); - } -}; +#include "material.h" //DEBUG struct oct_visibility : visibility_base { - vector vismap; - - visibility_state state; + bool subvis, evis; + int occ_res; - evis &get_visibility (int i, entity *e) + void clear () { - evis &evs = vismap [i]; - - if (evs.e != e) - { - evs.clear (); - evs.e = e; - } - - return evs; + occ_res = -1; + evis = true; + subvis = true; } oct_visibility (octant &oct) - : state(FULL) { + clear (); } }; @@ -71,8 +47,7 @@ void octant::clear_visibility (visibility_base *vs) { - ((oct_visibility *)vs)->vismap.clear (); - ((oct_visibility *)vs)->state = FULL; + ((oct_visibility *)vs)->clear (); } octant::~octant () @@ -141,8 +116,6 @@ bool octant::detect_visibility (view &ctx) //, bool fully_visible) { - ctx.stat1++;//D - sector centeri = orig - ctx.orig; point centerf = point (centeri); @@ -153,54 +126,50 @@ oct_visibility &vs = *(oct_visibility *)get_visibility (ctx); - //vs.state = FULL;//D - -#if 0 - if (max (abs (centeri)) <= extent) - ; - else + if (max (centeri) < extent) { -#endif - - //if (distance (ctx.frustum.t, centerf) < -rad) return false; - //if (distance (ctx.frustum.b, centerf) < -rad) return false; - //if (distance (ctx.frustum.l, centerf) < -rad) return false; - //if (distance (ctx.frustum.r, centerf) < -rad) return false; - ////if (distance (ctx.frustum.n, centerf) < -rad) return false; + vs.evis = true; + vs.occ_res = -1; + } + else if (distance (ctx.frustum.t, centerf) < -rad + || distance (ctx.frustum.b, centerf) < -rad + || distance (ctx.frustum.l, centerf) < -rad + || distance (ctx.frustum.r, centerf) < -rad + || distance (ctx.frustum.n, centerf) < -rad) + { + vs.clear (); + return false; + } #if 0 - GLfloat fd = distance (ctx.frustum.f, centerf); + GLfloat fd = distance (ctx.frustum.f, centerf); - if (fd < -(ctx.c_far - ctx.z_far) -rad * 3.F) - return false; + if (fd < -(ctx.c_far - ctx.z_far) -rad * 3.F) + return false; #endif // very important, optimize? GLfloat z = length (ctx.p - centerf) + rad; if (z < 0.F || ctx.perspfact * extent / z < 10.) // very crude "too small to see" check - return false; + { + vs.clear ();//D + return false; + } #if 0 if (vs.state == PARTIAL || vs.state == FULL) ctx.nc_far = max (ctx.nc_far, z); #endif - if (vs.state == OCCLUDED) + if (vs.occ_res > 0) + vs.evis = true; + else if (!(vs.subvis || vs.evis)) { -#if 0 - if (extent < ctx.z_far) - { -#endif - ctx.postdepthlist.push_back (this); - return false; -#if 0 - } - else - vs.state == PARTIAL; -#endif + ctx.postdepthlist.push_back (this); + return false; } - bool visible = size () && vs.state == FULL; + bool subvis = false; // node to start with unsigned char si = centeri.x > 0 ? 1 : 0 @@ -217,41 +186,45 @@ si ^= *next; if (sub[si]) - visible = visible | sub[si]->detect_visibility (ctx); + subvis = subvis | sub[si]->detect_visibility (ctx); } while (*++next); - if (visible) + vs.subvis = subvis; + + if (subvis) { if (size ()) - ctx.vislist.push_back (this); + { + ctx.postdepthlist.push_back (this); + ctx.vislist.push_back (this); + } - ctx.postdepthlist.push_back (this); + return true; } else { - //vs.state = OCCLUDED; ctx.postdepthlist.push_back (this); - } + ctx.vislist.push_back (this); - return visible; + return vs.evis || vs.occ_res > 0; + } } void octant::draw_depth (view &ctx) { oct_visibility &vs = *(oct_visibility *)get_visibility (ctx); - vs.vismap.resize (size ()); - - if (vs.state == PARTIAL || vs.state == OCCLUDED) + if (!vs.occ_res) return; for (int i = 0; i < size (); ++i) { entity *e = (*this)[i]; - const evis &evs = vs.get_visibility (i, e); - if (evs.state != OCCLUDED) + entity_visibility &evis = *(entity_visibility *)e->get_visibility (ctx); + + if (evis.occ_res) { if (!ctx.may_draw (e)) continue; @@ -272,39 +245,35 @@ { oct_visibility &vs = *(oct_visibility *)get_visibility (ctx); - if (vs.state == PARTIAL || vs.state == OCCLUDED) + if (!vs.evis) { - ctx.begin_occ_query (*this, 0); + ctx.begin_occ_query (vs.occ_res); sector s = orig - ctx.orig; gl::draw_bbox (s - extent, s + extent); ctx.end_occ_query (); } else { - int nvis = 0; + vs.evis = false; for (int i = 0; i < size (); ++i) { entity *e = (*this)[i]; - const evis &evs = vs.get_visibility (i, e); + entity_visibility &evis = *(entity_visibility *)e->get_visibility (ctx); - if (evs.state == OCCLUDED) + if (evis.occ_res) + vs.evis = true; + else { if (!ctx.may_draw (e)) continue; - ctx.begin_occ_query (*this, e); + ctx.stat1++; + ctx.begin_occ_query (evis.occ_res); gl::draw_bbox (e->a - ctx.orig, e->b - ctx.orig); ctx.end_occ_query (); } - else - nvis++; } - -#if 0 - if (nvis == 0 && size ()) - vs.state = PARTIAL; -#endif } } @@ -312,65 +281,27 @@ { oct_visibility &vs = *(oct_visibility *)get_visibility (ctx); -#if 0 - if (vs.state == PARTIAL || vs.state == OCCLUDED) - { - sector s = orig - ctx.orig; - gl::draw_bbox (s - extent, s + extent); - printf ("DLP %p\n", this);//D - } -#endif - - if (vs.state == PARTIAL || vs.state == OCCLUDED) + if (!vs.occ_res) return; #if 0 - { - static vertex_buffer vb; - static index_buffer ib; - + if (vs.state == FULL || vs.state == OCCLUDED) + { sector s = orig - ctx.orig; - sector a = s - extent, b = s + extent; - - vertex_v3f vd[] = { - point (a.x, a.y, a.z), - point (b.x, a.y, a.z), - point (a.x, b.y, a.z), - point (b.x, b.y, a.z), - point (a.x, a.y, b.z), - point (b.x, a.y, b.z), - point (a.x, b.y, b.z), - point (b.x, b.y, b.z), - }; - - if (!ib) - { - static GLushort verts[4*6] = { - 0, 4, 6, 2, // -x - 1, 3, 7, 5, // +x - 0, 1, 5, 4, // -y - 7, 3, 2, 6, // +y - 0, 2, 3, 1, // -z - 4, 5, 7, 6, // +z - }; - - ib.set (verts, 4*6, GL_STATIC_DRAW_ARB); - } - - vb.set (vd, 8, GL_STREAM_DRAW_ARB); - vb.bind (); - for (int i = 0; i < 6; i++) - ib.draw (GL_LINE_LOOP, i*4, 4); - - } + debugmat->enable (ctx); + if (max (s) >= extent) + gl::draw_bbox (s - extent, s + extent); + debugmat->disable (ctx); + //printf ("DLP %ld %ld %ld (%ld)\n", orig.x, orig.y, orig.z, extent);//D + } #endif for (int i = 0; i < size (); ++i) { entity *e = (*this)[i]; - evis &evs = vs.get_visibility (i, e); + entity_visibility &evis = *(entity_visibility *)e->get_visibility (ctx); - if (evs.state != OCCLUDED) + if (evis.occ_res) { if (!ctx.may_draw (e)) continue; @@ -379,14 +310,13 @@ GLfloat z = length (vec3 (center)); ctx.pixfact = ctx.perspfact / z; - if (ctx.pass->type != LIGHTED - || !ctx.first_lighted - || evs.last + 1. > timer.now) + if (!ctx.first_lighted + || evis.next > timer.now) e->draw (ctx); else { - evs.last = timer.now; - ctx.begin_occ_query (*this, e); + evis.next = timer.now + 0.2; + ctx.begin_occ_query (evis.occ_res); e->draw (ctx); ctx.end_occ_query (); } @@ -394,24 +324,3 @@ } } -void octant::event (occ_query &ev) -{ - oct_visibility &vs = *(oct_visibility *)get_visibility (ev.ctx); - entity *e = (entity *)ev.id; - - if (e) - { - for (vector::iterator i = vs.vismap.begin (); - i != vs.vismap.end (); - ++i) - if (i->e == e) - { - i->state = ev.count ? FULL : OCCLUDED; - return; - } - } - else - vs.state = ev.count ? (vs.state == PARTIAL ? PARTIAL : FULL) : OCCLUDED; -} - -