diff options
Diffstat (limited to 'src/game/world/bsp_draw.cpp')
| -rw-r--r-- | src/game/world/bsp_draw.cpp | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/src/game/world/bsp_draw.cpp b/src/game/world/bsp_draw.cpp new file mode 100644 index 0000000..30e6731 --- /dev/null +++ b/src/game/world/bsp_draw.cpp @@ -0,0 +1,124 @@ +#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<VERTEX3D> 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<VERTEX3D> 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<MAP_SPRITE>* 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 ); +} |
