diff options
Diffstat (limited to 'servers')
-rw-r--r-- | servers/physics_2d/godot_space_2d.cpp | 14 | ||||
-rw-r--r-- | servers/physics_3d/godot_collision_solver_3d.cpp | 6 | ||||
-rw-r--r-- | servers/physics_3d/godot_collision_solver_3d_sat.cpp | 79 | ||||
-rw-r--r-- | servers/physics_3d/godot_shape_3d.cpp | 8 | ||||
-rw-r--r-- | servers/physics_3d/godot_shape_3d.h | 7 | ||||
-rw-r--r-- | servers/physics_3d/godot_soft_body_3d.cpp | 10 | ||||
-rw-r--r-- | servers/physics_3d/godot_soft_body_3d.h | 3 | ||||
-rw-r--r-- | servers/physics_3d/godot_space_3d.cpp | 8 |
8 files changed, 90 insertions, 45 deletions
diff --git a/servers/physics_2d/godot_space_2d.cpp b/servers/physics_2d/godot_space_2d.cpp index 6465a5542c..7a5eb26bb3 100644 --- a/servers/physics_2d/godot_space_2d.cpp +++ b/servers/physics_2d/godot_space_2d.cpp @@ -439,8 +439,6 @@ bool GodotPhysicsDirectSpaceState2D::rest_info(const ShapeParameters &p_paramete GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid); ERR_FAIL_COND_V(!shape, 0); - real_t min_contact_depth = p_parameters.margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR; - Rect2 aabb = p_parameters.transform.xform(shape->get_aabb()); aabb = aabb.merge(Rect2(aabb.position + p_parameters.motion, aabb.size)); //motion aabb = aabb.grow(p_parameters.margin); @@ -448,10 +446,11 @@ bool GodotPhysicsDirectSpaceState2D::rest_info(const ShapeParameters &p_paramete int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace2D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); _RestCallbackData2D rcd; - rcd.best_len = 0; - rcd.best_object = nullptr; - rcd.best_shape = 0; - rcd.min_allowed_depth = min_contact_depth; + + // Allowed depth can't be lower than motion length, in order to handle contacts at low speed. + real_t motion_length = p_parameters.motion.length(); + real_t min_contact_depth = p_parameters.margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR; + rcd.min_allowed_depth = MIN(motion_length, min_contact_depth); for (int i = 0; i < amount; i++) { if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { @@ -879,9 +878,6 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D:: ugt.elements[2] += p_parameters.motion * unsafe; _RestCallbackData2D rcd; - rcd.best_len = 0; - rcd.best_object = nullptr; - rcd.best_shape = 0; // Allowed depth can't be lower than motion length, in order to handle contacts at low speed. rcd.min_allowed_depth = MIN(motion_length, min_contact_depth); diff --git a/servers/physics_3d/godot_collision_solver_3d.cpp b/servers/physics_3d/godot_collision_solver_3d.cpp index 686f3e4d59..540b16c6e3 100644 --- a/servers/physics_3d/godot_collision_solver_3d.cpp +++ b/servers/physics_3d/godot_collision_solver_3d.cpp @@ -264,7 +264,7 @@ bool GodotCollisionSolver3D::solve_soft_body(const GodotShape3D *p_shape_A, cons local_aabb.size[i] = smax - smin; } - concave_shape_A->cull(local_aabb, soft_body_concave_callback, &query_cinfo); + concave_shape_A->cull(local_aabb, soft_body_concave_callback, &query_cinfo, true); } else { AABB shape_aabb = p_transform_A.xform(p_shape_A->get_aabb()); shape_aabb.grow_by(collision_margin); @@ -346,7 +346,7 @@ bool GodotCollisionSolver3D::solve_concave(const GodotShape3D *p_shape_A, const local_aabb.size[i] = smax - smin; } - concave_B->cull(local_aabb, concave_callback, &cinfo); + concave_B->cull(local_aabb, concave_callback, &cinfo, false); return cinfo.collided; } @@ -559,7 +559,7 @@ bool GodotCollisionSolver3D::solve_distance(const GodotShape3D *p_shape_A, const local_aabb.size[i] = smax - smin; } - concave_B->cull(local_aabb, concave_distance_callback, &cinfo); + concave_B->cull(local_aabb, concave_distance_callback, &cinfo, false); if (!cinfo.collided) { r_point_A = cinfo.close_A; r_point_B = cinfo.close_B; diff --git a/servers/physics_3d/godot_collision_solver_3d_sat.cpp b/servers/physics_3d/godot_collision_solver_3d_sat.cpp index 0790333f65..4faa07b6c9 100644 --- a/servers/physics_3d/godot_collision_solver_3d_sat.cpp +++ b/servers/physics_3d/godot_collision_solver_3d_sat.cpp @@ -36,6 +36,8 @@ #define fallback_collision_solver gjk_epa_calculate_penetration +#define _BACKFACE_NORMAL_THRESHOLD -0.0002 + // Cylinder SAT analytic methods and face-circle contact points for cylinder-trimesh and cylinder-box collision are based on ODE colliders. /* @@ -612,13 +614,14 @@ class SeparatorAxisTest { const Transform3D *transform_A = nullptr; const Transform3D *transform_B = nullptr; real_t best_depth = 1e15; - Vector3 best_axis; _CollectorCallback *callback = nullptr; real_t margin_A = 0.0; real_t margin_B = 0.0; Vector3 separator_axis; public: + Vector3 best_axis; + _FORCE_INLINE_ bool test_previous_axis() { if (callback && callback->prev_axis && *callback->prev_axis != Vector3()) { return test_axis(*callback->prev_axis); @@ -627,7 +630,7 @@ public: } } - _FORCE_INLINE_ bool test_axis(const Vector3 &p_axis, bool p_directional = false) { + _FORCE_INLINE_ bool test_axis(const Vector3 &p_axis) { Vector3 axis = p_axis; if (axis.is_equal_approx(Vector3())) { @@ -661,12 +664,7 @@ public: //use the smallest depth if (min_B < 0.0) { // could be +0.0, we don't want it to become -0.0 - if (p_directional) { - min_B = max_B; - axis = -axis; - } else { - min_B = -min_B; - } + min_B = -min_B; } if (max_B < min_B) { @@ -1014,7 +1012,7 @@ static void _collision_sphere_face(const GodotShape3D *p_a, const Transform3D &p Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized(); - if (!separator.test_axis(normal, !face_B->backface_collision)) { + if (!separator.test_axis(normal)) { return; } @@ -1041,6 +1039,17 @@ static void _collision_sphere_face(const GodotShape3D *p_a, const Transform3D &p } } + if (!face_B->backface_collision) { + if (separator.best_axis.dot(normal) < _BACKFACE_NORMAL_THRESHOLD) { + if (face_B->invert_backface_collision) { + separator.best_axis = separator.best_axis.bounce(normal); + } else { + // Just ignore backface collision. + return; + } + } + } + separator.generate_contacts(); } @@ -1486,7 +1495,7 @@ static void _collision_box_face(const GodotShape3D *p_a, const Transform3D &p_tr Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized(); - if (!separator.test_axis(normal, !face_B->backface_collision)) { + if (!separator.test_axis(normal)) { return; } @@ -1591,6 +1600,17 @@ static void _collision_box_face(const GodotShape3D *p_a, const Transform3D &p_tr } } + if (!face_B->backface_collision) { + if (separator.best_axis.dot(normal) < _BACKFACE_NORMAL_THRESHOLD) { + if (face_B->invert_backface_collision) { + separator.best_axis = separator.best_axis.bounce(normal); + } else { + // Just ignore backface collision. + return; + } + } + } + separator.generate_contacts(); } @@ -1802,7 +1822,7 @@ static void _collision_capsule_face(const GodotShape3D *p_a, const Transform3D & Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized(); - if (!separator.test_axis(normal, !face_B->backface_collision)) { + if (!separator.test_axis(normal)) { return; } @@ -1858,6 +1878,17 @@ static void _collision_capsule_face(const GodotShape3D *p_a, const Transform3D & } } + if (!face_B->backface_collision) { + if (separator.best_axis.dot(normal) < _BACKFACE_NORMAL_THRESHOLD) { + if (face_B->invert_backface_collision) { + separator.best_axis = separator.best_axis.bounce(normal); + } else { + // Just ignore backface collision. + return; + } + } + } + separator.generate_contacts(); } @@ -1952,7 +1983,7 @@ static void _collision_cylinder_face(const GodotShape3D *p_a, const Transform3D Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized(); // Face B normal. - if (!separator.test_axis(normal, !face_B->backface_collision)) { + if (!separator.test_axis(normal)) { return; } @@ -2034,6 +2065,17 @@ static void _collision_cylinder_face(const GodotShape3D *p_a, const Transform3D } } + if (!face_B->backface_collision) { + if (separator.best_axis.dot(normal) < _BACKFACE_NORMAL_THRESHOLD) { + if (face_B->invert_backface_collision) { + separator.best_axis = separator.best_axis.bounce(normal); + } else { + // Just ignore backface collision. + return; + } + } + } + separator.generate_contacts(); } @@ -2174,7 +2216,7 @@ static void _collision_convex_polygon_face(const GodotShape3D *p_a, const Transf Vector3 normal = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized(); - if (!separator.test_axis(normal, !face_B->backface_collision)) { + if (!separator.test_axis(normal)) { return; } @@ -2266,6 +2308,17 @@ static void _collision_convex_polygon_face(const GodotShape3D *p_a, const Transf } } + if (!face_B->backface_collision) { + if (separator.best_axis.dot(normal) < _BACKFACE_NORMAL_THRESHOLD) { + if (face_B->invert_backface_collision) { + separator.best_axis = separator.best_axis.bounce(normal); + } else { + // Just ignore backface collision. + return; + } + } + } + separator.generate_contacts(); } diff --git a/servers/physics_3d/godot_shape_3d.cpp b/servers/physics_3d/godot_shape_3d.cpp index d1e919ab6a..5364a9833d 100644 --- a/servers/physics_3d/godot_shape_3d.cpp +++ b/servers/physics_3d/godot_shape_3d.cpp @@ -1401,7 +1401,7 @@ bool GodotConcavePolygonShape3D::_cull(int p_idx, _CullParams *p_params) const { return false; } -void GodotConcavePolygonShape3D::cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata) const { +void GodotConcavePolygonShape3D::cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata, bool p_invert_backface_collision) const { // make matrix local to concave if (faces.size() == 0) { return; @@ -1416,6 +1416,7 @@ void GodotConcavePolygonShape3D::cull(const AABB &p_local_aabb, QueryCallback p_ GodotFaceShape3D face; // use this to send in the callback face.backface_collision = backface_collision; + face.invert_backface_collision = p_invert_backface_collision; _CullParams params; params.aabb = local_aabb; @@ -1961,7 +1962,7 @@ void GodotHeightMapShape3D::_get_cell(const Vector3 &p_point, int &r_x, int &r_y r_z = (clamped_point.z < 0.0) ? (clamped_point.z - 0.5) : (clamped_point.z + 0.5); } -void GodotHeightMapShape3D::cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata) const { +void GodotHeightMapShape3D::cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata, bool p_invert_backface_collision) const { if (heights.is_empty()) { return; } @@ -1988,7 +1989,8 @@ void GodotHeightMapShape3D::cull(const AABB &p_local_aabb, QueryCallback p_callb int end_z = MIN(depth - 1, aabb_max[2]); GodotFaceShape3D face; - face.backface_collision = true; + face.backface_collision = !p_invert_backface_collision; + face.invert_backface_collision = p_invert_backface_collision; for (int z = start_z; z < end_z; z++) { for (int x = start_x; x < end_x; x++) { diff --git a/servers/physics_3d/godot_shape_3d.h b/servers/physics_3d/godot_shape_3d.h index 7a32b69166..43319510d4 100644 --- a/servers/physics_3d/godot_shape_3d.h +++ b/servers/physics_3d/godot_shape_3d.h @@ -107,7 +107,7 @@ public: // Returns true to stop the query. typedef bool (*QueryCallback)(void *p_userdata, GodotShape3D *p_convex); - virtual void cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata) const = 0; + virtual void cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata, bool p_invert_backface_collision) const = 0; GodotConcaveShape3D() {} }; @@ -370,7 +370,7 @@ public: virtual bool intersect_point(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; - virtual void cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata) const override; + virtual void cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata, bool p_invert_backface_collision) const override; virtual Vector3 get_moment_of_inertia(real_t p_mass) const override; @@ -433,7 +433,7 @@ public: virtual bool intersect_point(const Vector3 &p_point) const override; virtual Vector3 get_closest_point_to(const Vector3 &p_point) const override; - virtual void cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata) const override; + virtual void cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata, bool p_invert_backface_collision) const override; virtual Vector3 get_moment_of_inertia(real_t p_mass) const override; @@ -448,6 +448,7 @@ struct GodotFaceShape3D : public GodotShape3D { Vector3 normal; //cache Vector3 vertex[3]; bool backface_collision = false; + bool invert_backface_collision = false; virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_CONCAVE_POLYGON; } diff --git a/servers/physics_3d/godot_soft_body_3d.cpp b/servers/physics_3d/godot_soft_body_3d.cpp index b8e9ab4fb9..231b8686f5 100644 --- a/servers/physics_3d/godot_soft_body_3d.cpp +++ b/servers/physics_3d/godot_soft_body_3d.cpp @@ -964,12 +964,6 @@ void GodotSoftBody3D::apply_forces(const LocalVector<GodotArea3D *> &p_wind_area } } -void GodotSoftBody3D::_compute_area_gravity(const GodotArea3D *p_area) { - Vector3 area_gravity; - p_area->compute_gravity(get_transform().get_origin(), area_gravity); - gravity += area_gravity; -} - Vector3 GodotSoftBody3D::_compute_area_windforce(const GodotArea3D *p_area, const Face *p_face) { real_t wfm = p_area->get_wind_force_magnitude(); real_t waf = p_area->get_wind_attenuation_factor(); @@ -987,12 +981,12 @@ void GodotSoftBody3D::predict_motion(real_t p_delta) { ERR_FAIL_COND(!get_space()); - int ac = areas.size(); - bool gravity_done = false; + Vector3 gravity; LocalVector<GodotArea3D *> wind_areas; + int ac = areas.size(); if (ac) { areas.sort(); const AreaCMP *aa = &areas[0]; diff --git a/servers/physics_3d/godot_soft_body_3d.h b/servers/physics_3d/godot_soft_body_3d.h index c03951959f..5198186b5d 100644 --- a/servers/physics_3d/godot_soft_body_3d.h +++ b/servers/physics_3d/godot_soft_body_3d.h @@ -101,8 +101,6 @@ class GodotSoftBody3D : public GodotCollisionObject3D { real_t drag_coefficient = 0.0; // [0,1] LocalVector<int> pinned_vertices; - Vector3 gravity; - SelfList<GodotSoftBody3D> active_list; Set<GodotConstraint3D *> constraints; @@ -113,7 +111,6 @@ class GodotSoftBody3D : public GodotCollisionObject3D { uint64_t island_step = 0; - _FORCE_INLINE_ void _compute_area_gravity(const GodotArea3D *p_area); _FORCE_INLINE_ Vector3 _compute_area_windforce(const GodotArea3D *p_area, const Face *p_face); public: diff --git a/servers/physics_3d/godot_space_3d.cpp b/servers/physics_3d/godot_space_3d.cpp index e2f90b90ad..f503273c88 100644 --- a/servers/physics_3d/godot_space_3d.cpp +++ b/servers/physics_3d/godot_space_3d.cpp @@ -507,15 +507,17 @@ bool GodotPhysicsDirectSpaceState3D::rest_info(const ShapeParameters &p_paramete GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_parameters.shape_rid); ERR_FAIL_COND_V(!shape, 0); - real_t min_contact_depth = p_parameters.margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR; - AABB aabb = p_parameters.transform.xform(shape->get_aabb()); aabb = aabb.grow(p_parameters.margin); int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); _RestCallbackData rcd; - rcd.min_allowed_depth = min_contact_depth; + + // Allowed depth can't be lower than motion length, in order to handle contacts at low speed. + real_t motion_length = p_parameters.motion.length(); + real_t min_contact_depth = p_parameters.margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR; + rcd.min_allowed_depth = MIN(motion_length, min_contact_depth); for (int i = 0; i < amount; i++) { if (!_can_collide_with(space->intersection_query_results[i], p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas)) { |