diff --git a/src/collider.c b/src/collider.c index 44caab20..607c8d7e 100644 --- a/src/collider.c +++ b/src/collider.c @@ -384,6 +384,7 @@ struct collider_collision_points_result collider_collision_points(struct collide DBGSTEP; { const f32 wedge_epsilon = 0.001f; + //const f32 wedge_epsilon = 0.1f; /* shape0 a -> b winding = clockwise */ u32 id_a0; @@ -408,6 +409,7 @@ struct collider_collision_points_result collider_collision_points(struct collide struct v2 vap = v2_sub(p, a); struct v2 vpb = v2_sub(b, p); +#if 0 /* Swap a & b depending on winding order */ if (v2_wedge(vap, vpb) < 0) { u32 tmp_u32 = a_i; @@ -420,8 +422,11 @@ struct collider_collision_points_result collider_collision_points(struct collide vap = v2_neg(vpb); vpb = v2_neg(tmp_v2); } +#endif - if (v2_wedge(vap, normal) < (v2_wedge(vpb, normal) + wedge_epsilon)) { + f32 vap_wedge = v2_wedge(vap, normal); + f32 vpb_wedge = v2_wedge(vpb, normal); + if (vap_wedge < (vpb_wedge + wedge_epsilon)) { id_a0 = a_i; id_b0 = p_i; a0 = a; @@ -447,6 +452,7 @@ struct collider_collision_points_result collider_collision_points(struct collide struct v2 vap = v2_sub(p, a); struct v2 vpb = v2_sub(b, p); +#if 0 /* Swap a & b depending on winding order */ if (v2_wedge(vap, vpb) > 0) { u32 tmp_u32 = a_i; @@ -459,8 +465,11 @@ struct collider_collision_points_result collider_collision_points(struct collide vap = v2_neg(vpb); vpb = v2_neg(tmp_v2); } +#endif - if (v2_wedge(vap, normal) < (v2_wedge(vpb, normal) + wedge_epsilon)) { + f32 vap_wedge = v2_wedge(vap, normal); + f32 vpb_wedge = v2_wedge(vpb, normal); + if (vap_wedge < (vpb_wedge + wedge_epsilon)) { id_a1 = a_i; id_b1 = p_i; a1 = a; @@ -473,48 +482,6 @@ struct collider_collision_points_result collider_collision_points(struct collide } } -#if 1 - if (radius0 > 0.0) { - struct v2 scale = xform_get_scale(xf0); - struct v2 normal_radius = v2_mul_v2(v2_mul(normal, radius0), scale); - a0 = v2_add(a0, normal_radius); - b0 = v2_add(b0, normal_radius); - } - - if (radius1 > 0.0) { - struct v2 scale = xform_get_scale(xf1); - struct v2 normal_radius = v2_mul_v2(v2_mul(normal, radius1), scale); - a1 = v2_sub(a1, normal_radius); - b1 = v2_sub(b1, normal_radius); - } -#else - if (radius0 > 0.0) { - struct v2 scale = xform_get_scale(xf0); - struct v2 normal_radius = v2_mul_v2(v2_mul(normal, radius0), scale); - struct v2 perp_radius = v2_mul_v2(v2_with_len(v2_neg(v2_perp(v2_sub(b0, a0))), radius0), scale); - if (v2_dot(a0, normal) >= v2_dot(b0, normal)) { - a0 = v2_add(a0, normal_radius); - b0 = v2_add(b0, perp_radius); - } else { - a0 = v2_add(a0, perp_radius); - b0 = v2_add(b0, normal_radius); - } - } - - if (radius1 > 0.0) { - struct v2 scale = xform_get_scale(xf1); - struct v2 normal_radius = v2_mul_v2(v2_mul(normal, radius1), scale); - struct v2 perp_radius = v2_mul_v2(v2_with_len(v2_neg(v2_perp(v2_sub(b1, a1))), radius1), scale); - if (v2_dot(a1, normal) <= v2_dot(b1, normal)) { - a1 = v2_sub(a1, normal_radius); - b1 = v2_sub(b1, perp_radius); - } else { - a1 = v2_sub(a1, perp_radius); - b1 = v2_sub(b1, normal_radius); - } - } -#endif - f32 a0t = 0; f32 a1t = 0; f32 b0t = 0; @@ -559,16 +526,6 @@ struct collider_collision_points_result collider_collision_points(struct collide struct v2 contact_a = v2_add(a0_clipped, v2_mul(va0a1_clipped, 0.5f)); struct v2 contact_b = v2_add(b0_clipped, v2_mul(vb0b1_clipped, 0.5f)); - //b32 merge_contacts = v2_len_sq(v2_sub(contact_b, contact_a)) < (0.001f * 0.001f); - b32 merge_contacts = false; -#if 1 - if (math_fabs(v2_dot(vab0, normal)) > (0.01f) && - math_fabs(v2_dot(vab1, normal)) > (0.01f)) { - merge_contacts = true; - } -#endif - - if (a_sep < tolerance) { struct collider_collision_point *point = &points[num_points++]; point->id = id_a0 | (id_a1 << 4); @@ -576,26 +533,17 @@ struct collider_collision_points_result collider_collision_points(struct collide point->point = contact_a; } - if (b_sep < tolerance && !merge_contacts) { + if (b_sep < tolerance) { struct collider_collision_point *point = &points[num_points++]; point->id = id_b0 | (id_b1 << 4); point->separation = b_sep; point->point = contact_b; } - - -#if 0 res.a0 = a0_clipped; res.a1 = a1_clipped; res.b0 = b0_clipped; res.b1 = b1_clipped; -#else - res.a0 = a0; - res.a1 = a1; - res.b0 = b0; - res.b1 = b1; -#endif } } @@ -742,3 +690,555 @@ b32 collider_collision_boolean(struct collider_shape *shape0, struct collider_sh return false; } #endif + + + + + + + + +#if 0 +struct collider_collision_points_result collider_collision_points(struct collider_shape *shape0, struct collider_shape *shape1, struct xform xf0, struct xform xf1) +{ + struct temp_arena scratch = scratch_begin_no_conflict(); /* TODO: Only begin scratch for EPA */ + struct collider_collision_points_result res = ZI; + + struct v2 *points0 = shape0->points; + struct v2 *points1 = shape1->points; + u32 count0 = shape0->count; + u32 count1 = shape1->count; + f32 radius0 = shape0->radius; + f32 radius1 = shape1->radius; + (UNUSED)radius0; + (UNUSED)radius1; + + /* TODO: Parameterize */ + const f32 tolerance = 0.005f; /* How close can shapes be before collision is considered */ + const f32 min_unique_pt_dist_sq = 0.0001f * 0.0001f; + const u32 max_epa_iterations = 64; /* To prevent extremely large prototypes when origin is in exact center of rounded feature */ + + b32 colliding = false; + b32 simplex_is_closest_edge = false; + + struct collider_simplex s = ZI; + struct v2 *proto = NULL; + u32 proto_count = 0; + + struct v2 normal = ZI; + struct collider_collision_point points[2] = ZI; + u32 num_points = 0; + + struct v2 dir = ZI; + struct v2 m = ZI; + +#if COLLIDER_DEBUG + u32 dbg_step = 0; +#endif + + /* ========================== * + * GJK + * + * Determine encapsulating simplex if colliding, or closest edge / point to + * origin on simplex (for check if shape distances are within tolerance) + * ========================== */ + { + /* First point is support point in shape's general directions to eachother */ + dir = v2_sub(xf1.og, xf0.og); + if (v2_is_zero(dir)) dir = V2(1, 0); + s.a = menkowski_point(shape0, shape1, xf0, xf1, dir); + s.len = 1; + + struct v2 removed_a = ZI; + struct v2 removed_b = ZI; + u32 num_removed = 0; + while (true) { + if (s.len == 1) { + /* Second point is support point towards origin */ + dir = v2_neg(s.a); + + DBGSTEP; + m = menkowski_point(shape0, shape1, xf0, xf1, dir); + /* Check that new point is far enough away from existing point */ + if (v2_len_sq(v2_sub(m, s.a)) < min_unique_pt_dist_sq) { + simplex_is_closest_edge = true; + break; + } + s.b = s.a; + s.a = m; + s.len = 2; + + /* Third point is support point in direction of line normal towards origin */ + dir = v2_perp_towards_dir(v2_sub(s.b, s.a), v2_neg(s.a)); + } + + { + DBGSTEP; + m = menkowski_point(shape0, shape1, xf0, xf1, dir); + /* Check that new point is far enough away from existing points */ + if (v2_len_sq(v2_sub(m, s.a)) < min_unique_pt_dist_sq || + v2_len_sq(v2_sub(m, s.b)) < min_unique_pt_dist_sq || + ( + (num_removed >= 1) && ( + (v2_len_sq(v2_sub(m, removed_a)) < min_unique_pt_dist_sq) || + (num_removed >= 2 && v2_len_sq(v2_sub(m, removed_b)) < min_unique_pt_dist_sq)) + ) || + math_fabs(v2_wedge(v2_sub(s.b, s.a), v2_sub(m, s.a))) < min_unique_pt_dist_sq) { + simplex_is_closest_edge = true; + break; + } + s.c = s.b; + s.b = s.a; + s.a = m; + s.len = 3; + + if (math_fabs(v2_wedge(v2_sub(s.b, s.a), v2_neg(s.a))) <= min_unique_pt_dist_sq || + math_fabs(v2_wedge(v2_sub(s.c, s.a), v2_neg(s.a))) <= min_unique_pt_dist_sq || + math_fabs(v2_wedge(v2_sub(s.c, s.b), v2_neg(s.b))) <= min_unique_pt_dist_sq) { + /* Simplex lies on origin */ + colliding = true; + break; + } + } + + /* Determine region of the simplex in which the origin lies */ + DBGSTEP; + struct v2 vab = v2_sub(s.b, s.a); + struct v2 vac = v2_sub(s.c, s.a); + struct v2 vbc = v2_sub(s.c, s.b); + + struct v2 rab_dir = v2_perp_towards_dir(vab, v2_neg(vac)); + struct v2 rac_dir = v2_perp_towards_dir(vac, v2_neg(vab)); + struct v2 rbc_dir = v2_perp_towards_dir(vbc, vab); + + f32 rab_dot = v2_dot(rab_dir, v2_neg(s.a)); + f32 rac_dot = v2_dot(rac_dir, v2_neg(s.a)); + f32 rbc_dot = v2_dot(rbc_dir, v2_neg(s.b)); + + f32 vab_dot = v2_dot(vab, v2_neg(s.a)) / v2_len_sq(vab); + f32 vac_dot = v2_dot(vac, v2_neg(s.a)) / v2_len_sq(vac); + f32 vbc_dot = v2_dot(vbc, v2_neg(s.b)) / v2_len_sq(vbc); + + if (rab_dot >= 0 && vab_dot >= 0 && vab_dot <= 1) { + /* Region ab, remove c */ + num_removed = 1; + removed_a = s.c; + s.len = 2; + dir = rab_dir; /* Next third point is in direction of region ab */ + } else if (rac_dot >= 0 && vac_dot >= 0 && vac_dot <= 1) { + /* Region ac, remove b */ + num_removed = 1; + removed_a = s.b; + s.len = 2; + s.b = s.c; + dir = rac_dir; /* Next third point is in direction of region ac */ + } else if (rbc_dot >= 0 && vbc_dot >= 0 && vbc_dot <= 1) { + /* Region bc, remove a */ + num_removed = 1; + removed_a = s.a; + s.len = 2; + s.a = s.b; + s.b = s.c; + dir = rbc_dir; /* Next third point is in direction of region bc */ + } else if (vab_dot <= 0 && vac_dot <= 0) { + /* Region a, remove bc */ + num_removed = 2; + removed_a = s.b; + removed_b = s.c; + s.len = 1; + } else if (vab_dot >= 1 && vbc_dot <= 0) { + /* Region b, remove ac */ + num_removed = 2; + removed_a = s.a; + removed_b = s.c; + s.len = 1; + s.a = s.b; + } else if (vac_dot >= 1 && vbc_dot >= 1) { + /* Region c, remove ab */ + num_removed = 2; + removed_a = s.a; + removed_b = s.b; + s.len = 1; + s.a = s.c; + } else { + /* No region, must be in simplex */ + colliding = true; + break; + } + } + } + + if (colliding) { + /* ========================== * + * Epa (to find collision normal from inside shape) + * ========================== */ + + const f32 epa_epsilon_sq = 0.001f * 0.001f; + + proto = arena_dry_push(scratch.arena, struct v2); + proto_count = 0; + { + ASSERT(s.len == 3); + struct v2 *tmp = arena_push_array(scratch.arena, struct v2, 3); + tmp[0] = s.a; + tmp[1] = s.b; + tmp[2] = s.c; + proto_count = 3; + } + + u32 epa_iterations = 0; + while (colliding) { + ++epa_iterations; + f32 pen_len_sq = F32_INFINITY; + + /* Find dir from origin to closest edge */ + /* FIXME: Winding order of ps & pe index */ + u32 pen_ps_index = 0; + u32 pen_pe_index = 0; + struct v2 pen = ZI; + for (u32 i = 0; i < proto_count; ++i) { + u32 ps_index = i; + u32 pe_index = (i < proto_count - 1) ? (i + 1) : 0; + struct v2 ps = proto[ps_index]; + struct v2 pe = proto[pe_index]; + + struct v2 vse = v2_sub(pe, ps); + struct v2 vso = v2_neg(ps); + + struct v2 vsd = v2_mul(vse, (v2_dot(vso, vse) / v2_len_sq(vse))); + struct v2 pd = v2_add(ps, vsd); + + f32 pd_len_sq = v2_len_sq(pd); + if (pd_len_sq < pen_len_sq) { + pen_ps_index = ps_index; + pen_pe_index = pe_index; + pen_len_sq = pd_len_sq; + pen = pd; + } + } + + /* TODO: Remove this (debugging) */ + s.a = proto[pen_ps_index]; + s.b = proto[pen_pe_index]; + s.len = 2; + + /* Find new point in dir */ + DBGSTEP; + { + /* TODO: If winding order is guaranteed then this can become v2_perp_left/right? */ + struct v2 a = proto[pen_ps_index]; + struct v2 b = proto[pen_pe_index]; + struct v2 vab = v2_sub(b, a); + if (pen_len_sq < epa_epsilon_sq) { + /* Next point is in direction of line normal pointing outwards from simplex */ + struct v2 n = proto[(pen_pe_index < proto_count - 1) ? (pen_pe_index + 1) : 0]; /* Next point along prototype after edge */ + dir = v2_perp_towards_dir(vab, v2_sub(a, n)); + } else { + dir = v2_perp_towards_dir(vab, a); + } + + } + m = menkowski_point(shape0, shape1, xf0, xf1, dir); + + /* Check unique */ + /* TODO: Better */ + { + b32 unique = true; + for (u32 i = 0; i < proto_count; ++i) { + struct v2 edge_start = proto[i]; + struct v2 edge_end = i < proto_count - 1 ? proto[i + 1] : proto[0]; + struct v2 vsm = v2_sub(m, edge_start); + if (v2_len_sq(vsm) < min_unique_pt_dist_sq || + math_fabs(v2_wedge(v2_sub(edge_end, edge_start), vsm)) < min_unique_pt_dist_sq) { + unique = false; + break; + } + } + if (!unique || epa_iterations >= max_epa_iterations) { + res.path = 1; + if (pen_len_sq < epa_epsilon_sq) { + normal = v2_norm(dir); + } else { + normal = v2_norm(pen); + } + break; + } + } + + /* Insert point into prototype */ + /* FIXME: Preserve winding order */ + arena_push(scratch.arena, struct collider_menkowski_point); + ++proto_count; + for (u32 i = proto_count - 1; i > pen_pe_index; --i) { + u32 shift_from = (i > 0) ? i - 1 : proto_count - 1; + u32 shift_to = i; + proto[shift_to] = proto[shift_from]; + } + proto[pen_pe_index] = m; + } + } else if (simplex_is_closest_edge) { + if (s.len == 1) { + struct v2 p = v2_neg(s.a); + if (v2_len_sq(p) <= (tolerance * tolerance)) { + res.path = 2; + normal = v2_norm(dir); + colliding = true; + } + } else { + /* Shapes are not overlapping (origin is outside of simplex). Project + * origin to determine if distance is within tolerance. */ + ASSERT(s.len == 2); + struct v2 vab = v2_sub(s.b, s.a); + struct v2 vao = v2_neg(s.a); + f32 ratio = clamp_f32(v2_dot(vab, vao) / v2_dot(vab, vab), 0, 1); + struct v2 p = v2_add(s.a, v2_mul(vab, ratio)); + if (v2_len_sq(p) <= (tolerance * tolerance)) { + res.path = 2; + normal = v2_norm(dir); + colliding = true; + } + } + } + + if (colliding) { + /* ========================== * + * Clip to determine final points + * ========================== */ + + /* Max vertices must be < 16 to fit in 4 bit ids */ + CT_ASSERT(ARRAY_COUNT(shape0->points) <= 16); + + DBGSTEP; + { + //const f32 wedge_epsilon = 0.001f; + const f32 wedge_epsilon = 0.1f; + + /* shape0 a -> b winding = clockwise */ + u32 id_a0; + u32 id_b0; + struct v2 a0; + struct v2 b0; + + /* shape1 a -> b winding = counterclockwise */ + u32 id_a1; + u32 id_b1; + struct v2 a1; + struct v2 b1; + { + u32 p_i = collider_support_point_index(shape0, xf0, normal); + u32 a_i = (p_i > 0) ? (p_i - 1) : (count0 - 1); + u32 b_i = ((p_i + 1) < count0) ? (p_i + 1) : 0; + + struct v2 p = xform_mul_v2(xf0, points0[p_i]); + struct v2 a = xform_mul_v2(xf0, points0[a_i]); + struct v2 b = xform_mul_v2(xf0, points0[b_i]); + + struct v2 vap = v2_sub(p, a); + struct v2 vpb = v2_sub(b, p); + + /* Swap a & b depending on winding order */ + if (v2_wedge(vap, vpb) < 0) { + u32 tmp_u32 = a_i; + a_i = b_i; + b_i = tmp_u32; + struct v2 tmp_v2 = a; + a = b; + b = tmp_v2; + tmp_v2 = vap; + vap = v2_neg(vpb); + vpb = v2_neg(tmp_v2); + } + + f32 vap_wedge = v2_wedge(vap, normal); + f32 vpb_wedge = v2_wedge(vpb, normal); + if (vap_wedge < (vpb_wedge + wedge_epsilon)) { + id_a0 = a_i; + id_b0 = p_i; + a0 = a; + b0 = p; + } else { + id_a0 = p_i; + id_b0 = b_i; + a0 = p; + b0 = b; + } + } + { + struct v2 neg_normal = v2_neg(normal); + + u32 p_i = collider_support_point_index(shape1, xf1, neg_normal); + u32 a_i = ((p_i + 1) < count1) ? (p_i + 1) : 0; + u32 b_i = (p_i > 0) ? (p_i - 1) : (count1 - 1); + + struct v2 p = xform_mul_v2(xf1, points1[p_i]); + struct v2 a = xform_mul_v2(xf1, points1[a_i]); + struct v2 b = xform_mul_v2(xf1, points1[b_i]); + + struct v2 vap = v2_sub(p, a); + struct v2 vpb = v2_sub(b, p); + + /* Swap a & b depending on winding order */ + if (v2_wedge(vap, vpb) > 0) { + u32 tmp_u32 = a_i; + a_i = b_i; + b_i = tmp_u32; + struct v2 tmp_v2 = a; + a = b; + b = tmp_v2; + tmp_v2 = vap; + vap = v2_neg(vpb); + vpb = v2_neg(tmp_v2); + } + + f32 vap_wedge = v2_wedge(vap, normal); + f32 vpb_wedge = v2_wedge(vpb, normal); + if (vap_wedge < (vpb_wedge + wedge_epsilon)) { + id_a1 = a_i; + id_b1 = p_i; + a1 = a; + b1 = p; + } else { + id_a1 = p_i; + id_b1 = b_i; + a1 = p; + b1 = b; + } + } +#if 0 +#if 1 + if (radius0 > 0.0) { + struct v2 scale = xform_get_scale(xf0); + struct v2 normal_radius = v2_mul_v2(v2_mul(normal, radius0), scale); + a0 = v2_add(a0, normal_radius); + b0 = v2_add(b0, normal_radius); + } + + if (radius1 > 0.0) { + struct v2 scale = xform_get_scale(xf1); + struct v2 normal_radius = v2_mul_v2(v2_mul(normal, radius1), scale); + a1 = v2_sub(a1, normal_radius); + b1 = v2_sub(b1, normal_radius); + } +#else + if (radius0 > 0.0) { + struct v2 scale = xform_get_scale(xf0); + struct v2 perp_radius = v2_mul_v2(v2_with_len(v2_neg(v2_perp(v2_sub(b0, a0))), radius0), scale); + a0 = v2_add(a0, perp_radius); + b0 = v2_add(b0, perp_radius); + } + + if (radius1 > 0.0) { + struct v2 scale = xform_get_scale(xf1); + struct v2 perp_radius = v2_mul_v2(v2_with_len(v2_neg(v2_perp(v2_sub(b1, a1))), radius1), scale); + a1 = v2_sub(a1, perp_radius); + b1 = v2_sub(b1, perp_radius); + } +#endif +#endif + + f32 a0t = 0; + f32 a1t = 0; + f32 b0t = 0; + f32 b1t = 0; + + struct v2 vab0 = v2_sub(b0, a0); + struct v2 vab1 = v2_sub(b1, a1); + + { + struct v2 va0a1 = v2_sub(a1, a0); + struct v2 vb0b1 = v2_sub(b1, b0); + + f32 vab0_wedge_normal = v2_wedge(vab0, normal); + f32 vab1_wedge_normal = v2_wedge(vab1, normal); + f32 va0a1_wedge_normal = v2_wedge(va0a1, normal); + f32 vb0b1_wedge_normal = v2_wedge(vb0b1, normal); + + if (math_fabs(vab0_wedge_normal) > 0.01f) { + f32 w = 1 / vab0_wedge_normal; + a0t = clamp_f32(va0a1_wedge_normal * w, 0, 1); + b0t = clamp_f32(vb0b1_wedge_normal * -w, 0, 1); + } + + if (math_fabs(vab1_wedge_normal) > 0.01f) { + f32 w = 1 / vab1_wedge_normal; + a1t = clamp_f32(-va0a1_wedge_normal * w, 0, 1); + b1t = clamp_f32(-vb0b1_wedge_normal * -w, 0, 1); + } + } + + struct v2 a0_clipped = v2_add(a0, v2_mul(vab0, a0t)); + struct v2 a1_clipped = v2_add(a1, v2_mul(vab1, a1t)); + struct v2 b0_clipped = v2_add(b0, v2_mul(vab0, -b0t)); + struct v2 b1_clipped = v2_add(b1, v2_mul(vab1, -b1t)); + + struct v2 va0a1_clipped = v2_sub(a1_clipped, a0_clipped); + struct v2 vb0b1_clipped = v2_sub(b1_clipped, b0_clipped); + + f32 a_sep = v2_dot(va0a1_clipped, normal); + f32 b_sep = v2_dot(vb0b1_clipped, normal); + + struct v2 contact_a = v2_add(a0_clipped, v2_mul(va0a1_clipped, 0.5f)); + struct v2 contact_b = v2_add(b0_clipped, v2_mul(vb0b1_clipped, 0.5f)); + + //b32 merge_contacts = v2_len_sq(v2_sub(contact_b, contact_a)) < 0.01f; + b32 merge_contacts = false; + + b32 force = false; + +#if 0 + if (a_sep > tolerance && b_sep > tolerance) { + res.path = 999999999; + DEBUGBREAKABLE; + } +#endif + + if (force || a_sep < tolerance) { + struct collider_collision_point *point = &points[num_points++]; + point->id = id_a0 | (id_a1 << 4); + point->separation = a_sep; + point->point = contact_a; + } + + if (force || (b_sep < tolerance && !merge_contacts)) { + struct collider_collision_point *point = &points[num_points++]; + point->id = id_b0 | (id_b1 << 4); + point->separation = b_sep; + point->point = contact_b; + } + + res.a0 = a0_clipped; + res.a1 = a1_clipped; + res.b0 = b0_clipped; + res.b1 = b1_clipped; + } + } + + res.solved = true; +abort: + if (proto_count > 0) { + u32 len = min_u32(proto_count, ARRAY_COUNT(res.prototype.points)); + for (u32 i = 0; i < len; ++i) { + res.prototype.points[i] = proto[i]; + } + res.prototype.len = len; + } else { + if (s.len >= 1) { + res.prototype.points[0] = s.a; + if (s.len >= 2) { + res.prototype.points[1] = s.b; + if (s.len >= 3) { + res.prototype.points[2] = s.c; + } + } + } + res.prototype.len = s.len; + } + res.normal = normal; + res.points[0] = points[0]; + res.points[1] = points[1]; + res.num_points = num_points; + res.simplex = s; + scratch_end(scratch); + return res; +} +#endif diff --git a/src/game.c b/src/game.c index eadd5f92..62c33f65 100644 --- a/src/game.c +++ b/src/game.c @@ -183,6 +183,63 @@ INTERNAL void spawn_test_entities(f32 offset) player_ent = e; } +#if 0 + { + //struct v2 pos = V2(0.25, -10); + //struct v2 pos = V2(0.25, -7); + //struct v2 pos = V2(0.25, -5.27); + //struct v2 pos = V2(0.85, -2); + struct v2 pos = V2(0.25, -2); + //struct v2 pos = V2(1.1230469346046448864129274625156, -1); /* Touching right side of box */ + //struct v2 pos = V2(1.1230469346046448864129274625156 - 0.0001, -1); /* Touching right side of box */ + //struct v2 pos = V2(0.374142020941, -0.246118023992); /* Touching glitch spot */ + + pos = v2_add(pos, V2(0, offset)); + pos = v2_add(pos, V2(0, offset_all)); + + //struct v2 size = V2(1, 1); + struct v2 size = V2(0.5, 0.5); + //f32 r = PI; + //f32 r = PI / 4; + //f32 r = PI / 3; + //f32 r = 0.05; + //f32 r = PI / 2; + f32 r = 0; + //f32 skew = PI / 4; + f32 skew = 0; + + struct entity *e = entity_alloc(root); + + struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size); + xf = xform_skewed_to(xf, skew); + entity_set_xform(e, xf); + + //e->sprite = sprite_tag_from_path(STR("res/graphics/tim.ase")); + e->sprite = sprite_tag_from_path(STR("res/graphics/box.ase")); + //e->sprite_span_name = STR("idle.unarmed"); + //e->sprite_span_name = STR("idle.one_handed"); + e->sprite_span_name = STR("idle.two_handed"); + + //entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED); + //e->control_force = 4500; + //e->control_force = 1200; + e->control_force = 250; + e->control_torque = 10; + e->control.focus = V2(0, -1); + + entity_enable_prop(e, ENTITY_PROP_PHYSICAL); + e->mass_unscaled = 100; + //e->inertia_unscaled = F32_INFINITY; + e->inertia_unscaled = 25; + e->linear_ground_friction = 1000; + e->angular_ground_friction = 100; + + //entity_enable_prop(e, ENTITY_PROP_TEST); + + player_ent = e; + } +#endif + /* Weapon */ { #if 0 @@ -972,9 +1029,11 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) #elif 1 ent->local_collider.points[0] = V2(-0.5, 0.5); ent->local_collider.points[1] = V2(0.5, 0.5); + //ent->local_collider.points[1] = V2(0, 0.5); ent->local_collider.points[2] = V2(0, -0.5); ent->local_collider.count = 3; - ent->local_collider.radius = 0.25; + //ent->local_collider.radius = 0.25; + //ent->local_collider.radius = math_fabs(math_sin(G.tick.time) / 3); #else ent->local_collider.radius = 0.25; #endif diff --git a/src/user.c b/src/user.c index b297c899..2128c89d 100644 --- a/src/user.c +++ b/src/user.c @@ -1018,7 +1018,7 @@ INTERNAL void user_update(void) (UNUSED)e0_collider; (UNUSED)e1_collider; -#if 1 +#if 0 /* Draw menkowski */ { @@ -1048,18 +1048,16 @@ INTERNAL void user_update(void) } } - /* Draw pendir */ -#if 0 + /* Draw normal */ { - f32 thickness = 2; - u32 color = COLOR_YELLOW; - - struct v2 start = G.world_view.og; - struct v2 ray = xform_basis_mul_v2(G.world_view, ent->pendir); - - draw_solid_arrow_ray(G.viewport_canvas, start, ray, thickness, thickness * 4, color); + u32 color = COLOR_WHITE; + f32 len = 0.1f; + f32 arrow_thickness = 2; + f32 arrow_height = 5; + struct v2 start = xform_mul_v2(G.world_view, V2(0, 0)); + struct v2 end = xform_mul_v2(G.world_view, v2_mul(v2_norm(ent->manifold_normal), len)); + draw_solid_arrow_line(G.viewport_canvas, start, end, arrow_thickness, arrow_height, color); } -#endif /* Draw prototype */ { @@ -1172,17 +1170,22 @@ INTERNAL void user_update(void) #if 1 /* Draw clipping */ { - f32 thickness = 4; + f32 thickness = 2; + f32 radius = 4; u32 color = RGBA_32_F(1, 0, 1, 0.5); { struct v2 start = xform_mul_v2(G.world_view, ent->res.a0); struct v2 end = xform_mul_v2(G.world_view, ent->res.b0); draw_solid_line(G.viewport_canvas, start, end, thickness, color); + draw_solid_circle(G.viewport_canvas, start, radius, color, 10); + draw_solid_circle(G.viewport_canvas, end, radius, color, 10); } { struct v2 start = xform_mul_v2(G.world_view, ent->res.a1); struct v2 end = xform_mul_v2(G.world_view, ent->res.b1); draw_solid_line(G.viewport_canvas, start, end, thickness, color); + draw_solid_circle(G.viewport_canvas, start, radius, color, 10); + draw_solid_circle(G.viewport_canvas, end, radius, color, 10); } } #endif @@ -1206,7 +1209,6 @@ INTERNAL void user_update(void) u32 color = ent == active_camera ? RGBA_32_F(1, 1, 1, 0.5) : RGBA_32_F(0, 0.75, 0, 0.5); f32 thickness = 3; - struct xform quad_xf = xform_mul(xf, ent->camera_quad_xform); struct quad quad = xform_mul_quad(quad_xf, QUAD_UNIT_SQUARE_CENTERED); quad = xform_mul_quad(G.world_view, quad);