Merge pull request #16757 from AndreaCatania/kinpush

Improved kinematic body, Now can move rigid body
This commit is contained in:
Rémi Verschelde 2018-02-20 15:41:10 +01:00 committed by GitHub
commit 497a4e9e25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 96 additions and 88 deletions

View File

@ -825,12 +825,12 @@ PhysicsDirectBodyState *BulletPhysicsServer::body_get_direct_state(RID p_body) {
return BulletPhysicsDirectBodyState::get_singleton(body);
}
bool BulletPhysicsServer::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, MotionResult *r_result) {
bool BulletPhysicsServer::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result) {
RigidBodyBullet *body = rigid_body_owner.get(p_body);
ERR_FAIL_COND_V(!body, false);
ERR_FAIL_COND_V(!body->get_space(), false);
return body->get_space()->test_body_motion(body, p_from, p_motion, r_result);
return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, r_result);
}
RID BulletPhysicsServer::soft_body_create(bool p_init_sleeping) {

View File

@ -253,7 +253,7 @@ public:
// this function only works on physics process, errors and returns null otherwise
virtual PhysicsDirectBodyState *body_get_direct_state(RID p_body);
virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, MotionResult *r_result = NULL);
virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = NULL);
/* SOFT BODY API */

View File

@ -98,11 +98,16 @@ bool GodotKinClosestConvexResultCallback::needsCollision(btBroadphaseProxy *prox
if (gObj == m_self_object) {
return false;
} else {
if (m_ignore_areas && gObj->getType() == CollisionObjectBullet::TYPE_AREA) {
// A kinematic body can't be stopped by a rigid body since the mass of kinematic body is infinite
if (m_infinite_inertia && !btObj->isStaticOrKinematicObject())
return false;
} else if (m_self_object->has_collision_exception(gObj)) {
if (gObj->getType() == CollisionObjectBullet::TYPE_AREA)
return false;
if (m_self_object->has_collision_exception(gObj))
return false;
}
}
return true;
} else {

View File

@ -93,12 +93,12 @@ public:
struct GodotKinClosestConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback {
public:
const RigidBodyBullet *m_self_object;
const bool m_ignore_areas;
const bool m_infinite_inertia;
GodotKinClosestConvexResultCallback(const btVector3 &convexFromWorld, const btVector3 &convexToWorld, const RigidBodyBullet *p_self_object, bool p_ignore_areas) :
GodotKinClosestConvexResultCallback(const btVector3 &convexFromWorld, const btVector3 &convexToWorld, const RigidBodyBullet *p_self_object, bool p_infinite_inertia) :
btCollisionWorld::ClosestConvexResultCallback(convexFromWorld, convexToWorld),
m_self_object(p_self_object),
m_ignore_areas(p_ignore_areas) {}
m_infinite_inertia(p_infinite_inertia) {}
virtual bool needsCollision(btBroadphaseProxy *proxy0) const;
};

View File

@ -804,8 +804,7 @@ static Ref<SpatialMaterial> red_mat;
static Ref<SpatialMaterial> blue_mat;
#endif
#define IGNORE_AREAS_TRUE true
bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, PhysicsServer::MotionResult *r_result) {
bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer::MotionResult *r_result) {
#if debug_test_motion
/// Yes I know this is not good, but I've used it as fast debugging hack.
@ -839,16 +838,6 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f
}
#endif
///// Release all generated manifolds
//{
// if(p_body->get_kinematic_utilities()){
// for(int i= p_body->get_kinematic_utilities()->m_generatedManifold.size()-1; 0<=i; --i){
// dispatcher->releaseManifold( p_body->get_kinematic_utilities()->m_generatedManifold[i] );
// }
// p_body->get_kinematic_utilities()->m_generatedManifold.clear();
// }
//}
btTransform body_safe_position;
G_TO_B(p_from, body_safe_position);
UNSCALE_BT_BASIS(body_safe_position);
@ -857,7 +846,7 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f
btVector3 recover_initial_position(0, 0, 0);
{ /// Phase one - multi shapes depenetration using margin
for (int t(RECOVERING_MOVEMENT_CYCLES); 0 < t; --t) {
if (!recover_from_penetration(p_body, body_safe_position, RECOVERING_MOVEMENT_SCALE, recover_initial_position)) {
if (!recover_from_penetration(p_body, body_safe_position, RECOVERING_MOVEMENT_SCALE, p_infinite_inertia, recover_initial_position)) {
break;
}
}
@ -900,7 +889,7 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f
btTransform shape_world_to(shape_world_from);
shape_world_to.getOrigin() += motion;
GodotKinClosestConvexResultCallback btResult(shape_world_from.getOrigin(), shape_world_to.getOrigin(), p_body, IGNORE_AREAS_TRUE);
GodotKinClosestConvexResultCallback btResult(shape_world_from.getOrigin(), shape_world_to.getOrigin(), p_body, p_infinite_inertia);
btResult.m_collisionFilterGroup = p_body->get_collision_layer();
btResult.m_collisionFilterMask = p_body->get_collision_mask();
@ -926,7 +915,7 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f
real_t l_penetration_distance = 1e20;
for (int t(RECOVERING_MOVEMENT_CYCLES); 0 < t; --t) {
l_has_penetration = recover_from_penetration(p_body, body_safe_position, RECOVERING_MOVEMENT_SCALE, delta_recover_movement, &r_recover_result);
l_has_penetration = recover_from_penetration(p_body, body_safe_position, RECOVERING_MOVEMENT_SCALE, p_infinite_inertia, delta_recover_movement, &r_recover_result);
if (r_result) {
#if PERFORM_INITIAL_UNSTACK
@ -955,15 +944,6 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f
r_result->collider_shape = r_recover_result.other_compound_shape_index;
r_result->collision_local_shape = r_recover_result.local_shape_most_recovered;
//{ /// Add manifold point to manage collisions
// btPersistentManifold* manifold = dynamicsWorld->getDispatcher()->getNewManifold(p_body->getBtBody(), btRigid);
// btManifoldPoint manifoldPoint(result_callabck.m_pointWorld, result_callabck.m_pointWorld, result_callabck.m_pointNormalWorld, result_callabck.m_penetration_distance);
// manifoldPoint.m_index0 = r_result->collision_local_shape;
// manifoldPoint.m_index1 = r_result->collider_shape;
// manifold->addManifoldPoint(manifoldPoint);
// p_body->get_kinematic_utilities()->m_generatedManifold.push_back(manifold);
//}
#if debug_test_motion
Vector3 sup_line2;
B_TO_G(motion, sup_line2);
@ -1022,7 +1002,7 @@ public:
}
};
bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result) {
bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result) {
RecoverPenetrationBroadPhaseCallback recover_broad_result(p_body->get_bt_collision_object(), p_body->get_collision_layer(), p_body->get_collision_mask());
@ -1053,7 +1033,7 @@ bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTran
for (int i = recover_broad_result.result_collision_objects.size() - 1; 0 <= i; --i) {
btCollisionObject *otherObject = recover_broad_result.result_collision_objects[i];
if (!p_body->get_bt_collision_object()->checkCollideWith(otherObject) || !otherObject->checkCollideWith(p_body->get_bt_collision_object()))
if (!p_body->get_bt_collision_object()->checkCollideWith(otherObject) || !otherObject->checkCollideWith(p_body->get_bt_collision_object()) || (p_infinite_inertia && !otherObject->isStaticOrKinematicObject()))
continue;
if (otherObject->getCollisionShape()->isCompound()) {

View File

@ -172,7 +172,7 @@ public:
void update_gravity();
bool test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, PhysicsServer::MotionResult *r_result);
bool test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer::MotionResult *r_result);
private:
void create_empty_world(bool p_create_soft_world);
@ -199,7 +199,7 @@ private:
local_shape_most_recovered(0) {}
};
bool recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result = NULL);
bool recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result = NULL);
/// This is an API that recover a kinematic object from penetration
/// This allow only Convex Convex test and it always use GJK algorithm, With this API we don't benefit of Bullet special accelerated functions
bool RFP_convex_convex_test(const btConvexShape *p_shapeA, const btConvexShape *p_shapeB, btCollisionObject *p_objectB, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result = NULL);

