#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 glGenQueriesARB (1, &id); glBeginQuery (GL_SAMPLES_PASSED_ARB, id); return id; } #define end_occ_query() glEndQuery (GL_SAMPLES_PASSED_ARB); static GLuint occ_query_result (GLuint id) { GLuint count; glGetQueryObjectuivARB (id, GL_QUERY_RESULT_ARB, &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) { printf ("OCTANT %d,%d,%d+%d\n", orig.x, orig.y, orig.z, extent); 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) { printf ("overlap, add\n"); 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); } } } else printf ("no overlap\n"); } 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::OCCLUDED; #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; glColor3f (1, 1, 1); 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 (); #endif const sector &cam = ctx.v.orig; 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::VISIBLE; vs.generation = ctx.generation; } if (vs.visibility == visibility_state::VISIBLE && vs.generation == ctx.generation) { for (iterator i = end (); i-- != begin (); ) (*i)->display (ctx); for (int i = 8; i--; ) if (sub[i]) sub[i]->draw (ctx); } vs.generation = ctx.generation; }