whole
authorhgn <hgodden00@gmail.com>
Fri, 23 Sep 2022 02:05:50 +0000 (03:05 +0100)
committerhgn <hgodden00@gmail.com>
Fri, 23 Sep 2022 02:05:50 +0000 (03:05 +0100)
15 files changed:
blender_export.py
main.c
models_src/ch_new.mdl
models_src/mp_dev.mdl
models_src/rs_scoretext.mdl
physics_test.h
player.h
player_model.h
rigidbody.h
shaders/scoretext.h
shaders/scoretext.vs
shaders/viewchar.fs
shaders/viewchar.h
world.h
world_sfd.h

index 04fd6c344b69245f172dc139801d24196f5c1b04..acd28ec3bcfcadbd96bc17cc539bd1508a78f86d 100644 (file)
@@ -205,6 +205,9 @@ def write_model(collection_name):
    def emplace_material( mat ):
       nonlocal material_cache, material_buffer
 
+      if mat == None:
+         return 0
+
       if mat.name in material_cache:
          return material_cache[mat.name]
 
@@ -395,7 +398,9 @@ def write_model(collection_name):
          can_use_cache = True
 
          for mod in obj.modifiers:
-            if mod.type == 'DATA_TRANSFER' or mod.type == 'SHRINKWRAP':
+            if mod.type == 'DATA_TRANSFER' or mod.type == 'SHRINKWRAP' or \
+               mod.type == 'BOOLEAN' or mod.type == 'CURVE' or \
+               mod.type == 'ARRAY':
                can_use_cache = False
 
             if mod.type == 'ARMATURE':
@@ -471,7 +476,11 @@ def write_model(collection_name):
                   # WEight groups
                   #
                   if armature_def:
-                     weight_groups = sorted( data.vertices[vi].groups, key = \
+                     src_groups = [_ for _ in data.vertices[vi].groups \
+                                 if obj.vertex_groups[_.group].name in \
+                                    armature_def['bones']]
+
+                     weight_groups = sorted( src_groups, key = \
                                              lambda a: a.weight, reverse=True )
                      tot = 0.0
                      for ml in range(3):
@@ -653,12 +662,25 @@ def write_model(collection_name):
                         for pb in armature.pose.bones:
                            if pb.name == bone_name:
                               rb = armature.data.bones[ bone_name ]
-
-                              loc, rot, sca = pb.matrix_basis.decompose()
+                              
+                              # relative bone matrix
+                              if rb.parent is not None:
+                                 offset_mtx = rb.parent.matrix_local
+                                 offset_mtx = offset_mtx.inverted_safe() @ \
+                                              rb.matrix_local
+
+                                 inv_parent = pb.parent.matrix @ offset_mtx
+                                 inv_parent.invert_safe()
+                                 fpm = inv_parent @ pb.matrix 
+                              else:
+                                 bone_mtx = rb.matrix.to_4x4()
+                                 local_inv = rb.matrix_local.inverted_safe()
+                                 fpm = bone_mtx @ local_inv @ pb.matrix
+
+                              loc, rot, sca = fpm.decompose()
 
                               # local position
-                              vp = rb.matrix @ loc
-                              final_pos = Vector(( vp[0], vp[2], -vp[1] ))
+                              final_pos = Vector(( loc[0], loc[2], -loc[1] ))
 
                               # rotation
                               lc_m = pb.matrix_channel.to_3x3()
@@ -1011,7 +1033,7 @@ def cv_draw():
    for obj in bpy.context.collection.objects:
       if obj.type == 'ARMATURE':
          for bone in obj.data.bones:
-            if bone.cv_data.collider:
+            if bone.cv_data.collider and obj.data.pose_position == 'REST':
                c = bone.head_local
                a = bone.cv_data.v0
                b = bone.cv_data.v1
@@ -1336,17 +1358,10 @@ class CV_BONE_SETTINGS(bpy.types.PropertyGroup):
    v0: bpy.props.FloatVectorProperty(name="v0",size=3)
    v1: bpy.props.FloatVectorProperty(name="v1",size=3)
 
+   con0: bpy.props.BoolProperty(name="Constriant 0",default=False)
    mins: bpy.props.FloatVectorProperty(name="mins",size=3)
    maxs: bpy.props.FloatVectorProperty(name="maxs",size=3)
 
-   con0: bpy.props.BoolProperty(name="Constriant 0",default=False)
-   c0: bpy.props.FloatVectorProperty(name="dir",size=3)
-   s0: bpy.props.FloatVectorProperty(name="limits",size=3)
-
-   con1: bpy.props.BoolProperty(name="Constriant 1",default=False)
-   c1: bpy.props.FloatVectorProperty(name="dir",size=3)
-   s1: bpy.props.FloatVectorProperty(name="limits",size=3)
-
 class CV_BONE_PANEL(bpy.types.Panel):
    bl_label="Bone Config"
    bl_idname="SCENE_PT_cv_bone"
@@ -1366,16 +1381,9 @@ class CV_BONE_PANEL(bpy.types.Panel):
       _.layout.prop( bone.cv_data, "v1" )
 
       _.layout.label( text="Angle Limits" )
+      _.layout.prop( bone.cv_data, "con0" )
       _.layout.prop( bone.cv_data, "mins" )
       _.layout.prop( bone.cv_data, "maxs" )
-      
-      _.layout.prop( bone.cv_data, "con0" )
-      _.layout.prop( bone.cv_data, "c0" )
-      _.layout.prop( bone.cv_data, "s0" )
-
-      _.layout.prop( bone.cv_data, "con1" )
-      _.layout.prop( bone.cv_data, "c1" )
-      _.layout.prop( bone.cv_data, "s1" )
 
 class CV_SCENE_SETTINGS(bpy.types.PropertyGroup):
    use_hidden: bpy.props.BoolProperty( name="use hidden", default=False )
diff --git a/main.c b/main.c
index 76d06f60a3696a91fa60e698e86904b7fc173a83..b46f3771b5a565abba28504e852f745fe97f5bfc 100644 (file)
--- a/main.c
+++ b/main.c
@@ -18,6 +18,7 @@ static int debugview = 0;
 static int sv_debugcam = 0;
 static int lightedit = 0;
 static int sv_scene = 0;
+static int cl_ui = 1;
 
 /* Components */
 //#define SR_NETWORKED
@@ -138,6 +139,14 @@ void vg_start(void)
       .persistent = 1
    });
 