View File

@ -30,6 +30,7 @@
#include "physics_body_2d.h"
#include "core/method_bind_ext.gen.inc"
#include "engine.h"
#include "scene/scene_string_names.h"
@ -362,12 +363,12 @@ struct _RigidBody2DInOut {
int local_shape;
};
bool RigidBody2D::_test_motion(const Vector2 &p_motion, float p_margin, const Ref<Physics2DTestMotionResult> &p_result) {
bool RigidBody2D::_test_motion(const Vector2 &p_motion, bool p_infinite_inertia, float p_margin, const Ref<Physics2DTestMotionResult> &p_result) {
Physics2DServer::MotionResult *r = NULL;
if (p_result.is_valid())
r = p_result->get_result_ptr();
return Physics2DServer::get_singleton()->body_test_motion(get_rid(), get_global_transform(), p_motion, p_margin, r);
return Physics2DServer::get_singleton()->body_test_motion(get_rid(), get_global_transform(), p_motion, p_infinite_inertia, p_margin, r);
}
void RigidBody2D::_direct_state_changed(Object *p_state) {
@ -970,11 +971,11 @@ RigidBody2D::~RigidBody2D() {
//////////////////////////
Ref<KinematicCollision2D> KinematicBody2D::_move(const Vector2 &p_motion) {
Ref<KinematicCollision2D> KinematicBody2D::_move(const Vector2 &p_motion, bool p_infinite_inertia) {
Collision col;
if (move_and_collide(p_motion, col)) {
if (move_and_collide(p_motion, p_infinite_inertia, col)) {
if (motion_cache.is_null()) {
motion_cache.instance();
motion_cache->owner = this;
@ -988,11 +989,11 @@ Ref<KinematicCollision2D> KinematicBody2D::_move(const Vector2 &p_motion) {
return Ref<KinematicCollision2D>();
}
bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, Collision &r_collision) {
bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_inertia, Collision &r_collision) {
Transform2D gt = get_global_transform();
Physics2DServer::MotionResult result;
bool colliding = Physics2DServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, margin, &result);
bool colliding = Physics2DServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, margin, &result);
if (colliding) {
r_collision.collider_metadata = result.collider_metadata;
@ -1012,7 +1013,7 @@ bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, Collision &r_col
return colliding;
}
Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction, float p_slope_stop_min_velocity, int p_max_slides, float p_floor_max_angle) {
Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction, bool p_infinite_inertia, float p_slope_stop_min_velocity, int p_max_slides, float p_floor_max_angle) {
Vector2 motion = (floor_velocity + p_linear_velocity) * get_physics_process_delta_time();
Vector2 lv = p_linear_velocity;
@ -1027,7 +1028,7 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const
Collision collision;
bool collided = move_and_collide(motion, collision);
bool collided = move_and_collide(motion, p_infinite_inertia, collision);
if (collided) {
@ -1094,11 +1095,11 @@ Vector2 KinematicBody2D::get_floor_velocity() const {
return floor_velocity;
}
bool KinematicBody2D::test_move(const Transform2D &p_from, const Vector2 &p_motion) {
bool KinematicBody2D::test_move(const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia) {
ERR_FAIL_COND_V(!is_inside_tree(), false);
return Physics2DServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, margin);
return Physics2DServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, p_infinite_inertia, margin);
}
void KinematicBody2D::set_safe_margin(float p_margin) {
@ -1139,10 +1140,10 @@ Ref<KinematicCollision2D> KinematicBody2D::_get_slide_collision(int p_bounce) {
void KinematicBody2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec"), &KinematicBody2D::_move);
ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "slope_stop_min_velocity", "max_bounces", "floor_max_angle"), &KinematicBody2D::move_and_slide, DEFVAL(Vector2(0, 0)), DEFVAL(5), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)));
ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia"), &KinematicBody2D::_move, DEFVAL(true));
ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "infinite_inertia", "slope_stop_min_velocity", "max_bounces", "floor_max_angle"), &KinematicBody2D::move_and_slide, DEFVAL(Vector2(0, 0)), DEFVAL(true), DEFVAL(5), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)));
ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec"), &KinematicBody2D::test_move);
ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec", "infinite_inertia"), &KinematicBody2D::test_move);
ClassDB::bind_method(D_METHOD("is_on_floor"), &KinematicBody2D::is_on_floor);
ClassDB::bind_method(D_METHOD("is_on_ceiling"), &KinematicBody2D::is_on_ceiling);

