Переглянути джерело

Merge pull request #51447 from nekomatata/fix-moving-platform-rotation-3.x

[3.x] Fix applied rotation from moving platforms in move_and_slide
Rémi Verschelde 4 роки тому
батько
коміт
0403cb8ad5

+ 7 - 0
doc/classes/Physics2DDirectBodyState.xml

@@ -137,6 +137,13 @@
 				Returns the current state of the space, useful for queries.
 				Returns the current state of the space, useful for queries.
 			</description>
 			</description>
 		</method>
 		</method>
+		<method name="get_velocity_at_local_position" qualifiers="const">
+			<return type="Vector2" />
+			<argument index="0" name="local_position" type="Vector2" />
+			<description>
+				Returns the body's velocity at the given relative position, including both translation and rotation.
+			</description>
+		</method>
 		<method name="integrate_forces">
 		<method name="integrate_forces">
 			<return type="void" />
 			<return type="void" />
 			<description>
 			<description>

+ 7 - 0
doc/classes/PhysicsDirectBodyState.xml

@@ -138,6 +138,13 @@
 				Returns the current state of the space, useful for queries.
 				Returns the current state of the space, useful for queries.
 			</description>
 			</description>
 		</method>
 		</method>
+		<method name="get_velocity_at_local_position" qualifiers="const">
+			<return type="Vector3" />
+			<argument index="0" name="local_position" type="Vector3" />
+			<description>
+				Returns the body's velocity at the given relative position, including both translation and rotation.
+			</description>
+		</method>
 		<method name="integrate_forces">
 		<method name="integrate_forces">
 			<return type="void" />
 			<return type="void" />
 			<description>
 			<description>

+ 10 - 0
modules/bullet/rigid_body_bullet.cpp

@@ -114,6 +114,16 @@ Transform BulletPhysicsDirectBodyState::get_transform() const {
 	return body->get_transform();
 	return body->get_transform();
 }
 }
 
 
+Vector3 BulletPhysicsDirectBodyState::get_velocity_at_local_position(const Vector3 &p_position) const {
+	btVector3 local_position;
+	G_TO_B(p_position, local_position);
+
+	Vector3 velocity;
+	B_TO_G(body->btBody->getVelocityInLocalPoint(local_position), velocity);
+
+	return velocity;
+}
+
 void BulletPhysicsDirectBodyState::add_central_force(const Vector3 &p_force) {
 void BulletPhysicsDirectBodyState::add_central_force(const Vector3 &p_force) {
 	body->apply_central_force(p_force);
 	body->apply_central_force(p_force);
 }
 }

+ 2 - 0
modules/bullet/rigid_body_bullet.h

@@ -110,6 +110,8 @@ public:
 	virtual void set_transform(const Transform &p_transform);
 	virtual void set_transform(const Transform &p_transform);
 	virtual Transform get_transform() const;
 	virtual Transform get_transform() const;
 
 
+	virtual Vector3 get_velocity_at_local_position(const Vector3 &p_position) const;
+
 	virtual void add_central_force(const Vector3 &p_force);
 	virtual void add_central_force(const Vector3 &p_force);
 	virtual void add_force(const Vector3 &p_force, const Vector3 &p_pos);
 	virtual void add_force(const Vector3 &p_force, const Vector3 &p_pos);
 	virtual void add_torque(const Vector3 &p_torque);
 	virtual void add_torque(const Vector3 &p_torque);

+ 3 - 1
scene/2d/physics_body_2d.cpp

@@ -1115,7 +1115,9 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const
 		//this approach makes sure there is less delay between the actual body velocity and the one we saved
 		//this approach makes sure there is less delay between the actual body velocity and the one we saved
 		Physics2DDirectBodyState *bs = Physics2DServer::get_singleton()->body_get_direct_state(on_floor_body);
 		Physics2DDirectBodyState *bs = Physics2DServer::get_singleton()->body_get_direct_state(on_floor_body);
 		if (bs) {
 		if (bs) {
-			current_floor_velocity = bs->get_linear_velocity();
+			Transform2D gt = get_global_transform();
+			Vector2 local_position = gt.elements[2] - bs->get_transform().elements[2];
+			current_floor_velocity = bs->get_velocity_at_local_position(local_position);
 		}
 		}
 	}
 	}
 
 

+ 3 - 1
scene/3d/physics_body.cpp

