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:
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 );
+ }
}
}