View File

@ -185,7 +185,7 @@ private:
void _body_inout(int p_status, ObjectID p_instance, int p_body_shape, int p_local_shape);
void _direct_state_changed(Object *p_state);
bool _test_motion(const Vector2 &p_motion, float p_margin = 0.08, const Ref<Physics2DTestMotionResult> &p_result = Ref<Physics2DTestMotionResult>());
bool _test_motion(const Vector2 &p_motion, bool p_infinite_inertia = true, float p_margin = 0.08, const Ref<Physics2DTestMotionResult> &p_result = Ref<Physics2DTestMotionResult>());
protected:
void _notification(int p_what);
@ -296,20 +296,20 @@ private:
_FORCE_INLINE_ bool _ignores_mode(Physics2DServer::BodyMode) const;
Ref<KinematicCollision2D> _move(const Vector2 &p_motion);
Ref<KinematicCollision2D> _move(const Vector2 &p_motion, bool p_infinite_inertia = true);
Ref<KinematicCollision2D> _get_slide_collision(int p_bounce);
protected:
static void _bind_methods();
public:
bool move_and_collide(const Vector2 &p_motion, Collision &r_collision);
bool test_move(const Transform2D &p_from, const Vector2 &p_motion);
bool move_and_collide(const Vector2 &p_motion, bool p_infinite_inertia, Collision &r_collision);
bool test_move(const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia);
void set_safe_margin(float p_margin);
float get_safe_margin() const;
Vector2 move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction = Vector2(0, 0), float p_slope_stop_min_velocity = 5, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45));
Vector2 move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction = Vector2(0, 0), bool p_infinite_inertia = true, float p_slope_stop_min_velocity = 5, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45));
bool is_on_floor() const;
bool is_on_wall() const;
bool is_on_ceiling() const;

