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 );