@@ -1066,7 +1066,9 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve
 		// This approach makes sure there is less delay between the actual body velocity and the one we saved.
 		// 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);
 		PhysicsDirectBodyState *bs = PhysicsServer::get_singleton()->body_get_direct_state(on_floor_body);
 		if (bs) {
 		if (bs) {
-			current_floor_velocity = bs->get_linear_velocity();
+			Transform gt = get_global_transform();
+			Vector3 local_position = gt.origin - bs->get_transform().origin;
+			current_floor_velocity = bs->get_velocity_at_local_position(local_position);
 		}
 		}
 	}
 	}
 
 

+ 2 - 0
servers/physics/body_sw.h

@@ -402,6 +402,8 @@ public:
 	virtual void set_transform(const Transform &p_transform) { body->set_state(PhysicsServer::BODY_STATE_TRANSFORM, p_transform); }
 	virtual void set_transform(const Transform &p_transform) { body->set_state(PhysicsServer::BODY_STATE_TRANSFORM, p_transform); }
 	virtual Transform get_transform() const { return body->get_transform(); }
 	virtual Transform get_transform() const { return body->get_transform(); }
 
 
+	virtual Vector3 get_velocity_at_local_position(const Vector3 &p_position) const { return body->get_velocity_in_local_point(p_position); }
+
 	virtual void add_central_force(const Vector3 &p_force) { body->add_central_force(p_force); }
 	virtual void add_central_force(const Vector3 &p_force) { body->add_central_force(p_force); }
 	virtual void add_force(const Vector3 &p_force, const Vector3 &p_pos) { body->add_force(p_force, p_pos); }
 	virtual void add_force(const Vector3 &p_force, const Vector3 &p_pos) { body->add_force(p_force, p_pos); }
 	virtual void add_torque(const Vector3 &p_torque) { body->add_torque(p_torque); }
 	virtual void add_torque(const Vector3 &p_torque) { body->add_torque(p_torque); }

+ 6 - 0
servers/physics_2d/body_2d_sw.h

@@ -273,6 +273,10 @@ public:
 	void integrate_forces(real_t p_step);
 	void integrate_forces(real_t p_step);
 	void integrate_velocities(real_t p_step);
 	void integrate_velocities(real_t p_step);
 
 