View File

@ -928,10 +928,10 @@ RigidBody::~RigidBody() {
//////////////////////////////////////////////////////
//////////////////////////
Ref<KinematicCollision> KinematicBody::_move(const Vector3 &p_motion) {
Ref<KinematicCollision> KinematicBody::_move(const Vector3 &p_motion, bool p_infinite_inertia) {
Collision col;
if (move_and_collide(p_motion, col)) {
if (move_and_collide(p_motion, p_infinite_inertia, col)) {
if (motion_cache.is_null()) {
motion_cache.instance();
motion_cache->owner = this;
@ -945,11 +945,11 @@ Ref<KinematicCollision> KinematicBody::_move(const Vector3 &p_motion) {
return Ref<KinematicCollision>();
}
bool KinematicBody::move_and_collide(const Vector3 &p_motion, Collision &r_collision) {
bool KinematicBody::move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collision) {
Transform gt = get_global_transform();
PhysicsServer::MotionResult result;
bool colliding = PhysicsServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, &result);
bool colliding = PhysicsServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, &result);
if (colliding) {
r_collision.collider_metadata = result.collider_metadata;
@ -975,7 +975,7 @@ bool KinematicBody::move_and_collide(const Vector3 &p_motion, Collision &r_colli
return colliding;
}
Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction, float p_slope_stop_min_velocity, int p_max_slides, float p_floor_max_angle) {
Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction, bool p_infinite_inertia, float p_slope_stop_min_velocity, int p_max_slides, float p_floor_max_angle) {
Vector3 lv = p_linear_velocity;
@ -997,7 +997,7 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve
Collision collision;
bool collided = move_and_collide(motion, collision);
bool collided = move_and_collide(motion, p_infinite_inertia, collision);
if (collided) {
@ -1070,11 +1070,11 @@ Vector3 KinematicBody::get_floor_velocity() const {
return floor_velocity;
}
bool KinematicBody::test_move(const Transform &p_from, const Vector3 &p_motion) {
bool KinematicBody::test_move(const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia) {
ERR_FAIL_COND_V(!is_inside_tree(), false);
return PhysicsServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion);
return PhysicsServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, p_infinite_inertia);
}
void KinematicBody::set_axis_lock(PhysicsServer::BodyAxis p_axis, bool p_lock) {
@ -1123,10 +1123,10 @@ Ref<KinematicCollision> KinematicBody::_get_slide_collision(int p_bounce) {
void KinematicBody::_bind_methods() {
ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec"), &KinematicBody::_move);
ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "slope_stop_min_velocity", "max_slides", "floor_max_angle"), &KinematicBody::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(0.05), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)));
ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia"), &KinematicBody::_move, DEFVAL(true));
ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "infinite_inertia", "slope_stop_min_velocity", "max_slides", "floor_max_angle"), &KinematicBody::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(true), DEFVAL(0.05), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)));
ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec"), &KinematicBody::test_move);
ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec", "infinite_inertia"), &KinematicBody::test_move);
ClassDB::bind_method(D_METHOD("is_on_floor"), &KinematicBody::is_on_floor);
ClassDB::bind_method(D_METHOD("is_on_ceiling"), &KinematicBody::is_on_ceiling);

View File

@ -286,15 +286,15 @@ private:
_FORCE_INLINE_ bool _ignores_mode(PhysicsServer::BodyMode) const;
Ref<KinematicCollision> _move(const Vector3 &p_motion);
Ref<KinematicCollision> _move(const Vector3 &p_motion, bool p_infinite_inertia = true);
Ref<KinematicCollision> _get_slide_collision(int p_bounce);
protected:
static void _bind_methods();
public:
bool move_and_collide(const Vector3 &p_motion, Collision &r_collision);
bool test_move(const Transform &p_from, const Vector3 &p_motion);
bool move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collision);
bool test_move(const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia);
void set_axis_lock(PhysicsServer::BodyAxis p_axis, bool p_lock);
bool get_axis_lock(PhysicsServer::BodyAxis p_axis) const;
@ -302,7 +302,7 @@ public:
void set_safe_margin(float p_margin);
float get_safe_margin() const;
Vector3 move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction = Vector3(0, 0, 0), float p_slope_stop_min_velocity = 0.05, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45));
Vector3 move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction = Vector3(0, 0, 0), bool p_infinite_inertia = true, float p_slope_stop_min_velocity = 0.05, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45));
bool is_on_floor() const;
bool is_on_wall() const;
bool is_on_ceiling() const;

