medfall

A super great game engine
Log | Files | Refs

commit d1af86276eb202259d179f3a7ae0ef5c18d756fd
parent a256577930323d27adbeab804a4b4434660d0370
Author: Michael Savage <mikejsavage@gmail.com>
Date:   Thu,  9 Nov 2017 23:29:11 +0200

Fix collision detection. Quadtrees were generated from original terrain and not BC5 terrain!

Diffstat:
clipmap.cc | 42++++++------------------------------------
heightmap.cc | 40+++++++++++++++++++++++++++++++++++++++-
heightmap.h | 28+++++-----------------------
make.lua | 2+-
pp2.cc | 30+++++++++++++++++++++---------
5 files changed, 72 insertions(+), 70 deletions(-)

diff --git a/clipmap.cc b/clipmap.cc @@ -138,14 +138,7 @@ GAME_INIT( game_init ) { texture_config.border_colour = v4( 0 ); clipmap.heightmap = renderer_new_texture( texture_config ); - array2d< v2 > rg = alloc_array2d< v2 >( &mem->persistent_arena, 4096, 4096 ); - decompress_bc5( rg, heightmap_data ); - - for( size_t y = 0; y < 4096; y++ ) { - for( size_t x = 0; x < 4096; x++ ) { - clipmap.quadtree.hm->pixels[ y * 4096 + x ] = u16( ( rg( x, y ).x * 256.0f + rg( x, y ).y ) * 255.0f ); - } - } + bc5_to_heightmap( &mem->persistent_arena, clipmap.quadtree.hm, heightmap_data ); } // load normalmap @@ -254,30 +247,6 @@ static void draw_qt( MinMaxu32 aabb, const array< HeightmapQuadTreeNode > nodes, } } -static bool segment_vs_quadtree( const HeightmapQuadTree * qt, const v3 & start, const v3 & end, float * t, v3 * xnormal ) { - float dont_care_t; - v3 dont_care_normal; - if( t == NULL ) - t = &dont_care_t; - if( xnormal == NULL ) - xnormal = &dont_care_normal; - - *t = 1.0f; - - if( start == end ) return false; - Ray3 ray( start, end - start ); - float local_t; - v3 local_normal; - bool hit = ray_vs_quadtree( qt, ray, &local_t, &local_normal ); - if( !hit || local_t > 1.0f ) - return false; - - *t = local_t; - *xnormal = local_normal; - - return true; -} - GAME_FRAME( game_frame ) { float fb = float( input->keys[ KEY_W ] - input->keys[ KEY_S ] ); float lr = float( input->keys[ KEY_D ] - input->keys[ KEY_A ] ); @@ -427,7 +396,7 @@ GAME_FRAME( game_frame ) { } // TODO: this might be quite harmful - if( !game->on_ground && remaining_t > 0 ) { + if( !game->on_ground ) { // TODO: rk4 integration const float gravity = -30.0f; game->velocity += v3( 0, 0, gravity ) * remaining_t; @@ -577,12 +546,13 @@ GAME_FRAME( game_frame ) { for( size_t i = 0; i < fireballs.elems.n; i++ ) { Fireball * fireball = &fireballs.elems[ i ]; Ray3 ray( fireball->pos, fireball->velocity * dt ); + v3 end = fireball->pos + fireball->velocity * dt; float t; v3 normal; - if( ray_vs_quadtree( &clipmap.quadtree, ray, &t, &normal ) && t <= 1 ) { + if( segment_vs_quadtree( &clipmap.quadtree, fireball->pos, end, &t, &normal ) ) { Explosion * explosion = explosions.acquire(); - explosion->pos = fireball->pos + t * fireball->velocity; + explosion->pos = lerp( fireball->pos, t, end ); explosion->created_at = current_time; fireballs.release( fireball ); @@ -590,7 +560,7 @@ GAME_FRAME( game_frame ) { } else { const float gravity = 9.81f; - fireball->pos += fireball->velocity * dt; + fireball->pos = end; fireball->velocity.z -= dt * gravity; immediate_sphere( fireball->pos, 4, v4( 1, 0, 0, 1 ), 4 ); } diff --git a/heightmap.cc b/heightmap.cc @@ -6,6 +6,7 @@ #include "heightmap.h" #include "log.h" #include "memory_arena.h" +#include "decompress_bc.h" static float lerp( float a, float b, float t ) { return a * ( 1 - t ) + b * t; @@ -221,7 +222,7 @@ size_t heightmap_quadtree_max_nodes( const Heightmap * hm ) { return ( ( hm->width - 1 ) * ( hm->width - 1 ) ) / 3; } -HeightmapQuadTree heightmap_build_quadtree( const Heightmap * hm, array< HeightmapQuadTreeNode > & nodes ) { +HeightmapQuadTree heightmap_build_quadtree( Heightmap * hm, array< HeightmapQuadTreeNode > & nodes ) { ASSERT( nodes.n >= heightmap_quadtree_max_nodes( hm ) ); HeightmapQuadTree qt; @@ -340,3 +341,40 @@ bool ray_vs_quadtree( const HeightmapQuadTree * qt, const Ray3 & ray, float * t, return ray_vs_quadtree_node( qt, 0, aabb, ray, t, xnormal ); } + +bool segment_vs_quadtree( const HeightmapQuadTree * qt, const v3 & start, const v3 & end, float * t, v3 * xnormal ) { + v3 dont_care_normal; + if( xnormal == NULL ) + xnormal = &dont_care_normal; + + if( t != NULL ) + *t = 1.0f; + + if( start == end ) + return false; + + float nt; + Ray3 ray( start, normalize( end - start ) ); + bool ok = ray_vs_quadtree( qt, ray, &nt, xnormal ); + if( !ok ) + return false; + + float l = length( end - start ); + if( t != NULL ) + *t = nt / l; + return nt <= l; +} + +void bc5_to_heightmap( MemoryArena * arena, Heightmap * hm, u8 * bc5 ) { + MEMARENA_SCOPED_CHECKPOINT( arena ); + array2d< v2 > rg = alloc_array2d< v2 >( arena, hm->width, hm->height ); + decompress_bc5( rg, bc5 ); + + for( u32 y = 0; y < rg.h; y++ ) { + for( u32 x = 0; x < rg.w; x++ ) { + float r = rg( x, y ).x; + float g = rg( x, y ).y; + hm->pixels[ y * 4096 + x ] = u16( ( r * 256.0f + g ) * 255.0f ); + } + } +} diff --git a/heightmap.h b/heightmap.h @@ -1,6 +1,7 @@ #pragma once #include "intrinsics.h" +#include "memory_arena.h" #include "array.h" #include "linear_algebra.h" #include "aabb.h" @@ -33,32 +34,13 @@ struct HeightmapQuadTree { u32 dim; HeightmapQuadTreeNode * nodes_memory; array< HeightmapQuadTreeNode > nodes; - const Heightmap * hm; + Heightmap * hm; }; size_t heightmap_quadtree_max_nodes( const Heightmap * hm ); HeightmapQuadTree heightmap_build_quadtree( const Heightmap * hm, array< HeightmapQuadTreeNode > & nodes ); -// TODO: these are all pretty general -// struct Intersection { -// float t; -// glm::vec3 position; -// glm::vec3 normal; -// }; - -// template< typename T > -// bool open_interval_contains( T lo, T x, T hi ) { -// return ( x - lo ) < ( hi - lo ); -// } -// -// template< typename T > -// bool closed_interval_contains( T lo, T x, T hi ) { -// return ( x - lo ) <= ( hi - lo ); -// } -// -// template< typename T > -// bool closed_intervals_overlap( T lo0, T hi0, T lo1, T hi1 ) { -// return lo0 <= hi1 && lo1 <= hi0; -// } - bool ray_vs_quadtree( const HeightmapQuadTree * qt, const Ray3 & ray, float * t, v3 * xnormal ); +bool segment_vs_quadtree( const HeightmapQuadTree * qt, const v3 & start, const v3 & end, float * t, v3 * xnormal ); + +void bc5_to_heightmap( MemoryArena * arena, Heightmap * hm, u8 * bc5 ); diff --git a/make.lua b/make.lua @@ -68,7 +68,7 @@ bin( "pp", { "pp", "heightmap", common_objs }, { "lodepng", "lz4", "squish", "st gcc_obj_cxxflags( "pp", "-O2" ) msvc_obj_cxxflags( "pp", "/O2" ) -bin( "pp2", { "pp2", common_objs }, { "lz4", "squish", "stb_image", "stb_image_write" } ) +bin( "pp2", { "pp2", "heightmap", "decompress_bc", common_objs }, { "lz4", "squish", "stb_image", "stb_image_write" } ) gcc_obj_cxxflags( "pp2", "-O2" ) msvc_obj_cxxflags( "pp2", "/O2" ) diff --git a/pp2.cc b/pp2.cc @@ -5,6 +5,7 @@ #include "dynstr.h" #include "int_conversions.h" #include "heightmap.h" +#include "decompress_bc.h" #include "autogdb.h" #include "libs/lz4/lz4.h" @@ -177,20 +178,20 @@ static void write_compressed_file( MemoryArena * arena, const DynamicString & pa struct RGBA { u8 r, g, b, a; }; -static void write_compressed_texture( MemoryArena * arena, const DynamicString & path, const array2d< RGBA > data, int squish_flags ) { - MEMARENA_SCOPED_CHECKPOINT( arena ); - +static u8 * write_compressed_texture( MemoryArena * arena, const DynamicString & path, const array2d< RGBA > data, int squish_flags ) { int w = checked_cast< int >( data.w ); int h = checked_cast< int >( data.h ); int dxt_size = squish::GetStorageRequirements( w, h, squish_flags ); - void * dxt = memarena_push_size( arena, dxt_size ); + u8 * dxt = memarena_push_many( arena, u8, dxt_size ); squish::CompressImage( ( const u8 * ) data.ptr(), w, h, dxt, squish_flags ); write_compressed_file( arena, path, dxt, dxt_size ); // DynamicString png_path( "{}.png", path ); // stbi_write_png( png_path.c_str(), data.w, data.h, 4, data.ptr(), 0 ); + + return dxt; } int main( int argc, char ** argv ) { @@ -209,9 +210,9 @@ int main( int argc, char ** argv ) { ASSERT( png != NULL ); array2d< u16 > heightmap( png, w, h ); + u8 * bc5_heightmap; { - MEMARENA_SCOPED_CHECKPOINT( &arena ); printf( "computing heightmaps\n" ); array2d< RGBA > heightmap_split = alloc_array2d< RGBA >( &arena, w, h ); @@ -227,7 +228,7 @@ int main( int argc, char ** argv ) { printf( "compressing\n" ); DynamicString heightmap_path( "{}/heightmap.bc5.lz4", output_path ); - write_compressed_texture( &arena, heightmap_path, heightmap_split, squish::kBc5 ); + bc5_heightmap = write_compressed_texture( &arena, heightmap_path, heightmap_split, squish::kBc5 ); } { @@ -280,9 +281,20 @@ int main( int argc, char ** argv ) { printf( "computing quadtree\n" ); array2d< u16 > heightmap1 = alloc_array2d< u16 >( &arena, heightmap.w + 1, heightmap.h + 1 ); - for( size_t y = 0; y < heightmap1.h; y++ ) { - for( size_t x = 0; x < heightmap1.w; x++ ) { - heightmap1( x, y ) = heightmap.try_get( x, y, 0 ); + + // TODO: this should just use bc5_to_heightmap once the Heightmap stuff is cleaned up + { + MEMARENA_SCOPED_CHECKPOINT( &arena ); + array2d< v2 > rg = alloc_array2d< v2 >( &arena, heightmap.w, heightmap.h ); + decompress_bc5( rg, bc5_heightmap ); + + v2 zero( 0, 0 ); + for( u32 y = 0; y < heightmap1.h; y++ ) { + for( u32 x = 0; x < heightmap1.w; x++ ) { + float r = rg.try_get( x, y, zero ).x; + float g = rg.try_get( x, y, zero ).y; + heightmap1( x, y ) = u16( ( r * 256.0f + g ) * 255.0f ); + } } }