summaryrefslogtreecommitdiff
path: root/src/game/world/bsp_draw.cpp
diff options
context:
space:
mode:
authornavewindre <boneyaard@gmail.com>2025-09-03 20:10:09 +0200
committernavewindre <boneyaard@gmail.com>2025-09-03 20:10:09 +0200
commitf8b92ce3aa08b1445c9f956d8166830946562d12 (patch)
tree94e63a5aec9f8f52b577f56799e0c9201fd976a5 /src/game/world/bsp_draw.cpp
a
Diffstat (limited to 'src/game/world/bsp_draw.cpp')
-rw-r--r--src/game/world/bsp_draw.cpp124
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 );
+}