View File

@ -902,7 +902,7 @@ bool PhysicsServerSW::body_is_ray_pickable(RID p_body) const {
return body->is_ray_pickable();
}
bool PhysicsServerSW::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, MotionResult *r_result) {
bool PhysicsServerSW::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result) {
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body, false);
@ -911,7 +911,7 @@ bool PhysicsServerSW::body_test_motion(RID p_body, const Transform &p_from, cons
_update_shapes();
return body->get_space()->test_body_motion(body, p_from, p_motion, body->get_kinematic_margin(), r_result);
return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, body->get_kinematic_margin(), r_result);
}
PhysicsDirectBodyState *PhysicsServerSW::body_get_direct_state(RID p_body) {

View File

@ -225,7 +225,7 @@ public:
virtual void body_set_ray_pickable(RID p_body, bool p_enable);
virtual bool body_is_ray_pickable(RID p_body) const;
virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, MotionResult *r_result = NULL);
virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = NULL);
// this function only works on physics process, errors and returns null otherwise
virtual PhysicsDirectBodyState *body_get_direct_state(RID p_body);

View File

@ -541,7 +541,7 @@ int SpaceSW::_cull_aabb_for_body(BodySW *p_body, const AABB &p_aabb) {
return amount;
}
bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Vector3 &p_motion, real_t p_margin, PhysicsServer::MotionResult *r_result) {
bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer::MotionResult *r_result) {
//give me back regular physics engine logic
//this is madness

View File

@ -197,7 +197,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(BodySW *p_body, const Transform &p_from, const Vector3 &p_motion, real_t p_margin, PhysicsServer::MotionResult *r_result);
bool test_body_motion(BodySW *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer::MotionResult *r_result);
SpaceSW();
~SpaceSW();

View File

@ -962,14 +962,14 @@ void Physics2DServerSW::body_set_pickable(RID p_body, bool p_pickable) {
body->set_pickable(p_pickable);
}
bool Physics2DServerSW::body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin, MotionResult *r_result) {
bool Physics2DServerSW::body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, MotionResult *r_result) {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body, false);
ERR_FAIL_COND_V(!body->get_space(), false);
ERR_FAIL_COND_V(body->get_space()->is_locked(), false);
return body->get_space()->test_body_motion(body, p_from, p_motion, p_margin, r_result);
return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, p_margin, r_result);
}
Physics2DDirectBodyState *Physics2DServerSW::body_get_direct_state(RID p_body) {

View File

@ -232,7 +232,7 @@ public:
virtual void body_set_pickable(RID p_body, bool p_pickable);
virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, real_t p_margin = 0.001, MotionResult *r_result = NULL);
virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = NULL);
// this function only works on physics process, errors and returns null otherwise
virtual Physics2DDirectBodyState *body_get_direct_state(RID p_body);

View File

@ -245,10 +245,10 @@ 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.001, MotionResult *r_result = NULL) {
bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = NULL) {
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);
return physics_2d_server->body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r_result);
}
// this function only works on physics process, errors and returns null otherwise

