#include "bsp_draw.h" #include "../../game.h" #include "../../render/gl_3d.h" #include "../objlist.h" #include "map.h" #include "trace.h" void bsp_draw_leaf( BSP* bsp, GAME_DATA* game, I32 leafidx ) { BSP_LEAF* leaf = &bsp->leaves.data[leafidx]; // todo : handle transparency for( U32 i = 0; i < leaf->count; ++i ) { BSP_FACE* f = &bsp->faces.data[leaf->first + i]; U8 face_transparent = 0; if( !face_transparent ) { LIST verts = f->render_verts; SURF_PROPS* props = bsp_face_get_props( game->state.map, f ); gl_3d_polygon( game->render.batch_3d, verts.data, verts.size, props->tex ); } } // todo : sort by depth for( U32 i = 0; i < leaf->count; ++i ) { BSP_FACE* f = &bsp->faces.data[leaf->first + i]; U8 face_transparent = 0; if( face_transparent ) { LIST verts = f->render_verts; SURF_PROPS* props = bsp_face_get_props( game->state.map, f ); gl_3d_polygon( game->render.batch_3d, verts.data, verts.size, props->tex ); } } } U8 leaf_visible( I32 leaf_idx ) { // todo : pvs return 1; } I32 bsp_point_leaf( BSP* bsp, const VEC3& p ) { I32 n = bsp->root; for( ;; ) { if( bsp_is_leaf( n ) ) return bsp_leaf_index( n ); BSP_NODE* node = &bsp->nodes.data[n]; F32 dist = bsp_plane_dist( node->plane, p ); n = (dist >= 0.f)? node->front : node->back; } } void bsp_traverse_draw( BSP* bsp, GAME_DATA* game, I32 node, VEC3 campos ) { if( bsp_is_leaf( node ) ) { I32 i = bsp_leaf_index( node ); return bsp_draw_leaf( bsp, game, i ); } BSP_NODE* n = &bsp->nodes.data[node]; F32 dist = bsp_plane_dist( n->plane, campos ); I32 near = (dist >= 0.f)? n->front : n->back; I32 far = (dist >= 0.f)? n->back : n->front; // todo : set up vertex buffer, draw all in one call // todo todo : batch different shader calls separately bsp_traverse_draw( bsp, game, near, campos ); bsp_traverse_draw( bsp, game, far, campos ); } void bsp_draw_sprites( BSP* bsp, GAME_DATA* game ) { LIST* sprites = &game->state.map->sprites; for( U32 i = 0; i < sprites->size; ++i ) { MAP_SPRITE* sprite = &sprites->data[i]; BSP_TRACE t; t.in_start = player_get_view_pos( objl->pl ); t.in_end = sprite->pos; bsp_trace( &t, bsp ); if( !t.hit ) { VEC3 angle = vec_angles( sprite->pos, t.in_start ); gl_3d_plane( game->shaders.gl3d, sprite->pos, sprite->size, { -angle.x + 90.f, angle.y - 90.f }, sprite->tex, sprite->clr ); } } } void bsp_draw( BSP* bsp, GAME_DATA* game, VEC2 window, VEC2 winsize ) { gl_set_viewport( game->gl, window, winsize ); PLAYER* pl = objl->pl; F32 fov = pl->fov; gl_3d_projection_setup( game->shaders.gl3d, { pl->pos.x, pl->pos.y, pl->pos.z + pl->eyeoffset }, fov, pl->rot.y, pl->rot.x, 1.f, 9999.f, winsize ); gl_set_clip( game->gl, window, winsize ); gl_batch_empty( game->render.batch_3d ); glEnable( GL_DEPTH_TEST ); glEnable( GL_CULL_FACE ); // ??? glFrontFace( GL_CW ); glDepthFunc( GL_LESS ); bsp_traverse_draw( bsp, game, bsp->root, objl->pl->pos ); gl_batch_draw( game->render.batch_3d ); glDisable( GL_DEPTH_TEST ); glDisable( GL_CULL_FACE ); bsp_draw_sprites( bsp, game ); gl_reset_clip( game->gl ); VEC2 canvas = { (F32)game->gl->canvas_size[0], (F32)game->gl->canvas_size[1] }; gl_set_viewport( game->gl, {}, canvas ); }