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

make 2d constraint solving more deterministic by solving in push order

(cherry picked from commit 043b6c2d93a560209fcd59fbff6de083659835bc)
Jordan Schidlowsky 4 роки тому
батько
коміт
266314ba26

+ 1 - 1
servers/physics_2d/area_pair_2d_sw.cpp

@@ -89,7 +89,7 @@ AreaPair2DSW::~AreaPair2DSW() {
 		if (area->has_monitor_callback())
 			area->remove_body_from_query(body, body_shape, area_shape);
 	}
-	body->remove_constraint(this);
+	body->remove_constraint(this, 0);
 	area->remove_constraint(this);
 }
 

+ 3 - 6
servers/physics_2d/body_2d_sw.cpp

@@ -576,16 +576,13 @@ void Body2DSW::integrate_velocities(real_t p_step) {
 }
 
 void Body2DSW::wakeup_neighbours() {
-
-	for (Map<Constraint2DSW *, int>::Element *E = constraint_map.front(); E; E = E->next()) {
-
-		const Constraint2DSW *c = E->key();
+	for (List<Pair<Constraint2DSW *, int> >::Element *E = constraint_list.front(); E; E = E->next()) {
+		const Constraint2DSW *c = E->get().first;
 		Body2DSW **n = c->get_body_ptr();
 		int bc = c->get_body_count();
 
 		for (int i = 0; i < bc; i++) {
-
-			if (i == E->get())
+			if (i == E->get().second)
 				continue;
 			Body2DSW *b = n[i];
 			if (b->mode != Physics2DServer::BODY_MODE_RIGID)

+ 7 - 5
servers/physics_2d/body_2d_sw.h

@@ -33,6 +33,8 @@
 
 #include "area_2d_sw.h"
 #include "collision_object_2d_sw.h"
+#include "core/list.h"
+#include "core/pair.h"
 #include "core/vset.h"
 
 class Constraint2DSW;
@@ -84,7 +86,7 @@ class Body2DSW : public CollisionObject2DSW {
 	virtual void _shapes_changed();
 	Transform2D new_transform;
 
-	Map<Constraint2DSW *, int> constraint_map;
+	List<Pair<Constraint2DSW *, int> > constraint_list;
 
 	struct AreaCMP {
 
@@ -180,10 +182,10 @@ public:
 	_FORCE_INLINE_ Body2DSW *get_island_list_next() const { return island_list_next; }
 	_FORCE_INLINE_ void set_island_list_next(Body2DSW *p_next) { island_list_next = p_next; }
 
-	_FORCE_INLINE_ void add_constraint(Constraint2DSW *p_constraint, int p_pos) { constraint_map[p_constraint] = p_pos; }
-	_FORCE_INLINE_ void remove_constraint(Constraint2DSW *p_constraint) { constraint_map.erase(p_constraint); }
-	const Map<Constraint2DSW *, int> &get_constraint_map() const { return constraint_map; }
-	_FORCE_INLINE_ void clear_constraint_map() { constraint_map.clear(); }
+	_FORCE_INLINE_ void add_constraint(Constraint2DSW *p_constraint, int p_pos) { constraint_list.push_back({ p_constraint, p_pos }); }
+	_FORCE_INLINE_ void remove_constraint(Constraint2DSW *p_constraint, int p_pos) { constraint_list.erase({ p_constraint, p_pos }); }
+	const List<Pair<Constraint2DSW *, int> > &get_constraint_list() const { return constraint_list; }
+	_FORCE_INLINE_ void clear_constraint_list() { constraint_list.clear(); }
 
 	_FORCE_INLINE_ void set_omit_force_integration(bool p_omit_force_integration) { omit_force_integration = p_omit_force_integration; }
 	_FORCE_INLINE_ bool get_omit_force_integration() const { return omit_force_integration; }

+ 2 - 3
servers/physics_2d/body_pair_2d_sw.cpp

@@ -516,7 +516,6 @@ BodyPair2DSW::BodyPair2DSW(Body2DSW *p_A, int p_shape_A, Body2DSW *p_B, int p_sh
 }
 
 BodyPair2DSW::~BodyPair2DSW() {
-
-	A->remove_constraint(this);
-	B->remove_constraint(this);
+	A->remove_constraint(this, 0);
+	B->remove_constraint(this, 1);
 }

+ 10 - 11
servers/physics_2d/joints_2d_sw.cpp

@@ -204,11 +204,12 @@ PinJoint2DSW::PinJoint2DSW(const Vector2 &p_pos, Body2DSW *p_body_a, Body2DSW *p
 }
 
 PinJoint2DSW::~PinJoint2DSW() {
-
-	if (A)
-		A->remove_constraint(this);
-	if (B)
-		B->remove_constraint(this);
+	if (A) {
+		A->remove_constraint(this, 0);
+	}
+	if (B) {
+		B->remove_constraint(this, 1);
+	}
 }
 
 //////////////////////////////////////////////
@@ -350,9 +351,8 @@ GrooveJoint2DSW::GrooveJoint2DSW(const Vector2 &p_a_groove1, const Vector2 &p_a_
 }
 
 GrooveJoint2DSW::~GrooveJoint2DSW() {
-
-	A->remove_constraint(this);
-	B->remove_constraint(this);
+	A->remove_constraint(this, 0);
+	B->remove_constraint(this, 1);
 }
 
 //////////////////////////////////////////////
@@ -463,7 +463,6 @@ DampedSpringJoint2DSW::DampedSpringJoint2DSW(const Vector2 &p_anchor_a, const Ve
 }
 
 DampedSpringJoint2DSW::~DampedSpringJoint2DSW() {
-
-	A->remove_constraint(this);
-	B->remove_constraint(this);
+	A->remove_constraint(this, 0);
+	B->remove_constraint(this, 1);
 }

+ 1 - 1
servers/physics_2d/physics_2d_server_sw.cpp

@@ -598,7 +598,7 @@ void Physics2DServerSW::body_set_space(RID p_body, RID p_space) {
 	if (body->get_space() == space)
 		return; //pointless
 
-	body->clear_constraint_map();
+	body->clear_constraint_list();
 	body->set_space(space);
 };
 

+ 3 - 4
servers/physics_2d/step_2d_sw.cpp

@@ -37,9 +37,8 @@ void Step2DSW::_populate_island(Body2DSW *p_body, Body2DSW **p_island, Constrain
 	p_body->set_island_next(*p_island);
 	*p_island = p_body;
 
-	for (Map<Constraint2DSW *, int>::Element *E = p_body->get_constraint_map().front(); E; E = E->next()) {
-
-		Constraint2DSW *c = (Constraint2DSW *)E->key();
+	for (const List<Pair<Constraint2DSW *, int> >::Element *E = p_body->get_constraint_list().front(); E; E = E->next()) {
+		Constraint2DSW *c = (Constraint2DSW *)E->get().first;
 		if (c->get_island_step() == _step)
 			continue; //already processed
 		c->set_island_step(_step);
@@ -47,7 +46,7 @@ void Step2DSW::_populate_island(Body2DSW *p_body, Body2DSW **p_island, Constrain
 		*p_constraint_island = c;
 
 		for (int i = 0; i < c->get_body_count(); i++) {
-			if (i == E->get())
+			if (i == E->get().second)
 				continue;
 			Body2DSW *b = c->get_body_ptr()[i];
 			if (b->get_island_step() == _step || b->get_mode() == Physics2DServer::BODY_MODE_STATIC || b->get_mode() == Physics2DServer::BODY_MODE_KINEMATIC)