View File

@ -483,7 +483,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, Physics2DServer::MotionResult *r_result) {
bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, Physics2DServer::MotionResult *r_result) {
//give me back regular physics engine logic
//this is madness
@ -550,6 +550,13 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
const CollisionObject2DSW *col_obj = intersection_query_results[i];
int shape_idx = intersection_query_subindex_results[i];
if (CollisionObject2DSW::TYPE_BODY == col_obj->get_type()) {
const Body2DSW *b = static_cast<const Body2DSW *>(col_obj);
if (p_infinite_inertia && Physics2DServer::BODY_MODE_STATIC != b->get_mode() && Physics2DServer::BODY_MODE_KINEMATIC != b->get_mode()) {
continue;
}
}
if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) {
cbk.valid_dir = body_shape_xform.get_axis(1).normalized();
@ -638,6 +645,13 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
int col_shape_idx = intersection_query_subindex_results[i];
Shape2DSW *against_shape = col_obj->get_shape(col_shape_idx);
if (CollisionObject2DSW::TYPE_BODY == col_obj->get_type()) {
const Body2DSW *b = static_cast<const Body2DSW *>(col_obj);
if (p_infinite_inertia && Physics2DServer::BODY_MODE_STATIC != b->get_mode() && Physics2DServer::BODY_MODE_KINEMATIC != b->get_mode()) {
continue;
}
}
bool excluded = false;
for (int k = 0; k < excluded_shape_pair_count; k++) {
@ -768,6 +782,13 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
const CollisionObject2DSW *col_obj = intersection_query_results[i];
int shape_idx = intersection_query_subindex_results[i];
if (CollisionObject2DSW::TYPE_BODY == col_obj->get_type()) {
const Body2DSW *b = static_cast<const Body2DSW *>(col_obj);
if (p_infinite_inertia && Physics2DServer::BODY_MODE_STATIC != b->get_mode() && Physics2DServer::BODY_MODE_KINEMATIC != b->get_mode()) {
continue;
}
}
Shape2DSW *against_shape = col_obj->get_shape(shape_idx);
bool excluded = false;

View File

@ -182,7 +182,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, Physics2DServer::MotionResult *r_result);
bool test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, Physics2DServer::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.empty(); }

View File

@ -29,6 +29,7 @@
/*************************************************************************/
#include "physics_2d_server.h"
#include "core/method_bind_ext.gen.inc"
#include "core/project_settings.h"
#include "print_string.h"
@ -476,12 +477,12 @@ Physics2DTestMotionResult::Physics2DTestMotionResult() {
///////////////////////////////////////
bool Physics2DServer::_body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, float p_margin, const Ref<Physics2DTestMotionResult> &p_result) {
bool Physics2DServer::_body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, float p_margin, const Ref<Physics2DTestMotionResult> &p_result) {
MotionResult *r = NULL;
if (p_result.is_valid())
r = p_result->get_result_ptr();
return body_test_motion(p_body, p_from, p_motion, p_margin, r);
return body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r);
}
void Physics2DServer::_bind_methods() {
@ -598,7 +599,7 @@ void Physics2DServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_set_force_integration_callback", "body", "receiver", "method", "userdata"), &Physics2DServer::body_set_force_integration_callback, DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "margin", "result"), &Physics2DServer::_body_test_motion, DEFVAL(0.08), DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "infinite_inertia", "margin", "result"), &Physics2DServer::_body_test_motion, DEFVAL(0.08), DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &Physics2DServer::body_get_direct_state);

View File

@ -217,7 +217,7 @@ class Physics2DServer : public Object {
static Physics2DServer *singleton;
virtual bool _body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, float p_margin = 0.08, const Ref<Physics2DTestMotionResult> &p_result = Ref<Physics2DTestMotionResult>());
virtual bool _body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, float p_margin = 0.08, const Ref<Physics2DTestMotionResult> &p_result = Ref<Physics2DTestMotionResult>());
protected:
static void _bind_methods();
@ -479,7 +479,7 @@ public:
Variant collider_metadata;
};
virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, float p_margin = 0.001, MotionResult *r_result = NULL) = 0;
virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, float p_margin = 0.001, MotionResult *r_result = NULL) = 0;
/* JOINT API */

View File

@ -474,7 +474,7 @@ public:
Variant collider_metadata;
};
virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, MotionResult *r_result = NULL) = 0;
virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = NULL) = 0;
/* JOINT API */