From 5ea7dbbf0b1a39bd0337ee9179555b9c48722e39 Mon Sep 17 00:00:00 2001 From: Dragos Daian Date: Sat, 12 Aug 2023 19:54:58 +0200 Subject: [PATCH 1/7] add position and velocity iteration --- src/register_types.cpp | 24 +++--- src/servers/box2d_project_settings.cpp | 102 +++++++++++++++++++++++++ src/servers/box2d_project_settings.h | 11 +++ src/spaces/box2d_space.cpp | 8 +- src/spaces/box2d_space.h | 3 +- 5 files changed, 134 insertions(+), 14 deletions(-) create mode 100644 src/servers/box2d_project_settings.cpp create mode 100644 src/servers/box2d_project_settings.h diff --git a/src/register_types.cpp b/src/register_types.cpp index 0e01696..80a4a53 100644 --- a/src/register_types.cpp +++ b/src/register_types.cpp @@ -17,16 +17,22 @@ using namespace godot; static PhysicsServerBox2DFactory *box2d_factory = nullptr; void initialize_physics_server_box2d_module(ModuleInitializationLevel p_level) { - if (p_level != MODULE_INITIALIZATION_LEVEL_SERVERS) { - return; + switch (p_level) { + case MODULE_INITIALIZATION_LEVEL_SERVERS: { + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); + + box2d_factory = memnew(PhysicsServerBox2DFactory()); + PhysicsServer2DManager::get_singleton()->register_server("Box2D", Callable(box2d_factory, "create_box2d_callback")); + } break; + case MODULE_INITIALIZATION_LEVEL_SCENE: { + Box2DProjectSettings::register_settings(); + } break; + default: { + } break; } - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); - - box2d_factory = memnew(PhysicsServerBox2DFactory()); - PhysicsServer2DManager::get_singleton()->register_server("Box2D", Callable(box2d_factory, "create_box2d_callback")); } void uninitialize_physics_server_box2d_module(ModuleInitializationLevel p_level) { diff --git a/src/servers/box2d_project_settings.cpp b/src/servers/box2d_project_settings.cpp new file mode 100644 index 0000000..e965d5d --- /dev/null +++ b/src/servers/box2d_project_settings.cpp @@ -0,0 +1,102 @@ +#include "box2d_project_settings.h" + +#include + +using namespace godot; + +constexpr char RUN_ON_SEPARATE_THREAD[] = "physics/2d/run_on_separate_thread"; +constexpr char MAX_THREADS[] = "threading/worker_pool/max_threads"; +constexpr char POSITION_ITERATIONS[] = "physics/box_2d/solver/position_iterations"; +constexpr char VELOCITY_ITERATIONS[] = "physics/box_2d/solver/velocity_iterations"; + + +void register_setting( + const String& p_name, + const Variant& p_value, + bool p_needs_restart, + PropertyHint p_hint, + const String& p_hint_string +) { + ProjectSettings* project_settings = ProjectSettings::get_singleton(); + + if (!project_settings->has_setting(p_name)) { + project_settings->set(p_name, p_value); + } + + Dictionary property_info; + property_info["name"] = p_name; + property_info["type"] = p_value.get_type(); + property_info["hint"] = p_hint; + property_info["hint_string"] = p_hint_string; + + project_settings->add_property_info(property_info); + project_settings->set_initial_value(p_name, p_value); + project_settings->set_restart_if_changed(p_name, p_needs_restart); + + // HACK(mihe): We want our settings to appear in the order we register them in, but if we start + // the order at 0 we end up moving the entire `physics/` group to the top of the tree view, so + // instead we give it a hefty starting order and increment from there, which seems to give us + // the desired effect. + static int32_t order = 1000000; + + project_settings->set_order(p_name, order++); +} + +void register_setting_plain( + const String& p_name, + const Variant& p_value, + bool p_needs_restart = false +) { + register_setting(p_name, p_value, p_needs_restart, PROPERTY_HINT_NONE, {}); +} + +void register_setting_hinted( + const String& p_name, + const Variant& p_value, + const String& p_hint_string, + bool p_needs_restart = false +) { + register_setting(p_name, p_value, p_needs_restart, PROPERTY_HINT_NONE, p_hint_string); +} + +void register_setting_ranged( + const String& p_name, + const Variant& p_value, + const String& p_hint_string, + bool p_needs_restart = false +) { + register_setting(p_name, p_value, p_needs_restart, PROPERTY_HINT_RANGE, p_hint_string); +} + +void Box2DProjectSettings::register_settings() { + register_setting_ranged(VELOCITY_ITERATIONS, 8, U"2,16,or_greater"); + register_setting_ranged(POSITION_ITERATIONS, 3, U"1,16,or_greater"); +} + +template +TType get_setting(const char* p_setting) { + const ProjectSettings* project_settings = ProjectSettings::get_singleton(); + const Variant setting_value = project_settings->get_setting_with_override(p_setting); + const Variant::Type setting_type = setting_value.get_type(); + const Variant::Type expected_type = Variant(TType()).get_type(); + + ERR_FAIL_COND_V(setting_type != expected_type,Variant()); + + return setting_value; +} + +bool Box2DProjectSettings::should_run_on_separate_thread() { + return get_setting(RUN_ON_SEPARATE_THREAD); +} + +int Box2DProjectSettings::get_max_threads() { + return get_setting(MAX_THREADS); +} + +int Box2DProjectSettings::get_position_iterations() { + return get_setting(POSITION_ITERATIONS); +} + +int Box2DProjectSettings::get_velocity_iterations() { + return get_setting(VELOCITY_ITERATIONS); +} diff --git a/src/servers/box2d_project_settings.h b/src/servers/box2d_project_settings.h new file mode 100644 index 0000000..0e438e8 --- /dev/null +++ b/src/servers/box2d_project_settings.h @@ -0,0 +1,11 @@ +#pragma once + +class Box2DProjectSettings { +public: + static void register_settings(); + + static bool should_run_on_separate_thread(); + static int get_max_threads(); + static int get_position_iterations(); + static int get_velocity_iterations(); +}; diff --git a/src/spaces/box2d_space.cpp b/src/spaces/box2d_space.cpp index e22163e..a299aca 100644 --- a/src/spaces/box2d_space.cpp +++ b/src/spaces/box2d_space.cpp @@ -60,16 +60,16 @@ void Box2DSpace::set_debug_contacts(int32_t p_max_contacts) { } void Box2DSpace::set_solver_iterations(int32 p_iterations) { - solver_iterations = p_iterations; + // UNUSED } int32 Box2DSpace::get_solver_iterations() const { - return solver_iterations; + // UNUSED } void Box2DSpace::step(double p_step) { - const int32 velocityIterations = solver_iterations; - const int32 positionIterations = solver_iterations; + const int32 velocityIterations = Box2DProjectSettings::get_velocity_iterations(); + const int32 positionIterations = Box2DProjectSettings::get_position_iterations(); const SelfList::List *body_list = &get_active_body_list(); const SelfList *b = body_list->first(); diff --git a/src/spaces/box2d_space.h b/src/spaces/box2d_space.h index 4a0948e..2b5663c 100644 --- a/src/spaces/box2d_space.h +++ b/src/spaces/box2d_space.h @@ -1,5 +1,7 @@ #pragma once +#include "../servers/box2d_project_settings.h" + #include #include #include @@ -34,7 +36,6 @@ class Box2DSpace { int max_debug_contacts = 0; ProcessInfo process_info; bool locked = false; - double solver_iterations = 8; Box2DDirectSpaceState *direct_state = nullptr; Box2DSpaceContactFilter *contact_filter; From d14550e825d0cd681515d335b3e7e6c096eecaa1 Mon Sep 17 00:00:00 2001 From: Dragos Daian Date: Sat, 12 Aug 2023 19:55:58 +0200 Subject: [PATCH 2/7] lint --- src/servers/box2d_project_settings.cpp | 47 ++++++++++++-------------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/src/servers/box2d_project_settings.cpp b/src/servers/box2d_project_settings.cpp index e965d5d..cff95a2 100644 --- a/src/servers/box2d_project_settings.cpp +++ b/src/servers/box2d_project_settings.cpp @@ -9,15 +9,13 @@ constexpr char MAX_THREADS[] = "threading/worker_pool/max_threads"; constexpr char POSITION_ITERATIONS[] = "physics/box_2d/solver/position_iterations"; constexpr char VELOCITY_ITERATIONS[] = "physics/box_2d/solver/velocity_iterations"; - void register_setting( - const String& p_name, - const Variant& p_value, - bool p_needs_restart, - PropertyHint p_hint, - const String& p_hint_string -) { - ProjectSettings* project_settings = ProjectSettings::get_singleton(); + const String &p_name, + const Variant &p_value, + bool p_needs_restart, + PropertyHint p_hint, + const String &p_hint_string) { + ProjectSettings *project_settings = ProjectSettings::get_singleton(); if (!project_settings->has_setting(p_name)) { project_settings->set(p_name, p_value); @@ -43,28 +41,25 @@ void register_setting( } void register_setting_plain( - const String& p_name, - const Variant& p_value, - bool p_needs_restart = false -) { + const String &p_name, + const Variant &p_value, + bool p_needs_restart = false) { register_setting(p_name, p_value, p_needs_restart, PROPERTY_HINT_NONE, {}); } void register_setting_hinted( - const String& p_name, - const Variant& p_value, - const String& p_hint_string, - bool p_needs_restart = false -) { + const String &p_name, + const Variant &p_value, + const String &p_hint_string, + bool p_needs_restart = false) { register_setting(p_name, p_value, p_needs_restart, PROPERTY_HINT_NONE, p_hint_string); } void register_setting_ranged( - const String& p_name, - const Variant& p_value, - const String& p_hint_string, - bool p_needs_restart = false -) { + const String &p_name, + const Variant &p_value, + const String &p_hint_string, + bool p_needs_restart = false) { register_setting(p_name, p_value, p_needs_restart, PROPERTY_HINT_RANGE, p_hint_string); } @@ -73,14 +68,14 @@ void Box2DProjectSettings::register_settings() { register_setting_ranged(POSITION_ITERATIONS, 3, U"1,16,or_greater"); } -template -TType get_setting(const char* p_setting) { - const ProjectSettings* project_settings = ProjectSettings::get_singleton(); +template +TType get_setting(const char *p_setting) { + const ProjectSettings *project_settings = ProjectSettings::get_singleton(); const Variant setting_value = project_settings->get_setting_with_override(p_setting); const Variant::Type setting_type = setting_value.get_type(); const Variant::Type expected_type = Variant(TType()).get_type(); - ERR_FAIL_COND_V(setting_type != expected_type,Variant()); + ERR_FAIL_COND_V(setting_type != expected_type, Variant()); return setting_value; } From d23e87d9ddf2be778472881be9cbc5dc57ce326c Mon Sep 17 00:00:00 2001 From: Dragos Daian Date: Sat, 12 Aug 2023 22:36:15 +0200 Subject: [PATCH 3/7] fix windows err --- src/servers/physics_server_box2d.cpp | 22 ++-------------------- src/spaces/box2d_space.cpp | 8 -------- src/spaces/box2d_space.h | 3 --- 3 files changed, 2 insertions(+), 31 deletions(-) diff --git a/src/servers/physics_server_box2d.cpp b/src/servers/physics_server_box2d.cpp index 45e6a7b..f2cce3f 100644 --- a/src/servers/physics_server_box2d.cpp +++ b/src/servers/physics_server_box2d.cpp @@ -195,29 +195,11 @@ bool PhysicsServerBox2D::_space_is_active(const RID &p_space) const { } void PhysicsServerBox2D::_space_set_param(const RID &p_space, PhysicsServer2D::SpaceParameter p_param, double p_value) { - const Box2DSpace *space_const = space_owner.get_or_null(p_space); - ERR_FAIL_COND(!space_const); - switch (p_param) { - case SPACE_PARAM_SOLVER_ITERATIONS: { - Box2DSpace *space = const_cast(space_const); - space->set_solver_iterations((int32)p_value); - } break; - default: { - ERR_PRINT("Unsupported space property"); - } - } + // UNUSED } double PhysicsServerBox2D::_space_get_param(const RID &p_space, PhysicsServer2D::SpaceParameter p_param) const { - const Box2DSpace *space = space_owner.get_or_null(p_space); - ERR_FAIL_COND_V(!space, 0); - switch (p_param) { - case SPACE_PARAM_SOLVER_ITERATIONS: - return (double)space->get_solver_iterations(); - default: { - ERR_PRINT("Unsupported space property"); - } - } + // UNUSED return 0; } diff --git a/src/spaces/box2d_space.cpp b/src/spaces/box2d_space.cpp index a299aca..92dbc2b 100644 --- a/src/spaces/box2d_space.cpp +++ b/src/spaces/box2d_space.cpp @@ -59,14 +59,6 @@ void Box2DSpace::set_debug_contacts(int32_t p_max_contacts) { max_debug_contacts = p_max_contacts; } -void Box2DSpace::set_solver_iterations(int32 p_iterations) { - // UNUSED -} - -int32 Box2DSpace::get_solver_iterations() const { - // UNUSED -} - void Box2DSpace::step(double p_step) { const int32 velocityIterations = Box2DProjectSettings::get_velocity_iterations(); const int32 positionIterations = Box2DProjectSettings::get_position_iterations(); diff --git a/src/spaces/box2d_space.h b/src/spaces/box2d_space.h index 2b5663c..ca75e51 100644 --- a/src/spaces/box2d_space.h +++ b/src/spaces/box2d_space.h @@ -54,9 +54,6 @@ class Box2DSpace { void set_debug_contacts(int32_t max_contacts); - void set_solver_iterations(int32 iterations); - int32 get_solver_iterations() const; - void step(double p_step); void call_queries(); From 760f5b5e17180656b18d489d9fd48d93a3540741 Mon Sep 17 00:00:00 2001 From: Dragos Daian Date: Sun, 13 Aug 2023 13:56:00 +0200 Subject: [PATCH 4/7] upd --- .gitmodules | 2 +- CONTRIBUTING.md | 6 ++++++ src/shapes/box2d_shape_capsule.cpp | 2 +- src/shapes/box2d_shape_circle.cpp | 2 +- src/spaces/box2d_space_contact_listener.cpp | 23 ++++++++++++++------- 5 files changed, 25 insertions(+), 10 deletions(-) diff --git a/.gitmodules b/.gitmodules index d18ec66..499100b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,7 +4,7 @@ branch = 4.1 [submodule "box2d"] path = box2d - url = https://github.com/godot-box2d/box2d + url = https://github.com/appsinacup/box2d branch = common-assert-noop [submodule "Godot-Physics-Tests"] path = Godot-Physics-Tests diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f91ff23..cc1885f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -46,6 +46,12 @@ NOTE: the simulation for box2d goes slower (eg. 30 fps), while for godot physics *Note*: The `template_debug` target can also be loaded in the Godot editor. +## How to update submodule + +``` +git submodule foreach git pull +``` + ## Lint Run `scripts/clang-tidy.sh` in order to lint. diff --git a/src/shapes/box2d_shape_capsule.cpp b/src/shapes/box2d_shape_capsule.cpp index ddfeaf6..957ed05 100644 --- a/src/shapes/box2d_shape_capsule.cpp +++ b/src/shapes/box2d_shape_capsule.cpp @@ -35,7 +35,7 @@ int Box2DShapeCapsule::get_b2Shape_count(bool is_static) const { b2Shape *Box2DShapeCapsule::_get_transformed_b2Shape(ShapeInfo shape_info, Box2DCollisionObject *body) { ERR_FAIL_INDEX_V(shape_info.index, 3, nullptr); Vector2 scale = shape_info.transform.get_scale(); - if (scale.x != scale.y) { + if (fabs(scale.x - scale.y) > b2_epsilon) { ERR_PRINT("Capsules don't support non uniform scale."); } float radius_scaled = godot_to_box2d(radius * scale.x); diff --git a/src/shapes/box2d_shape_circle.cpp b/src/shapes/box2d_shape_circle.cpp index 7556e41..f5fda4c 100644 --- a/src/shapes/box2d_shape_circle.cpp +++ b/src/shapes/box2d_shape_circle.cpp @@ -21,7 +21,7 @@ b2Shape *Box2DShapeCircle::_get_transformed_b2Shape(ShapeInfo shape_info, Box2DC ERR_FAIL_INDEX_V(shape_info.index, 1, nullptr); b2CircleShape *shape = memnew(b2CircleShape); Vector2 scale = shape_info.transform.get_scale(); - if (scale.x != scale.y) { + if (fabs(scale.x - scale.y) > b2_epsilon) { ERR_PRINT("Circles don't support non uniform scale."); } shape->m_radius = godot_to_box2d(radius * scale.x); diff --git a/src/spaces/box2d_space_contact_listener.cpp b/src/spaces/box2d_space_contact_listener.cpp index b7cee0f..639dfa4 100644 --- a/src/spaces/box2d_space_contact_listener.cpp +++ b/src/spaces/box2d_space_contact_listener.cpp @@ -47,14 +47,23 @@ void Box2DSpaceContactListener::handle_static_constant_linear_velocity(b2Body *b } void Box2DSpaceContactListener::handle_one_way_direction(b2Vec2 one_way_collision_direction_A, b2Body *b2_body_A, b2Body *b2_body_B, b2Contact *contact) { - if (!world_manifold_computed) { - contact->GetWorldManifold(&worldManifold); - world_manifold_computed = true; - } + //if (!world_manifold_computed) { + //contact->GetWorldManifold(&worldManifold); + //world_manifold_computed = true; + //} b2Vec2 normal = b2Mul(b2_body_A->GetTransform().q, one_way_collision_direction_A); - b2Vec2 vel = b2_body_B->GetLinearVelocity(); - vel.Normalize(); - if (b2Dot(vel, normal) > 0.9f) { + b2Vec2 body_A_velocity = b2_body_A->GetLinearVelocity(); + b2Vec2 body_B_velocity = b2_body_B->GetLinearVelocity(); + b2Vec2 body_A_position = b2_body_A->GetPosition(); + b2Vec2 body_B_position = b2_body_B->GetPosition(); + b2Vec2 relative_position = body_B_position - body_A_position; + b2Vec2 local_normal = contact->GetManifold()->localNormal; + // relative velocity + body_B_velocity -= body_A_velocity; + body_B_velocity.Normalize(); + float dot_product = b2Dot(body_B_velocity, normal); + float passThroughThreshold = -b2_epsilon * 10; + if (dot_product >= passThroughThreshold) { contact->SetEnabled(false); return; } From 2f780930e8aec3204044ad08373e2656cfc10a6e Mon Sep 17 00:00:00 2001 From: Dragos Daian Date: Sun, 13 Aug 2023 14:50:41 +0200 Subject: [PATCH 5/7] upd --- src/shapes/box2d_shape_capsule.cpp | 2 +- src/spaces/box2d_space_contact_listener.cpp | 11 +++-------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/shapes/box2d_shape_capsule.cpp b/src/shapes/box2d_shape_capsule.cpp index 957ed05..1b4e08a 100644 --- a/src/shapes/box2d_shape_capsule.cpp +++ b/src/shapes/box2d_shape_capsule.cpp @@ -35,7 +35,7 @@ int Box2DShapeCapsule::get_b2Shape_count(bool is_static) const { b2Shape *Box2DShapeCapsule::_get_transformed_b2Shape(ShapeInfo shape_info, Box2DCollisionObject *body) { ERR_FAIL_INDEX_V(shape_info.index, 3, nullptr); Vector2 scale = shape_info.transform.get_scale(); - if (fabs(scale.x - scale.y) > b2_epsilon) { + if (fabs(scale.x - scale.y) > b2_epsilon) { ERR_PRINT("Capsules don't support non uniform scale."); } float radius_scaled = godot_to_box2d(radius * scale.x); diff --git a/src/spaces/box2d_space_contact_listener.cpp b/src/spaces/box2d_space_contact_listener.cpp index 639dfa4..6558def 100644 --- a/src/spaces/box2d_space_contact_listener.cpp +++ b/src/spaces/box2d_space_contact_listener.cpp @@ -48,16 +48,13 @@ void Box2DSpaceContactListener::handle_static_constant_linear_velocity(b2Body *b void Box2DSpaceContactListener::handle_one_way_direction(b2Vec2 one_way_collision_direction_A, b2Body *b2_body_A, b2Body *b2_body_B, b2Contact *contact) { //if (!world_manifold_computed) { - //contact->GetWorldManifold(&worldManifold); - //world_manifold_computed = true; + //contact->GetWorldManifold(&worldManifold); + //world_manifold_computed = true; //} b2Vec2 normal = b2Mul(b2_body_A->GetTransform().q, one_way_collision_direction_A); b2Vec2 body_A_velocity = b2_body_A->GetLinearVelocity(); b2Vec2 body_B_velocity = b2_body_B->GetLinearVelocity(); - b2Vec2 body_A_position = b2_body_A->GetPosition(); - b2Vec2 body_B_position = b2_body_B->GetPosition(); - b2Vec2 relative_position = body_B_position - body_A_position; - b2Vec2 local_normal = contact->GetManifold()->localNormal; + //b2Vec2 local_normal = contact->GetManifold()->localNormal; // relative velocity body_B_velocity -= body_A_velocity; body_B_velocity.Normalize(); @@ -88,11 +85,9 @@ void Box2DSpaceContactListener::PreSolve(b2Contact *contact, const b2Manifold *o b2Vec2 b2_body_B_position = b2_body_B->GetPosition(); if (one_way_collision_A) { handle_one_way_direction(one_way_collision_direction_A, b2_body_A, b2_body_B, contact); - return; } if (one_way_collision_B) { handle_one_way_direction(one_way_collision_direction_B, b2_body_B, b2_body_A, contact); - return; } } From ca0ba5853be45fb718e9693df88519aeb68260e3 Mon Sep 17 00:00:00 2001 From: Dragos Daian Date: Sun, 13 Aug 2023 14:54:52 +0200 Subject: [PATCH 6/7] upd --- box2d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/box2d b/box2d index 45a7855..15481c3 160000 --- a/box2d +++ b/box2d @@ -1 +1 @@ -Subproject commit 45a78558c1b357b0c6c7e67fa9eabe45cf82fdcb +Subproject commit 15481c3059c934077e879ee0cbb3ed8de709be2d From 2e7666d03798c2ee99f5e7b5f1c92f7b865eff5f Mon Sep 17 00:00:00 2001 From: Dragos Daian Date: Sun, 13 Aug 2023 14:55:21 +0200 Subject: [PATCH 7/7] upd --- CONTRIBUTING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cc1885f..9a0ff96 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -49,6 +49,8 @@ NOTE: the simulation for box2d goes slower (eg. 30 fps), while for godot physics ## How to update submodule ``` +git submodule sync +git submodule update git submodule foreach git pull ```