medfall

A super great game engine
Log | Files | Refs

commit 242e1b4e05b5d6fb56f4f5450ef910bd1647eaf6
parent 11b51becfbada63812df07399b07e09263e59598
Author: Michael Savage <mikejsavage@gmail.com>
Date:   Wed, 19 Dec 2018 17:41:21 +0200

BSP improvements

Diffstat:
bsp.cc | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
bsp.h | 2+-
bsp_renderer.cc | 120++++++++++++++++++++++++++++++-------------------------------------------------
bsp_renderer.h | 8+++-----
4 files changed, 117 insertions(+), 97 deletions(-)

diff --git a/bsp.cc b/bsp.cc @@ -33,6 +33,27 @@ float point_plane_distance( v3 point, v3 normal, float d ) { return dot( point, normal ) - d; } +const char * lump_names[] = { + "LUMP_ENTITIES", + "LUMP_TEXTURES", + "LUMP_PLANES", + "LUMP_NODES", + "LUMP_LEAVES", + "LUMP_LEAFFACES", + "LUMP_LEAFBRUSHES", + "LUMP_MODELS", + "LUMP_BRUSHES", + "LUMP_BRUSHSIDES", + "LUMP_VERTICES", + "LUMP_MESHVERTS", + "LUMP_FOGS", + "LUMP_FACES", + "LUMP_LIGHTING", + "LUMP_LIGHTGRID", + "LUMP_VISIBILITY", + "LUMP_LIGHTARRAY", +}; + void bsp_init( BSP * bsp, const char * filename ) { bsp->contents = file_get_contents( filename, NULL ); @@ -40,6 +61,16 @@ void bsp_init( BSP * bsp, const char * filename ) { bool ibsp = header->magic == 0x50534249; + for( int i = 0; i < LUMP_MAX; i++ ) { + u32 displayed_size = header->lumps[ i ].len / 1000; + const char * unit = "KB"; + if( displayed_size >= 1000 ) { + displayed_size /= 1000; + unit = "MB"; + } + ggprint( "{} size = {}{}\n", lump_names[ i ], displayed_size, unit ); + } + bsp->load_lump( bsp->num_textures, bsp->textures, LUMP_TEXTURES ); bsp->load_lump( bsp->num_planes, bsp->planes, LUMP_PLANES ); bsp->load_lump( bsp->num_nodes, bsp->nodes, LUMP_NODES ); @@ -93,6 +124,7 @@ void BSP::fixup_rbsp() { vertices = malloc_array< BSP_Vertex >( num_vertices ); for( u32 i = 0; i < num_vertices; i++ ) { vertices[ i ].pos = rbsp_vertices[ i ].pos; + vertices[ i ].normal = rbsp_vertices[ i ].normal; } brush_sides = malloc_array< BSP_BrushSide >( num_brush_sides ); @@ -294,7 +326,9 @@ BSP_Leaf & BSP::position_to_leaf( v3 pos ) const { return leaves[ -( node_idx + 1 ) ]; } -static v2 screen_pos( const m4 & P, const m4 & V, v3 camera_pos, v3 target, v2 clamp, float near_plane_depth ) { +static v2 screen_pos( const m4 & P, const m4 & V, v3 camera_pos, v3 target, v2 clamp, float near_plane_depth, bool * clamped ) { + *clamped = false; + v4 clip = P * V * v4( target, 1.0 ); if( abs( clip.z ) < near_plane_depth ) return v2( 0, 0 ); @@ -311,21 +345,21 @@ static v2 screen_pos( const m4 & P, const m4 & V, v3 camera_pos, v3 target, v2 c float ry = clamp.y / abs( res.y ); res *= min( rx, ry ); + + *clamped = true; } return res; } GAME_INIT( game_init ) { - bsp_init( &game->bsp, "assets/acidwdm2.bsp" ); - - MemoryArena arena = memarena_push_arena( &mem->persistent_arena, megabytes( 10 ) ); + bsp_init( &game->bsp, "assets/wbomb6.bsp" ); game->pos = v3( 0, -100, 450 ); game->pitch = 0; game->yaw = 0; - bspr_init( &game->bspr, &arena, &game->bsp ); + bspr_init( &game->bspr, &game->bsp ); { v2u32 window_size = get_window_size(); @@ -404,7 +438,7 @@ GAME_FRAME( game_frame ) { UniformBinding view_uniforms = renderer_uniforms( V, P ); UniformBinding world_model_uniforms = renderer_uniforms( m4_identity() ); - UniformBinding tree_model_uniforms = renderer_uniforms( m4_translation( 100, -600, 340 + 5 * sinf( current_time * 10 ) ) * m4_rotz( current_time ) * m4_rotx( deg_to_rad( 90 ) ) * m4_scale( 32 ) ); + UniformBinding tree_model_uniforms = renderer_uniforms( m4_translation( 100, -600, 340 + 5 * sinf( current_time * 2 ) ) * m4_rotz( current_time ) * m4_rotx( deg_to_rad( 90 ) ) * m4_scale( 32 ) ); // depth/normals pre pass { @@ -416,7 +450,7 @@ GAME_FRAME( game_frame ) { render_state.uniforms[ UNIFORMS_MODEL ] = world_model_uniforms; render_state.cull_face = CULLFACE_FRONT; - bspr_render( &game->bspr, game->pos, render_state ); + bspr_render( &game->bspr, render_state ); render_state.cull_face = CULLFACE_BACK; @@ -492,7 +526,7 @@ GAME_FRAME( game_frame ) { render_state.textures[ 1 ] = world_depth_and_normals.textures[ OUTPUT_DEPTH ]; render_state.textures[ 2 ] = model_depth_outline.textures[ OUTPUT_DEPTH ]; - bspr_render( &game->bspr, game->pos, render_state ); + bspr_render( &game->bspr, render_state ); render_state.cull_face = CULLFACE_BACK; @@ -560,32 +594,48 @@ GAME_FRAME( game_frame ) { render_state.depth_func = DEPTHFUNC_ALWAYS; immediate_render( render_state ); } + + // draw position indicator { + v3 target = v3( 100, -600, 400 + 5 * sinf( current_time * 2 ) ); + + v2u32 window_size = get_window_size(); const float aspect = get_aspect_ratio(); - const float crosshair_thickness = 0.0025f; const float crosshair_length = 0.01f; + float dist = length( target - game->pos ); - v3 target = v3( 100, -600, 400 + 5 * sinf( current_time * 10 ) ); - v2 a = screen_pos( P, V, game->pos, target, v2( 1.0f - 0.02f, 1.0f - 0.02f * aspect ), NEAR_PLANE_DEPTH ); + int pxsize = lerp( 12, saturate( unlerp( 100.0f, dist, 500.0f ) ), 20 ); + float w = float( pxsize ) / window_size.x; + float h = float( pxsize ) / window_size.y; + + bool clamped; + v2 a = screen_pos( P, V, game->pos, target, v2( 1.0f - 2 * w, 1.0f - 2 * h ), NEAR_PLANE_DEPTH, &clamped ); v3 t = v3( a, 1 ); const v4 red( 0, 0.5, 0, 1 ); immediate_triangle( - t + v3( -crosshair_length, crosshair_length * aspect, 0 ), - t + v3( -crosshair_length, -crosshair_length * aspect, 0 ), - t + v3( crosshair_length, crosshair_length * aspect, 0 ), + t + v3( -w, h, 0 ), + t + v3( -w, -h, 0 ), + t + v3( w, h, 0 ), red ); immediate_triangle( - t + v3( crosshair_length, -crosshair_length * aspect, 0 ), - t + v3( crosshair_length, crosshair_length * aspect, 0 ), - t + v3( -crosshair_length, -crosshair_length * aspect, 0 ), + t + v3( w, -h, 0 ), + t + v3( w, h, 0 ), + t + v3( -w, -h, 0 ), red ); RenderState render_state; render_state.shader = get_shader( SHADER_UI ); render_state.depth_func = DEPTHFUNC_ALWAYS; immediate_render( render_state ); + + if( !clamped ) { + v2 p = ( a + 1.0f ) / 2.0f; + p.y = 1.0f - p.y; + p *= v2( window_size.x, window_size.y ); + draw_centered_text( "DEFEND", p.x, p.y - 16 - pxsize / 2, 12 ); + } } { diff --git a/bsp.h b/bsp.h @@ -4,7 +4,7 @@ #include "linear_algebra.h" enum BSP_Lump { - LUMP_ENTITIES = 0, + LUMP_ENTITIES, LUMP_TEXTURES, LUMP_PLANES, LUMP_NODES, diff --git a/bsp_renderer.cc b/bsp_renderer.cc @@ -2,6 +2,7 @@ #include "intrinsics.h" #include "linear_algebra.h" +#include "array.h" #include "bsp.h" #include "bsp_renderer.h" #include "memory_arena.h" @@ -9,8 +10,8 @@ v3 bspr_face_colour( const BSP * bsp, const BSP_Face & face ) { if(strcmp(bsp->textures[face.texture].name, "textures/acidwdm2/sky_black") == 0) - return v3( 0.7, 0.7, 0.7 ); - return v3( 1, 1, 1 ); + return v3( 0.3, 0.3, 0.3 ); + return v3( 0.5, 0.5, 0.5 ); if(strcmp(bsp->textures[face.texture].name, "textures/acidwdm2/wall_olive033") == 0) { return v3(0, 0.33, 0); } else if(strcmp(bsp->textures[face.texture].name, "textures/acidwdm2/wall_olive066") == 0) { @@ -57,91 +58,62 @@ v3 bspr_face_colour( const BSP * bsp, const BSP_Face & face ) { } } -void bspr_init( BSPRenderer * bspr, MemoryArena * arena, const BSP * bsp ) { - bspr->arena = arena; - bspr->bsp = bsp; - bspr->meshes = memarena_push_many( arena, Mesh, bsp->num_leaves ); - - MEMARENA_SCOPED_CHECKPOINT( arena ); - array< v3 > positions = memarena_push_array( arena, v3, 16384 ); - array< v3 > normals = memarena_push_array( arena, v3, 16384 ); - array< v3 > colours = memarena_push_array( arena, v3, 16384 ); - array< u32 > indices = memarena_push_array( arena, u32, 16384 ); - size_t num_positions, num_normals, num_colours, num_indices; - - for( u32 l = 0; l < bsp->num_leaves; l++ ) { - num_positions = 0; - num_normals = 0; - num_colours = 0; - num_indices = 0; - - const BSP_Leaf & leaf = bsp->leaves[ l ]; - - for( u32 f = 0; f < leaf.num_faces; f++ ) { - u32 offset = num_positions; - - const BSP_LeafFace & leaf_face = bsp->leaf_faces[ f + leaf.first_face ]; - const BSP_Face & face = bsp->faces[ leaf_face ]; - const v3 colour = bspr_face_colour( bsp, face ); - - // drop outlines - if( strcmp( bsp->textures[ face.texture ].name, "textures/acidwdm2/ink" ) == 0 ) - continue; +struct VertexData { + v3 pos; + v3 normal; + v3 colour; +}; + +void bsp_to_mesh( const BSP * bsp, DynamicArray< VertexData > * verts, DynamicArray< u32 > * indices ) { + for( u32 i = 0; i < bsp->num_vertices; i++ ) { + VertexData v; + v.pos = bsp->vertices[ i ].pos; + v.normal = bsp->vertices[ i ].normal; + verts->add( v ); + } - const BSP_Vertex * vertices = &bsp->vertices[ face.first_vert ]; - const s32 * face_indices = &bsp->mesh_verts[ face.first_mesh_vert ]; + for( u32 f = 0; f < bsp->num_faces; f++ ) { + const BSP_Face & face = bsp->faces[ f ]; + v3 colour = bspr_face_colour( bsp, face ); - for( s32 v = 0; v < face.num_verts; v++ ) { - v3 pos = vertices[ v ].pos; + // drop outlines + if( strcmp( bsp->textures[ face.texture ].name, "textures/acidwdm2/ink" ) == 0 ) + continue; - positions[ num_positions++ ] = pos; - normals[ num_normals++ ] = face.normal; - colours[ num_colours++ ] = colour; - } + // if( face.type != 1 ) + // continue; - for( s32 m = 0; m < face.num_mesh_verts; m++ ) { - indices[ num_indices++ ] = face_indices[ m ] + offset; - } + for( s32 m = 0; m < face.num_mesh_verts; m++ ) { + u32 index = face.first_vert + bsp->mesh_verts[ face.first_mesh_vert + m ]; + indices->add( index ); + ( *verts )[ index ].colour = colour; } - - MeshConfig config; - config.positions = renderer_new_vb( positions.ptr(), num_positions * sizeof( v3 ) ); - config.normals = renderer_new_vb( normals.ptr(), num_normals * sizeof( v3 ) ); - config.colours = renderer_new_vb( colours.ptr(), num_colours * sizeof( v3 ) ); - config.indices = renderer_new_ib( indices.ptr(), num_indices * sizeof( u32 ) ); - config.num_vertices = num_indices; - - bspr->meshes[ l ] = renderer_new_mesh( config ); } } -void bspr_render( const BSPRenderer * bspr, v3 pos, const RenderState & render_state ) { - s32 cluster = bspr->bsp->position_to_leaf( pos ).cluster; - - if( cluster == -1 ) { - for( u32 i = 0; i < bspr->bsp->num_leaves; i++ ) { - renderer_draw_mesh( bspr->meshes[ i ], render_state ); - } +void bspr_init( BSPRenderer * bspr, const BSP * bsp ) { + bspr->bsp = bsp; - return; - } + DynamicArray< VertexData > verts; + DynamicArray< u32 > indices; + bsp_to_mesh( bsp, &verts, &indices ); - for( u32 i = 0; i < bspr->bsp->num_leaves; i++ ) { - const BSP_Leaf & leaf = bspr->bsp->leaves[ i ]; + MeshConfig mesh_config; + mesh_config.unified_buffer = renderer_new_vb( verts.ptr(), verts.num_bytes() ); + mesh_config.stride = sizeof( verts[ 0 ] ); + mesh_config.positions_offset = offsetof( VertexData, pos ); + mesh_config.normals_offset = offsetof( VertexData, normal ); + mesh_config.colours_offset = offsetof( VertexData, colour ); + mesh_config.indices = renderer_new_ib( indices.ptr(), indices.num_bytes() ); + mesh_config.num_vertices = indices.size(); - s32 other_cluster = leaf.cluster; - s32 pvs_idx = cluster * bspr->bsp->vis->cluster_size + other_cluster / 8; + bspr->mesh = renderer_new_mesh( mesh_config ); +} - if( bspr->bsp->vis->pvs[ pvs_idx ] & ( 1 << other_cluster % 8 ) ) { - renderer_draw_mesh( bspr->meshes[ i ], render_state ); - } - } +void bspr_render( const BSPRenderer * bspr, const RenderState & render_state ) { + renderer_draw_mesh( bspr->mesh, render_state ); } void bspr_destroy( BSPRenderer * bspr ) { - memarena_clear( bspr->arena ); - - for( u32 i = 0; i < bspr->bsp->num_leaves; i++ ) { - renderer_delete_mesh( bspr->meshes[ i ] ); - } + renderer_delete_mesh( bspr->mesh ); } diff --git a/bsp_renderer.h b/bsp_renderer.h @@ -1,15 +1,13 @@ #pragma once #include "bsp.h" -#include "memory_arena.h" #include "renderer.h" struct BSPRenderer { - MemoryArena * arena; const BSP * bsp; - Mesh * meshes; + Mesh mesh; }; -void bspr_init( BSPRenderer * bspr, MemoryArena * arena, const BSP * bsp ); -void bspr_render( const BSPRenderer * bspr, v3 pos, const RenderState & render_state ); +void bspr_init( BSPRenderer * bspr, const BSP * bsp ); +void bspr_render( const BSPRenderer * bspr, const RenderState & render_state ); void bspr_destroy( BSPRenderer * bspr );