Merge pull request #51458 from nekomatata/moving-platforms-3d-3.x
[3.x] Fix 3D moving platform logic
This commit is contained in:
commit
03c41fa34c
18 changed files with 111 additions and 56 deletions
|
@ -95,6 +95,7 @@
|
|||
[code]floor_max_angle[/code] is the maximum angle (in radians) where a slope is still considered a floor (or a ceiling), rather than a wall. The default value equals 45 degrees.
|
||||
If [code]infinite_inertia[/code] is [code]true[/code], body will be able to push [RigidBody] nodes, but it won't also detect any collisions with them. If [code]false[/code], it will interact with [RigidBody] nodes like with [StaticBody].
|
||||
Returns the [code]linear_velocity[/code] vector, rotated and/or scaled if a slide collision occurred. To get detailed information about collisions that occurred, use [method get_slide_collision].
|
||||
When the body touches a moving platform, the platform's velocity is automatically added to the body motion. If a collision occurs due to the platform's motion, it will always be first in the slide collisions.
|
||||
</description>
|
||||
</method>
|
||||
<method name="move_and_slide_with_snap">
|
||||
|
|
|
@ -93,6 +93,7 @@
|
|||
[code]floor_max_angle[/code] is the maximum angle (in radians) where a slope is still considered a floor (or a ceiling), rather than a wall. The default value equals 45 degrees.
|
||||
If [code]infinite_inertia[/code] is [code]true[/code], body will be able to push [RigidBody2D] nodes, but it won't also detect any collisions with them. If [code]false[/code], it will interact with [RigidBody2D] nodes like with [StaticBody2D].
|
||||
Returns the [code]linear_velocity[/code] vector, rotated and/or scaled if a slide collision occurred. To get detailed information about collisions that occurred, use [method get_slide_collision].
|
||||
When the body touches a moving platform, the platform's velocity is automatically added to the body motion. If a collision occurs due to the platform's motion, it will always be first in the slide collisions.
|
||||
</description>
|
||||
</method>
|
||||
<method name="move_and_slide_with_snap">
|
||||
|
|
|
@ -602,6 +602,8 @@
|
|||
<argument index="2" name="motion" type="Vector3" />
|
||||
<argument index="3" name="infinite_inertia" type="bool" />
|
||||
<argument index="4" name="result" type="PhysicsTestMotionResult" default="null" />
|
||||
<argument index="5" name="exclude_raycast_shapes" type="bool" default="true" />
|
||||
<argument index="6" name="exclude" type="Array" default="[ ]" />
|
||||
<description>
|
||||
Returns [code]true[/code] if a collision would result from moving in the given direction from a given point in space. [PhysicsTestMotionResult] can be passed to return additional information in.
|
||||
</description>
|
||||
|
|
|
@ -856,12 +856,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, bool p_infinite_inertia, MotionResult *r_result, bool p_exclude_raycast_shapes) {
|
||||
bool BulletPhysicsServer::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result, bool p_exclude_raycast_shapes, const Set<RID> &p_exclude) {
|
||||
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, p_infinite_inertia, r_result, p_exclude_raycast_shapes);
|
||||
return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, r_result, p_exclude_raycast_shapes, p_exclude);
|
||||
}
|
||||
|
||||
int BulletPhysicsServer::body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin) {
|
||||
|
|
|
@ -254,7 +254,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, bool p_infinite_inertia, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true);
|
||||
virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true, const Set<RID> &p_exclude = Set<RID>());
|
||||
virtual int body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001);
|
||||
|
||||
/* SOFT BODY API */
|
||||
|
|
|
@ -142,6 +142,10 @@ bool GodotKinClosestConvexResultCallback::needsCollision(btBroadphaseProxy *prox
|
|||
if (m_self_object->has_collision_exception(gObj) || gObj->has_collision_exception(m_self_object)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_exclude->has(gObj->get_self())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
|
|
|
@ -105,11 +105,13 @@ public:
|
|||
struct GodotKinClosestConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback {
|
||||
public:
|
||||
const RigidBodyBullet *m_self_object;
|
||||
const Set<RID> *m_exclude;
|
||||
const bool m_infinite_inertia;
|
||||
|
||||
GodotKinClosestConvexResultCallback(const btVector3 &convexFromWorld, const btVector3 &convexToWorld, const RigidBodyBullet *p_self_object, bool p_infinite_inertia) :
|
||||
GodotKinClosestConvexResultCallback(const btVector3 &convexFromWorld, const btVector3 &convexToWorld, const RigidBodyBullet *p_self_object, bool p_infinite_inertia, const Set<RID> *p_exclude) :
|
||||
btCollisionWorld::ClosestConvexResultCallback(convexFromWorld, convexToWorld),
|
||||
m_self_object(p_self_object),
|
||||
m_exclude(p_exclude),
|
||||
m_infinite_inertia(p_infinite_inertia) {}
|
||||
|
||||
virtual bool needsCollision(btBroadphaseProxy *proxy0) const;
|
||||
|
|
|
@ -928,7 +928,7 @@ static Ref<SpatialMaterial> red_mat;
|
|||
static Ref<SpatialMaterial> blue_mat;
|
||||
#endif
|
||||
|
||||
bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer::MotionResult *r_result, bool p_exclude_raycast_shapes) {
|
||||
bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer::MotionResult *r_result, bool p_exclude_raycast_shapes, const Set<RID> &p_exclude) {
|
||||
#if debug_test_motion
|
||||
/// Yes I know this is not good, but I've used it as fast debugging hack.
|
||||
/// I'm leaving it here just for speedup the other eventual debugs
|
||||
|
@ -968,7 +968,7 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f
|
|||
btVector3 initial_recover_motion(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_transform, RECOVERING_MOVEMENT_SCALE, p_infinite_inertia, initial_recover_motion)) {
|
||||
if (!recover_from_penetration(p_body, body_transform, RECOVERING_MOVEMENT_SCALE, p_infinite_inertia, initial_recover_motion, nullptr, p_exclude)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1020,7 +1020,7 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f
|
|||
break;
|
||||
}
|
||||
|
||||
GodotKinClosestConvexResultCallback btResult(shape_world_from.getOrigin(), shape_world_to.getOrigin(), p_body, p_infinite_inertia);
|
||||
GodotKinClosestConvexResultCallback btResult(shape_world_from.getOrigin(), shape_world_to.getOrigin(), p_body, p_infinite_inertia, &p_exclude);
|
||||
btResult.m_collisionFilterGroup = p_body->get_collision_layer();
|
||||
btResult.m_collisionFilterMask = p_body->get_collision_mask();
|
||||
|
||||
|
@ -1043,7 +1043,7 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f
|
|||
btVector3 __rec(0, 0, 0);
|
||||
RecoverResult r_recover_result;
|
||||
|
||||
has_penetration = recover_from_penetration(p_body, body_transform, 1, p_infinite_inertia, __rec, &r_recover_result);
|
||||
has_penetration = recover_from_penetration(p_body, body_transform, 1, p_infinite_inertia, __rec, &r_recover_result, p_exclude);
|
||||
|
||||
// Parse results
|
||||
if (r_result) {
|
||||
|
@ -1195,7 +1195,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
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) {
|
||||
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, const Set<RID> &p_exclude) {
|
||||
// Calculate the cumulative AABB of all shapes of the kinematic body
|
||||
btVector3 aabb_min, aabb_max;
|
||||
bool shapes_found = false;
|
||||
|
@ -1264,6 +1264,12 @@ bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTran
|
|||
|
||||
for (int i = recover_broad_result.results.size() - 1; 0 <= i; --i) {
|
||||
btCollisionObject *otherObject = recover_broad_result.results[i].collision_object;
|
||||
|
||||
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(otherObject->getUserPointer());
|
||||
if (p_exclude.has(gObj->get_self())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (p_infinite_inertia && !otherObject->isStaticOrKinematicObject()) {
|
||||
otherObject->activate(); // Force activation of hitten rigid, soft body
|
||||
continue;
|
||||
|
|
|
@ -185,7 +185,7 @@ public:
|
|||
real_t get_linear_damp() const { return linear_damp; }
|
||||
real_t get_angular_damp() const { return angular_damp; }
|
||||
|
||||
bool test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer::MotionResult *r_result, bool p_exclude_raycast_shapes);
|
||||
bool test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer::MotionResult *r_result, bool p_exclude_raycast_shapes, const Set<RID> &p_exclude = Set<RID>());
|
||||
int test_ray_separation(RigidBodyBullet *p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer::SeparationResult *r_results, int p_result_max, float p_margin);
|
||||
|
||||
private:
|
||||
|
@ -213,7 +213,7 @@ private:
|
|||
local_shape_most_recovered(0) {}
|
||||
};
|
||||
|
||||
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 = nullptr);
|
||||
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 = nullptr, const Set<RID> &p_exclude = Set<RID>());
|
||||
/// 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_A, 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 = nullptr);
|
||||
|
|
|
@ -1128,7 +1128,7 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const
|
|||
floor_normal = Vector2();
|
||||
floor_velocity = Vector2();
|
||||
|
||||
if (current_floor_velocity != Vector2()) {
|
||||
if (current_floor_velocity != Vector2() && on_floor_body.is_valid()) {
|
||||
Collision floor_collision;
|
||||
Set<RID> exclude;
|
||||
exclude.insert(on_floor_body);
|
||||
|
|
|
@ -973,14 +973,14 @@ Ref<KinematicCollision> KinematicBody::_move(const Vector3 &p_motion, bool p_inf
|
|||
return Ref<KinematicCollision>();
|
||||
}
|
||||
|
||||
bool KinematicBody::move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes, bool p_test_only, bool p_cancel_sliding) {
|
||||
bool KinematicBody::move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes, bool p_test_only, bool p_cancel_sliding, const Set<RID> &p_exclude) {
|
||||
if (sync_to_physics) {
|
||||
ERR_PRINT("Functions move_and_slide and move_and_collide do not work together with 'sync to physics' option. Please read the documentation.");
|
||||
}
|
||||
|
||||
Transform gt = get_global_transform();
|
||||
PhysicsServer::MotionResult result;
|
||||
bool colliding = PhysicsServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, &result, p_exclude_raycast_shapes);
|
||||
bool colliding = PhysicsServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, &result, p_exclude_raycast_shapes, p_exclude);
|
||||
|
||||
// Restore direction of motion to be along original motion,
|
||||
// in order to avoid sliding due to recovery,
|
||||
|
@ -1061,8 +1061,11 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve
|
|||
}
|
||||
}
|
||||
|
||||
// Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky
|
||||
float delta = Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time();
|
||||
|
||||
Vector3 current_floor_velocity = floor_velocity;
|
||||
if (on_floor && on_floor_body.is_valid()) {
|
||||
if ((on_floor || on_wall) && on_floor_body.is_valid()) {
|
||||
// This approach makes sure there is less delay between the actual body velocity and the one we saved.
|
||||
PhysicsDirectBodyState *bs = PhysicsServer::get_singleton()->body_get_direct_state(on_floor_body);
|
||||
if (bs) {
|
||||
|
@ -1072,17 +1075,26 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve
|
|||
}
|
||||
}
|
||||
|
||||
// Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky
|
||||
Vector3 motion = (current_floor_velocity + body_velocity) * (Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time());
|
||||
|
||||
colliders.clear();
|
||||
on_floor = false;
|
||||
on_floor_body = RID();
|
||||
on_ceiling = false;
|
||||
on_wall = false;
|
||||
colliders.clear();
|
||||
floor_normal = Vector3();
|
||||
floor_velocity = Vector3();
|
||||
|
||||
if (current_floor_velocity != Vector3() && on_floor_body.is_valid()) {
|
||||
Collision floor_collision;
|
||||
Set<RID> exclude;
|
||||
exclude.insert(on_floor_body);
|
||||
if (move_and_collide(current_floor_velocity * delta, p_infinite_inertia, floor_collision, true, false, false, exclude)) {
|
||||
colliders.push_back(floor_collision);
|
||||
_set_collision_direction(floor_collision, up_direction, p_floor_max_angle);
|
||||
}
|
||||
}
|
||||
|
||||
on_floor_body = RID();
|
||||
Vector3 motion = body_velocity * delta;
|
||||
|
||||
// No sliding on first attempt to keep floor motion stable when possible,
|
||||
// when stop on slope is enabled.
|
||||
bool sliding_enabled = !p_stop_on_slope;
|
||||
|
@ -1110,33 +1122,18 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve
|
|||
|
||||
colliders.push_back(collision);
|
||||
|
||||
if (up_direction == Vector3()) {
|
||||
//all is a wall
|
||||
on_wall = true;
|
||||
} else {
|
||||
if (Math::acos(collision.normal.dot(up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
|
||||
_set_collision_direction(collision, up_direction, p_floor_max_angle);
|
||||
|
||||
on_floor = true;
|
||||
floor_normal = collision.normal;
|
||||
on_floor_body = collision.collider_rid;
|
||||
floor_velocity = collision.collider_vel;
|
||||
|
||||
if (p_stop_on_slope) {
|
||||
if ((body_velocity_normal + up_direction).length() < 0.01) {
|
||||
Transform gt = get_global_transform();
|
||||
if (collision.travel.length() > margin) {
|
||||
gt.origin -= collision.travel.slide(up_direction);
|
||||
} else {
|
||||
gt.origin -= collision.travel;
|
||||
}
|
||||
set_global_transform(gt);
|
||||
return Vector3();
|
||||
}
|
||||
if (on_floor && p_stop_on_slope) {
|
||||
if ((body_velocity_normal + up_direction).length() < 0.01) {
|
||||
Transform gt = get_global_transform();
|
||||
if (collision.travel.length() > margin) {
|
||||
gt.origin -= collision.travel.slide(up_direction);
|
||||
} else {
|
||||
gt.origin -= collision.travel;
|
||||
}
|
||||
} else if (Math::acos(collision.normal.dot(-up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
|
||||
on_ceiling = true;
|
||||
} else {
|
||||
on_wall = true;
|
||||
set_global_transform(gt);
|
||||
return Vector3();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1162,6 +1159,11 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve
|
|||
}
|
||||
}
|
||||
|
||||
if (!on_floor && !on_wall) {
|
||||
// Add last platform velocity when just left a moving platform.
|
||||
return body_velocity + current_floor_velocity;
|
||||
}
|
||||
|
||||
return body_velocity;
|
||||
}
|
||||
|
||||
|
@ -1207,6 +1209,29 @@ Vector3 KinematicBody::move_and_slide_with_snap(const Vector3 &p_linear_velocity
|
|||
return ret;
|
||||
}
|
||||
|
||||
void KinematicBody::_set_collision_direction(const Collision &p_collision, const Vector3 &p_up_direction, float p_floor_max_angle) {
|
||||
on_floor = false;
|
||||
on_ceiling = false;
|
||||
on_wall = false;
|
||||
if (p_up_direction == Vector3()) {
|
||||
//all is a wall
|
||||
on_wall = true;
|
||||
} else {
|
||||
if (Math::acos(p_collision.normal.dot(p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
|
||||
on_floor = true;
|
||||
floor_normal = p_collision.normal;
|
||||
on_floor_body = p_collision.collider_rid;
|
||||
floor_velocity = p_collision.collider_vel;
|
||||
} else if (Math::acos(p_collision.normal.dot(-p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
|
||||
on_ceiling = true;
|
||||
} else {
|
||||
on_wall = true;
|
||||
on_floor_body = p_collision.collider_rid;
|
||||
floor_velocity = p_collision.collider_vel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool KinematicBody::is_on_floor() const {
|
||||
return on_floor;
|
||||
}
|
||||
|
|
|
@ -300,13 +300,14 @@ private:
|
|||
|
||||
Transform last_valid_transform;
|
||||
void _direct_state_changed(Object *p_state);
|
||||
void _set_collision_direction(const Collision &p_collision, const Vector3 &p_up_direction, float p_floor_max_angle);
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
bool move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes = true, bool p_test_only = false, bool p_cancel_sliding = true);
|
||||
bool move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes = true, bool p_test_only = false, bool p_cancel_sliding = true, const Set<RID> &p_exclude = Set<RID>());
|
||||
bool test_move(const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia);
|
||||
|
||||
bool separate_raycast_shapes(bool p_infinite_inertia, Collision &r_collision);
|
||||
|
|
|
@ -860,7 +860,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, bool p_infinite_inertia, MotionResult *r_result, bool p_exclude_raycast_shapes) {
|
||||
bool PhysicsServerSW::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result, bool p_exclude_raycast_shapes, const Set<RID> &p_exclude) {
|
||||
BodySW *body = body_owner.get(p_body);
|
||||
ERR_FAIL_COND_V(!body, false);
|
||||
ERR_FAIL_COND_V(!body->get_space(), false);
|
||||
|
@ -868,7 +868,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, p_infinite_inertia, body->get_kinematic_margin(), r_result, p_exclude_raycast_shapes);
|
||||
return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, body->get_kinematic_margin(), r_result, p_exclude_raycast_shapes, p_exclude);
|
||||
}
|
||||
|
||||
int PhysicsServerSW::body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin) {
|
||||
|
|
|
@ -233,7 +233,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, bool p_infinite_inertia, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true);
|
||||
virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true, const Set<RID> &p_exclude = Set<RID>());
|
||||
virtual int body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001);
|
||||
|
||||
// this function only works on physics process, errors and returns null otherwise
|
||||
|
|
|
@ -712,7 +712,7 @@ int SpaceSW::test_body_ray_separation(BodySW *p_body, const Transform &p_transfo
|
|||
return rays_found;
|
||||
}
|
||||
|
||||
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, bool p_exclude_raycast_shapes) {
|
||||
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, bool p_exclude_raycast_shapes, const Set<RID> &p_exclude) {
|
||||
//give me back regular physics engine logic
|
||||
//this is madness
|
||||
//and most people using this function will think
|
||||
|
@ -793,6 +793,9 @@ bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Ve
|
|||
|
||||
for (int i = 0; i < amount; i++) {
|
||||
const CollisionObjectSW *col_obj = intersection_query_results[i];
|
||||
if (p_exclude.has(col_obj->get_self())) {
|
||||
continue;
|
||||
}
|
||||
int shape_idx = intersection_query_subindex_results[i];
|
||||
|
||||
if (CollisionObjectSW::TYPE_BODY == col_obj->get_type()) {
|
||||
|
@ -882,6 +885,9 @@ bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Ve
|
|||
|
||||
for (int i = 0; i < amount; i++) {
|
||||
const CollisionObjectSW *col_obj = intersection_query_results[i];
|
||||
if (p_exclude.has(col_obj->get_self())) {
|
||||
continue;
|
||||
}
|
||||
int shape_idx = intersection_query_subindex_results[i];
|
||||
|
||||
if (CollisionObjectSW::TYPE_BODY == col_obj->get_type()) {
|
||||
|
@ -1008,6 +1014,9 @@ bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Ve
|
|||
|
||||
for (int i = 0; i < amount; i++) {
|
||||
const CollisionObjectSW *col_obj = intersection_query_results[i];
|
||||
if (p_exclude.has(col_obj->get_self())) {
|
||||
continue;
|
||||
}
|
||||
int shape_idx = intersection_query_subindex_results[i];
|
||||
|
||||
if (CollisionObjectSW::TYPE_BODY == col_obj->get_type()) {
|
||||
|
|
|
@ -199,7 +199,7 @@ public:
|
|||
uint64_t get_elapsed_time(ElapsedTime p_time) const { return elapsed_time[p_time]; }
|
||||
|
||||
int test_body_ray_separation(BodySW *p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer::SeparationResult *r_results, int p_result_max, real_t p_margin);
|
||||
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, bool p_exclude_raycast_shapes);
|
||||
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, bool p_exclude_raycast_shapes, const Set<RID> &p_exclude = Set<RID>());
|
||||
|
||||
SpaceSW();
|
||||
~SpaceSW();
|
||||
|
|
|
@ -436,12 +436,16 @@ void PhysicsTestMotionResult::_bind_methods() {
|
|||
|
||||
///////////////////////////////////////
|
||||
|
||||
bool PhysicsServer::_body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, const Ref<PhysicsTestMotionResult> &p_result) {
|
||||
bool PhysicsServer::_body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, const Ref<PhysicsTestMotionResult> &p_result, bool p_exclude_raycast_shapes, const Vector<RID> &p_exclude) {
|
||||
MotionResult *r = nullptr;
|
||||
if (p_result.is_valid()) {
|
||||
r = p_result->get_result_ptr();
|
||||
}
|
||||
return body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, r);
|
||||
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_infinite_inertia, r, p_exclude_raycast_shapes, exclude);
|
||||
}
|
||||
|
||||
void PhysicsServer::_bind_methods() {
|
||||
|
@ -565,7 +569,7 @@ void PhysicsServer::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("body_set_ray_pickable", "body", "enable"), &PhysicsServer::body_set_ray_pickable);
|
||||
ClassDB::bind_method(D_METHOD("body_is_ray_pickable", "body"), &PhysicsServer::body_is_ray_pickable);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "infinite_inertia", "result"), &PhysicsServer::_body_test_motion, DEFVAL(Variant()));
|
||||
ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "infinite_inertia", "result", "exclude_raycast_shapes", "exclude"), &PhysicsServer::_body_test_motion, DEFVAL(Variant()), DEFVAL(true), DEFVAL(Array()));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &PhysicsServer::body_get_direct_state);
|
||||
|
||||
|
|
|
@ -201,7 +201,7 @@ class PhysicsServer : public Object {
|
|||
|
||||
static PhysicsServer *singleton;
|
||||
|
||||
virtual bool _body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, const Ref<PhysicsTestMotionResult> &p_result = Ref<PhysicsTestMotionResult>());
|
||||
virtual bool _body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, const Ref<PhysicsTestMotionResult> &p_result = Ref<PhysicsTestMotionResult>(), bool p_exclude_raycast_shapes = true, const Vector<RID> &p_exclude = Vector<RID>());
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
@ -473,7 +473,7 @@ public:
|
|||
Variant collider_metadata;
|
||||
};
|
||||
|
||||
virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) = 0;
|
||||
virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true, const Set<RID> &p_exclude = Set<RID>()) = 0;
|
||||
|
||||
struct SeparationResult {
|
||||
float collision_depth;
|
||||
|
|
Loading…
Reference in a new issue