#include #include using namespace std; #define GL_GLEXT_PROTOTYPES #include #include "oct.h" #include "view.h" #include "entity.h" vector occ_query_objects; static GLuint begin_occ_query () { GLuint id; if (occ_query_objects.size ()) { id = *(occ_query_objects.end () - 1); occ_query_objects.pop_back (); } else glGenQueries (1, &id); glBeginQuery (GL_SAMPLES_PASSED, id); return id; } #define end_occ_query() glEndQuery (GL_SAMPLES_PASSED); static GLuint occ_query_result (GLuint id) { GLuint count; glGetQueryObjectuiv (id, GL_QUERY_RESULT, &count); occ_query_objects.push_back (id); return count; } octant world(0, sector (SOFFS_MIN, SOFFS_MIN, SOFFS_MIN), MAXEXTENT); octant::octant (octant *parent, const sector &orig, uoffs extent) : parent(parent), orig(orig), extent(extent) { for (fill = 8; fill--; ) sub[fill] = 0; } octant::~octant () { for (fill = 8; fill--; ) delete sub[fill]; } static bool overlap (const sector &o1, uoffs ea, const box &bbox) { sector a2, b2; ea /= 2; a2.x = o1.x + ea; a2.y = o1.y + ea; a2.z = o1.z + ea; b2.x = (bbox.a.x + bbox.b.x) / 2; b2.y = (bbox.a.y + bbox.b.y) / 2; b2.z = (bbox.a.z + bbox.b.z) / 2; return abs (a2.x - b2.x) <= ea + (bbox.b.x - bbox.a.x) && abs (a2.y - b2.y) <= ea + (bbox.b.y - bbox.a.y) && abs (a2.z - b2.z) <= ea + (bbox.b.z - bbox.a.z); } void octant::add (entity_base *e) { box bbox = translate (e->bbox, e->orig, sector (0, 0, 0)); uoffs size = max (abs (bbox.b.x - bbox.a.x), max (abs (bbox.b.y - bbox.a.y), abs (bbox.b.z - bbox.a.z))); if (overlap (orig, extent, bbox)) { uoffs extent2 = extent / 2; if (size > extent2 || !extent2) { push_back (e); e->o.push_back (this); return; } for (int i = 8; i--; ) { sector s = orig; s.offset (i, extent2); if (overlap (s, extent2, bbox)) { if (!sub[i]) sub[i] = new octant (this, s, extent2); sub[i]->add (e); } } } } void octant::remove (entity_base *e) { } void octant::draw (draw_context &ctx) { visibility_state &vs = ctx.vismap[this]; if (vs.generation != ctx.generation) vs.visibility = visibility_state::UNKNOWN; const sector &cam = ctx.v.orig; #if 0 if (cam.x >= orig.x && cam.x <= orig.x + extent && cam.y >= orig.y && cam.y <= orig.y + extent && cam.z >= orig.z && cam.z <= orig.z + extent) { vs.visibility = visibility_state::PARTIAL; vs.generation = ctx.generation; } else #endif { //printf ("OCTANT %d,%d,%d+%d\n", orig.x, orig.y, orig.z, extent); point center ( orig.x + (soffs)extent / 2 - cam.x , orig.y + (soffs)extent / 2 - cam.y , orig.z + (soffs)extent / 2 - cam.z ); GLfloat dia = (0.5 * sqrtf (3))*(GLfloat)extent; #if 0 printf ("DISTANCE %f,%f,%f TO near: %f\n", center.x, center.y, center.z, ctx.frustum.n.distance (center) ); #endif #if 0 printf ("DISTANCE %f,%f,%f TO far: %f\n", center.x, center.y, center.z, ctx.frustum.f.distance (center) ); #endif #if 1 if (ctx.frustum.t.distance (center) < -dia) return; if (ctx.frustum.b.distance (center) < -dia) return; if (ctx.frustum.l.distance (center) < -dia) return; if (ctx.frustum.r.distance (center) < -dia) return; if (ctx.frustum.n.distance (center) < -dia) return; if (ctx.frustum.f.distance (center) < -dia) return; #endif } #if 1 glBegin (GL_LINES); sector s = orig; s.x -= ctx.v.orig.x; s.y -= ctx.v.orig.y; s.z -= ctx.v.orig.z; vec3 clr(0, 0.8, 0); glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, (const GLfloat*)&clr); for (int i = 8; i--; ) for (int ji = 3; ji--; ) { int j = i | (1 << ji); if (i != j) { glVertex3i (s.x + !!(i & 1) * extent, s.y + !!(i & 2) * extent, s.z + !!(i & 4) * extent); glVertex3i (s.x + !!(j & 1) * extent, s.y + !!(j & 2) * extent, s.z + !!(j & 4) * extent); } } glEnd (); glDisable(GL_COLOR_MATERIAL); #endif #if 0 if (vs.visibility == visibility_state::PARTIAL && vs.generation == ctx.generation) #endif { for (iterator i = end (); i-- != begin (); ) #if 0 printf ("draw %p %d,%d,%d (%d,%d,%d - %d,%d,%d)\n", *i, (*i)->orig.x, (*i)->orig.y, (*i)->orig.z, (*i)->bbox.a.x, (*i)->bbox.a.y, (*i)->bbox.a.z, (*i)->bbox.b.x, (*i)->bbox.b.y, (*i)->bbox.b.z ), #endif (*i)->display (ctx); // node to start with unsigned char si = ctx.v.d.x < 0 ? 1 : 0 | ctx.v.d.y < 0 ? 2 : 0 | ctx.v.d.z < 0 ? 4 : 0; // bit-toggle to find next child for front-to-back order static unsigned char next[8] = { 0, 0^1, 1^2, 2^4, 4^3, 3^5, 5^6, 6^7 }; for (int i = 0; i < 8; i++) { si ^= next[i]; if (sub[si]) sub[si]->draw (ctx); } } vs.generation = ctx.generation; }