+   vg_convar_push( (struct vg_convar){
+      .name = "cl_ui",
+      .data = &cl_ui,
+      .data_type = k_convar_dtype_i32,
+      .opt_i32 = { .min=0, .max=1, .clamp=1 },
+      .persistent = 1
+   });
+
    vg_convar_push( (struct vg_convar){
       .name = "walk_speed",
       .data = &k_walkspeed,
@@ -146,6 +155,22 @@ void vg_start(void)
       .persistent = 1
    });
 
+   vg_convar_push( (struct vg_convar){
+      .name = "run_speed",
+      .data = &k_runspeed,
+      .data_type = k_convar_dtype_f32,
+      .opt_f32 = { .clamp = 0 },
+      .persistent = 1
+   });
+
+   vg_convar_push( (struct vg_convar){
+      .name = "walk_accel",
+      .data = &k_walk_accel,
+      .data_type = k_convar_dtype_f32,
+      .opt_f32 = { .clamp = 0 },
+      .persistent = 1
+   });
+
    vg_convar_push( (struct vg_convar){
       .name = "dt",
       .data = &ktimestep,
@@ -277,9 +302,12 @@ static void render_main_game(void)
    /* 
     * Draw world
     */
+
+   int draw_solid = player.is_dead | freecam;
    
-   draw_player();
    render_world( vg_pv, player.camera );
+   if( draw_solid )
+      draw_player();
    render_water_texture( player.camera );
 
    glBindFramebuffer( GL_FRAMEBUFFER, 0 );
@@ -305,14 +333,14 @@ static void render_main_game(void)
    else
       glClear( GL_COLOR_BUFFER_BIT );
    
-   if( !player.is_dead )
+   if( !draw_solid )
    {
       m4x4_projection( vg_pv, gpipeline.fov, 
             (float)vg_window_x / (float)vg_window_y, 
             0.01f, 600.0f );
       m4x4_mul( vg_pv, world_4x4, vg_pv );
+      draw_player();
    }
-   //draw_player();
 
    /* Draw back in the background
     *
@@ -451,7 +479,10 @@ void vg_ui(void)
    }
    
    //glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
-   render_world_routes_ui();
+   if( cl_ui )
+   {
+      render_world_routes_ui();
+   }
    //glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
 
 #if 0
index 271dcbecfd09efcd59f981f2a1029f6e138f0c36..0a9f1d74d7fc8a893492a33a7df546da8b07f1b6 100644 (file)
Binary files a/models_src/ch_new.mdl and b/models_src/ch_new.mdl differ
index f2f09ccc76b8856f061cfd0657917d663a8d5b78..6364062545b4cb7fdebd0de229cf823d7b4c0924 100644 (file)
Binary files a/models_src/mp_dev.mdl and b/models_src/mp_dev.mdl differ
index 359cc8a66f46cba31329305e4ec6e5de55d934c3..f038cf43dfc5e8ba35a38401198f792b3e8d3997 100644 (file)
Binary files a/models_src/rs_scoretext.mdl and b/models_src/rs_scoretext.mdl differ
index acf4ed3cd96c6e46183b3995a81093075a51601d..33a6b6b7f8c56b70a75470da8e96ea55b3d9eb90 100644 (file)
@@ -22,7 +22,7 @@ rigidbody blocky =
 rigidbody marko = 
 {
    .type = k_rb_shape_box,
-   .bbx = {{-2.0f,-2.0f,-2.0f},{2.0f,2.0f,2.0f}},
+   .bbx = {{-0.5f,-0.5f,-0.5f},{0.5f,0.5f,0.5f}},
    .co = {-36.0f,8.0f,-36.0f},
    .q = {0.0f,0.0f,0.0f,1.0f},
    .is_world = 0
@@ -73,7 +73,7 @@ rigidbody jeff1 = { .type = k_rb_shape_capsule,
 };
 
 rigidbody ball = { .type = k_rb_shape_sphere,
-                   .inf.sphere = { .radius = 4.0f },
+                   .inf.sphere = { .radius = 2.0f },
                    .co = {0.0f,20.0f,2.0f},
                    .q = {0.0f,0.0f,0.0f,1.0f}},
 
@@ -88,8 +88,6 @@ static void reorg_jeffs(void)
 {
    for( int i=0; i<vg_list_size(jeffs); i++ )
    {
-      v3_zero( jeffs[i].v );
-      v3_zero( jeffs[i].w );
       v3_copy( (v3f){ (vg_randf()-0.5f) * 10.0f,
                       (vg_randf()-0.5f) * 10.0f + 17.0f,
                       (vg_randf()-0.5f) * 10.0f }, jeffs[i].co );
@@ -99,7 +97,7 @@ static void reorg_jeffs(void)
       
       jeffs[i].type = k_rb_shape_capsule;
       jeffs[i].inf.capsule.radius = 0.75f;
-      jeffs[i].inf.capsule.height = 8.0f;
+      jeffs[i].inf.capsule.height = 3.0f;
 
       rb_init( &jeffs[i] );
    }
index 726d62483c5788bd3e713ad64fa9a355c7a1ff44..99cb6c8105af173d585f941ee7ad542442d721a2 100644 (file)
--- a/player.h
+++ b/player.h
@@ -13,7 +13,8 @@
  */
 
 static float 
-   k_walkspeed             = 2.0f,
+   k_walkspeed             = 7.0f,  /* no longer used */
+   k_runspeed              = 14.0f,
    k_board_radius          = 0.3f,
    k_board_length          = 0.45f,
    k_board_allowance       = 0.04f,
@@ -25,10 +26,14 @@ static float
    k_steer_ground          = 2.5f,
    k_steer_air             = 3.6f,
    k_steer_air_lerp        = 0.3f,
-   k_pump_force            = 000.0f,
+   k_pump_force            = 0.0f,
    k_downforce             = 5.0f,
    k_jump_charge_speed     = (1.0f/1.0f),
-   k_jump_force            = 5.0f;
+   k_jump_force            = 5.0f,
+   k_pitch_limit           = 1.5f,
+   k_look_speed            = 2.0f,
+   k_walk_accel            = 5.0f,
+   k_walk_friction         = 8.0f;
 
 static int freecam = 0;
 static int walk_grid_iterations = 1;
@@ -39,6 +44,9 @@ static struct gplayer
    /* Physics */
    rigidbody rb, collide_front, collide_back, rb_gate_frame;
 
+   /* TODO: eugh */
+   m3x3f gate_vr_frame, gate_vr_pstep_frame;
+
    v3f a, v_last, m, bob, vl;
 
    /* Utility */
@@ -53,7 +61,7 @@ static struct gplayer
    float pitch;
    float pushing, push_time;
    float jump;
-   int jump_charge;
+   int jump_charge, jump_dir;
    
    v3f land_target;
    v3f land_target_log[22];
@@ -81,11 +89,13 @@ static struct gplayer
          ffly,
          fpush,
          fairdir,
-         fsetup;
+         fsetup,
+         walk_timer,
+         fonboard;
 }
 player = 
 {
-   .on_board = 1,
+   .on_board = 0,
 
    .collide_front = { .type = k_rb_shape_sphere, .inf.sphere.radius = 0.3f },
    .collide_back  = { .type = k_rb_shape_sphere, .inf.sphere.radius = 0.3f }
@@ -313,6 +323,10 @@ static void player_physics_control(void)
    if( vg_get_button( "jump" ) )
    {
       player.jump += ktimestep * k_jump_charge_speed;
+
+      if( !player.jump_charge )
+         player.jump_dir = player.reverse > 0.0f? 1: 0;
+
       player.jump_charge = 1;
    }
 
@@ -438,6 +452,112 @@ static void player_init(void)
    rb_init( &player.collide_back  );
 }
 
+static void player_walk_physics(void)
+{
+   rigidbody *rbf = &player.collide_front,
+             *rbb = &player.collide_back;
+
+   m3x3_copy( player.rb.to_world, player.collide_front.to_world );
+   m3x3_copy( player.rb.to_world, player.collide_back.to_world );
+   
+   float h0 = 0.3f,
+         h1 = 0.9f;
+
+   m4x3_mulv( player.rb.to_world, (v3f){0.0f,h0,0.0f}, rbf->co );
+   v3_copy( rbf->co, rbf->to_world[3] );
+   m4x3_mulv( player.rb.to_world, (v3f){0.0f,h1,0.0f}, rbb->co );
+   v3_copy( rbb->co, rbb->to_world[3] );
+
+   m4x3_invert_affine( rbf->to_world, rbf->to_local );
+   m4x3_invert_affine( rbb->to_world, rbb->to_local );
+
+   rb_update_bounds( rbf );
+   rb_update_bounds( rbb );
+
+   rb_debug( rbf, 0xff0000ff );
+   rb_debug( rbb, 0xff0000ff );
+
+   rb_ct manifold[64];
+   int len = 0;
+
+   len += rb_sphere_scene( rbf, &world.rb_geo, manifold+len );
+   len += rb_sphere_scene( rbb, &world.rb_geo, manifold+len );
+
+   rb_presolve_contacts( manifold, len );
+
+   for( int j=0; j<5; j++ )
+   {
+      for( int i=0; i<len; i++ )
+      {
+         struct contact *ct = &manifold[i];
+         
+         /*normal */
+         float vn = -v3_dot( player.rb.v, ct->n );
+         vn += ct->bias;
+
+         float temp = ct->norm_impulse;
+         ct->norm_impulse = vg_maxf( temp + vn, 0.0f );
+         vn = ct->norm_impulse - temp;
+
+         v3f impulse;
+         v3_muls( ct->n, vn, impulse );
+
+         v3_add( impulse, player.rb.v, player.rb.v );
+
+         /* friction */
+         for( int j=0; j<2; j++ )
+         {
+            float     f = k_friction * ct->norm_impulse,
+                     vt = v3_dot( player.rb.v, ct->t[j] ),
+                 lambda = -vt;
+            
+            float temp = ct->tangent_impulse[j];
+            ct->tangent_impulse[j] = vg_clampf( temp + lambda, -f, f );
+            lambda = ct->tangent_impulse[j] - temp;
+
+            v3_muladds( player.rb.v, ct->t[j], lambda, player.rb.v );
+         }
+      }
+   }
+   
+   v3_zero( player.rb.w );
+   q_axis_angle( player.rb.q, (v3f){0.0f,1.0f,0.0f}, -player.angles[0] );
+
+   v3f forward_dir = { sinf(player.angles[0]),0.0f,-cosf(player.angles[0]) };
+
+   v3f p1;
+   v3_muladds( player.rb.co, forward_dir, 2.0f, p1 );
+   vg_line( player.rb.co, p1, 0xff0000ff );
+
+   float move_dead = 0.1f,
+         move = vg_get_axis("grabr")*0.5f + 0.5f - move_dead;
+
+   if( move > 0.0f )
+   {
+      float move_norm = move * (1.0f/(1.0f-move_dead)),
+            speed     = vg_lerpf( 0.1f*k_runspeed, k_runspeed, move_norm ),
+            amt       = k_walk_accel * ktimestep,
+            zvel      = v3_dot( player.rb.v, forward_dir ),
+            new_vel   = vg_minf( zvel + amt, speed ),
+            diff      = new_vel - vg_minf( zvel, speed );
+
+      v3_muladds( player.rb.v, forward_dir, diff, player.rb.v );
+
+      /* TODO move */
+      float walk_norm = (float)player.mdl.anim_walk->length / 30.0f,
+            run_norm  = (float)player.mdl.anim_run->length  / 30.0f;
+
+      player.walk_timer += ktimestep * vg_lerpf( walk_norm,run_norm,move_norm );
+   }
+   else
+   {
+      player.walk_timer = 0.0f;
+   }
+
+   player.rb.v[0] *= 1.0f - (ktimestep*k_walk_friction);
+   player.rb.v[2] *= 1.0f - (ktimestep*k_walk_friction);
+}
+
 static void player_physics(void)
 {
    /*
@@ -467,7 +587,7 @@ static void player_physics(void)
    rb_debug( rbf, 0xff00ffff );
    rb_debug( rbb, 0xffffff00 );
 
-   rb_ct manifold[24];
+   rb_ct manifold[64];
    int len = 0;
 
    len += rb_sphere_scene( rbf, &world.rb_geo, manifold+len );
@@ -581,8 +701,22 @@ static void player_physics(void)
 
       if( !player.jump_charge && player.jump > 0.2f )
       {
-         v3_muladds( player.rb.v, player.rb.up, k_jump_force*player.jump,
-                     player.rb.v );
+         v3f jumpdir;
+         
+         /* Launch more up if alignment is up else improve velocity */
+         float aup = fabsf(v3_dot( (v3f){0.0f,1.0f,0.0f}, player.rb.up )),
+               mod = 0.5f,
+               dir = mod + aup*(1.0f-mod);
+
+         v3_copy( player.rb.v, jumpdir );
+         v3_normalize( jumpdir );
+         v3_muls( jumpdir, 1.0f-dir, jumpdir );
+         v3_muladds( jumpdir, player.rb.up, dir, jumpdir );
+         v3_normalize( jumpdir );
+         
+         float force = k_jump_force*player.jump;
+         v3_muladds( player.rb.v, jumpdir, force, player.rb.v );
+         player.jump = 0.0f;
 
          player.jump_time = vg_time;
       }
@@ -605,7 +739,10 @@ static void player_do_motion(void)
    float horizontal = vg_get_axis("horizontal"),
          vertical = vg_get_axis("vertical");
 
-   player_physics();
+   if( player.on_board )
+      player_physics();
+   else
+      player_walk_physics();
    
    /* Integrate velocity */
    v3f prevco;
@@ -662,6 +799,9 @@ static void player_do_motion(void)
          
          world_routes_activate_gate( i );
          player.rb_gate_frame = player.rb;
+
+         m3x3_copy( player.vr, player.gate_vr_frame );
+         m3x3_copy( player.vr_pstep, player.gate_vr_pstep_frame );
          break;
       }
    }