+	_FORCE_INLINE_ Vector2 get_velocity_in_local_point(const Vector2 &rel_pos) const {
+		return linear_velocity + Vector2(-angular_velocity * rel_pos.y, angular_velocity * rel_pos.x);
+	}
+
 	_FORCE_INLINE_ Vector2 get_motion() const {
 	_FORCE_INLINE_ Vector2 get_motion() const {
 		if (mode > Physics2DServer::BODY_MODE_KINEMATIC) {
 		if (mode > Physics2DServer::BODY_MODE_KINEMATIC) {
 			return new_transform.get_origin() - get_transform().get_origin();
 			return new_transform.get_origin() - get_transform().get_origin();
@@ -359,6 +363,8 @@ public:
 	virtual void set_transform(const Transform2D &p_transform) { body->set_state(Physics2DServer::BODY_STATE_TRANSFORM, p_transform); }
 	virtual void set_transform(const Transform2D &p_transform) { body->set_state(Physics2DServer::BODY_STATE_TRANSFORM, p_transform); }
 	virtual Transform2D get_transform() const { return body->get_transform(); }
 	virtual Transform2D get_transform() const { return body->get_transform(); }
 
 
+	virtual Vector2 get_velocity_at_local_position(const Vector2 &p_position) const { return body->get_velocity_in_local_point(p_position); }
+
 	virtual void add_central_force(const Vector2 &p_force) { body->add_central_force(p_force); }
 	virtual void add_central_force(const Vector2 &p_force) { body->add_central_force(p_force); }
 	virtual void add_force(const Vector2 &p_offset, const Vector2 &p_force) { body->add_force(p_offset, p_force); }
 	virtual void add_force(const Vector2 &p_offset, const Vector2 &p_force) { body->add_force(p_offset, p_force); }
 	virtual void add_torque(real_t p_torque) { body->add_torque(p_torque); }
 	virtual void add_torque(real_t p_torque) { body->add_torque(p_torque); }

+ 2 - 0
servers/physics_2d_server.cpp

@@ -90,6 +90,8 @@ void Physics2DDirectBodyState::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_transform", "transform"), &Physics2DDirectBodyState::set_transform);
 	ClassDB::bind_method(D_METHOD("set_transform", "transform"), &Physics2DDirectBodyState::set_transform);
 	ClassDB::bind_method(D_METHOD("get_transform"), &Physics2DDirectBodyState::get_transform);
 	ClassDB::bind_method(D_METHOD("get_transform"), &Physics2DDirectBodyState::get_transform);
 
 
+	ClassDB::bind_method(D_METHOD("get_velocity_at_local_position", "local_position"), &Physics2DDirectBodyState::get_velocity_at_local_position);
+
 	ClassDB::bind_method(D_METHOD("add_central_force", "force"), &Physics2DDirectBodyState::add_central_force);
 	ClassDB::bind_method(D_METHOD("add_central_force", "force"), &Physics2DDirectBodyState::add_central_force);
 	ClassDB::bind_method(D_METHOD("add_force", "offset", "force"), &Physics2DDirectBodyState::add_force);
 	ClassDB::bind_method(D_METHOD("add_force", "offset", "force"), &Physics2DDirectBodyState::add_force);
 	ClassDB::bind_method(D_METHOD("add_torque", "torque"), &Physics2DDirectBodyState::add_torque);
 	ClassDB::bind_method(D_METHOD("add_torque", "torque"), &Physics2DDirectBodyState::add_torque);

+ 2 - 0
servers/physics_2d_server.h

@@ -60,6 +60,8 @@ public:
 	virtual void set_transform(const Transform2D &p_transform) = 0;
 	virtual void set_transform(const Transform2D &p_transform) = 0;
 	virtual Transform2D get_transform() const = 0;
 	virtual Transform2D get_transform() const = 0;
 
 
+	virtual Vector2 get_velocity_at_local_position(const Vector2 &p_position) const = 0;
+
 	virtual void add_central_force(const Vector2 &p_force) = 0;
 	virtual void add_central_force(const Vector2 &p_force) = 0;
 	virtual void add_force(const Vector2 &p_offset, const Vector2 &p_force) = 0;
 	virtual void add_force(const Vector2 &p_offset, const Vector2 &p_force) = 0;
 	virtual void add_torque(real_t p_torque) = 0;
 	virtual void add_torque(real_t p_torque) = 0;

+ 2 - 0
servers/physics_server.cpp

@@ -92,6 +92,8 @@ void PhysicsDirectBodyState::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_transform", "transform"), &PhysicsDirectBodyState::set_transform);
 	ClassDB::bind_method(D_METHOD("set_transform", "transform"), &PhysicsDirectBodyState::set_transform);
 	ClassDB::bind_method(D_METHOD("get_transform"), &PhysicsDirectBodyState::get_transform);
 	ClassDB::bind_method(D_METHOD("get_transform"), &PhysicsDirectBodyState::get_transform);
 
 
+	ClassDB::bind_method(D_METHOD("get_velocity_at_local_position", "local_position"), &PhysicsDirectBodyState::get_velocity_at_local_position);
+
 	ClassDB::bind_method(D_METHOD("add_central_force", "force"), &PhysicsDirectBodyState::add_central_force);
 	ClassDB::bind_method(D_METHOD("add_central_force", "force"), &PhysicsDirectBodyState::add_central_force);
 	ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &PhysicsDirectBodyState::add_force);
 	ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &PhysicsDirectBodyState::add_force);
 	ClassDB::bind_method(D_METHOD("add_torque", "torque"), &PhysicsDirectBodyState::add_torque);
 	ClassDB::bind_method(D_METHOD("add_torque", "torque"), &PhysicsDirectBodyState::add_torque);

+ 2 - 0
servers/physics_server.h

@@ -62,6 +62,8 @@ public:
 	virtual void set_transform(const Transform &p_transform) = 0;
 	virtual void set_transform(const Transform &p_transform) = 0;
 	virtual Transform get_transform() const = 0;
 	virtual Transform get_transform() const = 0;
 
 
+	virtual Vector3 get_velocity_at_local_position(const Vector3 &p_position) const = 0;
+
 	virtual void add_central_force(const Vector3 &p_force) = 0;
 	virtual void add_central_force(const Vector3 &p_force) = 0;
 	virtual void add_force(const Vector3 &p_force, const Vector3 &p_pos) = 0;
 	virtual void add_force(const Vector3 &p_force, const Vector3 &p_pos) = 0;
 	virtual void add_torque(const Vector3 &p_torque) = 0;
 	virtual void add_torque(const Vector3 &p_torque) = 0;