Skip to content

Commit

Permalink
Add deterministic base function. Fix freeze mode. Fix missing events/…
Browse files Browse the repository at this point in the history
…collisions. (#258)

Adds some ComplexField functions for determinism. Follows
#226
- Fixes #242
- Fixes #250
  • Loading branch information
Ughuuu authored Sep 24, 2024
1 parent c513a38 commit bc51f65
Show file tree
Hide file tree
Showing 13 changed files with 190 additions and 64 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/runner.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ on:
branches:
- "main"

concurrency:
group: ${{ github.ref }}
cancel-in-progress: true

jobs:
static-checks:
name: 📊 Static checks
Expand Down
43 changes: 27 additions & 16 deletions .github/workflows/test_checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,28 @@ on:
workflow_call:

jobs:
run-tests-2d:
name: Run Tests
run-unit-tests-2d:
name: Run Unit Tests 2D
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Run Unit Tests for 2D Build
shell: sh
run: |
cargo test --all-targets --features="build2d,test" --no-default-features
run-unit-tests-3d:
name: Run Unit Tests 3D
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Run Unit Tests for 3D Build
shell: sh
run: |
cargo test --all-targets --features="build3d,test" --no-default-features
run-integration-tests-2d:
name: Run Integration Tests 2D
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -15,17 +35,12 @@ jobs:
version: 4.3.0
use-dotnet: false
include-templates: true
- name: Run Unit Tests for 2D Build
shell: sh
run: |
cargo test --all-targets --features="build2d,test" --no-default-features
- name: Run Integration Tests for 2D Build
shell: sh
# Skip this for now
if: false
run: |
return
./scripts/build-dev-2d.sh
ls bin2d/addons/godot-rapier2d/bin
godot --headless --path ./bin2d test.tscn --quit-after 1000 > output.log 2>&1
echo "---------------------"
grep "ERROR:" output.log
Expand All @@ -40,8 +55,8 @@ jobs:
exit 1
fi
run-tests-3d:
name: Run Tests
run-integration-tests-3d:
name: Run Integration Tests 3D
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -51,16 +66,12 @@ jobs:
version: 4.3.0
use-dotnet: false
include-templates: true
- name: Run Unit Tests for 3D Build
shell: sh
run: |
cargo test --all-targets --features="build3d,test" --no-default-features
- name: Run Integration Tests for 3D Build
# Skip this for now
if: false
shell: sh
run: |
return
./scripts/build-dev-3d.sh
ls bin3d/addons/godot-rapier3d/bin
godot --headless --path ./bin3d test.tscn --quit-after 1000 > output.log 2>&1
echo "---------------------"
grep "ERROR:" output.log
Expand Down
4 changes: 2 additions & 2 deletions bin2d/addons/godot-rapier2d/fluid_2d_renderer.gd
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ extends MultiMeshInstance2D

@export var fluid: Fluid2D
@export var color: Color = Color(0.8, 0.8, 0.8, 0.3)

@export var mesh_scale: Vector2 = Vector2(5,5)

func _ready():
if multimesh == null:
Expand All @@ -23,7 +23,7 @@ func _process(_delta):
var points = fluid.points
for i in points.size():
var point = points[i]
var new_transform: Transform2D = Transform2D(0, Vector2(5, 5), 0, point)
var new_transform: Transform2D = Transform2D(0, mesh_scale, 0, point)
multimesh.set_instance_transform_2d(index, new_transform)
multimesh.set_instance_color(index, color)
index += 1
2 changes: 2 additions & 0 deletions bin2d/addons/godot-rapier2d/fluid_2d_shader_renderer.gd
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ extends CanvasLayer
update_configuration_warnings()
@export var camera: Camera2D
@export var water_material: Material = load("res://addons/godot-rapier2d/water_shader.tres")
@export var mesh_scale: Vector2 = Vector2(5,5)
var fluid_renderer: Fluid2DRenderer
var inside_camera: Camera2D:
set(value):
Expand Down Expand Up @@ -46,6 +47,7 @@ func _create_fluid_renderer():
fluid_renderer = Fluid2DRenderer.new()
fluid_renderer.name = "Fluid2DRenderer"
fluid_renderer.color = Color(255,0,255)
fluid_renderer.mesh_scale = mesh_scale
fluid_renderer.fluid = fluid
sub_viewport.add_child(fluid_renderer)

Expand Down
14 changes: 13 additions & 1 deletion bin2d/test.tscn
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
[gd_scene load_steps=3 format=3 uid="uid://cn4jscixu2bmf"]
[gd_scene load_steps=4 format=3 uid="uid://cn4jscixu2bmf"]

[ext_resource type="Script" path="res://test.gd" id="1_fs1uw"]

[sub_resource type="CircleShape2D" id="CircleShape2D_01opr"]

[sub_resource type="RectangleShape2D" id="RectangleShape2D_vkitq"]
size = Vector2(365, 37)

[node name="Test2D" type="Node2D"]
script = ExtResource("1_fs1uw")

Expand All @@ -12,3 +15,12 @@ position = Vector2(-18, -4)

[node name="CollisionShape2D" type="CollisionShape2D" parent="RigidBody2D"]
shape = SubResource("CircleShape2D_01opr")

[node name="StaticBody2D" type="StaticBody2D" parent="."]

[node name="CollisionShape2D" type="CollisionShape2D" parent="StaticBody2D"]
position = Vector2(10.5, 96.5)
shape = SubResource("RectangleShape2D_vkitq")

[node name="Camera2D" type="Camera2D" parent="."]
zoom = Vector2(4, 4)
15 changes: 0 additions & 15 deletions bin3d/test.gd
Original file line number Diff line number Diff line change
Expand Up @@ -14,40 +14,25 @@ func _ready() -> void:
get_tree().quit()

func test_capsule_shape():
RapierCapsuleShapeTests.test_allows_one_way_collision()
RapierCapsuleShapeTests.test_create()
RapierCapsuleShapeTests.test_get_data()
RapierCapsuleShapeTests.test_get_type()
RapierCapsuleShapeTests.test_set_data_from_array()
RapierCapsuleShapeTests.test_set_data_from_dictionary()
RapierCapsuleShapeTests.test_set_data_from_vector2()

func test_circle_shape():
RapierCircleShapeTests.test_allows_one_way_collision()
RapierCircleShapeTests.test_create()
RapierCircleShapeTests.test_get_data()
RapierCircleShapeTests.test_get_type()
RapierCircleShapeTests.test_set_data()

func test_concave_polygon_shape():
RapierConcavePolygonShapeTests.test_allows_one_way_collision()
RapierConcavePolygonShapeTests.test_create()
RapierConcavePolygonShapeTests.test_get_data()
RapierConcavePolygonShapeTests.test_get_type()
RapierConcavePolygonShapeTests.test_set_data()

func test_convex_polygon_shape(): # New function for convex polygon shape
RapierConvexPolygonShapeTests.test_allows_one_way_collision()
RapierConvexPolygonShapeTests.test_create()
RapierConvexPolygonShapeTests.test_get_data()
RapierConvexPolygonShapeTests.test_get_type()
RapierConvexPolygonShapeTests.test_set_data()

func test_cylinder_shape():
RapierCylinderShape3DTests.test_create()
RapierCylinderShape3DTests.test_get_type()
RapierCylinderShape3DTests.test_allows_one_way_collision()
RapierCylinderShape3DTests.test_set_data_array()
RapierCylinderShape3DTests.test_set_data_vector2()
RapierCylinderShape3DTests.test_set_data_dictionary()
RapierCylinderShape3DTests.test_get_data()
3 changes: 2 additions & 1 deletion src/bodies/rapier_body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1574,6 +1574,7 @@ impl RapierBody {
if p_mode.ord() >= BodyMode::RIGID.ord() {
self.mass_properties_changed(physics_engine, physics_spaces, physics_rids);
}
self.set_space_after(physics_engine, physics_spaces, physics_rids);
}

pub fn set_state(
Expand Down Expand Up @@ -1956,7 +1957,7 @@ impl RapierBody {
&mut self,
physics_engine: &mut PhysicsEngine,
physics_spaces: &mut PhysicsSpaces,
physics_rids: &mut PhysicsRids,
physics_rids: &PhysicsRids,
) {
if self.base.is_space_valid() && self.base.mode.ord() >= BodyMode::KINEMATIC.ord() {
if self.get_force_integration_callback().is_some() {
Expand Down
3 changes: 2 additions & 1 deletion src/rapier_wrapper/physics_world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,8 @@ impl PhysicsWorld {
+ collider1.contact_skin()
+ collider2.contact_skin()
{
continue;
// TODO comment this out for now since it might miss out events
//continue;
}
let collider_pos_1 = collider1.position() * contact_point.local_p1;
let collider_pos_2 = collider2.position() * contact_point.local_p2;
Expand Down
29 changes: 18 additions & 11 deletions src/rapier_wrapper/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,23 +415,30 @@ impl PhysicsEngine {
let shared_shape2 = scale_shape(raw_shared_shape2, shape_info2);
let shape_transform1 = shape_info1.transform;
let shape_transform2 = shape_info2.transform;
if let Ok(Some(contact)) = parry::query::contact(
match parry::query::contact(
&shape_transform1,
shared_shape1.as_ref(),
&shape_transform2,
shared_shape2.as_ref(),
prediction,
) {
// the distance is negative if there is intersection
// and positive if the objects are separated by distance less than margin
result.pixel_distance = contact.dist;
result.within_margin = contact.dist > 0.0;
result.collided = true;
result.normal1 = contact.normal1.into_inner();
result.normal2 = contact.normal2.into_inner();
result.pixel_point1 = (contact.point1 + contact.normal1.mul(prediction)).coords;
result.pixel_point2 = contact.point2.coords;
return result;
Ok(None) => {}
Ok(Some(contact)) => {
// the distance is negative if there is intersection
// and positive if the objects are separated by distance less than margin
result.pixel_distance = contact.dist;
result.within_margin = contact.dist > 0.0;
result.collided = true;
result.normal1 = contact.normal1.into_inner();
result.normal2 = contact.normal2.into_inner();
result.pixel_point1 =
(contact.point1 + contact.normal1.mul(prediction)).coords;
result.pixel_point2 = contact.point2.coords;
return result;
}
Err(err) => {
godot_error!("Shape Contact Error: {:?}", err);
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/servers/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use godot::prelude::*;

use crate::servers::rapier_project_settings::RapierProjectSettings;
pub mod rapier_math;
#[cfg(feature = "dim2")]
pub mod rapier_physics_server_2d;
#[cfg(feature = "dim3")]
Expand Down
97 changes: 97 additions & 0 deletions src/servers/rapier_math.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
use godot::prelude::*;
use rapier::na::ComplexField;
#[derive(GodotClass)]
#[class(base=Object, init)]
/// Contains Rapier Deterministic Math functions.
pub struct RapierMath {
base: Base<Object>,
}
#[godot_api]
impl RapierMath {
#[func]
/// Deterministically compute acos.
fn acos(x: real) -> real {
ComplexField::acos(x)
}

#[func]
/// Deterministically compute acosh.
fn acosh(x: real) -> real {
ComplexField::acosh(x)
}

#[func]
/// Deterministically compute asin.
fn asin(x: real) -> real {
ComplexField::asin(x)
}

#[func]
/// Deterministically compute asinh.
fn asinh(x: real) -> real {
ComplexField::asinh(x)
}

#[func]
/// Deterministically compute atan.
fn atan(x: real) -> real {
ComplexField::atan(x)
}

#[func]
/// Deterministically compute atanh.
fn atanh(x: real) -> real {
ComplexField::atanh(x)
}

#[func]
/// Deterministically compute cos.
fn cos(x: real) -> real {
ComplexField::cos(x)
}

#[func]
/// Deterministically compute cosh.
fn cosh(x: real) -> real {
ComplexField::cosh(x)
}

#[func]
/// Deterministically compute log.
fn log(x: real) -> real {
ComplexField::ln(x)
}

#[func]
/// Deterministically compute sin.
fn sin(x: real) -> real {
ComplexField::sin(x)
}

#[func]
/// Deterministically compute sinh.
fn sinh(x: real) -> real {
ComplexField::sinh(x)
}

#[func]
/// Deterministically compute tan.
fn tan(x: real) -> real {
ComplexField::tan(x)
}

#[func]
/// Deterministically compute tanh.
fn tanh(x: real) -> real {
ComplexField::tanh(x)
}

#[func]
/// Deterministically compute sqrt.
fn sqrt(x: real) -> real {
if let Some(result) = ComplexField::try_sqrt(x) {
return result;
}
real::NAN
}
}
Loading

0 comments on commit bc51f65

Please sign in to comment.