@@ -673,8 +813,53 @@ static void player_do_motion(void)
  * Animation
  */
 
+static void player_animate_offboard(void)
+{
+   mdl_keyframe apose[32], bpose[32];
+   struct skeleton *sk = &player.mdl.sk;
+
+   float walk_norm = 30.0f/(float)player.mdl.anim_walk->length,
+         run_norm  = 30.0f/(float)player.mdl.anim_run->length,
+         t = player.walk_timer,
+         l = vg_get_axis("grabr") * 0.5f + 0.5f;
+
+   skeleton_sample_anim( sk, player.mdl.anim_walk, t*walk_norm, apose );
+   skeleton_sample_anim( sk, player.mdl.anim_run,  t*run_norm,  bpose );
+
+   skeleton_lerp_pose( sk, apose, bpose, l, apose );
+
+   float idle_walk = vg_minf( l * 10.0f, 1.0f);
+
+   skeleton_sample_anim( sk, player.mdl.anim_idle, vg_time*0.1f, bpose );
+   skeleton_lerp_pose( sk, apose, bpose, 1.0f-idle_walk, apose );
+
+   skeleton_apply_pose( &player.mdl.sk, apose, k_anim_apply_defer_ik );
+   skeleton_apply_ik_pass( &player.mdl.sk );
+   skeleton_apply_pose( &player.mdl.sk, apose, k_anim_apply_deffered_only );
+
+   v3_copy( player.mdl.sk.final_mtx[player.mdl.id_head-1][3], 
+               player.mdl.cam_pos );
+
+   skeleton_apply_inverses( &player.mdl.sk );
+
+   m4x3f mtx;
+   v4f rot;
+   q_axis_angle( rot, (v3f){0.0f,1.0f,0.0f}, -player.angles[0] - VG_PIf*0.5f );
+   q_m3x3( rot, mtx );
+   v3_copy( player.rb.to_world[3], mtx[3] );
+
+   skeleton_apply_transform( &player.mdl.sk, mtx );
+   skeleton_debug( &player.mdl.sk );
+}
+
 static void player_animate(void)
 {
+   if( !player.on_board )
+   {
+      player_animate_offboard();
+      return;
+   }
+
    /* Camera position */
    v3_sub( player.rb.v, player.v_last, player.a );
    v3_copy( player.rb.v, player.v_last );
@@ -774,15 +959,19 @@ static void player_animate(void)
       skeleton_lerp_pose( sk, apose, bpose, player.fpush, apose );
 
       /* trick setup */
-      float setup_frame = player.jump * (12.0f/30.0f),
+      float jump_start_frame = 14.0f/30.0f;
+      float setup_frame = player.jump * jump_start_frame,
             setup_blend = vg_minf( player.jump*5.0f, 1.0f );
       
-      float jump_frame = (vg_time - player.jump_time) + (12.0f/30.0f);
-      if( jump_frame >= (12.0f/30.0f) && jump_frame <= (40.0f/30.0f) )
+      float jump_frame = (vg_time - player.jump_time) + jump_start_frame;
+      if( jump_frame >= jump_start_frame && jump_frame <= (40.0f/30.0f) )
          setup_frame = jump_frame;
 
-      skeleton_sample_anim_clamped( sk, player.mdl.anim_ollie, 
-                                       setup_frame, bpose );
+      struct skeleton_anim *jump_anim = player.jump_dir?
+                                        player.mdl.anim_ollie:
+                                        player.mdl.anim_ollie_reverse;
+
+      skeleton_sample_anim_clamped( sk, jump_anim, setup_frame, bpose );
       skeleton_lerp_pose( sk, apose, bpose, setup_blend, ground_pose );
    }
    
