#pragma once #include "map.h" #include "../../render/gl_3d.h" const F32 BSP_NORM_EPSILON = 0.0001f; const F32 BSP_DIST_EPSILON = 0.01f; const I32 BSP_DEPTH_MAX = 1024; struct BSP_PLANE { VEC3 normal; F32 dist; const bool operator==( const BSP_PLANE& other ) const { return fabsf( normal.x - other.normal.x ) < BSP_NORM_EPSILON && fabsf( normal.y - other.normal.y ) < BSP_NORM_EPSILON && fabsf( normal.z - other.normal.z ) < BSP_NORM_EPSILON && fabsf( dist - other.dist ) < BSP_DIST_EPSILON; } }; enum BspSide_t { BSP_SIDE_FRONT = 1, BSP_SIDE_BACK = 2, BSP_SIDE_ON = 4, BSP_SIDE_SPAN = 8, }; struct BSP_FACE { I32 propid; I32 id; LIST verts{}; LIST render_verts{}; }; struct BSP_NODE { BSP_PLANE plane; I32 front; I32 back; }; struct BSP_EDGE { BSP_PLANE plane; U32 face; U8 avgc; VEC3 v1, v2; }; struct BSP_LEAF { U32 first; U32 count; I32 cluster; LIST edges; }; struct BSP_WINDING { LIST points; }; struct BSP_PORTAL { BSP_WINDING w; // winding BSP_PLANE plane; I32 front; I32 back; }; struct BSP_CLUSTER { I32 first; I32 count; I32 pvs_off; }; struct BSP_PORTAL_STACK_FRAME { I32 idx; LIST planes; }; struct BSP_PORTAL_NODE { I32 leaf; BSP_WINDING w; }; struct BSP_PORTAL_QUEUE { I32 front; BSP_WINDING frustum; }; struct BSP_BITSET : public LIST {}; struct BSP { LIST nodes; LIST leaves; LIST faces; // >= 0 = node, < 0 = leaf I32 root; WORLD_MAP* map; LIST portals; LIST clusters; BSP_BITSET pvs_bits; }; extern LIST bsp_map_get_planes( WORLD_MAP* map ); extern LIST bsp_map_get_faces( WORLD_MAP* map ); extern BSP* bsp_build_map( WORLD_MAP* map ); extern void bsp_free( BSP* bsp ); inline U8 bsp_is_leaf( I32 child ) { return child < 0; } inline I32 bsp_leaf_index( I32 child ) { return ~child; } inline F32 bsp_plane_dist( const BSP_PLANE& p, const VEC3& v ) { return vec_dot( p.normal, v ) - p.dist; } inline SURF_PROPS* bsp_face_get_props( WORLD_MAP* w, BSP_FACE* s ) { return s->propid < 0 ? map_props_get_special( w, s->propid ) : &w->props[s->propid]; } inline VEC3 bsp_face_get_normal( const BSP_FACE* f ){ const VEC3 v0 = f->verts.data[0].pos; const VEC3 v1 = f->verts.data[1].pos; const VEC3 v2 = f->verts.data[2].pos; return vec_normalize( vec_cross( v1 - v0, v2 - v0 ) ); }