--- /dev/null
+#ifndef BVH_H
+#define BVH_H
+#include "common.h"
+
+/*
+ * Usage:
+ *
+ * create a bh_system with functions filled out for expand, centroid, and swap.
+ * optionally include item_debug and cast_ray functions if needed, otherwise,
+ * set them to null
+ *
+ * create a bh_tree struct with:
+ * user: a pointer back the base of the data you are ordering
+ * system: the system we created above which will deal with the data
+ *
+ * call bh_create( bh_tree *bh, u32 item_count, u32 item_size )
+ */
+
+typedef struct bh_node bh_node;
+typedef struct bh_tree bh_tree;
+typedef struct bh_system bh_system;
+
+struct bh_node
+{
+ boxf bbx;
+
+ /* if il is 0, this is a leaf */
+ u32 il, count;
+ union{ u32 ir, start; };
+};
+
+struct bh_tree
+{
+ bh_node *nodes;
+ u32 node_count;
+
+ bh_system *system;
+ void *user;
+};
+
+struct bh_system
+{
+ void (*expand_bound)( void *user, boxf bound, u32 item_index );
+ float (*item_centroid)( void *user, u32 item_index, int axis );
+ void (*item_swap)( void *user, u32 ia, u32 ib );
+ u32 item_size;
+
+ /*
+ * Optional:
+ * item_debug - draw this item quickly usually with lines
+ * cast_ray - shoot a ray against the object, if this is not set,
+ * raycasts will simply return the hit on the bvh node
+ */
+
+ void (*item_debug)( void *user, u32 item_index );
+ int (*cast_ray)( void *user, v3f co, v3f dir, ray_hit *hit );
+};
+
+static void bh_update_bounds( bh_tree *bh, u32 inode )
+{
+ bh_node *node = &bh->nodes[ inode ];
+
+ box_init_inf( node->bbx );
+ for( u32 i=0; i<node->count; i++ )
+ {
+ u32 idx = node->start+i;
+ bh->system->expand_bound( bh->user, node->bbx, idx );
+ }
+}
+
+static void bh_subdivide( bh_tree *bh, u32 inode )
+{
+ bh_node *node = &bh->nodes[ inode ];
+
+ v3f extent;
+ v3_sub( node->bbx[1], node->bbx[0], extent );
+
+ int axis = 0;
+ if( extent[1] > extent[0] ) axis = 1;
+ if( extent[2] > extent[axis] ) axis = 2;
+
+ float split = node->bbx[0][axis] + extent[axis]*0.5f;
+
+ float avg = 0.0;
+ for( u32 t=0; t<node->count; t++ )
+ {
+ u32 idx = node->start+t;
+ avg += bh->system->item_centroid( bh->user, idx, axis );
+ }
+ avg /= (float)node->count;
+
+ split = avg;
+
+ i32 i = node->start,
+ j = i + node->count-1;
+
+ while( i <= j )
+ {
+ if( bh->system->item_centroid( bh->user, i, axis ) < split )
+ i ++;
+ else
+ {
+ bh->system->item_swap( bh->user, i, j );
+ j --;
+ }
+ }
+
+ u32 left_count = i - node->start;
+ if( left_count == 0 || left_count == node->count ) return;
+
+ u32 il = bh->node_count ++,
+ ir = bh->node_count ++;
+
+ bh_node *lnode = &bh->nodes[il],
+ *rnode = &bh->nodes[ir];
+
+ lnode->start = node->start;
+ lnode->count = left_count;
+ rnode->start = i;
+ rnode->count = node->count - left_count;
+
+ node->il = il;
+ node->ir = ir;
+ node->count = 0;
+
+ /* TODO: Implement max depth, or stack */
+ bh_update_bounds( bh, il );
+ bh_update_bounds( bh, ir );
+ bh_subdivide( bh, il );
+ bh_subdivide( bh, ir );
+}
+
+static void bh_create( bh_tree *bh, bh_system *sys, u32 item_count )
+{
+ bh->system = sys;
+ bh->nodes = malloc( sys->item_size * (item_count*2-1) );
+
+ bh_node *root = &bh->nodes[0];
+ bh->node_count = 1;
+
+ root->il = 0;
+ root->ir = 0;
+ root->count = item_count;
+ root->start = 0;
+
+ bh_update_bounds( bh, 0 );
+ bh_subdivide( bh, 0 );
+
+ bh->nodes = realloc( bh->nodes, sys->item_size * bh->node_count );
+ vg_success( "BVH done, size: %u/%u\n", bh->node_count, (item_count*2-1) );
+}
+
+static void bh_debug_node( bh_tree *bh, u32 inode, v3f pos, u32 colour )
+{
+ bh_node *node = &bh->nodes[ inode ];
+
+ if( (pos[0] >= node->bbx[0][0] && pos[0] <= node->bbx[1][0]) &&
+ (pos[2] >= node->bbx[0][2] && pos[2] <= node->bbx[1][2]) )
+ {
+ if( !node->count )
+ {
+ vg_line_boxf( node->bbx, colour );
+
+ bh_debug_node( bh, node->il, pos, colour );
+ bh_debug_node( bh, node->ir, pos, colour );
+ }
+ else
+ {
+ vg_line_boxf( node->bbx, 0xff00ff00 );
+
+ if( bh->system->item_debug )
+ {
+ for( u32 i=0; i<node->count; i++ )
+ {
+ u32 idx = node->start+i;
+ bh->system->item_debug( bh->user, idx );
+ }
+ }
+ }
+ }
+}
+
+static int bh_ray( bh_tree *bh, u32 inode, v3f co, v3f dir, ray_hit *hit )
+{
+ int count = 0;
+ u32 stack[100];
+ u32 depth = 2;
+
+ stack[0] = 0;
+ stack[1] = bh->nodes[0].il;
+ stack[2] = bh->nodes[0].ir;
+
+ while(depth)
+ {
+ bh_node *inode = &bh->nodes[ stack[depth] ];
+ if( ray_aabb( inode->bbx, co, dir, hit->dist ) )
+ {
+ if( inode->count )
+ {
+ for( u32 i=0; i<inode->count; i++ )
+ {
+ u32 idx = inode->start+i;
+
+ if( bh->system->cast_ray )
+ count += bh->system->cast_ray( bh->user, co, dir, hit );
+ else
+ count ++;
+ }
+
+ depth --;
+ }
+ else
+ {
+ if( depth+1 >= vg_list_size(stack) )
+ {
+ vg_error( "Maximum stack reached!\n" );
+ return count;
+ }
+
+ stack[depth] = inode->il;
+ stack[depth+1] = inode->ir;
+ depth ++;
+ }
+ }
+ else
+ {
+ depth --;
+ }
+ }
+
+ return count;
+}
+
+static int bh_select( bh_tree *bh, boxf box, u32 *buffer, int len )
+{
+ int count = 0;
+ u32 stack[100];
+ u32 depth = 2;
+
+ stack[0] = 0;
+ stack[1] = bh->nodes[0].il;
+ stack[2] = bh->nodes[0].ir;
+
+ while(depth)
+ {
+ bh_node *inode = &bh->nodes[ stack[depth] ];
+ if( box_overlap( inode->bbx, box ) )
+ {
+ if( inode->count )
+ {
+ if( count + inode->count >= len )
+ {
+ vg_error( "Maximum buffer reached!\n" );
+ return count;
+ }
+
+ for( u32 i=0; i<inode->count; i++ )
+ buffer[ count ++ ] = inode->start+i;
+
+ depth --;
+ }
+ else
+ {
+ if( depth+1 >= vg_list_size(stack) )
+ {
+ vg_error( "Maximum stack reached!\n" );
+ return count;
+ }
+
+ stack[depth] = inode->il;
+ stack[depth+1] = inode->ir;
+ depth ++;
+ }
+ }
+ else
+ {
+ depth --;
+ }
+ }
+
+ return count;
+}
+
+#endif /* BVH_H */
.cam = {-0.3477f, 1.5884f, -0.0019f}
};
+static character_pose pose_stand_reverse =
+{
+ .b0 = {0.1624f, 1.0688f, -0.0632f},
+ .b1 = {0.0499f, 1.5564f, -0.0013f},
+ .p = {0.5423f, 1.2810f, -0.2368f},
+ .fr = {0.0535f, 0.1312f, -0.3647f},
+ .fl = {0.0354f, 0.1464f, 0.2917f},
+ .pl = {-0.4325f, 0.6889f, 0.4591f},
+ .pr = {-0.4794f, 0.7598f, -0.0842f},
+ .hl = {0.0498f, 1.0058f, 0.2317f},
+ .hr = {0.0188f, 0.9786f, -0.2725f},
+ .apl = {0.2898f, 1.3453f, 0.0695f},
+ .apr = {0.4715f, 1.2876f, -0.4982f},
+ .cam = {-0.3477f, 1.5884f, -0.0730f}
+};
+
static character_pose pose_fly =
{
.b0 = {0.2995f, 0.6819f, -0.1369f},
static void character_ragdoll_iter( struct character *ch )
{
for( int i=0; i<PART_COUNT; i++ )
- rb_build_manifold( &ch->ragdoll[i] );
+ {
+ rb_manifold_reset( &ch->ragdoll[i] );
+ rb_build_manifold_terrain( &ch->ragdoll[i] );
+
+ u32 colliders[16];
+ int len = bh_select( &world.bhcubes, ch->ragdoll[i].bbx_world,
+ colliders, 16 );
+
+ for( int j=0; j<len; j++ )
+ rb_build_manifold_rb_static( &ch->ragdoll[i],
+ &world.temp_rbs[colliders[j]] );
+ }
v3f rv;
k_classtype_gate = 1
};
+/* TODO: he needs a home somewhere */
+typedef struct ray_hit ray_hit;
+struct ray_hit
+{
+ float dist;
+ u32 *tri;
+ v3f pos, normal;
+};
+
#endif /* COMMON_H */
#include "model.h"
#include "render.h"
#include "shaders/gate.h"
+#include "shaders/gatelq.h"
+#include "water.h"
typedef struct teleport_gate teleport_gate;
{
GLuint fb, rgb, rb;
glmesh mdl;
+
+ int high_qual; /* If in high performance mode, we don't use RT's, and
+ instead use stencil buffers.
+ There is therefore no heat warp effect. */
}
-grender;
+grender =
+{
+ .high_qual = 0
+};
struct teleport_gate
{
static void gate_register(void)
{
shader_gate_register();
+ shader_gatelq_register();
}
static void gate_init(void)
if( v3_dot(v0, gatedir) >= 0.0f )
return;
+ if( v3_dist( viewpos, gate->co[0] ) > 100.0f )
+ return;
+
v3f a,b,c,d;
float sx = gate->dims[0],
vg_line_pt3( cam_new[3], 0.3f, 0xff00ff00 );
- glBindFramebuffer( GL_FRAMEBUFFER, grender.fb );
- glClearColor( 0.11f, 0.35f, 0.37f, 1.0f );
- glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
-
+ m4x3f gate_xform;
+ m4x3_copy( gate->to_world, gate_xform );
+ m4x3_scalev( gate_xform, (v3f){ gate->dims[0], gate->dims[1], 1.0f } );
+
m4x3f inverse;
m4x3_invert_affine( cam_new, inverse );
m4x4f projection;
pipeline_projection( projection, 0.1f, 900.0f );
-
m4x3_mulp( inverse, surface, surface );
surface[3] = -fabsf(surface[3]);
plane_clip_projection( projection, surface );
m4x4_mul( projection, view, projection );
-
- render_world( projection, cam_new );
- render_water_texture( cam_new );
- glBindFramebuffer( GL_FRAMEBUFFER, grender.fb );
- render_water_surface( projection );
- glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-
- shader_gate_use();
-
- m4x3f full;
- m4x3_copy( gate->to_world, full );
- m4x3_scalev( full, (v3f){ gate->dims[0], gate->dims[1], 1.0f } );
-
- shader_gate_uPv( vg_pv );
- shader_gate_uMdl( full );
-
- glActiveTexture( GL_TEXTURE0 );
- glBindTexture( GL_TEXTURE_2D, grender.rgb );
- shader_gate_uCam( viewpos );
- shader_gate_uTexMain( 0 );
- shader_gate_uTexWater( 1 );
- shader_gate_uTime( vg_time*0.25f );
- shader_gate_uInvRes( (v2f){
- 1.0f / (float)vg_window_x,
- 1.0f / (float)vg_window_y });
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
- glBlendEquation(GL_FUNC_ADD);
- mesh_bind( &grender.mdl );
- mesh_draw( &grender.mdl );
+ if( grender.high_qual )
+ {
+ glBindFramebuffer( GL_FRAMEBUFFER, grender.fb );
+ glClearColor( 0.11f, 0.35f, 0.37f, 1.0f );
+ glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
+ }
+ else
+ {
+ shader_gatelq_use();
+ shader_gatelq_uPv( vg_pv );
+ shader_gatelq_uMdl( gate_xform );
+ shader_gatelq_uCam( viewpos );
+ shader_gatelq_uTime( vg_time*0.25f );
+ shader_gatelq_uInvRes( (v2f){
+ 1.0f / (float)vg_window_x,
+ 1.0f / (float)vg_window_y });
+
+ glEnable( GL_STENCIL_TEST );
+ glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
+ glStencilFunc( GL_ALWAYS, 1, 0xFF );
+ glStencilMask( 0xFF );
+
+ mesh_bind( &grender.mdl );
+ mesh_draw( &grender.mdl );
+
+ glClear( GL_DEPTH_BUFFER_BIT );
+ glStencilFunc( GL_EQUAL, 1, 0xFF );
+ glStencilMask( 0x00 );
+ }
- glDisable(GL_BLEND);
+ render_world( projection, cam_new );
+
+ if( grender.high_qual )
+ {
+ /*
+ * TODO: Need to find a way to draw a stencil buffer into the water
+ * rendering
+ */
+
+ render_water_texture( cam_new );
+ glBindFramebuffer( GL_FRAMEBUFFER, grender.fb );
+ render_water_surface( projection );
+ glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+
+ shader_gate_use();
+
+ shader_gate_uPv( vg_pv );
+ shader_gate_uMdl( gate_xform );
+
+ glActiveTexture( GL_TEXTURE0 );
+ glBindTexture( GL_TEXTURE_2D, grender.rgb );
+ shader_gate_uCam( viewpos );
+ shader_gate_uTexMain( 0 );
+ shader_gate_uTexWater( 1 );
+ shader_gate_uTime( vg_time*0.25f );
+ shader_gate_uInvRes( (v2f){
+ 1.0f / (float)vg_window_x,
+ 1.0f / (float)vg_window_y });
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glBlendEquation(GL_FUNC_ADD);
+
+ mesh_bind( &grender.mdl );
+ mesh_draw( &grender.mdl );
+
+ glDisable(GL_BLEND);
+ }
+ else
+ {
+ glStencilMask( 0xFF );
+ glStencilFunc( GL_ALWAYS, 1, 0xFF );
+ glDisable( GL_STENCIL_TEST );
+ }
}
static int gate_intersect( teleport_gate *gate, v3f pos, v3f last )
glDisable( GL_DEPTH_TEST );
glClearColor( 0.11f, 0.35f, 0.37f, 1.0f );
- glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
float speed = freecam? 0.0f: v3_length( player.v );
v3f shake = { vg_randf()-0.5f, vg_randf()-0.5f, vg_randf()-0.5f };
float best_velocity_mod = 0.0f,
best_velocity_delta = -9999.9f;
+ float k_bias = 0.97f;
+
v3f axis, vup;
m3x3_mulv( player.to_world, (v3f){0.0f,1.0f,0.0f}, vup );
v3_cross( vup, player.v, axis );
v3f pco, pco1, pv;
v3_copy( player.co, pco );
- v3_copy( player.v, pv );
+ v3_muls( player.v, k_bias, pv );
/*
* Try different 'rotations' of the velocity to find the best possible
q_m3x3( vr_q, vr );
m3x3_mulv( vr, pv, pv );
- v3_muladds( pco, pv, ktimestep, pco );
+ v3_muladds( pco, pv, pstep, pco );
for( int i=0; i<50; i++ )
{
static void player_physics_air(void)
{
m3x3_mulv( player.vr, player.v, player.v );
- for( int i=0; i<player.land_log_count; i++ )
- draw_cross( player.land_target_log[i], player.land_target_colours[i], 1);
-
draw_cross( player.land_target, 0xff0000ff, 1 );
v3f ground_pos;
player.angles[0] = atan2f( player.vl[0], -player.vl[2] );
player.angles[1] = atan2f( -player.vl[1], sqrtf(player.vl[0]*player.vl[0]+
player.vl[2]*player.vl[2]) ) * 0.3f;
-
- player.air_blend = vg_lerpf( player.air_blend, player.in_air, 0.04f );
- v3_muladds( player.camera_pos, player.v, -0.05f*player.air_blend,
- player.camera_pos );
}
static int player_walkgrid_tri_walkable( u32 tri[3] )
amt_aero = amt_std * (1.0f-fstand),
amt_slide = amt_ground * fslide;
- character_final_pose( &player.mdl, offset, &pose_stand, amt_stand );
+ character_final_pose( &player.mdl, offset, &pose_stand, amt_stand*fdirz );
+ character_final_pose( &player.mdl, offset,
+ &pose_stand_reverse, amt_stand * (1.0f-fdirz) );
+
character_final_pose( &player.mdl, offset, &pose_aero, amt_aero*fdirz );
character_final_pose( &player.mdl, offset,
&pose_aero_reverse, amt_aero * (1.0f-fdirz) );
+
character_final_pose( &player.mdl, offset, &pose_slide, amt_slide*fdirx );
character_final_pose( &player.mdl, offset,
&pose_slide1, amt_slide*(1.0f-fdirx) );
player.camera_pos[1] = vg_clampf( player.camera_pos[1], 0.3f, kheight );
m4x3_mulv( player.to_world, player.camera_pos, player.camera_pos );
+ player.air_blend = vg_lerpf( player.air_blend, player.in_air, 0.04f );
+ v3_muladds( player.camera_pos, player.v, -0.05f*player.air_blend,
+ player.camera_pos );
+
/*
* Additive effects
* ==========================
for( int i=0; i<len; i++ )
{
- if( (points[i][2]-points[p][2])*(points[q][0]-points[i][0]) -
- (points[i][0]-points[p][0])*(points[q][2]-points[i][2])
- > 0.0001f )
+ float orient =
+ (points[i][2]-points[p][2])*(points[q][0]-points[i][0]) -
+ (points[i][0]-points[p][0])*(points[q][2]-points[i][2]);
+
+ if( orient > 0.0001f )
{
q = i;
}
m4x3_mulv( compound, (v3f){ a[0], b[1], a[2] }, verts[1] );
m4x3_mulv( compound, (v3f){ b[0], b[1], a[2] }, verts[2] );
m4x3_mulv( compound, (v3f){ b[0], a[1], a[2] }, verts[3] );
-
m4x3_mulv( compound, (v3f){ a[0], a[1], b[2] }, verts[4] );
m4x3_mulv( compound, (v3f){ a[0], b[1], b[2] }, verts[5] );
m4x3_mulv( compound, (v3f){ b[0], b[1], b[2] }, verts[6] );
int hull_indices[12*2 + 8];
int hull_len = 0;
+ for( int i=0; i<8; i++ )
+ {
+ int ia = indices[i][0];
+ float ya = verts[ia][1];
+
+ if( ya > 0.2f && ya < kheight )
+ {
+ int add_point = 1;
+ for( int j=0; j<hull_len; j++ )
+ {
+ v2f delta = { verts[ia][0]-hull[j][0], verts[ia][2]-hull[j][2] };
+ if( v2_length2( delta ) < 0.0004f )
+ {
+ add_point = 0;
+ break;
+ }
+ }
+
+ if( add_point )
+ v3_copy( verts[ia], hull[hull_len] );
+
+ hull[hull_len ++][1] = 0.2f;
+ }
+ }
+
for( int i=0; i<vg_list_size(indices); i++ )
{
int ia = indices[i][0],
d = 1.0f/(yb-ya),
qa;
- if( (ya-0.2f) * (yb-0.2f) < 0.0f )
+ float planes[] = { 0.2f, kheight };
+
+ for( int k=0; k<vg_list_size(planes); k++ )
{
- v3_muls( verts[ia], (yb-0.2f)*d, p0 );
- v3_muladds( p0, verts[ib], -(ya-0.2f)*d, p0 );
-
- v3_copy( p0, hull[hull_len] );
- hull[hull_len ++][1] = 0.2f;
-
- m4x3_mulv( player.to_world, p0, p0 );
- vg_line_pt3( p0, 0.1f, 0xffffff00 );
- }
+ float clip = planes[k];
- if( (ya-kheight) * (yb-kheight) < 0.0f )
- {
- v3_muls( verts[ia], (yb-kheight)*d, p0 );
- v3_muladds( p0, verts[ib], -(ya-kheight)*d, p0 );
+ if( (ya-clip) * (yb-clip) < 0.0f )
+ {
+ v3_muls( verts[ia], (yb-clip)*d, p0 );
+ v3_muladds( p0, verts[ib], -(ya-clip)*d, p0 );
+
+ int add_point = 1;
+ for( int j=0; j<hull_len; j++ )
+ {
+ v2f delta = { p0[0]-hull[j][0], p0[2]-hull[j][2] };
+ if( v2_length2( delta ) < 0.0004f )
+ {
+ add_point = 0;
+ break;
+ }
+ }
- v3_copy( p0, hull[hull_len] );
- hull[hull_len ++][1] = 0.2f;
+ if( add_point )
+ v3_copy( p0, hull[hull_len ++] );
- m4x3_mulv( player.to_world, p0, p0 );
- vg_line_pt3( p0, 0.1f, 0xff00ffff );
- }
- }
- for( int i=0; i<8; i++ )
- {
- int ia = indices[i][0];
- float ya = verts[ia][1];
-
- if( ya > 0.2f && ya < kheight )
- {
- v3_copy( verts[ia], hull[hull_len] );
- hull[hull_len ++][1] = 0.2f;
+ m4x3_mulv( player.to_world, p0, p0 );
+ vg_line_pt3( p0, 0.1f, 0xffffff00 );
+ }
}
}
v3f p0, p1, p2, p3;
v3_copy( hull[hull_indices[i]], p0 );
v3_copy( hull[hull_indices[(i+1)%len]], p1 );
+ p0[1] = 0.2f;
+ p1[1] = 0.2f;
v3_add( p0, (v3f){0,kheight-0.2f,0}, p2 );
v3_add( p1, (v3f){0,kheight-0.2f,0}, p3 );
vg_line( p0, p2, 0xff00ffa0 );
}
- int collide = 1;
- float min_dist = 99999.9f;
- v2f normal;
- for( int i=0; i<len; i++ )
+ v2f endpoints[] = {{ 0.0f, -1.0f },{ 0.0f, 1.0f }};
+
+ for( int j=0; j<vg_list_size(endpoints); j++ )
{
- v2f p0, p1;
- p0[0] = hull[hull_indices[i]][0];
- p0[1] = hull[hull_indices[i]][2];
- p1[0] = hull[hull_indices[(i+1)%len]][0];
- p1[1] = hull[hull_indices[(i+1)%len]][2];
-
- v2f t,n, rel;
- v2_sub( p1, p0, t );
- n[0] = -t[1];
- n[1] = t[0];
- v2_normalize(n);
-
- v2_sub( (v2f){ 0.0f, -1.0f }, p0, rel );
- float d = -v2_dot( n, rel ) + 0.5f;
+ v2f point;
+ v2_copy( endpoints[j], point );
- if( d < 0.0f )
+ int collide = 1;
+ float min_dist = 99999.9f;
+ v2f normal;
+ for( int i=0; i<len; i++ )
{
- collide = 0;
- break;
- }
+ v2f p0, p1;
+ p0[0] = hull[hull_indices[i]][0];
+ p0[1] = hull[hull_indices[i]][2];
+ p1[0] = hull[hull_indices[(i+1)%len]][0];
+ p1[1] = hull[hull_indices[(i+1)%len]][2];
+
+ v2f t,n, rel;
+ v2_sub( p1, p0, t );
+ n[0] = -t[1];
+ n[1] = t[0];
+ v2_normalize(n);
+
+ v2_sub( point, p0, rel );
+ float d = -v2_dot( n, rel ) + 0.5f;
- if( d < min_dist )
- {
- min_dist = d;
- v2_copy( n, normal );
- }
- }
+ if( d < 0.0f )
+ {
+ collide = 0;
+ break;
+ }
- if( collide )
- {
- v3f p0, p1;
- p0[0] = 0.0f;
- p0[1] = 0.2f;
- p0[2] = -1.0f;
+ if( d < min_dist )
+ {
+ min_dist = d;
+ v2_copy( n, normal );
+ }
+ }
- p1[0] = p0[0] + normal[0]*min_dist;
- p1[1] = p0[1];
- p1[2] = p0[2] + normal[1]*min_dist;
-
- m4x3_mulv( player.to_world, p0, p0 );
- m4x3_mulv( player.to_world, p1, p1 );
+ if( collide )
+ {
+ v3f p0, p1;
+ p0[0] = 0.0f;
+ p0[1] = 0.2f;
+ p0[2] = -1.0f;
+
+ p1[0] = p0[0] + normal[0]*min_dist;
+ p1[1] = p0[1];
+ p1[2] = p0[2] + normal[1]*min_dist;
+
+ m4x3_mulv( player.to_world, p0, p0 );
+ m4x3_mulv( player.to_world, p1, p1 );
- vg_line( p0, p1, 0xffffffff );
+ vg_line( p0, p1, 0xffffffff );
+
+ v3f vel;
+ m3x3_mulv( player.to_local, player.v, vel );
+ vel[1] = vel[2];
- v2f impulse;
- v2_muls( normal, min_dist, impulse );
- float rotation = v2_cross( (v2f){0.0f,-1.0f}, impulse )*0.08f;
-
- v3f vel;
- m3x3_mulv( player.to_local, player.v, vel );
- vel[1] = vel[2];
+ float vn = vg_maxf( -v2_dot( vel, normal ), 0.0f );
+ vn += -0.2f * (1.0f/k_rb_delta) * vg_minf( 0.0f, -min_dist+0.04f );
+
+ v2f impulse;
+ if( vn > 14.0f )
+ {
+ player.is_dead = 1;
+ character_ragdoll_copypose( &player.mdl, player.v );
+ return;
+ }
- float vn = vg_maxf( -v2_dot( vel, normal ), 0.0f );
- vn += -0.2f * (1.0f/k_rb_delta) * vg_minf( 0.0f, -min_dist+0.04f );
+ if( vn > 0.0f )
+ {
+ v2_muls( normal, min_dist, impulse );
+ float rotation = v2_cross( point, impulse )*0.08f;
+ v4f rot;
+ v3f up = {0.0f,1.0f,0.0f};
+ m3x3_mulv( player.to_world, up, up );
+ q_axis_angle( rot, up, -rotation );
+ q_mul( rot, player.rot, player.rot );
+ }
- v2_muls( normal, vn*0.03f, impulse );
- v3f impulse_world = { impulse[0], 0.0f, impulse[1] };
+ v2_muls( normal, vn*0.03f, impulse );
+ v3f impulse_world = { impulse[0], 0.0f, impulse[1] };
- m3x3_mulv( player.to_world, impulse_world, impulse_world );
- v3_add( impulse_world, player.v, player.v );
-
- v4f rot;
- v3f up = {0.0f,1.0f,0.0f};
- m3x3_mulv( player.to_world, up, up );
- q_axis_angle( rot, up, -rotation );
- q_mul( rot, player.rot, player.rot );
+ m3x3_mulv( player.to_world, impulse_world, impulse_world );
+ v3_add( impulse_world, player.v, player.v );
+ }
}
}
static void player_update(void)
{
+ for( int i=0; i<player.land_log_count; i++ )
+ draw_cross( player.land_target_log[i], player.land_target_colours[i], 1);
+
if( vg_get_axis("grabl")>0.0f)
reset_player(0,NULL);
{
if( player.on_board )
{
- for( int i=0; i<world.rb_count; i++ )
- player_do_collision( &world.temp_rbs[i] );
+ bh_debug_node(&world.bhcubes, 0,
+ player.camera_pos, 0xff80ff00 );
+
+ u32 colliders[16];
+ boxf wbox = {{ -2.0f, -2.0f, -2.0f },
+ { 2.0f, 2.0f, 2.0f }};
+ m4x3_transform_aabb( player.to_world, wbox );
+ int len = bh_select( &world.bhcubes, wbox, colliders, 32 );
+
+ for( int i=0; i<len; i++ )
+ player_do_collision( &world.temp_rbs[colliders[i]] );
player_do_motion();
player_animate();
* qu3e - Randy Gaul
*/
-#include "vg/vg.h"
+#include "common.h"
static void rb_tangent_basis( v3f n, v3f tx, v3f ty );
#ifndef RIGIDBODY_H
#define RIGIDBODY_H
+#include "bvh.h"
+
#define RB_DEPR
#define k_rb_delta (1.0f/60.0f)
{
v3f co, v, I;
v4f q;
- boxf bbx;
+ boxf bbx, bbx_world;
float inv_mass;
struct contact
v3f t[2];
float bias, norm_impulse, tangent_impulse[2];
}
- manifold[4];
+ manifold[12];
int manifold_count;
v3f delta; /* where is the origin of this in relation to a parent body */
v3_copy( rb->co, rb->to_world[3] );
m4x3_invert_affine( rb->to_world, rb->to_local );
+
+ box_copy( rb->bbx, rb->bbx_world );
+ m4x3_transform_aabb( rb->to_world, rb->bbx_world );
}
static void rb_init( rigidbody *rb )
#include "world.h"
-static void rb_build_manifold( rigidbody *rb )
+static void rb_manifold_reset( rigidbody *rb )
+{
+ rb->manifold_count = 0;
+}
+
+static void rb_build_manifold_terrain( rigidbody *rb )
{
v3f *box = rb->bbx;
v3f pts[8];
m4x3_mulv( rb->to_world, p110, p110 );
m4x3_mulv( rb->to_world, p111, p111 );
- rb->manifold_count = 0;
+ int count = 0;
for( int i=0; i<8; i++ )
{
ct->tangent_impulse[1] = 0.0f;
rb->manifold_count ++;
- if( rb->manifold_count == 4 )
+ count ++;
+ if( count == 4 )
break;
}
}
float impulse, bias;
};
-static int rb_angle_limit_force(
- rigidbody *rba, v3f va,
+static int rb_angle_limit_force( rigidbody *rba, v3f va,
rigidbody *rbb, v3f vb,
float max )
{
return 0;
}
+static void rb_build_manifold_rb_static( rigidbody *ra, rigidbody *rb_static )
+{
+ v3f verts[8];
+
+ v3f a, b;
+ v3_copy( ra->bbx[0], a );
+ v3_copy( ra->bbx[1], b );
+
+ m4x3_mulv( ra->to_world, (v3f){ a[0], a[1], a[2] }, verts[0] );
+ m4x3_mulv( ra->to_world, (v3f){ a[0], b[1], a[2] }, verts[1] );
+ m4x3_mulv( ra->to_world, (v3f){ b[0], b[1], a[2] }, verts[2] );
+ m4x3_mulv( ra->to_world, (v3f){ b[0], a[1], a[2] }, verts[3] );
+ m4x3_mulv( ra->to_world, (v3f){ a[0], a[1], b[2] }, verts[4] );
+ m4x3_mulv( ra->to_world, (v3f){ a[0], b[1], b[2] }, verts[5] );
+ m4x3_mulv( ra->to_world, (v3f){ b[0], b[1], b[2] }, verts[6] );
+ m4x3_mulv( ra->to_world, (v3f){ b[0], a[1], b[2] }, verts[7] );
+
+ int count = 0;
+
+ for( int i=0; i<8; i++ )
+ {
+ if( ra->manifold_count == vg_list_size(ra->manifold) )
+ return;
+
+ struct contact *ct = &ra->manifold[ ra->manifold_count ];
+
+ float p;
+ v3f normal;
+
+ if( rb_point_in_body( rb_static, verts[i], &p, normal ))
+ {
+ v3_copy( normal, ct->n );
+ v3_muladds( verts[i], ct->n, p*0.5f, ct->co );
+ v3_sub( ct->co, ra->co, ct->delta );
+
+ vg_line_pt3( ct->co, 0.0125f, 0xffff00ff );
+
+ ct->bias = -0.2f * (1.0f/k_rb_delta) * vg_minf( 0.0f, -p+0.04f );
+ rb_tangent_basis( ct->n, ct->t[0], ct->t[1] );
+
+ ct->norm_impulse = 0.0f;
+ ct->tangent_impulse[0] = 0.0f;
+ ct->tangent_impulse[1] = 0.0f;
+
+ ra->manifold_count ++;
+ count ++;
+ if( count == 4 )
+ return;
+ }
+ }
+}
+
+/*
+ * BVH implementation, this is ONLY for static rigidbodies, its to slow for
+ * realtime use.
+ */
+
+static void rb_bh_expand_bound( void *user, boxf bound, u32 item_index )
+{
+ rigidbody *rb = &((rigidbody *)user)[ item_index ];
+ box_concat( bound, rb->bbx_world );
+}
+
+static float rb_bh_centroid( void *user, u32 item_index, int axis )
+{
+ rigidbody *rb = &((rigidbody *)user)[ item_index ];
+ return (rb->bbx_world[axis][0] + rb->bbx_world[1][axis]) * 0.5f;
+}
+
+static void rb_bh_swap( void *user, u32 ia, u32 ib )
+{
+ rigidbody temp, *rba, *rbb;
+ rba = &((rigidbody *)user)[ ia ];
+ rbb = &((rigidbody *)user)[ ib ];
+
+ temp = *rba;
+ *rba = *rbb;
+ *rbb = temp;
+}
+
+static void rb_bh_debug( void *user, u32 item_index )
+{
+ rigidbody *rb = &((rigidbody *)user)[ item_index ];
+ rb_debug( rb, 0xff00ffff );
+}
+
+static bh_system bh_system_rigidbodies =
+{
+ .expand_bound = rb_bh_expand_bound,
+ .item_centroid = rb_bh_centroid,
+ .item_swap = rb_bh_swap,
+ .item_debug = rb_bh_debug,
+ .cast_ray = NULL,
+
+ .item_size = sizeof(rigidbody)
+};
+
#endif /* RIGIDBODY_H */
#ifndef SCENE_H
#define SCENE_H
-#include "vg/vg.h"
+#include "common.h"
#include "model.h"
typedef struct scene scene;
normal[2] = 0.0f;
}
+
+/*
+ *
+ *
+ * TODO: THIS SHIT IS DEPRECATED FOR THE NEW SHIT IN BVH.H
+ *
+ *
+ */
+
struct bvh_node
{
boxf bbx;
float split = node->bbx[0][axis] + extent[axis]*0.5f;
- /* To beat: 121,687 / 136,579
- * 136,375
- */
-
float avg = 0.0;
for( u32 t=0; t<node->count; t++ )
{
u32 *ti = &s->indices[(node->start+t)*3];
float a = s->verts[ti[0]].co[axis],
- b = s->verts[ti[1]].co[axis],
- c = s->verts[ti[2]].co[axis];
- avg += (a+b+c)/3.0;
+ b = s->verts[ti[1]].co[axis],
+ c = s->verts[ti[2]].co[axis];
+ avg += (a+b+c) * (1.0f/3.0f);
}
avg /= (float)node->count;
b = s->verts[ti[1]].co[axis],
c = s->verts[ti[2]].co[axis];
- if( ((a+b+c) / 3.0f) < split )
+ if( (a+b+c) * (1.0f/3.0f) < split )
i ++;
else
{
bvh_debug_node( s, 0, pos, 0x4000ffa8 );
}
-typedef struct ray_hit ray_hit;
-struct ray_hit
-{
- float dist;
- u32 *tri;
- v3f pos, normal;
-};
-
-int ray_aabb( boxf box, v3f co, v3f dir, float dist )
-{
- v3f v0, v1;
- float tmin, tmax;
-
- v3_sub( box[0], co, v0 );
- v3_sub( box[1], co, v1 );
- v3_div( v0, dir, v0 );
- v3_div( v1, dir, v1 );
-
- tmin = vg_minf( v0[0], v1[0] );
- tmax = vg_maxf( v0[0], v1[0] );
- tmin = vg_maxf( tmin, vg_minf( v0[1], v1[1] ));
- tmax = vg_minf( tmax, vg_maxf( v0[1], v1[1] ));
- tmin = vg_maxf( tmin, vg_minf( v0[2], v1[2] ));
- tmax = vg_minf( tmax, vg_maxf( v0[2], v1[2] ));
-
- return tmax >= tmin && tmin < dist && tmax > 0;
-}
-
static int bvh_ray_tri( scene *sc, u32 *tri, v3f co, v3f dir, ray_hit *hit )
{
v3f positions[3];
static int bvh_ray( scene *s, u32 inode, v3f co, v3f dir, ray_hit *hit )
{
+#if 0
bvh_node *node = &s->bvh.nodes[ inode ];
if( !ray_aabb( node->bbx, co, dir, hit->dist ))
count += bvh_ray( s, node->ir, co, dir, hit );
}
+ return count;
+#endif
+
+ int count = 0;
+ u32 stack[100];
+ u32 depth = 2;
+
+ stack[0] = 0;
+ stack[1] = s->bvh.nodes[0].il;
+ stack[2] = s->bvh.nodes[0].ir;
+
+ while(depth)
+ {
+ bvh_node *inode = &s->bvh.nodes[ stack[depth] ];
+ if( ray_aabb( inode->bbx, co, dir, hit->dist ) )
+ {
+ if( inode->count )
+ {
+ for( u32 i=0; i<inode->count; i++ )
+ {
+ u32 *indices = &s->indices[ (inode->start+i)*3 ];
+ count += bvh_ray_tri( s, indices, co, dir, hit );
+ }
+
+ depth --;
+ }
+ else
+ {
+ if( depth+1 >= vg_list_size(stack) )
+ {
+ vg_error( "Maximum stack reached!\n" );
+ return count;
+ }
+
+ stack[depth] = inode->il;
+ stack[depth+1] = inode->ir;
+ depth ++;
+ }
+ }
+ else
+ {
+ depth --;
+ }
+ }
+
return count;
}
--- /dev/null
+out vec4 FragColor;
+
+uniform float uTime;
+uniform vec3 uCam;
+uniform vec2 uInvRes;
+
+in vec3 aNorm;
+in vec2 aUv;
+in vec3 aCo;
+
+void main()
+{
+ vec2 ssuv = gl_FragCoord.xy;
+ float opacity = 1.0-smoothstep(0.4,1.0,aUv.y);
+
+ vec3 vDither = vec3( dot( vec2( 171.0, 231.0 ), ssuv) );
+ float dither = fract( vDither.g / 71.0 ) - 0.5;
+
+ if( opacity+dither<0.5 )
+ discard;
+
+ FragColor = vec4( 0.0, 1.0, 0.0, 1.0 );
+}
--- /dev/null
+#ifndef SHADER_gatelq_H
+#define SHADER_gatelq_H
+static void shader_gatelq_link(void);
+static void shader_gatelq_register(void);
+static struct vg_shader _shader_gatelq = {
+ .name = "gatelq",
+ .link = shader_gatelq_link,
+ .vs =
+{
+.orig_file = "../shaders/gate.vs",
+.static_src =
+"layout (location=0) in vec3 a_co;\n"
+"layout (location=1) in vec3 a_norm;\n"
+"layout (location=2) in vec4 a_colour;\n"
+"layout (location=3) in vec2 a_uv;\n"
+"\n"
+"#line 2 0 \n"
+"uniform mat4 uPv;\n"
+"uniform mat4x3 uMdl;\n"
+"\n"
+"out vec3 aNorm;\n"
+"out vec2 aUv;\n"
+"out vec3 aCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+" vec3 world_pos = uMdl * vec4( a_co, 1.0 );\n"
+" gl_Position = uPv * vec4(world_pos,1.0);\n"
+"\n"
+" aNorm = a_norm;\n"
+" aCo = world_pos;\n"
+" aUv = a_uv;\n"
+"}\n"
+""},
+ .fs =
+{
+.orig_file = "../shaders/gate_lq.fs",
+.static_src =
+"out vec4 FragColor;\n"
+"\n"
+"uniform float uTime;\n"
+"uniform vec3 uCam;\n"
+"uniform vec2 uInvRes;\n"
+"\n"
+"in vec3 aNorm;\n"
+"in vec2 aUv;\n"
+"in vec3 aCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+" vec2 ssuv = gl_FragCoord.xy;\n"
+" float opacity = 1.0-smoothstep(0.4,1.0,aUv.y);\n"
+" \n"
+" vec3 vDither = vec3( dot( vec2( 171.0, 231.0 ), ssuv) );\n"
+" float dither = fract( vDither.g / 71.0 ) - 0.5;\n"
+"\n"
+" if( opacity+dither<0.5 )\n"
+" discard;\n"
+"\n"
+" FragColor = vec4( 0.0, 1.0, 0.0, 1.0 );\n"
+"}\n"
+""},
+};
+
+static GLuint _uniform_gatelq_uPv;
+static GLuint _uniform_gatelq_uMdl;
+static GLuint _uniform_gatelq_uTime;
+static GLuint _uniform_gatelq_uCam;
+static GLuint _uniform_gatelq_uInvRes;
+static void shader_gatelq_uPv(m4x4f m){
+ glUniformMatrix4fv( _uniform_gatelq_uPv, 1, GL_FALSE, (float *)m );
+}
+static void shader_gatelq_uMdl(m4x3f m){
+ glUniformMatrix4x3fv( _uniform_gatelq_uMdl, 1, GL_FALSE, (float *)m );
+}
+static void shader_gatelq_uTime(float f){
+ glUniform1f( _uniform_gatelq_uTime, f );
+}
+static void shader_gatelq_uCam(v3f v){
+ glUniform3fv( _uniform_gatelq_uCam, 1, v );
+}
+static void shader_gatelq_uInvRes(v2f v){
+ glUniform2fv( _uniform_gatelq_uInvRes, 1, v );
+}
+static void shader_gatelq_register(void){
+ vg_shader_register( &_shader_gatelq );
+}
+static void shader_gatelq_use(void){ glUseProgram(_shader_gatelq.id); }
+static void shader_gatelq_link(void){
+ _uniform_gatelq_uPv = glGetUniformLocation( _shader_gatelq.id, "uPv" );
+ _uniform_gatelq_uMdl = glGetUniformLocation( _shader_gatelq.id, "uMdl" );
+ _uniform_gatelq_uTime = glGetUniformLocation( _shader_gatelq.id, "uTime" );
+ _uniform_gatelq_uCam = glGetUniformLocation( _shader_gatelq.id, "uCam" );
+ _uniform_gatelq_uInvRes = glGetUniformLocation( _shader_gatelq.id, "uInvRes" );
+}
+#endif /* SHADER_gatelq_H */
shader unlit standard.vs unlit.fs
shader character character.vs character.fs
shader gate gate.vs gate.fs
+shader gatelq gate.vs gate_lq.fs
shader water water.vs water.fs
shader sky standard.vs sky.fs
#include "water.h"
#include "rigidbody.h"
#include "gate.h"
+#include "bvh.h"
#include "shaders/standard.h"
teleport_gate gates[16];
u32 gate_count;
-
+
rigidbody temp_rbs[32];
u32 rb_count;
+
+ bh_tree bhcubes;
}
world;
+
+
static void render_world( m4x4f projection, m4x3f camera )
{
render_sky( camera );
return hit->tri[0] < world.sm_road.vertex_count;
}
+static bh_system bh_system_rigidbodies;
static void world_load(void)
{
/* Setup scene */
*
* then compute bvh
*/
-#if 0
- scene_add_foliage( &world.foliage, mworld, boxtest, world.box.to_world );
-#endif
-
-
-#if 0
- submodel *boxtest = submodel_get( mworld, "cubey" );
-
-#endif
for( int i=0; i<mworld->layer_count; i++ )
{
rb_update_transform( rb );
}
-
free( mworld );
v3f volume;
free( mfoliage );
scene_upload( &world.foliage );
+
+ world.bhcubes.user = world.temp_rbs;
+ bh_create( &world.bhcubes, &bh_system_rigidbodies, world.rb_count );
}
#endif /* WORLD_H */