@@ -793,22 +982,35 @@ static void player_animate(void)
       
       float air_frame = (player.fairdir*0.5f+0.5f) * (15.0f/30.0f);
       
-      skeleton_sample_anim( sk, player.mdl.anim_air, air_frame, air_pose );
+      skeleton_sample_anim( sk, player.mdl.anim_air, air_frame, apose );
+
+      static v2f grab_choice;
+      v2_lerp( grab_choice, (v2f){ vg_get_axis("h1"), vg_get_axis("v1") },
+                            0.04f, grab_choice );
+
+      float ang = atan2f( grab_choice[0], grab_choice[1] ),
+            ang_unit = (ang+VG_PIf) * (1.0f/VG_TAUf),
+            grab_frame = ang_unit * (15.0f/30.0f);
+
+      skeleton_sample_anim( sk, player.mdl.anim_grabs, grab_frame, bpose );
+      skeleton_lerp_pose( sk, apose, bpose, player.grab, air_pose );
    }
 
    skeleton_lerp_pose( sk, ground_pose, air_pose, player.ffly, apose );
 
+   float add_grab_mod = player.ffly * player.grab;
+
    /* additive effects */
-   apose[player.mdl.id_hip-1].co[0] += offset[0];
-   apose[player.mdl.id_hip-1].co[2] += offset[2];
-   apose[player.mdl.id_ik_hand_l-1].co[0] += offset[0];
-   apose[player.mdl.id_ik_hand_l-1].co[2] += offset[2];
-   apose[player.mdl.id_ik_hand_r-1].co[0] += offset[0];
-   apose[player.mdl.id_ik_hand_r-1].co[2] += offset[2];
-   apose[player.mdl.id_ik_elbow_l-1].co[0] += offset[0];
-   apose[player.mdl.id_ik_elbow_l-1].co[2] += offset[2];
-   apose[player.mdl.id_ik_elbow_r-1].co[0] += offset[0];
-   apose[player.mdl.id_ik_elbow_r-1].co[2] += offset[2];
+   apose[player.mdl.id_hip-1].co[0] += offset[0]*add_grab_mod;
+   apose[player.mdl.id_hip-1].co[2] += offset[2]*add_grab_mod;
+   apose[player.mdl.id_ik_hand_l-1].co[0] += offset[0]*add_grab_mod;
+   apose[player.mdl.id_ik_hand_l-1].co[2] += offset[2]*add_grab_mod;
+   apose[player.mdl.id_ik_hand_r-1].co[0] += offset[0]*add_grab_mod;
+   apose[player.mdl.id_ik_hand_r-1].co[2] += offset[2]*add_grab_mod;
+   apose[player.mdl.id_ik_elbow_l-1].co[0] += offset[0]*add_grab_mod;
+   apose[player.mdl.id_ik_elbow_l-1].co[2] += offset[2]*add_grab_mod;
+   apose[player.mdl.id_ik_elbow_r-1].co[0] += offset[0]*add_grab_mod;
+   apose[player.mdl.id_ik_elbow_r-1].co[2] += offset[2]*add_grab_mod;
 
    skeleton_apply_pose( &player.mdl.sk, apose, k_anim_apply_defer_ik );
    skeleton_apply_ik_pass( &player.mdl.sk );
