From: hgn Date: Wed, 24 Jan 2024 06:32:18 +0000 (+0000) Subject: seperation of body initialization, glider model X-Git-Url: https://harrygodden.com/git/?p=carveJwlIkooP6JGAAIwe30JlM.git;a=commitdiff_plain;h=171b279a489f1b906265759b33249f61d48d3d5f seperation of body initialization, glider model --- diff --git a/player.c b/player.c index 3a5c100..f52c8bd 100644 --- a/player.c +++ b/player.c @@ -245,7 +245,7 @@ static void player__im_gui(void) static void player__setpos( v3f pos ){ v3_copy( pos, localplayer.rb.co ); v3_zero( localplayer.rb.v ); - rb_update_transform( &localplayer.rb ); + rb_update_matrices( &localplayer.rb ); } static void player__clean_refs(void){ @@ -277,7 +277,7 @@ static void player__reset(void){ if( (l < 0.9f) || (l > 1.1f) ) q_identity( localplayer.rb.q ); - rb_update_transform( &localplayer.rb ); + rb_update_matrices( &localplayer.rb ); localplayer.subsystem = k_player_subsystem_walk; player__walk_reset(); diff --git a/player_dead.c b/player_dead.c index 7733c32..625ff0e 100644 --- a/player_dead.c +++ b/player_dead.c @@ -15,11 +15,11 @@ static void player__dead_post_update(void){ v3f ext_co; v4f ext_q; - rb_extrapolate( &part->obj.rb, ext_co, ext_q ); + rb_extrapolate( &part->rb, ext_co, ext_q ); v3_lerp( d->co_lpf, ext_co, vg.time_frame_delta*4.0f, d->co_lpf ); - v3_lerp( d->v_lpf, part->obj.rb.v, vg.time_frame_delta*4.0f, d->v_lpf ); - v3_lerp( d->w_lpf, part->obj.rb.w, vg.time_frame_delta*4.0f, d->w_lpf ); + v3_lerp( d->v_lpf, part->rb.v, vg.time_frame_delta*4.0f, d->v_lpf ); + v3_lerp( d->w_lpf, part->rb.w, vg.time_frame_delta*4.0f, d->w_lpf ); v3_copy( d->co_lpf, localplayer.rb.co ); v3_zero( localplayer.rb.v ); @@ -66,9 +66,9 @@ static void player__dead_animate(void){ v3f co_int; float substep = vg.time_fixed_extrapolate; - v3_lerp( part->prev_co, part->obj.rb.co, substep, co_int ); - q_nlerp( part->prev_q, part->obj.rb.q, substep, q_int ); - v4_copy( part->obj.rb.q, q_int ); + v3_lerp( part->prev_co, part->rb.co, substep, co_int ); + q_nlerp( part->prev_q, part->rb.q, substep, q_int ); + v4_copy( part->rb.q, q_int ); q_m3x3( q_int, mtx ); v3_copy( co_int, mtx[3] ); @@ -144,9 +144,9 @@ static void player__dead_transition( enum player_die_type type ){ struct ragdoll_part *part = &localplayer.ragdoll.parts[ localplayer.id_hip-1 ]; - v3_copy( part->obj.rb.co, player_dead.co_lpf ); - v3_copy( part->obj.rb.v, player_dead.v_lpf ); - v3_copy( part->obj.rb.w, player_dead.w_lpf ); + v3_copy( part->rb.co, player_dead.co_lpf ); + v3_copy( part->rb.v, player_dead.v_lpf ); + v3_copy( part->rb.w, player_dead.w_lpf ); gui_helper_clear(); vg_str str; diff --git a/player_drive.c b/player_drive.c index 38b7e58..7881302 100644 --- a/player_drive.c +++ b/player_drive.c @@ -17,10 +17,10 @@ static void player__drive_pre_update(void){ static void player__drive_update(void){} static void player__drive_post_update(void){ - v3_copy( player_drive.vehicle->obj.rb.co,localplayer.rb.co ); - v3_copy( player_drive.vehicle->obj.rb.v, localplayer.rb.v ); - v4_copy( player_drive.vehicle->obj.rb.q, localplayer.rb.q ); - v3_copy( player_drive.vehicle->obj.rb.w, localplayer.rb.w ); + v3_copy( player_drive.vehicle->rb.co,localplayer.rb.co ); + v3_copy( player_drive.vehicle->rb.v, localplayer.rb.v ); + v4_copy( player_drive.vehicle->rb.q, localplayer.rb.q ); + v3_copy( player_drive.vehicle->rb.w, localplayer.rb.w ); } static void player__drive_animate(void){} @@ -39,7 +39,7 @@ static void player__drive_post_animate(void){ else localplayer.cam_velocity_influence = 1.0f; - rigidbody *rb = &gzoomer.obj.rb; + rigidbody *rb = &gzoomer.rb; float yaw = atan2f( -rb->to_world[2][0], rb->to_world[2][2] ), pitch = atan2f ( diff --git a/player_glide.c b/player_glide.c index 3ec1fac..3091e57 100644 --- a/player_glide.c +++ b/player_glide.c @@ -60,8 +60,7 @@ static void calculate_drag( v3f vl, f32 cd, v3f out_force ){ } static void player_glide_update(void){ - rigidbody *rb = &localplayer.rb; - vg_line_sphere( rb->to_world, 1.0f, 0 ); + rigidbody *rb = &player_glide.rb; v2f steer; joystick_state( k_srjoystick_steer, steer ); @@ -116,11 +115,68 @@ static void player_glide_update(void){ m3x3_mulv( rb->to_world, Fw, Fw ); v3_muladds( rb->w, Fw, k_rb_delta, rb->w ); + /* + * collisions & constraints + */ + world_instance *world = world_current_instance(); + rb_solver_reset(); + + rigidbody _null = {0}; + _null.inv_mass = 0.0f; + m3x3_zero( _null.iI ); + for( u32 i=0; i < vg_list_size(player_glide.parts); i ++ ){ + m4x3f mmdl; + m4x3_mul( rb->to_world, player_glide.parts[i].mdl, mmdl ); + + if( player_glide.parts[i].shape == k_rb_shape_capsule ){ + vg_line_capsule( mmdl, + player_glide.parts[i].inf.r, + player_glide.parts[i].inf.h, + VG__BLACK ); + } + else if( player_glide.parts[i].shape == k_rb_shape_sphere ){ + vg_line_sphere( mmdl, player_glide.parts[i].r, 0 ); + } + + if( rb_global_has_space() ){ + rb_ct *buf = rb_global_buffer(); + + u32 l = 0; + + if( player_glide.parts[i].shape == k_rb_shape_capsule ){ + l = rb_capsule__scene( mmdl, &player_glide.parts[i].inf, + NULL, world->geo_bh, buf, + k_material_flag_ghosts ); + } + else if( player_glide.parts[i].shape == k_rb_shape_sphere ){ + l = rb_sphere__scene( mmdl, player_glide.parts[i].r, + NULL, world->geo_bh, buf, + k_material_flag_ghosts ); + } + + for( u32 j=0; jcollider_mtx ); + rp->type = bone->collider; if( bone->collider == k_bone_collider_box ){ v3f delta; v3_sub( bone->hitbox[1], bone->hitbox[0], delta ); v3_muls( delta, 0.5f, delta ); v3_add( bone->hitbox[0], delta, rp->collider_mtx[3] ); - v3_copy( delta, rp->obj.rb.bbx[1] ); - v3_muls( delta, -1.0f, rp->obj.rb.bbx[0] ); + v3_muls( delta, -1.0f, rp->inf.box[0] ); + v3_copy( delta, rp->inf.box[1] ); - q_identity( rp->obj.rb.q ); - rp->obj.type = k_rb_shape_box; rp->colour = 0xffcccccc; + + rb_setbody_box( &rp->rb, rp->inf.box, k_density, k_inertia_scale ); } else if( bone->collider == k_bone_collider_capsule ){ v3f v0, v1, tx, ty; @@ -88,9 +92,9 @@ static void player_init_ragdoll_bone_collider( struct skeleton_bone *bone, v1[ major_axis ] = 1.0f; v3_tangent_basis( v1, tx, ty ); - float r = (fabsf(v3_dot(tx,v0)) + fabsf(v3_dot(ty,v0))) * 0.25f, - l = fabsf(v0[ major_axis ]); - + rp->inf.capsule.r = (fabsf(v3_dot(tx,v0)) + fabsf(v3_dot(ty,v0))) * 0.25f; + rp->inf.capsule.h = fabsf(v0[ major_axis ]); + /* orientation */ v3_muls( tx, -1.0f, rp->collider_mtx[0] ); v3_muls( v1, -1.0f, rp->collider_mtx[1] ); @@ -98,11 +102,10 @@ static void player_init_ragdoll_bone_collider( struct skeleton_bone *bone, v3_add( bone->hitbox[0], bone->hitbox[1], rp->collider_mtx[3] ); v3_muls( rp->collider_mtx[3], 0.5f, rp->collider_mtx[3] ); - rp->obj.type = k_rb_shape_capsule; - rp->obj.inf.capsule.height = l; - rp->obj.inf.capsule.radius = r; - rp->colour = 0xff000000 | (0xff << (major_axis*8)); + + rb_setbody_capsule( &rp->rb, rp->inf.capsule.r, rp->inf.capsule.h, + k_density, k_inertia_scale ); } else{ vg_warn( "type: %u\n", bone->collider ); @@ -112,11 +115,11 @@ static void player_init_ragdoll_bone_collider( struct skeleton_bone *bone, m4x3_invert_affine( rp->collider_mtx, rp->inv_collider_mtx ); /* Position collider into rest */ - m3x3_q( rp->collider_mtx, rp->obj.rb.q ); - v3_add( rp->collider_mtx[3], bone->co, rp->obj.rb.co ); - v3_zero( rp->obj.rb.v ); - v3_zero( rp->obj.rb.w ); - rb_init_object( &rp->obj, 4.0f ); + m3x3_q( rp->collider_mtx, rp->rb.q ); + v3_add( rp->collider_mtx[3], bone->co, rp->rb.co ); + v3_zero( rp->rb.v ); + v3_zero( rp->rb.w ); + rb_update_matrices( &rp->rb ); } /* @@ -187,8 +190,8 @@ static void setup_ragdoll_from_skeleton( struct skeleton *sk, rd->constraint_associations[conid][1] = part_id; /* Convention: rba -- parent, rbb -- child */ - c->rba = &pp->obj.rb; - c->rbb = &rp->obj.rb; + c->rba = &pp->rb; + c->rbb = &rp->rb; v3f delta; v3_sub( bj->co, bp->co, delta ); @@ -201,8 +204,8 @@ static void setup_ragdoll_from_skeleton( struct skeleton *sk, struct rb_constr_swingtwist *a = &rd->cone_constraints[ rd->cone_constraints_count ++ ]; - a->rba = &pp->obj.rb; - a->rbb = &rp->obj.rb; + a->rba = &pp->rb; + a->rbb = &rp->rb; a->conet = cosf( inf->conet )-0.0001f; /* Store constraint in local space vectors */ @@ -240,8 +243,8 @@ static void copy_ragdoll_pose_to_localplayer( struct player_ragdoll *rd ){ v3f co_int; float substep = vg.time_fixed_extrapolate; - v3_lerp( part->prev_co, part->obj.rb.co, substep, co_int ); - q_nlerp( part->prev_q, part->obj.rb.q, substep, q_int ); + v3_lerp( part->prev_co, part->rb.co, substep, co_int ); + q_nlerp( part->prev_q, part->rb.q, substep, q_int ); q_m3x3( q_int, mtx ); v3_copy( co_int, mtx[3] ); @@ -292,30 +295,30 @@ static void copy_localplayer_to_ragdoll( struct player_ragdoll *rd, m4x3_mulv( bone_mtx, localplayer.skeleton.bones[bone].co, pos ); m3x3_mulv( bone_mtx, part->collider_mtx[3], offset ); - v3_add( pos, offset, part->obj.rb.co ); + v3_add( pos, offset, part->rb.co ); m3x3f r; m3x3_mul( bone_mtx, part->collider_mtx, r ); - m3x3_q( r, part->obj.rb.q ); + m3x3_q( r, part->rb.q ); v3f ra, v; - v3_sub( part->obj.rb.co, centroid, ra ); + v3_sub( part->rb.co, centroid, ra ); v3_cross( localplayer.rb.w, ra, v ); - v3_add( localplayer.rb.v, v, part->obj.rb.v ); + v3_add( localplayer.rb.v, v, part->rb.v ); if( type == k_player_die_type_feet ){ if( (bone == localplayer.id_foot_l) || (bone == localplayer.id_foot_r) ){ - v3_zero( part->obj.rb.v ); + v3_zero( part->rb.v ); } } - v3_copy( localplayer.rb.w, part->obj.rb.w ); + v3_copy( localplayer.rb.w, part->rb.w ); - v3_copy( part->obj.rb.co, part->prev_co ); - v4_copy( part->obj.rb.q, part->prev_q ); + v3_copy( part->rb.co, part->prev_co ); + v4_copy( part->rb.q, part->prev_q ); - rb_update_transform( &part->obj.rb ); + rb_update_matrices( &part->rb ); } } @@ -337,32 +340,36 @@ static void player_ragdoll_iter( struct player_ragdoll *rd ){ float contact_velocities[256]; + rigidbody _null = {0}; + _null.inv_mass = 0.0f; + m3x3_zero( _null.iI ); + for( int i=0; ipart_count; i ++ ){ - v4_copy( rd->parts[i].obj.rb.q, rd->parts[i].prev_q ); - v3_copy( rd->parts[i].obj.rb.co, rd->parts[i].prev_co ); + v4_copy( rd->parts[i].rb.q, rd->parts[i].prev_q ); + v3_copy( rd->parts[i].rb.co, rd->parts[i].prev_co ); if( rb_global_has_space() ){ rb_ct *buf = rb_global_buffer(); int l; - if( rd->parts[i].obj.type == k_rb_shape_capsule ){ - l = rb_capsule__scene( rd->parts[i].obj.rb.to_world, - &rd->parts[i].obj.inf.capsule, - NULL, &world->rb_geo.inf.scene, buf, + if( rd->parts[i].type == k_bone_collider_capsule ){ + l = rb_capsule__scene( rd->parts[i].rb.to_world, + &rd->parts[i].inf.capsule, + NULL, world->geo_bh, buf, k_material_flag_ghosts ); } - else if( rd->parts[i].obj.type == k_rb_shape_box ){ - l = rb_box__scene( rd->parts[i].obj.rb.to_world, - rd->parts[i].obj.rb.bbx, - NULL, &world->rb_geo.inf.scene, buf, + else if( rd->parts[i].type == k_bone_collider_box ){ + l = rb_box__scene( rd->parts[i].rb.to_world, + rd->parts[i].inf.box, + NULL, world->geo_bh, buf, k_material_flag_ghosts ); } else continue; for( int j=0; jparts[i].obj.rb; - buf[j].rbb = &world->rb_geo.rb; + buf[j].rba = &rd->parts[i].rb; + buf[j].rbb = &_null; } rb_contact_count += l; @@ -378,23 +385,23 @@ static void player_ragdoll_iter( struct player_ragdoll *rd ){ if( !rb_global_has_space() ) break; - if( rd->parts[j].obj.type != k_rb_shape_capsule ) + if( rd->parts[j].type != k_bone_collider_capsule ) continue; - if( rd->parts[i].obj.type != k_rb_shape_capsule ) + if( rd->parts[i].type != k_bone_collider_capsule ) continue; rb_ct *buf = rb_global_buffer(); - int l = rb_capsule__capsule( rd->parts[i].obj.rb.to_world, - &rd->parts[i].obj.inf.capsule, - rd->parts[j].obj.rb.to_world, - &rd->parts[j].obj.inf.capsule, + int l = rb_capsule__capsule( rd->parts[i].rb.to_world, + &rd->parts[i].inf.capsule, + rd->parts[j].rb.to_world, + &rd->parts[j].inf.capsule, buf ); for( int k=0; kparts[i].obj.rb; - buf[k].rbb = &rd->parts[j].obj.rb; + buf[k].rba = &rd->parts[i].rb; + buf[k].rbb = &rd->parts[j].rb; } rb_contact_count += l; @@ -407,7 +414,7 @@ static void player_ragdoll_iter( struct player_ragdoll *rd ){ struct ragdoll_part *pj = &rd->parts[j]; if( run_sim ){ - rb_effect_simple_bouyency( &pj->obj.rb, world->water.plane, + rb_effect_simple_bouyency( &pj->rb, world->water.plane, k_ragdoll_floatyiness, k_ragdoll_floatydrag ); } @@ -437,8 +444,18 @@ static void player_ragdoll_iter( struct player_ragdoll *rd ){ * DEBUG */ if( k_ragdoll_debug_collider ){ - for( u32 i=0; ipart_count; i ++ ) - rb_object_debug( &rd->parts[i].obj, rd->parts[i].colour ); + for( u32 i=0; ipart_count; i ++ ){ + struct ragdoll_part *rp = &rd->parts[i]; + + if( rp->type == k_bone_collider_capsule ){ + vg_line_capsule( rp->rb.to_world, + rp->inf.capsule.r, rp->inf.capsule.h, rp->colour ); + } + else if( rp->type == k_bone_collider_box ){ + vg_line_boxf_transformed( rp->rb.to_world, + rp->inf.box, rp->colour ); + } + } } if( k_ragdoll_debug_constraints ){ @@ -474,19 +491,19 @@ static void player_ragdoll_iter( struct player_ragdoll *rd ){ k_ragdoll_correction * 0.25f ); for( int i=0; ipart_count; i++ ){ - rb_iter( &rd->parts[i].obj.rb ); + rb_iter( &rd->parts[i].rb ); v3f w; - v3_copy( rd->parts[i].obj.rb.w, w ); + v3_copy( rd->parts[i].rb.w, w ); if( v3_length2( w ) > 0.00001f ){ v3_normalize( w ); - v3_muladds( rd->parts[i].obj.rb.w, w, -k_ragdoll_angular_drag, - rd->parts[i].obj.rb.w ); + v3_muladds( rd->parts[i].rb.w, w, -k_ragdoll_angular_drag, + rd->parts[i].rb.w ); } } for( int i=0; ipart_count; i++ ) - rb_update_transform( &rd->parts[i].obj.rb ); + rb_update_matrices( &rd->parts[i].rb ); } rb_ct *stress = NULL; diff --git a/player_ragdoll.h b/player_ragdoll.h index 6f5a331..77118f1 100644 --- a/player_ragdoll.h +++ b/player_ragdoll.h @@ -20,9 +20,17 @@ struct player_ragdoll{ u32 use_limits; v3f limits[2]; - rb_object obj; u32 parent; u32 colour; + + rigidbody rb; + enum bone_collider type; + + union { + rb_capsule capsule; + boxf box; + } + inf; } parts[32]; u32 part_count; diff --git a/player_replay.c b/player_replay.c index 31c4c74..f3b4a51 100644 --- a/player_replay.c +++ b/player_replay.c @@ -305,7 +305,7 @@ static void skaterift_record_frame( replay_buffer *replay, else if( localplayer.subsystem == k_player_subsystem_dead ){ struct replay_rb *arr = dst; for( u32 i=0; ico, arr[i].co ); v3_copy( rb->w, arr[i].w ); v3_copy( rb->v, arr[i].v ); @@ -376,7 +376,7 @@ void skaterift_restore_frame( replay_frame *frame ){ for( u32 i=0; iobj.rb; + rigidbody *rb = &part->rb; v3_copy( arr[i].co, rb->co ); v3_copy( arr[i].w, rb->w ); diff --git a/player_skate.c b/player_skate.c index 6d9aa92..0cd5e35 100644 --- a/player_skate.c +++ b/player_skate.c @@ -12,7 +12,7 @@ static void player__skate_bind(void){ struct skeleton *sk = &localplayer.skeleton; - rb_update_transform( &localplayer.rb ); + rb_update_matrices( &localplayer.rb ); struct { struct skeleton_anim **anim; const char *name; } bindings[] = { @@ -61,11 +61,11 @@ static void player__skate_kill_audio(void){ * Does collision detection on a sphere vs world, and applies some smoothing * filters to the manifold afterwards */ -static int skate_collide_smooth( m4x3f mtx, rb_sphere *sphere, rb_ct *man ){ +static int skate_collide_smooth( m4x3f mtx, f32 r, rb_ct *man ){ world_instance *world = world_current_instance(); int len = 0; - len = rb_sphere__scene( mtx, sphere, NULL, &world->rb_geo.inf.scene, man, + len = rb_sphere__scene( mtx, r, NULL, world->geo_bh, man, k_material_flag_walking ); for( int i=0; iflip_time += state->flip_rate * k_rb_delta; - rb_update_transform( &localplayer.rb ); + rb_update_matrices( &localplayer.rb ); } static enum trick_type player_skate_trick_input(void){ @@ -1209,7 +1209,7 @@ static void player__skate_pre_update(void){ m3x3_q( transfer, qtransfer ); q_mul( qtransfer, state->store_smoothed, state->smoothed_rotation ); q_normalize( state->smoothed_rotation ); - rb_update_transform( &localplayer.rb ); + rb_update_matrices( &localplayer.rb ); if( end ){ state->activity = k_skate_activity_air; @@ -1222,6 +1222,13 @@ static void player__skate_pre_update(void){ if( state->activity <= k_skate_activity_air_to_grind ){ localplayer.subsystem = k_player_subsystem_glide; + + v3_copy( localplayer.rb.co, player_glide.rb.co ); + v4_copy( localplayer.rb.q, player_glide.rb.q ); + v3_copy( localplayer.rb.v, player_glide.rb.v ); + v3_copy( localplayer.rb.w, player_glide.rb.w ); + rb_update_matrices( &player_glide.rb ); + player__begin_holdout( (v3f){0,0,0} ); return; } @@ -2466,7 +2473,7 @@ begin_collision:; v3_add( localplayer.rb.co, cg_offset, localplayer.rb.co ); } - rb_update_transform( &localplayer.rb ); + rb_update_matrices( &localplayer.rb ); localplayer.rb.v[1] += -state->gravity_bias * player_skate.substep_delta; player_skate.substep -= player_skate.substep_delta; @@ -2486,7 +2493,7 @@ begin_collision:; k_material_flag_walking ) != -1) ) { v3_lerp( start_co, localplayer.rb.co, t, localplayer.rb.co ); - rb_update_transform( &localplayer.rb ); + rb_update_matrices( &localplayer.rb ); player__dead_transition( k_player_die_type_head ); return; @@ -2504,12 +2511,10 @@ begin_collision:; m4x3f mtx; m3x3_identity( mtx ); m4x3_mulv( localplayer.rb.to_world, wheels[i].pos, mtx[3] ); - - rb_sphere collider = { .radius = wheels[i].radius }; rb_ct *man = &manifold[ manifold_len ]; - int l = skate_collide_smooth( mtx, &collider, man ); + int l = skate_collide_smooth( mtx, wheels[i].radius, man ); if( l ) wheels[i].state = k_collider_state_colliding; @@ -2517,8 +2522,8 @@ begin_collision:; } float grind_radius = k_board_radius * 0.75f; - rb_capsule capsule = { .height = (k_board_length+0.2f)*2.0f, - .radius=grind_radius }; + rb_capsule capsule = { .h = (k_board_length+0.2f)*2.0f, + .r = grind_radius }; m4x3f mtx; v3_muls( localplayer.rb.to_world[0], 1.0f, mtx[0] ); v3_muls( localplayer.rb.to_world[2], -1.0f, mtx[1] ); @@ -2528,7 +2533,7 @@ begin_collision:; rb_ct *cman = &manifold[manifold_len]; - int l = rb_capsule__scene( mtx, &capsule, NULL, &world->rb_geo.inf.scene, + int l = rb_capsule__scene( mtx, &capsule, NULL, world->geo_bh, cman, k_material_flag_walking ); /* weld joints */ @@ -2540,7 +2545,7 @@ begin_collision:; manifold_len += l; if( vg_lines.draw ) - vg_line_capsule( mtx, capsule.radius, capsule.height, VG__WHITE ); + vg_line_capsule( mtx, capsule.r, capsule.h, VG__WHITE ); /* add limits */ if( state->activity >= k_skate_activity_grind_any ){ @@ -2640,7 +2645,7 @@ begin_collision:; v3f dt; rb_depenetrate( manifold, manifold_len, dt ); v3_add( dt, localplayer.rb.co, localplayer.rb.co ); - rb_update_transform( &localplayer.rb ); + rb_update_matrices( &localplayer.rb ); substep_count ++; @@ -2710,7 +2715,9 @@ begin_collision:; q_mul( transport_rotation, localplayer.rb.q, localplayer.rb.q ); q_mul( transport_rotation, state->smoothed_rotation, state->smoothed_rotation ); - rb_update_transform( &localplayer.rb ); + q_normalize( localplayer.rb.q ); + q_normalize( state->smoothed_rotation ); + rb_update_matrices( &localplayer.rb ); player__pass_gate( id ); } diff --git a/player_walk.c b/player_walk.c index 9c23978..6b0def6 100644 --- a/player_walk.c +++ b/player_walk.c @@ -47,7 +47,7 @@ static void player_walk_generic_to_skate( enum skate_activity init, f32 yaw ){ player__begin_holdout( (v3f){0.0f,0.0f,0.0f} ); player__skate_reset_animator(); player__skate_clear_mechanics(); - rb_update_transform( &localplayer.rb ); + rb_update_matrices( &localplayer.rb ); v3_copy( (v3f){yaw,0.0f,0.0f}, player_skate.state.trick_euler ); if( init == k_skate_activity_air ) @@ -68,7 +68,7 @@ static void player_walk_drop_in_to_skate(void){ v3f init_velocity; player_walk_drop_in_vector( init_velocity ); - rb_update_transform( &localplayer.rb ); + rb_update_matrices( &localplayer.rb ); v3_muladds( localplayer.rb.co, localplayer.rb.to_world[1], 1.0f, player_skate.state.cog ); v3_copy( init_velocity, player_skate.state.cog_v ); @@ -457,14 +457,14 @@ static void player_walk_update_generic(void){ enum walk_activity prev_state = w->state.activity; - w->collider.height = 2.0f; - w->collider.radius = 0.3f; + w->collider.h = 2.0f; + w->collider.r = 0.3f; m4x3f mtx; m3x3_copy( localplayer.rb.to_world, mtx ); v3_add( localplayer.rb.co, (v3f){0,1,0}, mtx[3] ); - vg_line_capsule( mtx, w->collider.radius, w->collider.height, VG__WHITE ); + vg_line_capsule( mtx, w->collider.r, w->collider.h, VG__WHITE ); rb_ct manifold[64]; int len; @@ -479,7 +479,7 @@ static void player_walk_update_generic(void){ */ len = rb_capsule__scene( mtx, &w->collider, NULL, - &world->rb_geo.inf.scene, manifold, 0 ); + world->geo_bh, manifold, 0 ); player_walk_custom_filter( world, manifold, len, 0.01f ); len = rb_manifold_apply_filtered( manifold, len ); @@ -582,17 +582,17 @@ static void player_walk_update_generic(void){ v3f pa, pb; v3_copy( localplayer.rb.co, pa ); - pa[1] += w->collider.radius + max_dist; + pa[1] += w->collider.r + max_dist; v3_add( pa, (v3f){0, -max_dist * 2.0f, 0}, pb ); vg_line( pa, pb, 0xff000000 ); v3f n; float t; if( spherecast_world( world, pa, pb, - w->collider.radius, &t, n, 0 ) != -1 ){ + w->collider.r, &t, n, 0 ) != -1 ){ if( player_walk_normal_standable(n) ){ v3_lerp( pa, pb, t, localplayer.rb.co ); - localplayer.rb.co[1] += -w->collider.radius - k_penetration_slop; + localplayer.rb.co[1] += -w->collider.r - k_penetration_slop; w->state.activity = k_walk_activity_ground; float d = -v3_dot(n,localplayer.rb.v); @@ -622,7 +622,7 @@ static void player_walk_update_generic(void){ v3_muladds( localplayer.rb.co, localplayer.rb.v, k_rb_delta, localplayer.rb.co ); v3_add( localplayer.rb.co, (v3f){0,1,0}, mtx[3] ); - vg_line_capsule( mtx, w->collider.radius, w->collider.height, VG__GREEN ); + vg_line_capsule( mtx, w->collider.r, w->collider.h, VG__GREEN ); /* * CCD routine @@ -631,7 +631,7 @@ static void player_walk_update_generic(void){ */ v3f lwr_prev, lwr_now, - lwr_offs = { 0.0f, w->collider.radius, 0.0f }; + lwr_offs = { 0.0f, w->collider.r, 0.0f }; v3_add( lwr_offs, w->state.prev_pos, lwr_prev ); v3_add( lwr_offs, localplayer.rb.co, lwr_now ); @@ -642,16 +642,15 @@ static void player_walk_update_generic(void){ float movedist = v3_length( movedelta ); if( movedist > 0.3f ){ - float t, sr = w->collider.radius-0.04f; + float t, sr = w->collider.r-0.04f; v3f n; if( spherecast_world( world, lwr_prev, lwr_now, sr, &t, n, 0 ) != -1 ){ v3_lerp( lwr_prev, lwr_now, vg_maxf(0.01f,t), localplayer.rb.co ); - localplayer.rb.co[1] -= w->collider.radius; - rb_update_transform( &localplayer.rb ); - + localplayer.rb.co[1] -= w->collider.r; + rb_update_matrices( &localplayer.rb ); v3_add( localplayer.rb.co, (v3f){0,1,0}, mtx[3] ); - vg_line_capsule( mtx, w->collider.radius, w->collider.height, VG__RED); + vg_line_capsule( mtx, w->collider.r, w->collider.h, VG__RED); } } @@ -664,11 +663,11 @@ static void player_walk_update_generic(void){ v4f transport_rotation; m3x3_q( gate->transport, transport_rotation ); q_mul( transport_rotation, localplayer.rb.q, localplayer.rb.q ); - - rb_update_transform( &localplayer.rb ); + q_normalize( localplayer.rb.q ); + rb_update_matrices( &localplayer.rb ); player__pass_gate( id ); } - rb_update_transform( &localplayer.rb ); + rb_update_matrices( &localplayer.rb ); if( (prev_state == k_walk_activity_oregular) || (prev_state == k_walk_activity_oair) || @@ -690,7 +689,7 @@ static void player__walk_post_update(void){ float substep = vg.time_fixed_extrapolate; v3_muladds( mtx[3], localplayer.rb.v, k_rb_delta*substep, mtx[3] ); - vg_line_capsule( mtx, w->collider.radius, w->collider.height, VG__YELOW ); + vg_line_capsule( mtx, w->collider.r, w->collider.h, VG__YELOW ); /* Calculate header */ v3f v; @@ -797,7 +796,7 @@ static void player_walk_animate_drop_in(void){ v3_lerp( localplayer.rb.co, final_co, animator->transition_t, localplayer.rb.co ); - rb_update_transform( &localplayer.rb ); + rb_update_matrices( &localplayer.rb ); v3_muladds( localplayer.rb.co, localplayer.rb.to_world[1], -0.1f*animator->transition_t, localplayer.rb.co ); @@ -1132,7 +1131,7 @@ static void player__walk_transition( bool grounded, f32 board_yaw ){ w->state.walk_timer = 0.0f; w->state.step_phase = 0; w->animator.board_yaw = fmodf( board_yaw, 2.0f ); - rb_update_transform( &localplayer.rb ); + rb_update_matrices( &localplayer.rb ); } static void player__walk_reset(void){ @@ -1145,7 +1144,7 @@ static void player__walk_reset(void){ q_axis_angle( localplayer.rb.q, (v3f){0.0f,1.0f,0.0f}, atan2f(fwd[0], fwd[2]) ); - rb_update_transform( &localplayer.rb ); + rb_update_matrices( &localplayer.rb ); } static void player__walk_animator_exchange( bitpack_ctx *ctx, void *data ){ diff --git a/rigidbody.h b/rigidbody.h index 992bdba..75139e0 100644 --- a/rigidbody.h +++ b/rigidbody.h @@ -13,8 +13,6 @@ #include -static bh_system bh_system_rigidbodies; - #ifndef RIGIDBODY_H #define RIGIDBODY_H @@ -33,7 +31,8 @@ static const float k_penetration_slop = 0.01f, k_inertia_scale = 4.0f, k_phys_baumgarte = 0.2f, - k_gravity = 9.6f; + k_gravity = 9.6f, + k_rb_density = 8.0f; static float k_limit_bias = 0.02f, @@ -48,6 +47,13 @@ static void rb_register_cvar(void){ VG_VAR_F32( k_joint_impulse, flags=VG_VAR_CHEAT ); } +enum rb_shape { + k_rb_shape_none = 0, + k_rb_shape_box = 1, + k_rb_shape_sphere = 2, + k_rb_shape_capsule = 3, +}; + /* * ----------------------------------------------------------------------------- * structure definitions @@ -55,55 +61,23 @@ static void rb_register_cvar(void){ */ typedef struct rigidbody rigidbody; -typedef struct rb_object rb_object; typedef struct contact rb_ct; -typedef struct rb_sphere rb_sphere; typedef struct rb_capsule rb_capsule; -typedef struct rb_scene rb_scene; - -struct rb_sphere{ - float radius; -}; struct rb_capsule{ - float height, radius; -}; - -struct rb_scene{ - bh_tree *bh_scene; + f32 h, r; }; struct rigidbody{ v3f co, v, w; v4f q; - boxf bbx, bbx_world; - float inv_mass; + f32 inv_mass; - /* inertia model and inverse world tensor */ - m3x3f iI, iIw; + m3x3f iI, iIw; /* inertia model and inverse world tensor */ m4x3f to_world, to_local; }; -/* simple objects */ -struct rb_object{ - rigidbody rb; - enum rb_shape{ - k_rb_shape_box = 0, - k_rb_shape_sphere = 1, - k_rb_shape_capsule = 2, - k_rb_shape_scene = 3 - } - type; - - union{ - struct rb_sphere sphere; - struct rb_capsule capsule; - struct rb_scene scene; - } - inf; -}; - static struct contact{ rigidbody *rba, *rbb; v3f co, n; @@ -162,27 +136,6 @@ static void rb_debug_contact( rb_ct *ct ){ } } - -static void rb_object_debug( rb_object *obj, u32 colour ){ - if( obj->type == k_rb_shape_box ){ - v3f *box = obj->rb.bbx; - vg_line_boxf_transformed( obj->rb.to_world, obj->rb.bbx, colour ); - } - else if( obj->type == k_rb_shape_sphere ){ - vg_line_sphere( obj->rb.to_world, obj->inf.sphere.radius, colour ); - } - else if( obj->type == k_rb_shape_capsule ){ - m4x3f m0, m1; - float h = obj->inf.capsule.height, - r = obj->inf.capsule.radius; - - vg_line_capsule( obj->rb.to_world, r, h, colour ); - } - else if( obj->type == k_rb_shape_scene ){ - vg_line_boxf( obj->rb.bbx, colour ); - } -} - /* * ----------------------------------------------------------------------------- * Integration @@ -190,37 +143,24 @@ static void rb_object_debug( rb_object *obj, u32 colour ){ */ /* - * Update world space bounding box based on local one - */ -static void rb_update_bounds( rigidbody *rb ){ - box_init_inf( rb->bbx_world ); - m4x3_expand_aabb_aabb( rb->to_world, rb->bbx_world, rb->bbx ); -} - -/* - * Commit transform to rigidbody. Updates matrices + * Update ALL matrices and tensors on rigidbody */ -static void rb_update_transform( rigidbody *rb ) -{ - q_normalize( rb->q ); +static void rb_update_matrices( rigidbody *rb ){ + //q_normalize( rb->q ); q_m3x3( rb->q, rb->to_world ); v3_copy( rb->co, rb->to_world[3] ); - m4x3_invert_affine( rb->to_world, rb->to_local ); /* I = R I_0 R^T */ m3x3_mul( rb->to_world, rb->iI, rb->iIw ); m3x3_mul( rb->iIw, rb->to_local, rb->iIw ); - - rb_update_bounds( rb ); } /* * Extrapolate rigidbody into a transform based on vg accumulator. * Useful for rendering */ -static void rb_extrapolate( rigidbody *rb, v3f co, v4f q ) -{ +static void rb_extrapolate( rigidbody *rb, v3f co, v4f q ){ float substep = vg.time_fixed_extrapolate; v3_muladds( rb->co, rb->v, k_rb_delta*substep, co ); @@ -241,98 +181,141 @@ static void rb_extrapolate( rigidbody *rb, v3f co, v4f q ) } /* - * Initialize rigidbody and calculate masses, inertia + * Inertia + * ----------------------------------------------------------------------------- */ -static void rb_init_object( rb_object *obj, f32 inertia_scale ){ - float volume = 1.0f; - int inert = 0; - - if( obj->type == k_rb_shape_box ){ - v3f dims; - v3_sub( obj->rb.bbx[1], obj->rb.bbx[0], dims ); - volume = dims[0]*dims[1]*dims[2]; - } - else if( obj->type == k_rb_shape_sphere ){ - volume = vg_sphere_volume( obj->inf.sphere.radius ); - v3_fill( obj->rb.bbx[0], -obj->inf.sphere.radius ); - v3_fill( obj->rb.bbx[1], obj->inf.sphere.radius ); - } - else if( obj->type == k_rb_shape_capsule ){ - float r = obj->inf.capsule.radius, - h = obj->inf.capsule.height; - volume = vg_sphere_volume( r ) + VG_PIf * r*r * (h - r*2.0f); - - v3_fill( obj->rb.bbx[0], -r ); - v3_fill( obj->rb.bbx[1], r ); - obj->rb.bbx[0][1] = -h; - obj->rb.bbx[1][1] = h; - } - else if( obj->type == k_rb_shape_scene ){ - inert = 1; - box_copy( obj->inf.scene.bh_scene->nodes[0].bbx, obj->rb.bbx ); - } - if( inert ){ - obj->rb.inv_mass = 0.0f; - m3x3_zero( obj->rb.iI ); - } - else{ - f32 mass = 8.0f*volume; - obj->rb.inv_mass = 1.0f/mass; +/* + * Translate existing inertia tensor + */ +static void rb_translate_inertia( m3x3f inout_inertia, f32 mass, v3f d ){ + /* + * I = I_0 + m*[(d.d)E_3 - d(X)d] + * + * I: updated tensor + * I_0: original tensor + * m: scalar mass + * d: translation vector + * (X): outer product + * E_3: identity matrix + */ + m3x3f t, outer, scale; + m3x3_diagonal( t, v3_dot(d,d) ); + m3x3_outer_product( outer, d, d ); + m3x3_sub( t, outer, t ); + m3x3_diagonal( scale, mass ); + m3x3_mul( scale, t, t ); + m3x3_add( inout_inertia, t, inout_inertia ); +} + +/* + * Rotate existing inertia tensor + */ +static void rb_rotate_inertia( m3x3f inout_inertia, m3x3f rotation ){ + /* + * I = R I_0 R^T + * + * I: updated tensor + * I_0: original tensor + * R: rotation matrix + * R^T: tranposed rotation matrix + */ + + m3x3f Rt; + m3x3_transpose( rotation, Rt ); + m3x3_mul( rotation, inout_inertia, inout_inertia ); + m3x3_mul( inout_inertia, Rt, inout_inertia ); +} +/* + * Create inertia tensor for box + */ +static void rb_box_inertia( boxf box, f32 mass, m3x3f out_inertia ){ + v3f e, com; + v3_sub( box[1], box[0], e ); + v3_muladds( box[0], e, 0.5f, com ); + + f32 ex2 = e[0]*e[0], + ey2 = e[1]*e[1], + ez2 = e[2]*e[2], + ix = (ey2+ez2) * mass * (1.0f/12.0f), + iy = (ex2+ez2) * mass * (1.0f/12.0f), + iz = (ex2+ey2) * mass * (1.0f/12.0f); + + m3x3_identity( out_inertia ); + m3x3_setdiagonalv3( out_inertia, (v3f){ ix, iy, iz } ); + rb_translate_inertia( out_inertia, mass, com ); +} + +/* + * Create inertia tensor for sphere + */ +static void rb_sphere_inertia( f32 r, f32 mass, m3x3f out_inertia ){ + f32 ixyz = r*r * mass * (2.0f/5.0f); + + m3x3_identity( out_inertia ); + m3x3_setdiagonalv3( out_inertia, (v3f){ ixyz, ixyz, ixyz } ); +} - v3f extent, com; - v3_sub( obj->rb.bbx[1], obj->rb.bbx[0], extent ); - v3_muladds( obj->rb.bbx[0], extent, 0.5f, com ); +/* + * Create inertia tensor for capsule + * + * TODO: UNTESTED + */ +static void rb_capsule_inertia( f32 r, f32 h, f32 mass, m3x3f out_inertia ){ + f32 density = mass / vg_capsule_volume( r, h ), + ch = h-r*2.0f, /* cylinder height */ + cm = VG_PIf * ch*r*r * density, /* cylinder mass */ + hm = VG_TAUf * (1.0f/3.0f) * r*r*r * density, /* hemisphere mass */ + + iy = r*r*cm * 0.5f, + ixz = iy * 0.5f + cm*ch*ch*(1.0f/12.0f), - /* local intertia tensor */ - f32 ex2 = extent[0]*extent[0], - ey2 = extent[1]*extent[1], - ez2 = extent[2]*extent[2]; + aux0= (hm*2.0f*r*r)/5.0f; - /* compute inertia tensor */ - v3f I; + iy += aux0 * 2.0f; - if( obj->type == k_rb_shape_box ){ - I[0] = inertia_scale * (ey2+ez2) * mass * (1.0f/12.0f); - I[1] = inertia_scale * (ex2+ez2) * mass * (1.0f/12.0f); - I[2] = inertia_scale * (ex2+ey2) * mass * (1.0f/12.0f); - } - else if( obj->type == k_rb_shape_sphere ){ - f32 r = obj->inf.sphere.radius; - v3_fill( I, inertia_scale * r*r * mass * (2.0f/5.0f) ); - } - else if( obj->type == k_rb_shape_capsule ){ - f32 r = obj->inf.capsule.radius; - I[1] = inertia_scale * r*r * mass * (2.0f/5.0f); - I[0] = inertia_scale * (ey2+ez2) * mass * (1.0f/12.0f); - I[2] = inertia_scale * (ey2+ex2) * mass * (1.0f/12.0f); - } - else { - vg_fatal_error( "" ); - } + f32 aux1= ch*0.5f, + aux2= aux0 + hm*(aux1*aux1 + 3.0f*(1.0f/8.0f)*ch*r); - m3x3f i; - m3x3_identity( i ); - m3x3_setdiagonalv3( i, I ); + ixz += aux2*2.0f; - /* compute translation */ - m3x3f i_t, i_t_outer, i_t_scale; - m3x3_diagonal( i_t, v3_dot(com,com) ); - m3x3_outer_product( i_t_outer, com, com ); - m3x3_sub( i_t, i_t_outer, i_t ); - m3x3_diagonal( i_t_scale, mass ); - m3x3_mul( i_t_scale, i_t, i_t ); + m3x3_identity( out_inertia ); + m3x3_setdiagonalv3( out_inertia, (v3f){ ixz, iy, ixz } ); +} - /* TODO: compute rotation */ +static void rb_setbody_capsule( rigidbody *rb, f32 r, f32 h, + f32 density, f32 inertia_scale ){ + f32 vol = vg_capsule_volume( r, h ), + mass = vol*density; - /* add Ic and Ict */ - m3x3_add( i, i_t, i ); + rb->inv_mass = 1.0f/mass; - /* store as inverted */ - m3x3_inv( i, obj->rb.iI ); - } + m3x3f I; + rb_capsule_inertia( r, h, mass * inertia_scale, I ); + m3x3_inv( I, rb->iI ); +} + +static void rb_setbody_box( rigidbody *rb, boxf box, + f32 density, f32 inertia_scale ){ + f32 vol = vg_box_volume( box ), + mass = vol*density; + + rb->inv_mass = 1.0f/mass; + + m3x3f I; + rb_box_inertia( box, mass * inertia_scale, I ); + m3x3_inv( I, rb->iI ); +} - rb_update_transform( &obj->rb ); +static void rb_setbody_sphere( rigidbody *rb, f32 r, + f32 density, f32 inertia_scale ){ + f32 vol = vg_sphere_volume( r ), + mass = vol*density; + + rb->inv_mass = 1.0f/mass; + m3x3f I; + rb_sphere_inertia( r, mass * inertia_scale, I ); + m3x3_inv( I, rb->iI ); } static void rb_iter( rigidbody *rb ){ @@ -351,8 +334,7 @@ static void rb_iter( rigidbody *rb ){ v3_lerp( rb->w, (v3f){0.0f,0.0f,0.0f}, 0.0025f, rb->w ); /* inegrate inertia */ - if( v3_length2( rb->w ) > 0.0f ) - { + if( v3_length2( rb->w ) > 0.0f ){ v4f rotation; v3f axis; v3_copy( rb->w, axis ); @@ -361,16 +343,10 @@ static void rb_iter( rigidbody *rb ){ v3_divs( axis, mag, axis ); q_axis_angle( rotation, axis, mag*k_rb_delta ); q_mul( rotation, rb->q, rb->q ); + q_normalize( rb->q ); } - -#if 0 - /* damping */ - v3_muls( rb->v, 1.0f/(1.0f+k_rb_delta*k_damp_linear), rb->v ); - v3_muls( rb->w, 1.0f/(1.0f+k_rb_delta*k_damp_angular), rb->w ); -#endif } - /* * ----------------------------------------------------------------------------- * Boolean shape overlap functions @@ -658,11 +634,11 @@ static void rb_capsule_manifold_init( capsule_manifold *manifold ){ } static int rb_capsule__manifold_done( m4x3f mtx, rb_capsule *c, - capsule_manifold *manifold, - rb_ct *buf ){ + capsule_manifold *manifold, + rb_ct *buf ){ v3f p0, p1; - v3_muladds( mtx[3], mtx[1], -c->height*0.5f+c->radius, p0 ); - v3_muladds( mtx[3], mtx[1], c->height*0.5f-c->radius, p1 ); + v3_muladds( mtx[3], mtx[1], -c->h*0.5f+c->r, p0 ); + v3_muladds( mtx[3], mtx[1], c->h*0.5f-c->r, p1 ); int count = 0; if( manifold->t0 <= 1.0f ){ @@ -674,7 +650,7 @@ static int rb_capsule__manifold_done( m4x3f mtx, rb_capsule *c, float d = v3_length( manifold->d0 ); v3_muls( manifold->d0, 1.0f/d, ct->n ); - v3_muladds( pa, ct->n, -c->radius, ct->co ); + v3_muladds( pa, ct->n, -c->r, ct->co ); ct->p = manifold->r0 - d; ct->type = k_contact_type_default; @@ -690,7 +666,7 @@ static int rb_capsule__manifold_done( m4x3f mtx, rb_capsule *c, float d = v3_length( manifold->d1 ); v3_muls( manifold->d1, 1.0f/d, ct->n ); - v3_muladds( pa, ct->n, -c->radius, ct->co ); + v3_muladds( pa, ct->n, -c->r, ct->co ); ct->p = manifold->r1 - d; ct->type = k_contact_type_default; @@ -708,11 +684,12 @@ static int rb_capsule__manifold_done( m4x3f mtx, rb_capsule *c, return count; } +#if 0 static int rb_capsule_sphere( rb_object *obja, rb_object *objb, rb_ct *buf ){ rigidbody *rba = &obja->rb, *rbb = &objb->rb; - float h = obja->inf.capsule.height, - ra = obja->inf.capsule.radius, - rb = objb->inf.sphere.radius; + float h = obja->inf.capsule.h, + ra = obja->inf.capsule.r, + rb = objb->inf.sphere.r; v3f p0, p1; v3_muladds( rba->co, rba->to_world[1], -h*0.5f+ra, p0 ); @@ -747,14 +724,15 @@ static int rb_capsule_sphere( rb_object *obja, rb_object *objb, rb_ct *buf ){ return 0; } +#endif static int rb_capsule__capsule( m4x3f mtxA, rb_capsule *ca, - m4x3f mtxB, rb_capsule *cb, rb_ct *buf ){ - float ha = ca->height, - hb = cb->height, - ra = ca->radius, - rb = cb->radius, - r = ra+rb; + m4x3f mtxB, rb_capsule *cb, rb_ct *buf ){ + f32 ha = ca->h, + hb = cb->h, + ra = ca->r, + rb = cb->r, + r = ra+rb; v3f p0, p1, p2, p3; v3_muladds( mtxA[3], mtxA[1], -ha*0.5f+ra, p0 ); @@ -766,7 +744,7 @@ static int rb_capsule__capsule( m4x3f mtxA, rb_capsule *ca, rb_capsule_manifold_init( &manifold ); v3f pa, pb; - float ta, tb; + f32 ta, tb; closest_segment_segment( p0, p1, p2, p3, &ta, &tb, pa, pb ); rb_capsule_manifold( pa, pb, ta, r, &manifold ); @@ -783,6 +761,7 @@ static int rb_capsule__capsule( m4x3f mtxA, rb_capsule *ca, return rb_capsule__manifold_done( mtxA, ca, &manifold, buf ); } +#if 0 static int rb_sphere_box( rb_object *obja, rb_object *objb, rb_ct *buf ){ v3f co, delta; rigidbody *rba = &obja->rb, *rbb = &objb->rb; @@ -837,7 +816,9 @@ static int rb_sphere_box( rb_object *obja, rb_object *objb, rb_ct *buf ){ return 0; } +#endif +#if 0 static int rb_sphere_sphere( rb_object *obja, rb_object *objb, rb_ct *buf ){ rigidbody *rba = &obja->rb, *rbb = &objb->rb; v3f delta; @@ -866,16 +847,14 @@ static int rb_sphere_sphere( rb_object *obja, rb_object *objb, rb_ct *buf ){ return 0; } +#endif -static int rb_sphere__triangle( m4x3f mtxA, rb_sphere *b, - v3f tri[3], rb_ct *buf ){ +static int rb_sphere__triangle( m4x3f mtxA, f32 r, + v3f tri[3], rb_ct *buf ){ v3f delta, co; enum contact_type type = closest_on_triangle_1( mtxA[3], tri, co ); - v3_sub( mtxA[3], co, delta ); - - float d2 = v3_length2( delta ), - r = b->radius; + f32 d2 = v3_length2( delta ); if( d2 <= r*r ){ rb_ct *ct = buf; @@ -906,14 +885,13 @@ static int rb_sphere__triangle( m4x3f mtxA, rb_sphere *b, return 0; } -static int rb_sphere__scene( m4x3f mtxA, rb_sphere *b, - m4x3f mtxB, rb_scene *s, rb_ct *buf, - u16 ignore ){ - scene_context *sc = s->bh_scene->user; +static int rb_sphere__scene( m4x3f mtxA, f32 r, + m4x3f mtxB, bh_tree *scene_bh, rb_ct *buf, + u16 ignore ){ + scene_context *sc = scene_bh->user; int count = 0; - float r = b->radius + 0.1f; boxf box; v3_sub( mtxA[3], (v3f){ r,r,r }, box[0] ); v3_add( mtxA[3], (v3f){ r,r,r }, box[1] ); @@ -922,7 +900,7 @@ static int rb_sphere__scene( m4x3f mtxA, rb_sphere *b, i32 idx; bh_iter_init_box( 0, &it, box ); - while( bh_next( s->bh_scene, &it, &idx ) ){ + while( bh_next( scene_bh, &it, &idx ) ){ u32 *ptri = &sc->arrindices[ idx*3 ]; v3f tri[3]; @@ -937,7 +915,7 @@ static int rb_sphere__scene( m4x3f mtxA, rb_sphere *b, vg_line( tri[1],tri[2],0x70ff6000 ); vg_line( tri[2],tri[0],0x70ff6000 ); - int contact = rb_sphere__triangle( mtxA, b, tri, &buf[count] ); + int contact = rb_sphere__triangle( mtxA, r, tri, &buf[count] ); count += contact; if( count == 16 ){ @@ -950,8 +928,9 @@ static int rb_sphere__scene( m4x3f mtxA, rb_sphere *b, } static int rb_box__scene( m4x3f mtxA, boxf bbx, - m4x3f mtxB, rb_scene *s, rb_ct *buf, u16 ignore ){ - scene_context *sc = s->bh_scene->user; + m4x3f mtxB, bh_tree *scene_bh, + rb_ct *buf, u16 ignore ){ + scene_context *sc = scene_bh->user; v3f tri[3]; v3f extent, center; @@ -978,7 +957,7 @@ static int rb_box__scene( m4x3f mtxA, boxf bbx, vg_line_boxf( world_bbx, VG__RED ); - while( bh_next( s->bh_scene, &it, &idx ) ){ + while( bh_next( scene_bh, &it, &idx ) ){ u32 *ptri = &sc->arrindices[ idx*3 ]; if( sc->arrvertices[ptri[0]].flags & ignore ) continue; @@ -1106,8 +1085,8 @@ static int rb_box__scene( m4x3f mtxA, boxf bbx, static int rb_capsule__triangle( m4x3f mtxA, rb_capsule *c, v3f tri[3], rb_ct *buf ){ v3f pc, p0w, p1w; - v3_muladds( mtxA[3], mtxA[1], -c->height*0.5f+c->radius, p0w ); - v3_muladds( mtxA[3], mtxA[1], c->height*0.5f-c->radius, p1w ); + v3_muladds( mtxA[3], mtxA[1], -c->h*0.5f+c->r, p0w ); + v3_muladds( mtxA[3], mtxA[1], c->h*0.5f-c->r, p1w ); capsule_manifold manifold; rb_capsule_manifold_init( &manifold ); @@ -1131,7 +1110,7 @@ static int rb_capsule__triangle( m4x3f mtxA, rb_capsule *c, * not very 'correct' */ f32 dist; if( ray_tri( tri, p0w, mtxA[1], &dist, 1 ) ){ - f32 l = c->height - c->radius*2.0f; + f32 l = c->h - c->r*2.0f; if( (dist >= 0.0f) && (dist < l) ){ v3f co; v3_muladds( p0w, mtxA[1], dist, co ); @@ -1141,7 +1120,7 @@ static int rb_capsule__triangle( m4x3f mtxA, rb_capsule *c, v3_sub( p0w, co, d0 ); v3_sub( p1w, co, d1 ); - f32 p = vg_minf( v3_dot( n, d0 ), v3_dot( n, d1 ) ) - c->radius; + f32 p = vg_minf( v3_dot( n, d0 ), v3_dot( n, d1 ) ) - c->r; rb_ct *ct = buf; ct->p = -p; @@ -1169,9 +1148,9 @@ static int rb_capsule__triangle( m4x3f mtxA, rb_capsule *c, /* the two balls at the ends */ if( v3_dot( da, d0 ) <= 0.01f ) - rb_capsule_manifold( p0w, c0, 0.0f, c->radius, &manifold ); + rb_capsule_manifold( p0w, c0, 0.0f, c->r, &manifold ); if( v3_dot( da, d1 ) >= -0.01f ) - rb_capsule_manifold( p1w, c1, 1.0f, c->radius, &manifold ); + rb_capsule_manifold( p1w, c1, 1.0f, c->r, &manifold ); /* the edges to edges */ for( int i=0; i<3; i++ ){ @@ -1181,7 +1160,7 @@ static int rb_capsule__triangle( m4x3f mtxA, rb_capsule *c, v3f ca, cb; float ta, tb; closest_segment_segment( p0w, p1w, tri[i0], tri[i1], &ta, &tb, ca, cb ); - rb_capsule_manifold( ca, cb, ta, c->radius, &manifold ); + rb_capsule_manifold( ca, cb, ta, c->r, &manifold ); } int count = rb_capsule__manifold_done( mtxA, c, &manifold, buf ); @@ -1193,20 +1172,20 @@ static int rb_capsule__triangle( m4x3f mtxA, rb_capsule *c, /* mtxB is defined only for tradition; it is not used currently */ static int rb_capsule__scene( m4x3f mtxA, rb_capsule *c, - m4x3f mtxB, rb_scene *s, - rb_ct *buf, u16 ignore ){ + m4x3f mtxB, bh_tree *scene_bh, + rb_ct *buf, u16 ignore ){ int count = 0; boxf bbx; - v3_sub( mtxA[3], (v3f){ c->height, c->height, c->height }, bbx[0] ); - v3_add( mtxA[3], (v3f){ c->height, c->height, c->height }, bbx[1] ); + v3_sub( mtxA[3], (v3f){ c->h, c->h, c->h }, bbx[0] ); + v3_add( mtxA[3], (v3f){ c->h, c->h, c->h }, bbx[1] ); - scene_context *sc = s->bh_scene->user; + scene_context *sc = scene_bh->user; bh_iter it; bh_iter_init_box( 0, &it, bbx ); i32 idx; - while( bh_next( s->bh_scene, &it, &idx ) ){ + while( bh_next( scene_bh, &it, &idx ) ){ u32 *ptri = &sc->arrindices[ idx*3 ]; if( sc->arrvertices[ptri[0]].flags & ignore ) continue; @@ -1833,7 +1812,7 @@ static void rb_correct_position_constraints( rb_constr_pos *buf, int len, #if 1 v3_muladds( rbb->co, d, -1.0f * amt, rbb->co ); - rb_update_transform( rbb ); + rb_update_matrices( rbb ); #else f32 mt = 1.0f/(rba->inv_mass+rbb->inv_mass), a = mt * (k_phys_baumgarte/k_rb_delta); @@ -1865,7 +1844,8 @@ static void rb_correct_swingtwist_constraints( rb_constr_swingtwist *buf, v4f correction; q_axis_angle( correction, axis, angle ); q_mul( correction, st->rbb->q, st->rbb->q ); - rb_update_transform( st->rbb ); + q_normalize( st->rbb->q ); + rb_update_matrices( st->rbb ); #else f32 mt = 1.0f/(st->rba->inv_mass+st->rbb->inv_mass), wa = mt * acosf(angle) * (k_phys_baumgarte/k_rb_delta); @@ -1895,7 +1875,8 @@ static void rb_correct_swingtwist_constraints( rb_constr_swingtwist *buf, v4f correction; q_axis_angle( correction, axis, angle ); q_mul( correction, st->rbb->q, st->rbb->q ); - rb_update_transform( st->rbb ); + q_normalize( st->rbb->q ); + rb_update_matrices( st->rbb ); #else f32 mt = 1.0f/(st->rba->inv_mass+st->rbb->inv_mass), wa = mt * acosf(angle) * (k_phys_baumgarte/k_rb_delta); diff --git a/testing.c b/testing.c index b5b4cec..ad98cce 100644 --- a/testing.c +++ b/testing.c @@ -1,10 +1,13 @@ #include "rigidbody.h" -static rb_object baller = { - .type = k_rb_shape_box, - .rb.bbx = {{ -0.1f, -0.2f, -0.1f }, - { 0.1f, 1.0f, 0.1f }}, +struct { + rigidbody rb; + boxf box; +} +static baller = { .rb.q = { 0,0,0,1 }, + .box = {{ -0.1f, -0.2f, -0.1f }, + { 0.1f, 1.0f, 0.1f }}, }; static void testing_update(void){ @@ -13,20 +16,24 @@ static void testing_update(void){ v3_zero( baller.rb.w ); v3_zero( baller.rb.v ); q_identity( baller.rb.q ); - rb_update_transform( &baller.rb ); + rb_update_matrices( &baller.rb ); } - rb_object_debug( &baller, VG__RED ); + vg_line_boxf_transformed( baller.rb.to_world, baller.box, VG__RED ); world_instance *world = world_current_instance(); + rigidbody _null = {0}; + _null.inv_mass = 0.0f; + m3x3_zero( _null.iI ); + rb_solver_reset(); rb_ct *buf = rb_global_buffer(); - rb_contact_count += rb_box__scene( baller.rb.to_world, baller.rb.bbx, - NULL, &world->rb_geo.inf.scene, buf, + rb_contact_count += rb_box__scene( baller.rb.to_world, baller.box, + NULL, world->geo_bh, buf, k_material_flag_ghosts ); for( u32 j=0; jrb_geo.rb; + buf[j].rbb = &_null; } rb_presolve_contacts( rb_contact_buffer, rb_contact_count ); @@ -35,9 +42,9 @@ static void testing_update(void){ rb_solve_contacts( rb_contact_buffer, rb_contact_count ); rb_iter( &baller.rb ); - rb_update_transform( &baller.rb ); + rb_update_matrices( &baller.rb ); } static void testing_init(void){ - rb_init_object( &baller, 1.0f ); + rb_setbody_box( &baller.rb, baller.box, 8.0f, 1.0f ); } diff --git a/vehicle.c b/vehicle.c index b367a1c..3555a97 100644 --- a/vehicle.c +++ b/vehicle.c @@ -9,16 +9,16 @@ static int spawn_car( int argc, const char *argv[] ){ v3_muladds( ra, skaterift.cam.transform[2], -10.0f, rb ); float t; - if( spherecast_world( world_current_instance(), ra, rb, - gzoomer.obj.inf.sphere.radius, &t, rx, 0 ) != -1 ) + if( spherecast_world( world_current_instance(), + ra, rb, 1.0f, &t, rx, 0 ) != -1 ) { - v3_lerp( ra, rb, t, gzoomer.obj.rb.co ); - gzoomer.obj.rb.co[1] += 4.0f; - q_axis_angle( gzoomer.obj.rb.q, (v3f){1.0f,0.0f,0.0f}, 0.001f ); - v3_zero( gzoomer.obj.rb.v ); - v3_zero( gzoomer.obj.rb.w ); + v3_lerp( ra, rb, t, gzoomer.rb.co ); + gzoomer.rb.co[1] += 4.0f; + q_axis_angle( gzoomer.rb.q, (v3f){1.0f,0.0f,0.0f}, 0.001f ); + v3_zero( gzoomer.rb.v ); + v3_zero( gzoomer.rb.w ); - rb_update_transform( &gzoomer.obj.rb ); + rb_update_matrices( &gzoomer.rb ); gzoomer.alive = 1; vg_success( "Spawned car\n" ); @@ -30,13 +30,12 @@ static int spawn_car( int argc, const char *argv[] ){ return 0; } -static void vehicle_init(void) -{ - q_identity( gzoomer.obj.rb.q ); - v3_zero( gzoomer.obj.rb.w ); - v3_zero( gzoomer.obj.rb.v ); - v3_zero( gzoomer.obj.rb.co ); - rb_init_object( &gzoomer.obj, 1.0f ); +static void vehicle_init(void){ + q_identity( gzoomer.rb.q ); + v3_zero( gzoomer.rb.w ); + v3_zero( gzoomer.rb.v ); + v3_zero( gzoomer.rb.co ); + rb_setbody_sphere( &gzoomer.rb, 1.0f, 8.0f, 1.0f ); VG_VAR_F32( k_car_spring, flags=VG_VAR_PERSISTENT ); VG_VAR_F32( k_car_spring_damp, flags=VG_VAR_PERSISTENT ); @@ -58,11 +57,10 @@ static void vehicle_init(void) v3_copy((v3f){ 1.0f, -0.25f, 1.5f }, gzoomer.wheels_local[3] ); } -static void vehicle_wheel_force( int index ) -{ +static void vehicle_wheel_force( int index ){ v3f pa, pb, n; - m4x3_mulv( gzoomer.obj.rb.to_world, gzoomer.wheels_local[index], pa ); - v3_muladds( pa, gzoomer.obj.rb.to_world[1], -k_car_spring_length, pb ); + m4x3_mulv( gzoomer.rb.to_world, gzoomer.wheels_local[index], pa ); + v3_muladds( pa, gzoomer.rb.to_world[1], -k_car_spring_length, pb ); #if 1 @@ -89,7 +87,7 @@ static void vehicle_wheel_force( int index ) v3_lerp( pa, pb, t, pc ); m4x3f mtx; - m3x3_copy( gzoomer.obj.rb.to_world, mtx ); + m3x3_copy( gzoomer.rb.to_world, mtx ); v3_copy( pc, mtx[3] ); vg_line_sphere( mtx, k_car_wheel_radius, VG__BLACK ); vg_line( pa, pc, VG__WHITE ); @@ -100,22 +98,20 @@ static void vehicle_wheel_force( int index ) float Fv = (1.0f-t) * k_car_spring*k_rb_delta; v3f delta; - v3_sub( pa, gzoomer.obj.rb.co, delta ); + v3_sub( pa, gzoomer.rb.co, delta ); v3f rv; - v3_cross( gzoomer.obj.rb.w, delta, rv ); - v3_add( gzoomer.obj.rb.v, rv, rv ); + v3_cross( gzoomer.rb.w, delta, rv ); + v3_add( gzoomer.rb.v, rv, rv ); - Fv += v3_dot( rv, gzoomer.obj.rb.to_world[1] ) - * -k_car_spring_damp*k_rb_delta; + Fv += v3_dot(rv, gzoomer.rb.to_world[1]) * -k_car_spring_damp*k_rb_delta; /* scale by normal incident */ - Fv *= v3_dot( n, gzoomer.obj.rb.to_world[1] ); + Fv *= v3_dot( n, gzoomer.rb.to_world[1] ); v3f F; - v3_muls( gzoomer.obj.rb.to_world[1], Fv, F ); - - rb_linear_impulse( &gzoomer.obj.rb, delta, F ); + v3_muls( gzoomer.rb.to_world[1], Fv, F ); + rb_linear_impulse( &gzoomer.rb, delta, F ); /* friction vectors * -------------------------------------------------------------*/ @@ -124,7 +120,7 @@ static void vehicle_wheel_force( int index ) if( index <= 1 ) v3_cross( gzoomer.steerv, n, tx ); else - v3_cross( n, gzoomer.obj.rb.to_world[2], tx ); + v3_cross( n, gzoomer.rb.to_world[2], tx ); v3_cross( tx, n, ty ); v3_copy( tx, gzoomer.tangent_vectors[ index ][0] ); @@ -136,26 +132,26 @@ static void vehicle_wheel_force( int index ) /* orient inverse inertia tensors */ v3f raW; - m3x3_mulv( gzoomer.obj.rb.to_world, gzoomer.wheels_local[index], raW ); + m3x3_mulv( gzoomer.rb.to_world, gzoomer.wheels_local[index], raW ); v3f raCtx, raCtxI, raCty, raCtyI; v3_cross( tx, raW, raCtx ); v3_cross( ty, raW, raCty ); - m3x3_mulv( gzoomer.obj.rb.iIw, raCtx, raCtxI ); - m3x3_mulv( gzoomer.obj.rb.iIw, raCty, raCtyI ); + m3x3_mulv( gzoomer.rb.iIw, raCtx, raCtxI ); + m3x3_mulv( gzoomer.rb.iIw, raCty, raCtyI ); - gzoomer.tangent_mass[index][0] = gzoomer.obj.rb.inv_mass; + gzoomer.tangent_mass[index][0] = gzoomer.rb.inv_mass; gzoomer.tangent_mass[index][0] += v3_dot( raCtx, raCtxI ); gzoomer.tangent_mass[index][0] = 1.0f/gzoomer.tangent_mass[index][0]; - gzoomer.tangent_mass[index][1] = gzoomer.obj.rb.inv_mass; + gzoomer.tangent_mass[index][1] = gzoomer.rb.inv_mass; gzoomer.tangent_mass[index][1] += v3_dot( raCty, raCtyI ); gzoomer.tangent_mass[index][1] = 1.0f/gzoomer.tangent_mass[index][1]; /* apply drive force */ if( index >= 2 ){ v3_muls( ty, -gzoomer.drive * k_car_drive_force * k_rb_delta, F ); - rb_linear_impulse( &gzoomer.obj.rb, raW, F ); + rb_linear_impulse( &gzoomer.rb, raW, F ); } } else{ @@ -165,9 +161,8 @@ static void vehicle_wheel_force( int index ) } } -static void vehicle_solve_friction(void) -{ - rigidbody *rb = &gzoomer.obj.rb; +static void vehicle_solve_friction(void){ + rigidbody *rb = &gzoomer.rb; for( int i=0; i<4; i++ ){ v3f raW; m3x3_mulv( rb->to_world, gzoomer.wheels_local[i], raW ); @@ -203,7 +198,7 @@ static void vehicle_update_fixed(void) if( !gzoomer.alive ) return; - rigidbody *rb = &gzoomer.obj.rb; + rigidbody *rb = &gzoomer.rb; v3_muls( rb->to_world[2], -cosf(gzoomer.steer), gzoomer.steerv ); v3_muladds( gzoomer.steerv, rb->to_world[0], @@ -222,13 +217,17 @@ static void vehicle_update_fixed(void) for( int i=0; i<4; i++ ) vehicle_wheel_force( i ); + rigidbody _null = {0}; + _null.inv_mass = 0.0f; + m3x3_zero( _null.iI ); + rb_ct manifold[64]; - int len = rb_sphere__scene( rb->to_world, &gzoomer.obj.inf.sphere, NULL, - &world_current_instance()->rb_geo.inf.scene, + int len = rb_sphere__scene( rb->to_world, 1.0f, NULL, + world_current_instance()->geo_bh, manifold, 0 ); for( int j=0; jrb_geo.rb; + manifold[j].rbb = &_null; } rb_manifold_filter_coplanar( manifold, len, 0.05f ); @@ -246,15 +245,14 @@ static void vehicle_update_fixed(void) } rb_iter( rb ); - rb_update_transform( rb ); + rb_update_matrices( rb ); } -static void vehicle_update_post(void) -{ +static void vehicle_update_post(void){ if( !gzoomer.alive ) return; - rb_object_debug( &gzoomer.obj, VG__WHITE ); + vg_line_sphere( gzoomer.rb.to_world, 1.0f, VG__WHITE ); /* draw friction vectors */ v3f p0, px, py; diff --git a/vehicle.h b/vehicle.h index bdd12f0..ca8943d 100644 --- a/vehicle.h +++ b/vehicle.h @@ -21,7 +21,7 @@ typedef struct drivable_vehicle drivable_vehicle; struct drivable_vehicle { int alive, inside; - rb_object obj; + rigidbody rb; v3f wheels[4]; @@ -37,8 +37,7 @@ struct drivable_vehicle } static gzoomer = { - .obj = { .type = k_rb_shape_sphere, .inf.sphere.radius = 1.0f, - .rb.co = {-2000,-2000,-2000}} + .rb.co = {-2000,-2000,-2000} }; static int spawn_car( int argc, const char *argv[] ); diff --git a/world.h b/world.h index 642e757..7b10743 100644 --- a/world.h +++ b/world.h @@ -217,8 +217,6 @@ struct world_instance { mesh_water; u32 cubemap_cooldown, cubemap_side; - rb_object rb_geo; - /* leaderboards */ struct leaderboard_cache *leaderboard_cache; diff --git a/world_gen.c b/world_gen.c index b86c5cf..6572876 100644 --- a/world_gen.c +++ b/world_gen.c @@ -266,19 +266,8 @@ static void world_gen_generate_meshes( world_instance *world ){ /* need send off the memory to the gpu before we can create the bvh. */ vg_async_stall(); vg_info( "creating bvh\n" ); - - /* setup spacial mapping and rigidbody */ world->geo_bh = scene_bh_create( world->heap, &world->scene_geo ); - v3_zero( world->rb_geo.rb.co ); - v3_zero( world->rb_geo.rb.v ); - q_identity( world->rb_geo.rb.q ); - v3_zero( world->rb_geo.rb.w ); - - world->rb_geo.type = k_rb_shape_scene; - world->rb_geo.inf.scene.bh_scene = world->geo_bh; - rb_init_object( &world->rb_geo, 0.0f ); - /* * Generate scene: non-collidable geometry * ---------------------------------------------------------------- diff --git a/world_render.h b/world_render.h index 540e0be..ecbd3d2 100644 --- a/world_render.h +++ b/world_render.h @@ -51,12 +51,12 @@ struct world_render{ u32 timer_text_count; struct text_particle{ - rb_object obj; + rigidbody rb; m4x3f mlocal; ent_glyph *glyph; v4f colour; - m4x3f mdl; + f32 radius; } text_particles[6*4]; u32 text_particle_count; diff --git a/world_routes.c b/world_routes.c index daba459..b0af904 100644 --- a/world_routes.c +++ b/world_routes.c @@ -666,27 +666,31 @@ static void world_routes_update( world_instance *world ){ for( u32 i=0; iobj, VG__RED ); + //rb_object_debug( &particle->obj, VG__RED ); } } static void world_routes_fixedupdate( world_instance *world ){ rb_solver_reset(); + rigidbody _null = {0}; + _null.inv_mass = 0.0f; + m3x3_zero( _null.iI ); + for( u32 i=0; iobj.rb.to_world, - &particle->obj.inf.sphere, - NULL, &world->rb_geo.inf.scene, buf, + int l = rb_sphere__scene( particle->rb.to_world, + particle->radius, + NULL, world->geo_bh, buf, k_material_flag_ghosts ); for( int j=0; jobj.rb; - buf[j].rbb = &world->rb_geo.rb; + buf[j].rba = &particle->rb; + buf[j].rbb = &_null; } rb_contact_count += l; @@ -705,12 +709,12 @@ static void world_routes_fixedupdate( world_instance *world ){ for( u32 i=0; iobj.rb ); + rb_iter( &particle->rb ); } for( u32 i=0; iobj.rb ); + rb_update_matrices( &particle->rb ); } } @@ -878,26 +882,24 @@ static void world_routes_fracture( world_instance *world, ent_gate *gate, v3_add( offset, origin, world_co ); m4x3_mulv( transform, world_co, world_co ); - float r = vg_maxf( s[0]*glyph->size[0], s[1]*glyph->size[1] )*0.5f; m3x3_identity( particle->mlocal ); m3x3_scale( particle->mlocal, s ); origin[2] *= s[2]; v3_muls( origin, -1.0f, particle->mlocal[3] ); - v3_copy( world_co, particle->obj.rb.co ); - v3_muls( imp_v, 1.0f+vg_randf64(&vg.rand), particle->obj.rb.v ); - particle->obj.rb.v[1] += 2.0f; - - v4_copy( q, particle->obj.rb.q ); - particle->obj.rb.w[0] = vg_randf64(&vg.rand)*2.0f-1.0f; - particle->obj.rb.w[1] = vg_randf64(&vg.rand)*2.0f-1.0f; - particle->obj.rb.w[2] = vg_randf64(&vg.rand)*2.0f-1.0f; + v3_copy( world_co, particle->rb.co ); + v3_muls( imp_v, 1.0f+vg_randf64(&vg.rand), particle->rb.v ); + particle->rb.v[1] += 2.0f; - particle->obj.type = k_rb_shape_sphere; - particle->obj.inf.sphere.radius = r*0.6f; + v4_copy( q, particle->rb.q ); + particle->rb.w[0] = vg_randf64(&vg.rand)*2.0f-1.0f; + particle->rb.w[1] = vg_randf64(&vg.rand)*2.0f-1.0f; + particle->rb.w[2] = vg_randf64(&vg.rand)*2.0f-1.0f; - rb_init_object( &particle->obj, 1.0f ); + f32 r = vg_maxf( s[0]*glyph->size[0], s[1]*glyph->size[1] )*0.5f; + particle->radius = r*0.6f; + rb_setbody_sphere( &particle->rb, particle->radius, 1.0f, 1.0f ); } offset[0] += glyph->size[0]; } @@ -1009,7 +1011,7 @@ static void render_world_routes( world_instance *world, v4f q; m4x3f model; - rb_extrapolate( &particle->obj.rb, model[3], q ); + rb_extrapolate( &particle->rb, model[3], q ); q_m3x3( q, model ); m4x3_mul( model, particle->mlocal, particle->mdl );