diff options
Diffstat (limited to 'servers')
-rw-r--r-- | servers/physics_2d/physics_server_2d_sw.cpp | 4 | ||||
-rw-r--r-- | servers/physics_2d/physics_server_2d_sw.h | 2 | ||||
-rw-r--r-- | servers/physics_2d/physics_server_2d_wrap_mt.h | 4 | ||||
-rw-r--r-- | servers/physics_2d/space_2d_sw.cpp | 55 | ||||
-rw-r--r-- | servers/physics_2d/space_2d_sw.h | 2 | ||||
-rw-r--r-- | servers/physics_3d/physics_server_3d_sw.cpp | 4 | ||||
-rw-r--r-- | servers/physics_3d/physics_server_3d_sw.h | 2 | ||||
-rw-r--r-- | servers/physics_3d/physics_server_3d_wrap_mt.h | 4 | ||||
-rw-r--r-- | servers/physics_3d/space_3d_sw.cpp | 62 | ||||
-rw-r--r-- | servers/physics_3d/space_3d_sw.h | 2 | ||||
-rw-r--r-- | servers/physics_server_2d.cpp | 78 | ||||
-rw-r--r-- | servers/physics_server_2d.h | 60 | ||||
-rw-r--r-- | servers/physics_server_3d.cpp | 137 | ||||
-rw-r--r-- | servers/physics_server_3d.h | 70 | ||||
-rw-r--r-- | servers/register_server_types.cpp | 2 |
15 files changed, 296 insertions, 192 deletions
diff --git a/servers/physics_2d/physics_server_2d_sw.cpp b/servers/physics_2d/physics_server_2d_sw.cpp index 4315b55df4..c2205e33b0 100644 --- a/servers/physics_2d/physics_server_2d_sw.cpp +++ b/servers/physics_2d/physics_server_2d_sw.cpp @@ -948,7 +948,7 @@ void PhysicsServer2DSW::body_set_pickable(RID p_body, bool p_pickable) { body->set_pickable(p_pickable); } -bool PhysicsServer2DSW::body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, MotionResult *r_result, bool p_collide_separation_ray, const Set<RID> &p_exclude) { +bool PhysicsServer2DSW::body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result) { Body2DSW *body = body_owner.get_or_null(p_body); ERR_FAIL_COND_V(!body, false); ERR_FAIL_COND_V(!body->get_space(), false); @@ -956,7 +956,7 @@ bool PhysicsServer2DSW::body_test_motion(RID p_body, const Transform2D &p_from, _update_shapes(); - return body->get_space()->test_body_motion(body, p_from, p_motion, p_margin, r_result, p_collide_separation_ray, p_exclude); + return body->get_space()->test_body_motion(body, p_parameters, r_result); } PhysicsDirectBodyState2D *PhysicsServer2DSW::body_get_direct_state(RID p_body) { diff --git a/servers/physics_2d/physics_server_2d_sw.h b/servers/physics_2d/physics_server_2d_sw.h index 1f35e83995..b8e375a087 100644 --- a/servers/physics_2d/physics_server_2d_sw.h +++ b/servers/physics_2d/physics_server_2d_sw.h @@ -246,7 +246,7 @@ public: virtual void body_set_pickable(RID p_body, bool p_pickable) override; - virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08, MotionResult *r_result = nullptr, bool p_collide_separation_ray = false, const Set<RID> &p_exclude = Set<RID>()) override; + virtual bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override; // this function only works on physics process, errors and returns null otherwise virtual PhysicsDirectBodyState2D *body_get_direct_state(RID p_body) override; diff --git a/servers/physics_2d/physics_server_2d_wrap_mt.h b/servers/physics_2d/physics_server_2d_wrap_mt.h index 7925344d76..8d9e366661 100644 --- a/servers/physics_2d/physics_server_2d_wrap_mt.h +++ b/servers/physics_2d/physics_server_2d_wrap_mt.h @@ -254,9 +254,9 @@ public: FUNC2(body_set_pickable, RID, bool); - bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08, MotionResult *r_result = nullptr, bool p_collide_separation_ray = false, const Set<RID> &p_exclude = Set<RID>()) override { + bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false); - return physics_2d_server->body_test_motion(p_body, p_from, p_motion, p_margin, r_result, p_collide_separation_ray, p_exclude); + return physics_2d_server->body_test_motion(p_body, p_parameters, r_result); } // this function only works on physics process, errors and returns null otherwise diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index 5cd9bf3223..5e25d7f7c4 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -525,7 +525,7 @@ int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body, const Rect2 &p_aabb) { return amount; } -bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, PhysicsServer2D::MotionResult *r_result, bool p_collide_separation_ray, const Set<RID> &p_exclude) { +bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::MotionParameters &p_parameters, PhysicsServer2D::MotionResult *r_result) { //give me back regular physics engine logic //this is madness //and most people using this function will think @@ -557,25 +557,25 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co if (!shapes_found) { if (r_result) { *r_result = PhysicsServer2D::MotionResult(); - r_result->travel = p_motion; + r_result->travel = p_parameters.motion; } return false; } // Undo the currently transform the physics server is aware of and apply the provided one - body_aabb = p_from.xform(p_body->get_inv_transform().xform(body_aabb)); - body_aabb = body_aabb.grow(p_margin); + body_aabb = p_parameters.from.xform(p_body->get_inv_transform().xform(body_aabb)); + body_aabb = body_aabb.grow(p_parameters.margin); static const int max_excluded_shape_pairs = 32; ExcludedShapeSW excluded_shape_pairs[max_excluded_shape_pairs]; int excluded_shape_pair_count = 0; - real_t min_contact_depth = p_margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR; + real_t min_contact_depth = p_parameters.margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR; - real_t motion_length = p_motion.length(); - Vector2 motion_normal = p_motion / motion_length; + real_t motion_length = p_parameters.motion.length(); + Vector2 motion_normal = p_parameters.motion / motion_length; - Transform2D body_transform = p_from; + Transform2D body_transform = p_parameters.from; bool recovered = false; @@ -612,7 +612,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co for (int i = 0; i < amount; i++) { const CollisionObject2DSW *col_obj = intersection_query_results[i]; - if (p_exclude.has(col_obj->get_self())) { + if (p_parameters.exclude_bodies.has(col_obj->get_self())) { continue; } @@ -624,7 +624,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co cbk.valid_dir = col_obj_shape_xform.get_axis(1).normalized(); real_t owc_margin = col_obj->get_shape_one_way_collision_margin(shape_idx); - cbk.valid_depth = MAX(owc_margin, p_margin); //user specified, but never less than actual margin or it won't work + cbk.valid_depth = MAX(owc_margin, p_parameters.margin); //user specified, but never less than actual margin or it won't work cbk.invalid_by_dir = 0; if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) { @@ -649,7 +649,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co bool did_collide = false; Shape2DSW *against_shape = col_obj->get_shape(shape_idx); - if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), cbkres, cbkptr, nullptr, p_margin)) { + if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), cbkres, cbkptr, nullptr, p_parameters.margin)) { did_collide = cbk.passed > current_passed; //more passed, so collision actually existed } @@ -714,7 +714,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co // STEP 2 ATTEMPT MOTION Rect2 motion_aabb = body_aabb; - motion_aabb.position += p_motion; + motion_aabb.position += p_parameters.motion; motion_aabb = motion_aabb.merge(body_aabb); int amount = _cull_aabb_for_body(p_body, motion_aabb); @@ -728,7 +728,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co // Colliding separation rays allows to properly snap to the ground, // otherwise it's not needed in regular motion. - if (!p_collide_separation_ray && (body_shape->get_type() == PhysicsServer2D::SHAPE_SEPARATION_RAY)) { + if (!p_parameters.collide_separation_ray && (body_shape->get_type() == PhysicsServer2D::SHAPE_SEPARATION_RAY)) { // When slide on slope is on, separation ray shape acts like a regular shape. if (!static_cast<SeparationRayShape2DSW *>(body_shape)->get_slide_on_slope()) { continue; @@ -744,9 +744,10 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co for (int i = 0; i < amount; i++) { const CollisionObject2DSW *col_obj = intersection_query_results[i]; - if (p_exclude.has(col_obj->get_self())) { + if (p_parameters.exclude_bodies.has(col_obj->get_self())) { continue; } + int col_shape_idx = intersection_query_subindex_results[i]; Shape2DSW *against_shape = col_obj->get_shape(col_shape_idx); @@ -765,7 +766,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co Transform2D col_obj_shape_xform = col_obj->get_transform() * col_obj->get_shape_transform(col_shape_idx); //test initial overlap, does it collide if going all the way? - if (!CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion, against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, nullptr, 0)) { + if (!CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_parameters.motion, against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, nullptr, 0)) { continue; } @@ -790,7 +791,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co real_t fraction = low + (hi - low) * fraction_coeff; Vector2 sep = motion_normal; //important optimization for this to work fast enough - bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * fraction, against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, &sep, 0); + bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_parameters.motion * fraction, against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, &sep, 0); if (collided) { hi = fraction; @@ -827,7 +828,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co cbk.valid_depth = 10e20; Vector2 sep = motion_normal; //important optimization for this to work fast enough - bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * (hi + contact_max_allowed_penetration), col_obj->get_shape(col_shape_idx), col_obj_shape_xform, Vector2(), PhysicsServer2DSW::_shape_col_cbk, &cbk, &sep, 0); + bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_parameters.motion * (hi + contact_max_allowed_penetration), col_obj->get_shape(col_shape_idx), col_obj_shape_xform, Vector2(), PhysicsServer2DSW::_shape_col_cbk, &cbk, &sep, 0); if (!collided || cbk.amount == 0) { continue; } @@ -865,7 +866,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co //it collided, let's get the rest info in unsafe advance Transform2D ugt = body_transform; - ugt.elements[2] += p_motion * unsafe; + ugt.elements[2] += p_parameters.motion * unsafe; _RestCallbackData2D rcd; rcd.best_len = 0; @@ -886,13 +887,13 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co Transform2D body_shape_xform = ugt * p_body->get_shape_transform(j); Shape2DSW *body_shape = p_body->get_shape(j); - body_aabb.position += p_motion * unsafe; + body_aabb.position += p_parameters.motion * unsafe; int amount = _cull_aabb_for_body(p_body, body_aabb); for (int i = 0; i < amount; i++) { const CollisionObject2DSW *col_obj = intersection_query_results[i]; - if (p_exclude.has(col_obj->get_self())) { + if (p_parameters.exclude_bodies.has(col_obj->get_self())) { continue; } @@ -917,7 +918,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co rcd.valid_dir = col_obj_shape_xform.get_axis(1).normalized(); real_t owc_margin = col_obj->get_shape_one_way_collision_margin(shape_idx); - rcd.valid_depth = MAX(owc_margin, p_margin); //user specified, but never less than actual margin or it won't work + rcd.valid_depth = MAX(owc_margin, p_parameters.margin); //user specified, but never less than actual margin or it won't work if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) { const Body2DSW *b = static_cast<const Body2DSW *>(col_obj); @@ -939,7 +940,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co rcd.object = col_obj; rcd.shape = shape_idx; rcd.local_shape = j; - bool sc = CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), _rest_cbk_result, &rcd, nullptr, p_margin); + bool sc = CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), _rest_cbk_result, &rcd, nullptr, p_parameters.margin); if (!sc) { continue; } @@ -962,9 +963,9 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co Vector2 rel_vec = r_result->collision_point - (body->get_transform().get_origin() + body->get_center_of_mass()); r_result->collider_velocity = Vector2(-body->get_angular_velocity() * rel_vec.y, body->get_angular_velocity() * rel_vec.x) + body->get_linear_velocity(); - r_result->travel = safe * p_motion; - r_result->remainder = p_motion - safe * p_motion; - r_result->travel += (body_transform.get_origin() - p_from.get_origin()); + r_result->travel = safe * p_parameters.motion; + r_result->remainder = p_parameters.motion - safe * p_parameters.motion; + r_result->travel += (body_transform.get_origin() - p_parameters.from.get_origin()); } collided = true; @@ -972,9 +973,9 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co } if (!collided && r_result) { - r_result->travel = p_motion; + r_result->travel = p_parameters.motion; r_result->remainder = Vector2(); - r_result->travel += (body_transform.get_origin() - p_from.get_origin()); + r_result->travel += (body_transform.get_origin() - p_parameters.from.get_origin()); } return collided; diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h index a1a8a77ee4..746b5c6c9a 100644 --- a/servers/physics_2d/space_2d_sw.h +++ b/servers/physics_2d/space_2d_sw.h @@ -187,7 +187,7 @@ public: int get_collision_pairs() const { return collision_pairs; } - bool test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, PhysicsServer2D::MotionResult *r_result, bool p_collide_separation_ray = false, const Set<RID> &p_exclude = Set<RID>()); + bool test_body_motion(Body2DSW *p_body, const PhysicsServer2D::MotionParameters &p_parameters, PhysicsServer2D::MotionResult *r_result); void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); } _FORCE_INLINE_ bool is_debugging_contacts() const { return !contact_debug.is_empty(); } diff --git a/servers/physics_3d/physics_server_3d_sw.cpp b/servers/physics_3d/physics_server_3d_sw.cpp index 36f81e072d..b16e199a03 100644 --- a/servers/physics_3d/physics_server_3d_sw.cpp +++ b/servers/physics_3d/physics_server_3d_sw.cpp @@ -868,7 +868,7 @@ void PhysicsServer3DSW::body_set_ray_pickable(RID p_body, bool p_enable) { body->set_ray_pickable(p_enable); } -bool PhysicsServer3DSW::body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin, MotionResult *r_result, int p_max_collisions, bool p_collide_separation_ray, const Set<RID> &p_exclude) { +bool PhysicsServer3DSW::body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result) { Body3DSW *body = body_owner.get_or_null(p_body); ERR_FAIL_COND_V(!body, false); ERR_FAIL_COND_V(!body->get_space(), false); @@ -876,7 +876,7 @@ bool PhysicsServer3DSW::body_test_motion(RID p_body, const Transform3D &p_from, _update_shapes(); - return body->get_space()->test_body_motion(body, p_from, p_motion, p_margin, r_result, p_max_collisions, p_collide_separation_ray, p_exclude); + return body->get_space()->test_body_motion(body, p_parameters, r_result); } PhysicsDirectBodyState3D *PhysicsServer3DSW::body_get_direct_state(RID p_body) { diff --git a/servers/physics_3d/physics_server_3d_sw.h b/servers/physics_3d/physics_server_3d_sw.h index 106e260311..54a787198d 100644 --- a/servers/physics_3d/physics_server_3d_sw.h +++ b/servers/physics_3d/physics_server_3d_sw.h @@ -242,7 +242,7 @@ public: virtual void body_set_ray_pickable(RID p_body, bool p_enable) override; - virtual bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001, MotionResult *r_result = nullptr, int p_max_collisions = 1, bool p_collide_separation_ray = false, const Set<RID> &p_exclude = Set<RID>()) override; + virtual bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override; // this function only works on physics process, errors and returns null otherwise virtual PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) override; diff --git a/servers/physics_3d/physics_server_3d_wrap_mt.h b/servers/physics_3d/physics_server_3d_wrap_mt.h index a86fb5a3d3..17d02addda 100644 --- a/servers/physics_3d/physics_server_3d_wrap_mt.h +++ b/servers/physics_3d/physics_server_3d_wrap_mt.h @@ -253,9 +253,9 @@ public: FUNC2(body_set_ray_pickable, RID, bool); - bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001, MotionResult *r_result = nullptr, int p_max_collisions = 1, bool p_collide_separation_ray = false, const Set<RID> &p_exclude = Set<RID>()) override { + bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override { ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false); - return physics_3d_server->body_test_motion(p_body, p_from, p_motion, p_margin, r_result, p_max_collisions, p_collide_separation_ray, p_exclude); + return physics_3d_server->body_test_motion(p_body, p_parameters, r_result); } // this function only works on physics process, errors and returns null otherwise diff --git a/servers/physics_3d/space_3d_sw.cpp b/servers/physics_3d/space_3d_sw.cpp index 369dad45eb..f5f497e167 100644 --- a/servers/physics_3d/space_3d_sw.cpp +++ b/servers/physics_3d/space_3d_sw.cpp @@ -620,7 +620,7 @@ int Space3DSW::_cull_aabb_for_body(Body3DSW *p_body, const AABB &p_aabb) { return amount; } -bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin, PhysicsServer3D::MotionResult *r_result, int p_max_collisions, bool p_collide_separation_ray, const Set<RID> &p_exclude) { +bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::MotionParameters &p_parameters, PhysicsServer3D::MotionResult *r_result) { //give me back regular physics engine logic //this is madness //and most people using this function will think @@ -628,7 +628,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co //this took about a week to get right.. //but is it right? who knows at this point.. - ERR_FAIL_INDEX_V(p_max_collisions, PhysicsServer3D::MotionResult::MAX_COLLISIONS, false); + ERR_FAIL_INDEX_V(p_parameters.max_collisions, PhysicsServer3D::MotionResult::MAX_COLLISIONS, false); if (r_result) { *r_result = PhysicsServer3D::MotionResult(); @@ -652,22 +652,22 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co if (!shapes_found) { if (r_result) { - r_result->travel = p_motion; + r_result->travel = p_parameters.motion; } return false; } // Undo the currently transform the physics server is aware of and apply the provided one - body_aabb = p_from.xform(p_body->get_inv_transform().xform(body_aabb)); - body_aabb = body_aabb.grow(p_margin); + body_aabb = p_parameters.from.xform(p_body->get_inv_transform().xform(body_aabb)); + body_aabb = body_aabb.grow(p_parameters.margin); - real_t min_contact_depth = p_margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR; + real_t min_contact_depth = p_parameters.margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR; - real_t motion_length = p_motion.length(); - Vector3 motion_normal = p_motion / motion_length; + real_t motion_length = p_parameters.motion.length(); + Vector3 motion_normal = p_parameters.motion / motion_length; - Transform3D body_transform = p_from; + Transform3D body_transform = p_parameters.from; bool recovered = false; @@ -701,13 +701,13 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co for (int i = 0; i < amount; i++) { const CollisionObject3DSW *col_obj = intersection_query_results[i]; - if (p_exclude.has(col_obj->get_self())) { + if (p_parameters.exclude_bodies.has(col_obj->get_self())) { continue; } int shape_idx = intersection_query_subindex_results[i]; - if (CollisionSolver3DSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, p_margin)) { + if (CollisionSolver3DSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, p_parameters.margin)) { collided = cbk.amount > 0; } } @@ -757,7 +757,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co // STEP 2 ATTEMPT MOTION AABB motion_aabb = body_aabb; - motion_aabb.position += p_motion; + motion_aabb.position += p_parameters.motion; motion_aabb = motion_aabb.merge(body_aabb); int amount = _cull_aabb_for_body(p_body, motion_aabb); @@ -771,7 +771,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co // Colliding separation rays allows to properly snap to the ground, // otherwise it's not needed in regular motion. - if (!p_collide_separation_ray && (body_shape->get_type() == PhysicsServer3D::SHAPE_SEPARATION_RAY)) { + if (!p_parameters.collide_separation_ray && (body_shape->get_type() == PhysicsServer3D::SHAPE_SEPARATION_RAY)) { // When slide on slope is on, separation ray shape acts like a regular shape. if (!static_cast<SeparationRayShape3DSW *>(body_shape)->get_slide_on_slope()) { continue; @@ -783,7 +783,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co Transform3D body_shape_xform_inv = body_shape_xform.affine_inverse(); MotionShape3DSW mshape; mshape.shape = body_shape; - mshape.motion = body_shape_xform_inv.basis.xform(p_motion); + mshape.motion = body_shape_xform_inv.basis.xform(p_parameters.motion); bool stuck = false; @@ -792,7 +792,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co for (int i = 0; i < amount; i++) { const CollisionObject3DSW *col_obj = intersection_query_results[i]; - if (p_exclude.has(col_obj->get_self())) { + if (p_parameters.exclude_bodies.has(col_obj->get_self())) { continue; } @@ -821,7 +821,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co for (int k = 0; k < 8; k++) { //steps should be customizable.. real_t fraction = low + (hi - low) * fraction_coeff; - mshape.motion = body_shape_xform_inv.basis.xform(p_motion * fraction); + mshape.motion = body_shape_xform_inv.basis.xform(p_parameters.motion * fraction); Vector3 lA, lB; Vector3 sep = motion_normal; //important optimization for this to work fast enough @@ -883,13 +883,13 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co //it collided, let's get the rest info in unsafe advance Transform3D ugt = body_transform; - ugt.origin += p_motion * unsafe; + ugt.origin += p_parameters.motion * unsafe; _RestResultData results[PhysicsServer3D::MotionResult::MAX_COLLISIONS]; _RestCallbackData rcd; - if (p_max_collisions > 1) { - rcd.max_results = p_max_collisions; + if (p_parameters.max_collisions > 1) { + rcd.max_results = p_parameters.max_collisions; rcd.other_results = results; } @@ -907,20 +907,20 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co Transform3D body_shape_xform = ugt * p_body->get_shape_transform(j); Shape3DSW *body_shape = p_body->get_shape(j); - body_aabb.position += p_motion * unsafe; + body_aabb.position += p_parameters.motion * unsafe; int amount = _cull_aabb_for_body(p_body, body_aabb); for (int i = 0; i < amount; i++) { const CollisionObject3DSW *col_obj = intersection_query_results[i]; - if (p_exclude.has(col_obj->get_self())) { + if (p_parameters.exclude_bodies.has(col_obj->get_self())) { continue; } int shape_idx = intersection_query_subindex_results[i]; rcd.object = col_obj; rcd.shape = shape_idx; - bool sc = CollisionSolver3DSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, p_margin); + bool sc = CollisionSolver3DSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, p_parameters.margin); if (!sc) { continue; } @@ -948,12 +948,12 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co collision.collider_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(rel_vec); } - r_result->travel = safe * p_motion; - r_result->remainder = p_motion - safe * p_motion; - r_result->travel += (body_transform.get_origin() - p_from.get_origin()); + r_result->travel = safe * p_parameters.motion; + r_result->remainder = p_parameters.motion - safe * p_parameters.motion; + r_result->travel += (body_transform.get_origin() - p_parameters.from.get_origin()); - r_result->safe_fraction = safe; - r_result->unsafe_fraction = unsafe; + r_result->collision_safe_fraction = safe; + r_result->collision_unsafe_fraction = unsafe; r_result->collision_count = rcd.result_count; } @@ -963,12 +963,12 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co } if (!collided && r_result) { - r_result->travel = p_motion; + r_result->travel = p_parameters.motion; r_result->remainder = Vector3(); - r_result->travel += (body_transform.get_origin() - p_from.get_origin()); + r_result->travel += (body_transform.get_origin() - p_parameters.from.get_origin()); - r_result->safe_fraction = 1.0; - r_result->unsafe_fraction = 1.0; + r_result->collision_safe_fraction = 1.0; + r_result->collision_unsafe_fraction = 1.0; } return collided; diff --git a/servers/physics_3d/space_3d_sw.h b/servers/physics_3d/space_3d_sw.h index daa1244bf8..69cc3c4bbd 100644 --- a/servers/physics_3d/space_3d_sw.h +++ b/servers/physics_3d/space_3d_sw.h @@ -207,7 +207,7 @@ public: void set_elapsed_time(ElapsedTime p_time, uint64_t p_msec) { elapsed_time[p_time] = p_msec; } uint64_t get_elapsed_time(ElapsedTime p_time) const { return elapsed_time[p_time]; } - bool test_body_motion(Body3DSW *p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin, PhysicsServer3D::MotionResult *r_result, int p_max_collisions = 1, bool p_collide_separation_ray = false, const Set<RID> &p_exclude = Set<RID>()); + bool test_body_motion(Body3DSW *p_body, const PhysicsServer3D::MotionParameters &p_parameters, PhysicsServer3D::MotionResult *r_result); Space3DSW(); ~Space3DSW(); diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index 2a4240baee..ad53f9ed20 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -412,6 +412,49 @@ void PhysicsDirectSpaceState2D::_bind_methods() { /////////////////////////////// +Vector<RID> PhysicsTestMotionParameters2D::get_exclude_bodies() const { + Vector<RID> exclude; + exclude.resize(parameters.exclude_bodies.size()); + + int body_index = 0; + for (RID body : parameters.exclude_bodies) { + exclude.write[body_index++] = body; + } + + return exclude; +} + +void PhysicsTestMotionParameters2D::set_exclude_bodies(const Vector<RID> &p_exclude) { + for (RID body : p_exclude) { + parameters.exclude_bodies.insert(body); + } +} + +void PhysicsTestMotionParameters2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_from"), &PhysicsTestMotionParameters2D::get_from); + ClassDB::bind_method(D_METHOD("set_from"), &PhysicsTestMotionParameters2D::set_from); + + ClassDB::bind_method(D_METHOD("get_motion"), &PhysicsTestMotionParameters2D::get_motion); + ClassDB::bind_method(D_METHOD("set_motion"), &PhysicsTestMotionParameters2D::set_motion); + + ClassDB::bind_method(D_METHOD("get_margin"), &PhysicsTestMotionParameters2D::get_margin); + ClassDB::bind_method(D_METHOD("set_margin"), &PhysicsTestMotionParameters2D::set_margin); + + ClassDB::bind_method(D_METHOD("is_collide_separation_ray_enabled"), &PhysicsTestMotionParameters2D::is_collide_separation_ray_enabled); + ClassDB::bind_method(D_METHOD("set_collide_separation_ray_enabled"), &PhysicsTestMotionParameters2D::set_collide_separation_ray_enabled); + + ClassDB::bind_method(D_METHOD("get_exclude_bodies"), &PhysicsTestMotionParameters2D::get_exclude_bodies); + ClassDB::bind_method(D_METHOD("set_exclude_bodies"), &PhysicsTestMotionParameters2D::set_exclude_bodies); + + ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "from"), "set_from", "get_from"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion"), "set_motion", "get_motion"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin"), "set_margin", "get_margin"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_separation_ray"), "set_collide_separation_ray_enabled", "is_collide_separation_ray_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_bodies"), "set_exclude_bodies", "get_exclude_bodies"); +} + +/////////////////////////////// + Vector2 PhysicsTestMotionResult2D::get_travel() const { return result.travel; } @@ -448,6 +491,10 @@ int PhysicsTestMotionResult2D::get_collider_shape() const { return result.collider_shape; } +int PhysicsTestMotionResult2D::get_collision_local_shape() const { + return result.collision_local_shape; +} + real_t PhysicsTestMotionResult2D::get_collision_depth() const { return result.collision_depth; } @@ -470,36 +517,23 @@ void PhysicsTestMotionResult2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_collider_rid"), &PhysicsTestMotionResult2D::get_collider_rid); ClassDB::bind_method(D_METHOD("get_collider"), &PhysicsTestMotionResult2D::get_collider); ClassDB::bind_method(D_METHOD("get_collider_shape"), &PhysicsTestMotionResult2D::get_collider_shape); + ClassDB::bind_method(D_METHOD("get_collision_local_shape"), &PhysicsTestMotionResult2D::get_collision_local_shape); ClassDB::bind_method(D_METHOD("get_collision_depth"), &PhysicsTestMotionResult2D::get_collision_depth); ClassDB::bind_method(D_METHOD("get_collision_safe_fraction"), &PhysicsTestMotionResult2D::get_collision_safe_fraction); ClassDB::bind_method(D_METHOD("get_collision_unsafe_fraction"), &PhysicsTestMotionResult2D::get_collision_unsafe_fraction); - - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "travel"), "", "get_travel"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "remainder"), "", "get_remainder"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "collision_point"), "", "get_collision_point"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "collision_normal"), "", "get_collision_normal"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "collider_velocity"), "", "get_collider_velocity"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_id", PROPERTY_HINT_OBJECT_ID), "", "get_collider_id"); - ADD_PROPERTY(PropertyInfo(Variant::RID, "collider_rid"), "", "get_collider_rid"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "collider"), "", "get_collider"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_shape"), "", "get_collider_shape"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_depth"), "", "get_collision_depth"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_safe_fraction"), "", "get_collision_safe_fraction"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_unsafe_fraction"), "", "get_collision_unsafe_fraction"); } /////////////////////////////////////// -bool PhysicsServer2D::_body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, const Ref<PhysicsTestMotionResult2D> &p_result, bool p_collide_separation_ray, const Vector<RID> &p_exclude) { - MotionResult *r = nullptr; +bool PhysicsServer2D::_body_test_motion(RID p_body, const Ref<PhysicsTestMotionParameters2D> &p_parameters, const Ref<PhysicsTestMotionResult2D> &p_result) { + ERR_FAIL_COND_V(!p_parameters.is_valid(), false); + + MotionResult *result_ptr = nullptr; if (p_result.is_valid()) { - r = p_result->get_result_ptr(); - } - Set<RID> exclude; - for (int i = 0; i < p_exclude.size(); i++) { - exclude.insert(p_exclude[i]); + result_ptr = p_result->get_result_ptr(); } - return body_test_motion(p_body, p_from, p_motion, p_margin, r, p_collide_separation_ray, exclude); + + return body_test_motion(p_body, p_parameters->get_parameters(), result_ptr); } void PhysicsServer2D::_bind_methods() { @@ -626,7 +660,7 @@ void PhysicsServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("body_set_force_integration_callback", "body", "callable", "userdata"), &PhysicsServer2D::body_set_force_integration_callback, DEFVAL(Variant())); - ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "margin", "result", "collide_separation_ray", "exclude"), &PhysicsServer2D::_body_test_motion, DEFVAL(0.08), DEFVAL(Variant()), DEFVAL(false), DEFVAL(Array())); + ClassDB::bind_method(D_METHOD("body_test_motion", "body", "parameters", "result"), &PhysicsServer2D::_body_test_motion, DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &PhysicsServer2D::body_get_direct_state); diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index ed0584aaa6..1028be05b7 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -198,6 +198,7 @@ public: PhysicsDirectSpaceState2D(); }; +class PhysicsTestMotionParameters2D; class PhysicsTestMotionResult2D; class PhysicsServer2D : public Object { @@ -205,7 +206,7 @@ class PhysicsServer2D : public Object { static PhysicsServer2D *singleton; - virtual bool _body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08, const Ref<PhysicsTestMotionResult2D> &p_result = Ref<PhysicsTestMotionResult2D>(), bool p_collide_separation_ray = false, const Vector<RID> &p_exclude = Vector<RID>()); + virtual bool _body_test_motion(RID p_body, const Ref<PhysicsTestMotionParameters2D> &p_parameters, const Ref<PhysicsTestMotionResult2D> &p_result = Ref<PhysicsTestMotionResult2D>()); protected: static void _bind_methods(); @@ -465,6 +466,21 @@ public: // this function only works on physics process, errors and returns null otherwise virtual PhysicsDirectBodyState2D *body_get_direct_state(RID p_body) = 0; + struct MotionParameters { + Transform2D from; + Vector2 motion; + real_t margin = 0.08; + bool collide_separation_ray = false; + Set<RID> exclude_bodies; + + MotionParameters() {} + + MotionParameters(const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08) : + from(p_from), + motion(p_motion), + margin(p_margin) {} + }; + struct MotionResult { Vector2 travel; Vector2 remainder; @@ -485,18 +501,7 @@ public: } }; - virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.08, MotionResult *r_result = nullptr, bool p_collide_separation_ray = false, const Set<RID> &p_exclude = Set<RID>()) = 0; - - struct SeparationResult { - real_t collision_depth; - Vector2 collision_point; - Vector2 collision_normal; - Vector2 collider_velocity; - int collision_local_shape; - ObjectID collider_id; - RID collider; - int collider_shape; - }; + virtual bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) = 0; /* JOINT API */ @@ -579,11 +584,37 @@ public: ~PhysicsServer2D(); }; +class PhysicsTestMotionParameters2D : public RefCounted { + GDCLASS(PhysicsTestMotionParameters2D, RefCounted); + + PhysicsServer2D::MotionParameters parameters; + +protected: + static void _bind_methods(); + +public: + const PhysicsServer2D::MotionParameters &get_parameters() const { return parameters; } + + const Transform2D &get_from() const { return parameters.from; } + void set_from(const Transform2D &p_from) { parameters.from = p_from; } + + const Vector2 &get_motion() const { return parameters.motion; } + void set_motion(const Vector2 &p_motion) { parameters.motion = p_motion; } + + real_t get_margin() const { return parameters.margin; } + void set_margin(real_t p_margin) { parameters.margin = p_margin; } + + bool is_collide_separation_ray_enabled() const { return parameters.collide_separation_ray; } + void set_collide_separation_ray_enabled(bool p_enabled) { parameters.collide_separation_ray = p_enabled; } + + Vector<RID> get_exclude_bodies() const; + void set_exclude_bodies(const Vector<RID> &p_exclude); +}; + class PhysicsTestMotionResult2D : public RefCounted { GDCLASS(PhysicsTestMotionResult2D, RefCounted); PhysicsServer2D::MotionResult result; - friend class PhysicsServer2D; protected: static void _bind_methods(); @@ -601,6 +632,7 @@ public: RID get_collider_rid() const; Object *get_collider() const; int get_collider_shape() const; + int get_collision_local_shape() const; real_t get_collision_depth() const; real_t get_collision_safe_fraction() const; real_t get_collision_unsafe_fraction() const; diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index f444c2883d..1b47eba134 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -362,6 +362,53 @@ void PhysicsDirectSpaceState3D::_bind_methods() { /////////////////////////////// +Vector<RID> PhysicsTestMotionParameters3D::get_exclude_bodies() const { + Vector<RID> exclude; + exclude.resize(parameters.exclude_bodies.size()); + + int body_index = 0; + for (RID body : parameters.exclude_bodies) { + exclude.write[body_index++] = body; + } + + return exclude; +} + +void PhysicsTestMotionParameters3D::set_exclude_bodies(const Vector<RID> &p_exclude) { + for (RID body : p_exclude) { + parameters.exclude_bodies.insert(body); + } +} + +void PhysicsTestMotionParameters3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_from"), &PhysicsTestMotionParameters3D::get_from); + ClassDB::bind_method(D_METHOD("set_from"), &PhysicsTestMotionParameters3D::set_from); + + ClassDB::bind_method(D_METHOD("get_motion"), &PhysicsTestMotionParameters3D::get_motion); + ClassDB::bind_method(D_METHOD("set_motion"), &PhysicsTestMotionParameters3D::set_motion); + + ClassDB::bind_method(D_METHOD("get_margin"), &PhysicsTestMotionParameters3D::get_margin); + ClassDB::bind_method(D_METHOD("set_margin"), &PhysicsTestMotionParameters3D::set_margin); + + ClassDB::bind_method(D_METHOD("get_max_collisions"), &PhysicsTestMotionParameters3D::get_max_collisions); + ClassDB::bind_method(D_METHOD("set_max_collisions"), &PhysicsTestMotionParameters3D::set_max_collisions); + + ClassDB::bind_method(D_METHOD("is_collide_separation_ray_enabled"), &PhysicsTestMotionParameters3D::is_collide_separation_ray_enabled); + ClassDB::bind_method(D_METHOD("set_collide_separation_ray_enabled"), &PhysicsTestMotionParameters3D::set_collide_separation_ray_enabled); + + ClassDB::bind_method(D_METHOD("get_exclude_bodies"), &PhysicsTestMotionParameters3D::get_exclude_bodies); + ClassDB::bind_method(D_METHOD("set_exclude_bodies"), &PhysicsTestMotionParameters3D::set_exclude_bodies); + + ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "from"), "set_from", "get_from"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "motion"), "set_motion", "get_motion"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin"), "set_margin", "get_margin"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_collisions"), "set_max_collisions", "get_max_collisions"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_separation_ray"), "set_collide_separation_ray_enabled", "is_collide_separation_ray_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_bodies"), "set_exclude_bodies", "get_exclude_bodies"); +} + +/////////////////////////////// + Vector3 PhysicsTestMotionResult3D::get_travel() const { return result.travel; } @@ -370,12 +417,12 @@ Vector3 PhysicsTestMotionResult3D::get_remainder() const { return result.remainder; } -real_t PhysicsTestMotionResult3D::get_safe_fraction() const { - return result.safe_fraction; +real_t PhysicsTestMotionResult3D::get_collision_safe_fraction() const { + return result.collision_safe_fraction; } -real_t PhysicsTestMotionResult3D::get_unsafe_fraction() const { - return result.unsafe_fraction; +real_t PhysicsTestMotionResult3D::get_collision_unsafe_fraction() const { + return result.collision_unsafe_fraction; } int PhysicsTestMotionResult3D::get_collision_count() const { @@ -417,48 +464,21 @@ int PhysicsTestMotionResult3D::get_collider_shape(int p_collision_index) const { return result.collisions[p_collision_index].collider_shape; } +int PhysicsTestMotionResult3D::get_collision_local_shape(int p_collision_index) const { + ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, 0); + return result.collisions[p_collision_index].local_shape; +} + real_t PhysicsTestMotionResult3D::get_collision_depth(int p_collision_index) const { ERR_FAIL_INDEX_V(p_collision_index, result.collision_count, 0.0); return result.collisions[p_collision_index].depth; } -Vector3 PhysicsTestMotionResult3D::get_best_collision_point() const { - return result.collision_count ? get_collision_point() : Vector3(); -} - -Vector3 PhysicsTestMotionResult3D::get_best_collision_normal() const { - return result.collision_count ? get_collision_normal() : Vector3(); -} - -Vector3 PhysicsTestMotionResult3D::get_best_collider_velocity() const { - return result.collision_count ? get_collider_velocity() : Vector3(); -} - -ObjectID PhysicsTestMotionResult3D::get_best_collider_id() const { - return result.collision_count ? get_collider_id() : ObjectID(); -} - -RID PhysicsTestMotionResult3D::get_best_collider_rid() const { - return result.collision_count ? get_collider_rid() : RID(); -} - -Object *PhysicsTestMotionResult3D::get_best_collider() const { - return result.collision_count ? get_collider() : nullptr; -} - -int PhysicsTestMotionResult3D::get_best_collider_shape() const { - return result.collision_count ? get_collider_shape() : 0; -} - -real_t PhysicsTestMotionResult3D::get_best_collision_depth() const { - return result.collision_count ? get_collision_depth() : 0.0; -} - void PhysicsTestMotionResult3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_travel"), &PhysicsTestMotionResult3D::get_travel); ClassDB::bind_method(D_METHOD("get_remainder"), &PhysicsTestMotionResult3D::get_remainder); - ClassDB::bind_method(D_METHOD("get_safe_fraction"), &PhysicsTestMotionResult3D::get_safe_fraction); - ClassDB::bind_method(D_METHOD("get_unsafe_fraction"), &PhysicsTestMotionResult3D::get_unsafe_fraction); + ClassDB::bind_method(D_METHOD("get_collision_safe_fraction"), &PhysicsTestMotionResult3D::get_collision_safe_fraction); + ClassDB::bind_method(D_METHOD("get_collision_unsafe_fraction"), &PhysicsTestMotionResult3D::get_collision_unsafe_fraction); ClassDB::bind_method(D_METHOD("get_collision_count"), &PhysicsTestMotionResult3D::get_collision_count); ClassDB::bind_method(D_METHOD("get_collision_point", "collision_index"), &PhysicsTestMotionResult3D::get_collision_point, DEFVAL(0)); ClassDB::bind_method(D_METHOD("get_collision_normal", "collision_index"), &PhysicsTestMotionResult3D::get_collision_normal, DEFVAL(0)); @@ -467,44 +487,21 @@ void PhysicsTestMotionResult3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_collider_rid", "collision_index"), &PhysicsTestMotionResult3D::get_collider_rid, DEFVAL(0)); ClassDB::bind_method(D_METHOD("get_collider", "collision_index"), &PhysicsTestMotionResult3D::get_collider, DEFVAL(0)); ClassDB::bind_method(D_METHOD("get_collider_shape", "collision_index"), &PhysicsTestMotionResult3D::get_collider_shape, DEFVAL(0)); + ClassDB::bind_method(D_METHOD("get_collision_local_shape", "collision_index"), &PhysicsTestMotionResult3D::get_collision_local_shape, DEFVAL(0)); ClassDB::bind_method(D_METHOD("get_collision_depth", "collision_index"), &PhysicsTestMotionResult3D::get_collision_depth, DEFVAL(0)); - - ClassDB::bind_method(D_METHOD("get_best_collision_point"), &PhysicsTestMotionResult3D::get_best_collision_point); - ClassDB::bind_method(D_METHOD("get_best_collision_normal"), &PhysicsTestMotionResult3D::get_best_collision_normal); - ClassDB::bind_method(D_METHOD("get_best_collider_velocity"), &PhysicsTestMotionResult3D::get_best_collider_velocity); - ClassDB::bind_method(D_METHOD("get_best_collider_id"), &PhysicsTestMotionResult3D::get_best_collider_id); - ClassDB::bind_method(D_METHOD("get_best_collider_rid"), &PhysicsTestMotionResult3D::get_best_collider_rid); - ClassDB::bind_method(D_METHOD("get_best_collider"), &PhysicsTestMotionResult3D::get_best_collider); - ClassDB::bind_method(D_METHOD("get_best_collider_shape"), &PhysicsTestMotionResult3D::get_best_collider_shape); - ClassDB::bind_method(D_METHOD("get_best_collision_depth"), &PhysicsTestMotionResult3D::get_best_collision_depth); - - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "travel"), "", "get_travel"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "remainder"), "", "get_remainder"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "safe_fraction"), "", "get_safe_fraction"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "unsafe_fraction"), "", "get_unsafe_fraction"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_count"), "", "get_collision_count"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "collision_point"), "", "get_best_collision_point"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "collision_normal"), "", "get_best_collision_normal"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "collider_velocity"), "", "get_best_collider_velocity"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_id", PROPERTY_HINT_OBJECT_ID), "", "get_best_collider_id"); - ADD_PROPERTY(PropertyInfo(Variant::RID, "collider_rid"), "", "get_best_collider_rid"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "collider"), "", "get_best_collider"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_shape"), "", "get_best_collider_shape"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_depth"), "", "get_best_collision_depth"); } /////////////////////////////////////// -bool PhysicsServer3D::_body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin, const Ref<PhysicsTestMotionResult3D> &p_result, bool p_collide_separation_ray, const Vector<RID> &p_exclude, int p_max_collisions) { - MotionResult *r = nullptr; +bool PhysicsServer3D::_body_test_motion(RID p_body, const Ref<PhysicsTestMotionParameters3D> &p_parameters, const Ref<PhysicsTestMotionResult3D> &p_result) { + ERR_FAIL_COND_V(!p_parameters.is_valid(), false); + + MotionResult *result_ptr = nullptr; if (p_result.is_valid()) { - r = p_result->get_result_ptr(); + result_ptr = p_result->get_result_ptr(); } - Set<RID> exclude; - for (int i = 0; i < p_exclude.size(); i++) { - exclude.insert(p_exclude[i]); - } - return body_test_motion(p_body, p_from, p_motion, p_margin, r, p_max_collisions, p_collide_separation_ray, exclude); + + return body_test_motion(p_body, p_parameters->get_parameters(), result_ptr); } RID PhysicsServer3D::shape_create(ShapeType p_shape) { @@ -662,7 +659,7 @@ void PhysicsServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("body_set_ray_pickable", "body", "enable"), &PhysicsServer3D::body_set_ray_pickable); - ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "margin", "result", "collide_separation_ray", "exclude", "max_collisions"), &PhysicsServer3D::_body_test_motion, DEFVAL(0.001), DEFVAL(Variant()), DEFVAL(false), DEFVAL(Array()), DEFVAL(1)); + ClassDB::bind_method(D_METHOD("body_test_motion", "body", "parameters", "result"), &PhysicsServer3D::_body_test_motion, DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &PhysicsServer3D::body_get_direct_state); diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index dbd734ba32..3d884de095 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -203,6 +203,7 @@ public: virtual ~RenderingServerHandler() {} }; +class PhysicsTestMotionParameters3D; class PhysicsTestMotionResult3D; class PhysicsServer3D : public Object { @@ -210,7 +211,7 @@ class PhysicsServer3D : public Object { static PhysicsServer3D *singleton; - virtual bool _body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001, const Ref<PhysicsTestMotionResult3D> &p_result = Ref<PhysicsTestMotionResult3D>(), bool p_collide_separation_ray = false, const Vector<RID> &p_exclude = Vector<RID>(), int p_max_collisions = 1); + virtual bool _body_test_motion(RID p_body, const Ref<PhysicsTestMotionParameters3D> &p_parameters, const Ref<PhysicsTestMotionResult3D> &p_result = Ref<PhysicsTestMotionResult3D>()); protected: static void _bind_methods(); @@ -483,6 +484,22 @@ public: // this function only works on physics process, errors and returns null otherwise virtual PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) = 0; + struct MotionParameters { + Transform3D from; + Vector3 motion; + real_t margin = 0.001; + int max_collisions = 1; + bool collide_separation_ray = false; + Set<RID> exclude_bodies; + + MotionParameters() {} + + MotionParameters(const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001) : + from(p_from), + motion(p_motion), + margin(p_margin) {} + }; + struct MotionCollision { Vector3 position; Vector3 normal; @@ -501,15 +518,15 @@ public: struct MotionResult { Vector3 travel; Vector3 remainder; - real_t safe_fraction = 0.0; - real_t unsafe_fraction = 0.0; + real_t collision_safe_fraction = 0.0; + real_t collision_unsafe_fraction = 0.0; static const int MAX_COLLISIONS = 32; MotionCollision collisions[MAX_COLLISIONS]; int collision_count = 0; }; - virtual bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, real_t p_margin = 0.001, MotionResult *r_result = nullptr, int p_max_collisions = 1, bool p_collide_separation_ray = false, const Set<RID> &p_exclude = Set<RID>()) = 0; + virtual bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) = 0; /* SOFT BODY */ @@ -760,11 +777,40 @@ public: ~PhysicsServer3D(); }; +class PhysicsTestMotionParameters3D : public RefCounted { + GDCLASS(PhysicsTestMotionParameters3D, RefCounted); + + PhysicsServer3D::MotionParameters parameters; + +protected: + static void _bind_methods(); + +public: + const PhysicsServer3D::MotionParameters &get_parameters() const { return parameters; } + + const Transform3D &get_from() const { return parameters.from; } + void set_from(const Transform3D &p_from) { parameters.from = p_from; } + + const Vector3 &get_motion() const { return parameters.motion; } + void set_motion(const Vector3 &p_motion) { parameters.motion = p_motion; } + + real_t get_margin() const { return parameters.margin; } + void set_margin(real_t p_margin) { parameters.margin = p_margin; } + + int get_max_collisions() const { return parameters.max_collisions; } + void set_max_collisions(int p_max_collisions) { parameters.max_collisions = p_max_collisions; } + + bool is_collide_separation_ray_enabled() const { return parameters.collide_separation_ray; } + void set_collide_separation_ray_enabled(bool p_enabled) { parameters.collide_separation_ray = p_enabled; } + + Vector<RID> get_exclude_bodies() const; + void set_exclude_bodies(const Vector<RID> &p_exclude); +}; + class PhysicsTestMotionResult3D : public RefCounted { GDCLASS(PhysicsTestMotionResult3D, RefCounted); PhysicsServer3D::MotionResult result; - friend class PhysicsServer3D; protected: static void _bind_methods(); @@ -774,8 +820,8 @@ public: Vector3 get_travel() const; Vector3 get_remainder() const; - real_t get_safe_fraction() const; - real_t get_unsafe_fraction() const; + real_t get_collision_safe_fraction() const; + real_t get_collision_unsafe_fraction() const; int get_collision_count() const; @@ -786,16 +832,8 @@ public: RID get_collider_rid(int p_collision_index = 0) const; Object *get_collider(int p_collision_index = 0) const; int get_collider_shape(int p_collision_index = 0) const; + int get_collision_local_shape(int p_collision_index = 0) const; real_t get_collision_depth(int p_collision_index = 0) const; - - Vector3 get_best_collision_point() const; - Vector3 get_best_collision_normal() const; - Vector3 get_best_collider_velocity() const; - ObjectID get_best_collider_id() const; - RID get_best_collider_rid() const; - Object *get_best_collider() const; - int get_best_collider_shape() const; - real_t get_best_collision_depth() const; }; typedef PhysicsServer3D *(*CreatePhysicsServer3DCallback)(); diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp index c5effeb243..28cd8374c0 100644 --- a/servers/register_server_types.cpp +++ b/servers/register_server_types.cpp @@ -208,12 +208,14 @@ void register_server_types() { GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState2D); GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState2D); + GDREGISTER_CLASS(PhysicsTestMotionParameters2D); GDREGISTER_CLASS(PhysicsTestMotionResult2D); GDREGISTER_CLASS(PhysicsShapeQueryParameters2D); GDREGISTER_CLASS(PhysicsShapeQueryParameters3D); GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState3D); GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState3D); + GDREGISTER_CLASS(PhysicsTestMotionParameters3D); GDREGISTER_CLASS(PhysicsTestMotionResult3D); // Physics 2D |