@@ -868,34 +1070,66 @@ static void player_animate_death_cam(void)
 static void player_animate_camera(void)
 {
    static v3f lerp_cam = {0.0f,0.0f,0.0f};
-   v3f offs = { -0.4f, 0.15f, 0.0f };
+   v3f cam_pos;
 
-   v3_lerp( lerp_cam, player.mdl.cam_pos, 0.8f, lerp_cam );
-   v3_add( lerp_cam, offs, offs );
-   m4x3_mulv( player.rb.to_world, offs, player.camera_pos );
-   
-   /* Look angles */
-   v3_lerp( player.vl, player.rb.v, 0.05f, player.vl );
+   player.fonboard = vg_lerpf(player.fonboard, player.on_board, ktimestep*1.0f);
 
-   float yaw = atan2f(  player.vl[0], -player.vl[2] ),
-       pitch = atan2f( -player.vl[1], 
-             sqrtf(
-               player.vl[0]*player.vl[0] + player.vl[2]*player.vl[2]
-             )) * 0.7f;
-
-   player.angles[0] = yaw;
-   player.angles[1] = pitch + 0.30f;
-
-   /* Camera shake */
-   static v2f shake_damp = {0.0f,0.0f};
-   v2f shake = { vg_randf()-0.5f, vg_randf()-0.5f };
-   v2_muls( shake, v3_length(player.rb.v)*0.3f 
-                        * (1.0f+fabsf(player.slip)), shake);
-
-   v2_lerp( shake_damp, shake, 0.01f, shake_damp );
-   shake_damp[0] *= 0.2f;
+   if( player.on_board )
+   {
+      v3f offs = { -0.4f, 0.15f, 0.0f };
+      v3_lerp( lerp_cam, player.mdl.cam_pos, 0.8f, lerp_cam );
+      v3_add( lerp_cam, offs, cam_pos );
+
+      /* Look angles */
+      v3_lerp( player.vl, player.rb.v, 0.05f, player.vl );
+
+      float yaw = atan2f(  player.vl[0], -player.vl[2] ),
+          pitch = atan2f( -player.vl[1], 
+                sqrtf(
+                  player.vl[0]*player.vl[0] + player.vl[2]*player.vl[2]
+                )) * 0.7f;
+
+      player.angles[0] = yaw;
+      player.angles[1] = vg_lerpf( player.angles[1], pitch + 0.30f, 
+                                                         player.fonboard );
+
+      /* Camera shake */
+      static v2f shake_damp = {0.0f,0.0f};
+      v2f shake = { vg_randf()-0.5f, vg_randf()-0.5f };
+      v2_muls( shake, v3_length(player.rb.v)*0.3f 
+                           * (1.0f+fabsf(player.slip)), shake);
+
+      v2_lerp( shake_damp, shake, 0.01f, shake_damp );
+      shake_damp[0] *= 0.2f;
+
+      v2_muladds( player.angles, shake_damp, 0.1f, player.angles );
+      m4x3_mulv( player.rb.to_world, cam_pos, player.camera_pos );
+   }
+   else
+   {
+      float speed = ktimestep * k_look_speed;
+      player.angles[0] += vg_get_axis( "horizontal" ) * speed;
+      player.angles[1] += vg_get_axis( "vertical" ) * speed;
+      
+      player.angles[1] = vg_clampf( player.angles[1], 
+                                       -k_pitch_limit, k_pitch_limit );
+      
+      float s =  sinf(player.angles[0]) * 0.2f,
+            c = -cosf(player.angles[0]) * 0.2f;
+      v3f forward_dir = { s,0.15f,c };
 
-   v2_muladds( player.angles, shake_damp, 0.1f, player.angles );
+      
+      m4x3f mtx;
+      v4f rot;
+      q_axis_angle( rot, (v3f){0.0f,1.0f,0.0f}, 
+                              -player.angles[0] -VG_PIf*0.5f );
+      q_m3x3( rot, mtx );
+      v3_copy( player.rb.to_world[3], mtx[3] );
+
+      m4x3_mulv( mtx, player.mdl.cam_pos, cam_pos );
+      v3_add( cam_pos, forward_dir, player.camera_pos );
+      v3_lerp( player.vl, player.rb.v, 0.3f, player.vl );
+   }
 }
 
 /* 
@@ -1015,6 +1249,8 @@ static int reset_player( int argc, char const *argv[] )
    
    rb_update_transform( &player.rb );
    m3x3_mulv( player.rb.to_world, (v3f){ 0.0f, 0.0f, -1.2f }, player.rb.v );
+   m3x3_identity( player.gate_vr_frame );
+   m3x3_identity( player.gate_vr_pstep_frame );
 
    player.rb_gate_frame = player.rb;
    return 1;
@@ -1029,6 +1265,8 @@ static void player_update(void)
    if( vg_get_axis("grabl")>0.0f)
    {
       player.rb = player.rb_gate_frame;
+      m3x3_copy( player.gate_vr_frame, player.vr );
+      m3x3_copy( player.gate_vr_pstep_frame, player.vr_pstep );
       player.is_dead = 0;
       player.in_air = 1;
       m3x3_identity( player.vr );
@@ -1060,14 +1298,11 @@ static void player_update(void)
    }
    else
    {
-      if( player.on_board )
-      {
-         player_do_motion();
-         player_animate();
+      player_do_motion();
+      player_animate();
 
-         if( !freecam )
-            player_animate_camera();
-      }
+      if( !freecam )
+         player_animate_camera();
    }
 
    if( freecam )
index e1e43a5770c48b338f43f24881a954fe94037d03..652753c81d71a23335f7c13dd2d65381a169b26c 100644 (file)
@@ -1,4 +1,4 @@
-#ifndef CHARACTER_H
+#ifndef CHARACTER_H 
 #define CHARACTER_H
 
 #include "common.h"
@@ -31,7 +31,9 @@ struct character
                         *anim_slide,
                         *anim_air,
                         *anim_push, *anim_push_reverse,
-                        *anim_ollie;
+                        *anim_ollie, *anim_ollie_reverse,
+                        *anim_grabs, *anim_stop,
+                        *anim_walk, *anim_run, *anim_idle;
 
    u32 id_hip,
        id_ik_hand_l,
@@ -79,6 +81,11 @@ static int character_load( struct character *ch, const char *name )
    ch->anim_push  = skeleton_get_anim( &ch->sk, "push" );
    ch->anim_push_reverse = skeleton_get_anim( &ch->sk, "push_reverse" );
    ch->anim_ollie = skeleton_get_anim( &ch->sk, "ollie" );
+   ch->anim_ollie_reverse = skeleton_get_anim( &ch->sk, "ollie_reverse" );
+   ch->anim_grabs = skeleton_get_anim( &ch->sk, "grabs" );
+   ch->anim_walk  = skeleton_get_anim( &ch->sk, "walk" );
+   ch->anim_run   = skeleton_get_anim( &ch->sk, "run" );
+   ch->anim_idle  = skeleton_get_anim( &ch->sk, "idle_cycle" );
 
    ch->id_hip = skeleton_bone_id( &ch->sk, "hips" );
    ch->id_ik_hand_l = skeleton_bone_id( &ch->sk, "hand.IK.L" );
index 5d5ffdfa4290c10ba4b7f692ed5dec0801e717d3..05d2db1100fe78310d8a548691d99138c90a9d3a 100644 (file)
@@ -25,10 +25,11 @@ static const float
    k_friction         = 0.6f,
    k_damp_linear      = 0.05f,               /* scale velocity 1/(1+x) */
    k_damp_angular     = 0.1f,                /* scale angular  1/(1+x) */
