aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThierry Berger <contact@thierryberger.com>2024-07-15 14:39:56 +0200
committerGitHub <noreply@github.com>2024-07-15 14:39:56 +0200
commit6a295d3e8e372390174cc5b3e286631eb47495c1 (patch)
tree73c42fa0f5fa79589dfa2f4494e24d3d65336e4c
parent685dc1729d066af1b1a71a6536d9c35af9503d00 (diff)
downloadrapier-6a295d3e8e372390174cc5b3e286631eb47495c1.tar.gz
rapier-6a295d3e8e372390174cc5b3e286631eb47495c1.tar.bz2
rapier-6a295d3e8e372390174cc5b3e286631eb47495c1.zip
Fix string serialization for broadphase multisap (#675)
-rw-r--r--CHANGELOG.md2
-rw-r--r--crates/rapier2d-f64/Cargo.toml17
-rw-r--r--crates/rapier2d/Cargo.toml19
-rw-r--r--crates/rapier3d-f64/Cargo.toml22
-rw-r--r--crates/rapier3d/Cargo.toml22
-rw-r--r--src/geometry/broad_phase_multi_sap/broad_phase_multi_sap.rs7
-rw-r--r--src/utils.rs72
7 files changed, 150 insertions, 11 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1f6007f..122dd4d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,7 @@
- Fix crash when removing a multibody joint, or a rigid-body with a multipody-joint attached to it.
- Fix crash when inserting multibody joints in an arbitrary order (instead of incrementally from root to leaf).
+- Fix `BroadphaseMultiSap` not being able to serialize correctly with serde_json.
### Added
@@ -14,6 +15,7 @@
- Divided by two the value of each `QueryFilterFlags` variant so that
the smallest one is 1 instead of 2 (fixes a bug in rapier.js).
+- `BroadphaseMultiSap` now serializes its `colliders_proxy_ids` as `Vec[(ColliderHandle, BroadPhaseProxyIndex)]`.
## v0.21.0 (23 June 2024)
diff --git a/crates/rapier2d-f64/Cargo.toml b/crates/rapier2d-f64/Cargo.toml
index 2606f7d..e5347a5 100644
--- a/crates/rapier2d-f64/Cargo.toml
+++ b/crates/rapier2d-f64/Cargo.toml
@@ -7,7 +7,13 @@ documentation = "https://docs.rs/rapier2d"
homepage = "https://rapier.rs"
repository = "https://github.com/dimforge/rapier"
readme = "README.md"
-categories = ["science", "game-development", "mathematics", "simulation", "wasm"]
+categories = [
+ "science",
+ "game-development",
+ "mathematics",
+ "simulation",
+ "wasm",
+]
keywords = ["physics", "dynamics", "rigid", "real-time", "impulse_joints"]
license = "Apache-2.0"
edition = "2021"
@@ -26,7 +32,13 @@ simd-nightly = ["simba/portable_simd", "simd-is-enabled"]
# enabled with the "simd-stable" or "simd-nightly" feature.
simd-is-enabled = ["dep:vec_map"]
wasm-bindgen = ["instant/wasm-bindgen"]
-serde-serialize = ["nalgebra/serde-serialize", "parry2d-f64/serde-serialize", "dep:serde", "bit-vec/serde", "arrayvec/serde"]
+serde-serialize = [
+ "nalgebra/serde-serialize",
+ "parry2d-f64/serde-serialize",
+ "dep:serde",
+ "bit-vec/serde",
+ "arrayvec/serde",
+]
enhanced-determinism = ["simba/libm_force", "parry2d-f64/enhanced-determinism"]
debug-render = []
profiler = ["dep:instant"] # Enables the internal profiler.
@@ -70,5 +82,6 @@ thiserror = "1"
[dev-dependencies]
bincode = "1"
+serde_json = "1"
serde = { version = "1", features = ["derive"] }
oorandom = { version = "11", default-features = false }
diff --git a/crates/rapier2d/Cargo.toml b/crates/rapier2d/Cargo.toml
index ec363c1..e8e1ad2 100644
--- a/crates/rapier2d/Cargo.toml
+++ b/crates/rapier2d/Cargo.toml
@@ -7,7 +7,13 @@ documentation = "https://docs.rs/rapier2d"
homepage = "https://rapier.rs"
repository = "https://github.com/dimforge/rapier"
readme = "README.md"
-categories = ["science", "game-development", "mathematics", "simulation", "wasm"]
+categories = [
+ "science",
+ "game-development",
+ "mathematics",
+ "simulation",
+ "wasm",
+]
keywords = ["physics", "dynamics", "rigid", "real-time", "impulse_joints"]
license = "Apache-2.0"
edition = "2021"
@@ -26,7 +32,13 @@ simd-nightly = ["simba/portable_simd", "simd-is-enabled"]
# enabled with the "simd-stable" or "simd-nightly" feature.
simd-is-enabled = ["dep:vec_map"]
wasm-bindgen = ["instant/wasm-bindgen"]
-serde-serialize = ["nalgebra/serde-serialize", "parry2d/serde-serialize", "dep:serde", "bit-vec/serde", "arrayvec/serde"]
+serde-serialize = [
+ "nalgebra/serde-serialize",
+ "parry2d/serde-serialize",
+ "dep:serde",
+ "bit-vec/serde",
+ "arrayvec/serde",
+]
enhanced-determinism = ["simba/libm_force", "parry2d/enhanced-determinism"]
debug-render = []
profiler = ["dep:instant"] # Enables the internal profiler.
@@ -70,5 +82,6 @@ thiserror = "1"
[dev-dependencies]
bincode = "1"
+serde_json = "1"
serde = { version = "1", features = ["derive"] }
-oorandom = { version = "11", default-features = false } \ No newline at end of file
+oorandom = { version = "11", default-features = false }
diff --git a/crates/rapier3d-f64/Cargo.toml b/crates/rapier3d-f64/Cargo.toml
index 17390e7..c1d9ce7 100644
--- a/crates/rapier3d-f64/Cargo.toml
+++ b/crates/rapier3d-f64/Cargo.toml
@@ -7,7 +7,13 @@ documentation = "https://docs.rs/rapier3d"
homepage = "https://rapier.rs"
repository = "https://github.com/dimforge/rapier"
readme = "README.md"
-categories = ["science", "game-development", "mathematics", "simulation", "wasm"]
+categories = [
+ "science",
+ "game-development",
+ "mathematics",
+ "simulation",
+ "wasm",
+]
keywords = ["physics", "dynamics", "rigid", "real-time", "impulse_joints"]
license = "Apache-2.0"
edition = "2021"
@@ -21,12 +27,21 @@ dim3 = []
f64 = []
parallel = ["dep:rayon"]
simd-stable = ["parry3d-f64/simd-stable", "simba/wide", "simd-is-enabled"]
-simd-nightly = ["parry3d-f64/simd-nightly", "simba/portable_simd", "simd-is-enabled"]
+simd-nightly = [
+ "parry3d-f64/simd-nightly",
+ "simba/portable_simd",
+ "simd-is-enabled",
+]
# Do not enable this feature directly. It is automatically
# enabled with the "simd-stable" or "simd-nightly" feature.
simd-is-enabled = ["dep:vec_map"]
wasm-bindgen = ["instant/wasm-bindgen"]
-serde-serialize = ["nalgebra/serde-serialize", "parry3d-f64/serde-serialize", "dep:serde", "bit-vec/serde"]
+serde-serialize = [
+ "nalgebra/serde-serialize",
+ "parry3d-f64/serde-serialize",
+ "dep:serde",
+ "bit-vec/serde",
+]
enhanced-determinism = ["simba/libm_force", "parry3d-f64/enhanced-determinism"]
debug-render = []
profiler = ["dep:instant"] # Enables the internal profiler.
@@ -70,5 +85,6 @@ thiserror = "1"
[dev-dependencies]
bincode = "1"
+serde_json = "1"
serde = { version = "1", features = ["derive"] }
oorandom = { version = "11", default-features = false }
diff --git a/crates/rapier3d/Cargo.toml b/crates/rapier3d/Cargo.toml
index 3f45d7b..03947ef 100644
--- a/crates/rapier3d/Cargo.toml
+++ b/crates/rapier3d/Cargo.toml
@@ -7,7 +7,13 @@ documentation = "https://docs.rs/rapier3d"
homepage = "https://rapier.rs"
repository = "https://github.com/dimforge/rapier"
readme = "README.md"
-categories = ["science", "game-development", "mathematics", "simulation", "wasm"]
+categories = [
+ "science",
+ "game-development",
+ "mathematics",
+ "simulation",
+ "wasm",
+]
keywords = ["physics", "dynamics", "rigid", "real-time", "impulse_joints"]
license = "Apache-2.0"
edition = "2021"
@@ -21,12 +27,21 @@ dim3 = []
f32 = []
parallel = ["dep:rayon"]
simd-stable = ["parry3d/simd-stable", "simba/wide", "simd-is-enabled"]
-simd-nightly = ["parry3d/simd-nightly", "simba/portable_simd", "simd-is-enabled"]
+simd-nightly = [
+ "parry3d/simd-nightly",
+ "simba/portable_simd",
+ "simd-is-enabled",
+]
# Do not enable this feature directly. It is automatically
# enabled with the "simd-stable" or "simd-nightly" feature.
simd-is-enabled = ["dep:vec_map"]
wasm-bindgen = ["instant/wasm-bindgen"]
-serde-serialize = ["nalgebra/serde-serialize", "parry3d/serde-serialize", "dep:serde", "bit-vec/serde"]
+serde-serialize = [
+ "nalgebra/serde-serialize",
+ "parry3d/serde-serialize",
+ "dep:serde",
+ "bit-vec/serde",
+]
enhanced-determinism = ["simba/libm_force", "parry3d/enhanced-determinism"]
debug-render = []
profiler = ["dep:instant"] # Enables the internal profiler.
@@ -70,5 +85,6 @@ thiserror = "1"
[dev-dependencies]
bincode = "1"
+serde_json = "1"
serde = { version = "1", features = ["derive"] }
oorandom = { version = "11", default-features = false }
diff --git a/src/geometry/broad_phase_multi_sap/broad_phase_multi_sap.rs b/src/geometry/broad_phase_multi_sap/broad_phase_multi_sap.rs
index 87b2269..1d0f2a4 100644
--- a/src/geometry/broad_phase_multi_sap/broad_phase_multi_sap.rs
+++ b/src/geometry/broad_phase_multi_sap/broad_phase_multi_sap.rs
@@ -90,6 +90,13 @@ pub struct BroadPhaseMultiSap {
// Another alternative would be to remove ColliderProxyId and
// just use a Coarena. But this seems like it could use too
// much memory.
+ #[cfg_attr(
+ feature = "serde-serialize",
+ serde(
+ serialize_with = "crate::utils::serde::serialize_to_vec_tuple",
+ deserialize_with = "crate::utils::serde::deserialize_from_vec_tuple"
+ )
+ )]
colliders_proxy_ids: HashMap<ColliderHandle, BroadPhaseProxyIndex>,
#[cfg_attr(feature = "serde-serialize", serde(skip))]
region_pool: SAPRegionPool, // To avoid repeated allocations.
diff --git a/src/utils.rs b/src/utils.rs
index 102c85f..84acb21 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -667,3 +667,75 @@ pub fn smallest_abs_diff_between_angles<N: SimdRealCopy>(a: N, b: N) -> N {
let s_err_is_smallest = s_err.simd_abs().simd_lt(s_err_complement.simd_abs());
s_err.select(s_err_is_smallest, s_err_complement)
}
+
+/// Helpers around serialization.
+#[cfg(feature = "serde-serialize")]
+pub mod serde {
+ use serde::{Deserialize, Serialize};
+ use std::iter::FromIterator;
+
+ /// Serializes to a `Vec<(K, V)>`.
+ ///
+ /// Useful for [`std::collections::HashMap`] with a non-string key,
+ /// which is unsupported by [`serde_json`].
+ pub fn serialize_to_vec_tuple<
+ 'a,
+ S: serde::Serializer,
+ T: IntoIterator<Item = (&'a K, &'a V)>,
+ K: Serialize + 'a,
+ V: Serialize + 'a,
+ >(
+ target: T,
+ s: S,
+ ) -> Result<S::Ok, S::Error> {
+ let container: Vec<_> = target.into_iter().collect();
+ serde::Serialize::serialize(&container, s)
+ }
+
+ /// Deserializes from a `Vec<(K, V)>`.
+ ///
+ /// Useful for [`std::collections::HashMap`] with a non-string key,
+ /// which is unsupported by [`serde_json`].
+ pub fn deserialize_from_vec_tuple<
+ 'de,
+ D: serde::Deserializer<'de>,
+ T: FromIterator<(K, V)>,
+ K: Deserialize<'de>,
+ V: Deserialize<'de>,
+ >(
+ d: D,
+ ) -> Result<T, D::Error> {
+ let hashmap_as_vec: Vec<(K, V)> = Deserialize::deserialize(d)?;
+ Ok(T::from_iter(hashmap_as_vec))
+ }
+
+ #[cfg(test)]
+ mod test {
+ use std::collections::HashMap;
+
+ /// This test uses serde_json because json doesn't support non string
+ /// keys in hashmaps, which requires a custom serialization.
+ #[test]
+ fn serde_json_hashmap() {
+ #[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
+ struct Test {
+ #[cfg_attr(
+ feature = "serde-serialize",
+ serde(
+ serialize_with = "crate::utils::serde::serialize_to_vec_tuple",
+ deserialize_with = "crate::utils::serde::deserialize_from_vec_tuple"
+ )
+ )]
+ pub map: HashMap<usize, String>,
+ }
+
+ let s = Test {
+ map: [(42, "Forty-Two".to_string())].into(),
+ };
+ let j = serde_json::to_string(&s).unwrap();
+ assert_eq!(&j, "{\"map\":[[42,\"Forty-Two\"]]}");
+ let p: Test = serde_json::from_str(&j).unwrap();
+ assert_eq!(&p, &s);
+ }
+ }
+}