+ for( int i=4; i<PART_COUNT; i++ )
+ {
+#if 0
+ if( i == k_chpart_head || i == k_chpart_neck )
+ continue;
+#endif
+
+ shader_character_uMdl( ch->matrices[i] );
+ mdl_draw_submesh( &ch->parts[i] );
+ }
+
+ for( int i=0; i<2; i++ )
+ {
+ if( ch->shoes[i] )
+ {
+ shader_character_uMdl( ch->matrices[i] );
+ mdl_draw_submesh( &ch->parts[i] );
+ }
+ else
+ {
+ shader_character_uMdl( ch->matrices[i+2] );
+ mdl_draw_submesh( &ch->parts[i] );
+ shader_character_uMdl( ch->matrices[i] );
+ mdl_draw_submesh( &ch->parts[i+2] );
+ }
+ }
+}
+
+/*
+ * Ragdoll Stuff
+ */
+
+static void character_rd_box( struct character *ch, enum character_part id,
+ v3f dims )
+{
+ v3_muls( dims, -0.5f, ch->ragdoll[id].bbx[0] );
+ v3_muls( dims, 0.5f, ch->ragdoll[id].bbx[1] );
+}
+
+struct rd_joint
+{
+ enum character_part ia, ib;
+ v3f lca, lcb;
+
+ struct rd_joint_axis
+ {
+ v3f va, vb;
+ float spring, ang;
+ }
+ min, maj;
+};
+
+static const float k_human_major = 0.5f,
+ k_human_minor = 0.5f,
+ k_human_major_max = 0.4f,
+ k_human_minor_max = 0.1f;
+
+#define HUMAN_VERTICAL_DEFAULT \
+.min = { \
+ .va = {1.0f,0.0f,0.0f}, .vb = {1.0f,0.0f,0.0f}, \
+ .spring = k_human_minor, .ang = k_human_minor_max \
+}, \
+.maj = { \
+ .va = {0.0f,1.0f,0.0f}, .vb = {0.0f,1.0f,0.0f}, \
+ .spring = k_human_major, .ang = k_human_major_max \
+}
+
+#define HUMAN_ARM_LEFT \
+.min = { \
+ .va = {1.0f,0.0f,0.0f}, .vb = {1.0f,0.0f,0.0f}, \
+ .spring = k_human_minor, .ang = k_human_minor_max \
+}, \
+.maj = { \
+ .va = {0.0f,0.0f,1.0f}, .vb = {0.0f,0.0f,1.0f}, \
+ .spring = k_human_major, .ang = k_human_major_max \
+}
+
+#define HUMAN_ARM_RIGHT \
+.min = { \
+ .va = {1.0f,0.0f,0.0f}, .vb = {1.0f,0.0f,0.0f}, \
+ .spring = k_human_minor, .ang = k_human_minor_max \
+}, \
+.maj = { \
+ .va = {0.0f,0.0f,-1.0f}, .vb = {0.0f,0.0f,-1.0f}, \
+ .spring = k_human_major, .ang = k_human_major_max \
+}
+
+static struct rd_joint rd_joints[] =
+{
+ { .ia = k_chpart_leg_l1, .ib = k_chpart_foot_l, HUMAN_VERTICAL_DEFAULT },
+ { .ia = k_chpart_leg_r1, .ib = k_chpart_foot_r, HUMAN_VERTICAL_DEFAULT },
+
+ { .ia = k_chpart_body0, .ib = k_chpart_body1, HUMAN_VERTICAL_DEFAULT },
+ { .ia = k_chpart_body1, .ib = k_chpart_neck, HUMAN_VERTICAL_DEFAULT },
+ { .ia = k_chpart_neck, .ib = k_chpart_head, HUMAN_VERTICAL_DEFAULT },
+ { .ia = k_chpart_body0, .ib = k_chpart_leg_l0, HUMAN_VERTICAL_DEFAULT },
+ { .ia = k_chpart_leg_l0, .ib = k_chpart_leg_l1, HUMAN_VERTICAL_DEFAULT },
+ { .ia = k_chpart_body0, .ib = k_chpart_leg_r0, HUMAN_VERTICAL_DEFAULT },
+ { .ia = k_chpart_leg_r0, .ib = k_chpart_leg_r1, HUMAN_VERTICAL_DEFAULT },
+
+ { .ia = k_chpart_body1, .ib = k_chpart_arm_l0, HUMAN_ARM_LEFT },
+ { .ia = k_chpart_arm_l0, .ib = k_chpart_arm_l1, HUMAN_ARM_LEFT },
+ { .ia = k_chpart_arm_l1, .ib = k_chpart_hand_l, HUMAN_ARM_LEFT },
+
+ { .ia = k_chpart_body1, .ib = k_chpart_arm_r0, HUMAN_ARM_RIGHT },
+ { .ia = k_chpart_arm_r0, .ib = k_chpart_arm_r1, HUMAN_ARM_RIGHT },
+ { .ia = k_chpart_arm_r1, .ib = k_chpart_hand_r, HUMAN_ARM_RIGHT }
+};
+
+/* Ragdoll should be in rest pose when calling this function */
+static void character_init_ragdoll_joints( struct character *ch )
+{
+ for( int i=0; i<vg_list_size(rd_joints); i++ )
+ {
+ struct rd_joint *joint = &rd_joints[i];
+
+ float *hinge = ch->origins[joint->ib];
+ v3_sub( hinge, ch->ragdoll[joint->ia].co, joint->lca );
+ v3_sub( hinge, ch->ragdoll[joint->ib].co, joint->lcb );
+ }
+
+ for( int i=0; i<PART_COUNT; i++ )
+ {
+ float *pivot = ch->origins[i];
+ v3_sub( ch->ragdoll[i].co, pivot, ch->ragdoll[i].delta );
+ }
+}
+
+static void character_init_ragdoll( struct character *ch )
+{
+ v3f *offs = ch->offsets;
+ rigidbody *rbs = ch->ragdoll;
+
+ /* CHest */
+ float chest_width = fabsf(offs[k_chpart_arm_r0][2])*2.0f,
+ chest_depth = chest_width * 0.571f,
+ chest_height = offs[k_chpart_neck][1];
+ v3f chest_dims = { chest_depth, chest_height, chest_width };
+ character_rd_box( ch, k_chpart_body1, chest_dims );
+
+ v3_copy( ch->origins[k_chpart_body1], rbs[k_chpart_body1].co );
+ rbs[k_chpart_body1].co[1] += chest_height*0.5f;
+
+ /* Torso */
+ v3f torso_dims = { chest_depth,
+ offs[k_chpart_body1][1]-offs[k_chpart_leg_l0][1],
+ chest_width*0.85f };
+ v3_copy( ch->origins[k_chpart_body0], rbs[k_chpart_body0].co );
+ character_rd_box( ch, k_chpart_body0, torso_dims );
+
+ /* Neck */
+ v3f neck_dims = { chest_depth*0.5f,
+ offs[k_chpart_head][1],
+ chest_depth*0.5f };
+ v3_copy( ch->origins[k_chpart_neck], rbs[k_chpart_neck].co );
+ rbs[k_chpart_neck].co[1] += neck_dims[1]*0.5f;
+ character_rd_box( ch, k_chpart_neck, neck_dims );
+
+ /* Head */
+ v3f head_dims = { chest_width*0.5f, chest_width*0.5f, chest_width*0.5f };
+ v3_copy( ch->origins[k_chpart_head], rbs[k_chpart_head].co );
+ rbs[k_chpart_head].co[1] += head_dims[1]*0.5f;
+ character_rd_box( ch, k_chpart_head, head_dims );
+
+ /* ARms */
+ v3f ua_dims = { 0.0f, 0.0f, fabsf(offs[k_chpart_arm_l1][2]) };
+ ua_dims[1] = 0.38f*ua_dims[2];
+ ua_dims[0] = 0.38f*ua_dims[2];
+ v3f la_dims = { ua_dims[0], ua_dims[1], fabsf(offs[k_chpart_hand_l][2]) };
+ v3f hand_dims = { ua_dims[1], ua_dims[1]*0.5f, ua_dims[1] };
+
+ character_rd_box( ch, k_chpart_arm_l0, ua_dims );
+ character_rd_box( ch, k_chpart_arm_r0, ua_dims );
+ character_rd_box( ch, k_chpart_arm_l1, la_dims );
+ character_rd_box( ch, k_chpart_arm_r1, la_dims );
+ character_rd_box( ch, k_chpart_hand_l, hand_dims );
+ character_rd_box( ch, k_chpart_hand_r, hand_dims );
+
+ v3_copy( ch->origins[k_chpart_arm_l0], rbs[k_chpart_arm_l0].co );
+ rbs[k_chpart_arm_l0].co[2] += ua_dims[2] * 0.5f;
+ v3_copy( ch->origins[k_chpart_arm_l1], rbs[k_chpart_arm_l1].co );
+ rbs[k_chpart_arm_l1].co[2] += la_dims[2] * 0.5f;
+ v3_copy( ch->origins[k_chpart_hand_l], rbs[k_chpart_hand_l].co );
+ rbs[k_chpart_hand_l].co[2] += hand_dims[2] * 0.5f;
+
+ v3_copy( ch->origins[k_chpart_arm_r0], rbs[k_chpart_arm_r0].co );
+ rbs[k_chpart_arm_r0].co[2] -= ua_dims[2] * 0.5f;
+ v3_copy( ch->origins[k_chpart_arm_r1], rbs[k_chpart_arm_r1].co );
+ rbs[k_chpart_arm_r1].co[2] -= la_dims[2] * 0.5f;
+ v3_copy( ch->origins[k_chpart_hand_r], rbs[k_chpart_hand_r].co );
+ rbs[k_chpart_hand_r].co[2] -= hand_dims[2] * 0.5f;
+
+ /* LEgs */
+ v3f ul_dims = { 0.0f, fabsf(offs[k_chpart_leg_l1][1]), 0.0f };
+ ul_dims[0] = 0.38f*ul_dims[1];
+ ul_dims[2] = 0.38f*ul_dims[1];
+ v3f ll_dims = { ul_dims[0], fabsf(offs[k_chpart_foot_l][1]), ul_dims[2] };
+ v3f foot_dims = { 2.0f*ul_dims[0], ul_dims[0], ul_dims[0] };
+
+ character_rd_box( ch, k_chpart_leg_l0, ul_dims );
+ character_rd_box( ch, k_chpart_leg_r0, ul_dims );
+ character_rd_box( ch, k_chpart_leg_l1, ll_dims );
+ character_rd_box( ch, k_chpart_leg_r1, ll_dims );
+ character_rd_box( ch, k_chpart_foot_l, foot_dims );
+ character_rd_box( ch, k_chpart_foot_r, foot_dims );
+
+ v3_copy( ch->origins[k_chpart_leg_l0], rbs[k_chpart_leg_l0].co );
+ rbs[k_chpart_leg_l0].co[1] -= ul_dims[1] * 0.5f;
+ v3_copy( ch->origins[k_chpart_leg_l1], rbs[k_chpart_leg_l1].co );
+ rbs[k_chpart_leg_l1].co[1] -= ll_dims[1] * 0.5f;
+ v3_copy( ch->origins[k_chpart_foot_l], rbs[k_chpart_foot_l].co );
+ rbs[k_chpart_foot_l].co[1] -= foot_dims[1] * 0.5f;
+ rbs[k_chpart_foot_l].co[0] -= foot_dims[0] * 0.5f;
+
+ v3_copy( ch->origins[k_chpart_leg_r0], rbs[k_chpart_leg_r0].co );
+ rbs[k_chpart_leg_r0].co[1] -= ul_dims[1] * 0.5f;
+ v3_copy( ch->origins[k_chpart_leg_r1], rbs[k_chpart_leg_r1].co );
+ rbs[k_chpart_leg_r1].co[1] -= ll_dims[1] * 0.5f;
+ v3_copy( ch->origins[k_chpart_foot_r], rbs[k_chpart_foot_r].co );
+ rbs[k_chpart_foot_r].co[1] -= foot_dims[1] * 0.5f;
+ rbs[k_chpart_foot_r].co[0] -= foot_dims[0] * 0.5f;
+
+ character_rd_box( ch, k_chpart_sock_l, foot_dims );
+ character_rd_box( ch, k_chpart_sock_r, foot_dims );
+ v3_copy( rbs[k_chpart_foot_l].co, rbs[k_chpart_sock_l].co );
+ v3_copy( rbs[k_chpart_foot_r].co, rbs[k_chpart_sock_r].co );
+
+ box_copy( (boxf){{-0.2f,-0.2f,-0.7f},{0.2f,0.2f,0.7f}},
+ rbs[k_chpart_board].bbx );
+
+ for( int i=0; i<PART_COUNT; i++ )
+ rb_init( &ch->ragdoll[i] );
+
+ character_init_ragdoll_joints( ch );
+}
+
+static void character_ragdoll_go( struct character *ch, v3f pos )
+{
+ character_init_ragdoll( ch );
+ for( int i=0; i<PART_COUNT; i++ )
+ v3_add( pos, ch->ragdoll[i].co, ch->ragdoll[i].co );
+}
+
+static void character_ragdoll_copypose( struct character *ch, v3f v )
+{
+ for( int i=0; i<PART_COUNT; i++ )
+ {
+ rigidbody *rb = &ch->ragdoll[i];
+
+ m4x3_mulv( ch->matrices[i], rb->delta, rb->co );
+ m3x3_q( ch->matrices[i], rb->q );
+ v3_copy( v, rb->v );
+ v3_zero( rb->I );
+ rb->manifold_count = 0; /* ? */
+
+ rb_update_transform( rb );
+ }
+
+ float vel = v3_length(v);
+
+ ch->shoes[0] = 1;
+ ch->shoes[1] = 1;
+}
+
+static void character_mimic_ragdoll( struct character *ch )
+{