-   k_limit_bias       = 0.04f,
+   k_limit_bias       = 0.02f,
    k_joint_bias       = 0.08f,               /* positional joints */
    k_joint_correction = 0.01f,
-   k_penetration_slop = 0.01f;
+   k_penetration_slop = 0.01f,
+   k_inertia_scale    = 4.0f;
 
 /* 
  * -----------------------------------------------------------------------------
@@ -382,7 +383,7 @@ static void rb_init( rigidbody *rb )
       v3_muls( extent, 0.5f, extent );
 
       /* local intertia tensor */
-      float scale = 4.0f;
+      float scale = k_inertia_scale;
       float ex2 = scale*extent[0]*extent[0],
             ey2 = scale*extent[1]*extent[1],
             ez2 = scale*extent[2]*extent[2];
index a96b999935e6e57085caacf480e50d886d8764db..99b702c088c0f418bcbac3a54ad68ad8e190a205 100644 (file)
@@ -31,7 +31,7 @@ static struct vg_shader _shader_scoretext = {
 "\n"
 "void main()\n"
 "{\n"
-"   float w = a_colour.g + fract(uInfo.z+0.5)-0.75;\n"
+"   float w = (a_colour.g * 8.0)-5.5 + fract(uInfo.z+0.5);\n"
 "   float c = -cos(w*0.2);\n"
 "   float s = -sin(w*0.2);\n"
 "   float r = 0.2;\n"
index bc7db92104b2582d4b3d1d0f04b0e77c272425ad..f8a940cc7386c96a23b9e74e262cd4eb131c07e5 100644 (file)
@@ -13,7 +13,7 @@ out vec3 aWorldCo;
 
 void main()
 {
-   float w = a_colour.g + fract(uInfo.z+0.5)-0.75;
+   float w = (a_colour.g * 8.0)-5.5 + fract(uInfo.z+0.5);
    float c = -cos(w*0.2);
    float s = -sin(w*0.2);
    float r = 0.2;
index 92e11bed3ae2cfa943a08118b1dab41fe2625b3b..fedd3e1172721a0976c524b4572861298e75a62b 100644 (file)
@@ -20,8 +20,10 @@ void main()
    float fdist = length( halfview );
    halfview /= fdist;
 
-   vfrag = do_light_diffuse( vfrag, aNorm );
-   vfrag = do_light_spec( vfrag, aNorm, halfview, 0.1 );
+   vec3 qnorm = normalize(floor(aNorm*2.0)*0.5) + vec3(0.001,0.0,0.0);
+
+   vfrag = do_light_diffuse( vfrag, qnorm );
+   vfrag = do_light_spec( vfrag, qnorm, halfview, 0.1 );
    vfrag = do_light_shadowing( vfrag );
    vfrag = apply_fog( vfrag, fdist );
 
index 551804a44be99347a4b4df781e7401088338f07a..00dc353ae372541bc8a63cbcf5629acc6e060258 100644 (file)
@@ -172,8 +172,10 @@ static struct vg_shader _shader_viewchar = {
 "   float fdist = length( halfview );\n"
 "   halfview /= fdist;\n"
 "\n"
-"   vfrag = do_light_diffuse( vfrag, aNorm );\n"
-"   vfrag = do_light_spec( vfrag, aNorm, halfview, 0.1 );\n"
+"   vec3 qnorm = normalize(floor(aNorm*2.0)*0.5) + vec3(0.001,0.0,0.0);\n"
+"\n"
+"   vfrag = do_light_diffuse( vfrag, qnorm );\n"
+"   vfrag = do_light_spec( vfrag, qnorm, halfview, 0.1 );\n"
 "   vfrag = do_light_shadowing( vfrag );\n"
 "   vfrag = apply_fog( vfrag, fdist );\n"
 "\n"
diff --git a/world.h b/world.h
index f970b0a3204f68152656d8fa366db6f9817aad44..3734dbf353963295c2b75eb8ec25aa4436509436 100644 (file)
--- a/world.h
+++ b/world.h
@@ -65,7 +65,7 @@ static struct gworld
    /* TODO Maybe make this less hardcoded */
    mdl_submesh sm_geo_std_oob, sm_geo_std, sm_geo_vb,
                sm_foliage_main, sm_foliage_alphatest,
-               sm_graffiti, sm_subworld;
+               sm_graffiti, sm_subworld, sm_terrain;
 
    glmesh skybox, skydome;
    mdl_submesh dome_upper, dome_lower;
@@ -115,9 +115,22 @@ static int ray_world( v3f pos, v3f dir, ray_hit *hit )
    return scene_raycast( &world.geo, pos, dir, hit );
 }
 
+static int ray_hit_is_terrain( ray_hit *hit )
+{
+   u32 valid_start = 0,
+       valid_end   = world.sm_terrain.vertex_count;
+
+   return (hit->tri[0] >= valid_start) &&
+          (hit->tri[0]  < valid_end);
+}
+
 static int ray_hit_is_ramp( ray_hit *hit )
 {
-   return hit->tri[0] > world.sm_geo_std_oob.vertex_count;
+   u32 valid_start = world.sm_geo_std.vertex_start,
+       valid_end   = world.sm_geo_vb.vertex_start;
+
+   return (hit->tri[0] >= valid_start) &&
+          (hit->tri[0]  < valid_end);
 }
 
 static void world_register(void)
@@ -205,8 +218,8 @@ static void world_apply_procedural_foliage(void)
 
       if( ray_world( pos, (v3f){0.0f,-1.0f,0.0f}, &hit ))
       {
-         if( hit.normal[1] > 0.8f && !ray_hit_is_ramp(&hit) &&
-             hit.pos[1] > water_height()+10.0f )
+         if( (hit.normal[1] > 0.8f) && ray_hit_is_terrain(&hit) &&
+             (hit.pos[1] > water_height()+10.0f) )
          {
             v4f qsurface, qrandom;
             v3f axis;
@@ -356,7 +369,8 @@ static void world_load(void)
        mat_vertex_blend = 0,
        mat_alphatest = 0,
        mat_graffiti = 0,
-       mat_subworld = 0;
+       mat_subworld = 0,
+       mat_terrain = 0;
 
    for( int i=1; i<mworld->material_count; i++ )
    {
@@ -373,13 +387,17 @@ static void world_load(void)
          mat_alphatest = i;
       else if( !strcmp( "graffitibox", mat_name ))
          mat_graffiti = i;
-      else if( !strcmp( "subworld", mat_name ))
-         mat_subworld = i;
+      else if( !strcmp( "terrain", mat_name ) )
+         mat_terrain = i;
    }
 
    m4x3f midentity;
    m4x3_identity( midentity );
 
+   if( mat_terrain )
+      add_all_if_material( midentity, &world.geo, mworld, mat_terrain );
+   scene_copy_slice( &world.geo, &world.sm_terrain );
+
    if( mat_surf_oob )
       add_all_if_material( midentity, &world.geo, mworld, mat_surf_oob );
    else
@@ -390,10 +408,6 @@ static void world_load(void)
       add_all_if_material( midentity, &world.geo, mworld, mat_surf );
    scene_copy_slice( &world.geo, &world.sm_geo_std );
 
-   if( mat_subworld )
-      add_all_if_material( midentity, &world.geo, mworld, mat_subworld );
-   scene_copy_slice( &world.geo, &world.sm_subworld );
-
    if( mat_vertex_blend )
       add_all_if_material( midentity, &world.geo, mworld, mat_vertex_blend );
    scene_copy_slice( &world.geo, &world.sm_geo_vb );
@@ -635,6 +649,7 @@ static void render_terrain( m4x4f projection, v3f camera )
    shader_terrain_uCamera( camera );
 
    scene_bind( &world.geo );
+   mdl_draw_submesh( &world.sm_terrain );
    mdl_draw_submesh( &world.sm_geo_std_oob );
    mdl_draw_submesh( &world.sm_geo_std );
    mdl_draw_submesh( &world.sm_subworld );
@@ -737,7 +752,7 @@ static void render_world( m4x4f projection, m4x3f camera )
    q_axis_angle( t, (v3f){0.0f,1.0f,0.0f}, 2.3f );
    q_m3x3( t, identity_matrix );
 
-   sfd_render( &world.sfd.tester, projection, camera[3], identity_matrix );
+   //sfd_render( &world.sfd.tester, projection, camera[3], identity_matrix );
 }
 
 static void render_world_depth( m4x4f projection, m4x3f camera )
index 3977e62e1edab68f934fad91587386b49d9fc738..71fee37a59acacd60417f7bd0e3bd52c321c9f00 100644 (file)
@@ -120,7 +120,6 @@ static void sfd_update( struct sfd_instance *display )
 static void sfd_render( struct sfd_instance *display, 
                         m4x4f projection, v3f camera, m4x3f transform )
 {
-   return;
    struct subworld_sfd *sfd = subworld_sfd();
    scene_bind( &sfd->mesh );
 
@@ -207,7 +206,7 @@ static void world_sfd_init(void)
          float const k_glyph_uvw = 1.0f/64.0f;
          vert->uv[0] -= k_glyph_uvw * (float)(i-4);
          vert->colour[0] = 0.0f;
-         vert->colour[1] = i-4;
+         vert->colour[1] = i*36;
       }
    }