1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
#include "bsp_draw.h"
#include "../../game.h"
#include "../../render/gl_3d.h"
#include "../objlist.h"
#include "bsp.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{ .hitmask = HG_SOLID };
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 );
}
|