From 0978fe1381d438524c02215320a67121c131965d Mon Sep 17 00:00:00 2001 From: salam Date: Mon, 11 Nov 2024 17:45:36 +0900 Subject: [PATCH 01/25] add: lint parameters --- Cargo.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 4b8bcc2..f332183 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,10 @@ description = "a library for generating colliders, for bevy apps, from images wi keywords = ["bevy", "rapier", "png", "collider", "2d"] readme = "README.md" +[lints.clippy] +cast_precision_loss = { level = "allow", priority = 1 } +pedantic = { level = "warn", priority = 0 } + [features] default = ["avian2d", "rapier2d"] avian2d = ["dep:avian2d"] From 298a383f7b5b387e3075f66011e562c3382009be Mon Sep 17 00:00:00 2001 From: salam Date: Mon, 11 Nov 2024 17:50:04 +0900 Subject: [PATCH 02/25] fix: linter warnings --- examples/avian2d_colliders.rs | 52 ++++++++++++++---------- examples/rapier2d_colliders.rs | 43 +++++++++++--------- src/collider/avian2d.rs | 47 +++++++++++++++------- src/collider/rapier2d.rs | 73 +++++++++++++++++++++------------- 4 files changed, 134 insertions(+), 81 deletions(-) diff --git a/examples/avian2d_colliders.rs b/examples/avian2d_colliders.rs index c129bed..a73ceb2 100644 --- a/examples/avian2d_colliders.rs +++ b/examples/avian2d_colliders.rs @@ -1,18 +1,26 @@ -use avian2d::math::Vector; -use avian2d::prelude::*; -use bevy::asset::LoadState; -use bevy::color::palettes::css; -use bevy::pbr::wireframe::WireframePlugin; -use bevy::prelude::*; -use bevy::render::settings::{RenderCreation, WgpuFeatures, WgpuSettings}; -use bevy::render::RenderPlugin; -use bevy_collider_gen::avian2d::single_convex_polyline_collider_translated; +#![allow(clippy::needless_pass_by_value)] +use avian2d::{math::Vector, prelude::*}; +use bevy::{ + asset::LoadState, + color::palettes::css, + pbr::wireframe::WireframePlugin, + prelude::*, + render::{ + settings::{RenderCreation, WgpuFeatures, WgpuSettings}, + RenderPlugin, + }, +}; use bevy_collider_gen::{ - avian2d::{multi_convex_polyline_collider_translated, single_heightfield_collider_translated}, + avian2d::{ + multi_convex_polyline_collider_translated, single_convex_polyline_collider_translated, + single_heightfield_collider_translated, + }, Edges, }; -use bevy_prototype_lyon::prelude::{Fill, GeometryBuilder, ShapePlugin}; -use bevy_prototype_lyon::shapes; +use bevy_prototype_lyon::{ + prelude::{Fill, GeometryBuilder, ShapePlugin}, + shapes, +}; use indoc::indoc; use std::collections::HashMap; @@ -25,9 +33,9 @@ use std::collections::HashMap; /// w (zoom in) /// d (zoom out) -/// Custom PNG: convex_polyline collider +/// Custom PNG: `convex_polyline` collider /// from png path specified as cli argument -pub fn custom_png_spawn( +fn custom_png_spawn( mut commands: Commands, game_assets: Res, image_assets: Res>, @@ -59,9 +67,9 @@ pub struct Car { pub initial_xyz: Vec3, } -/// Car: convex_polyline collider +/// Car: `convex_polyline` collider /// from assets/sprite/car.png -pub fn car_spawn( +fn car_spawn( mut commands: Commands, game_assets: Res, image_assets: Res>, @@ -88,7 +96,7 @@ pub fn car_spawn( /// Terrain: heightfield collider /// from assets/sprite/terrain.png -pub fn terrain_spawn( +fn terrain_spawn( mut commands: Commands, game_assets: Res, image_assets: Res>, @@ -111,9 +119,9 @@ pub fn terrain_spawn( } /// Boulder: using groups of edge coordinates to create geometry to color fill -/// multiple convex_polyline colliders +/// multiple `convex_polyline` colliders /// from assets/sprite/boulders.png -pub fn boulders_spawn( +fn boulders_spawn( mut commands: Commands, game_assets: Res, image_assets: Res>, @@ -236,7 +244,7 @@ pub fn check_assets( return; } - state.set(AppState::Running) + state.set(AppState::Running); } pub fn camera_spawn(mut commands: Commands) { @@ -247,7 +255,7 @@ pub fn camera_movement( mut query: Query<(&Camera, &mut OrthographicProjection, &mut Transform)>, keys: Res>, ) { - for (_, mut projection, mut transform) in query.iter_mut() { + for (_, mut projection, mut transform) in &mut query { if keys.pressed(KeyCode::ArrowLeft) { transform.translation.x += 10.0; } @@ -358,7 +366,7 @@ pub fn car_movement( mut query: Query<(&Car, &mut LinearVelocity, &mut Transform)>, keys: Res>, ) { - for (car, mut linear_velocity, mut transform) in query.iter_mut() { + for (car, mut linear_velocity, mut transform) in &mut query { if keys.pressed(KeyCode::KeyD) { linear_velocity.x += 30.0; } diff --git a/examples/rapier2d_colliders.rs b/examples/rapier2d_colliders.rs index 4c1ae73..21bcf0b 100644 --- a/examples/rapier2d_colliders.rs +++ b/examples/rapier2d_colliders.rs @@ -1,8 +1,13 @@ -use bevy::asset::LoadState; -use bevy::pbr::wireframe::WireframePlugin; -use bevy::prelude::*; -use bevy::render::settings::{RenderCreation, WgpuFeatures, WgpuSettings}; -use bevy::render::RenderPlugin; +#![allow(clippy::needless_pass_by_value)] +use bevy::{ + asset::LoadState, + pbr::wireframe::WireframePlugin, + prelude::*, + render::{ + settings::{RenderCreation, WgpuFeatures, WgpuSettings}, + RenderPlugin, + }, +}; use bevy_collider_gen::{ rapier2d::{ multi_convex_polyline_collider_translated, single_convex_polyline_collider_translated, @@ -10,8 +15,10 @@ use bevy_collider_gen::{ }, Edges, }; -use bevy_prototype_lyon::prelude::{Fill, GeometryBuilder, ShapePlugin}; -use bevy_prototype_lyon::shapes; +use bevy_prototype_lyon::{ + prelude::{Fill, GeometryBuilder, ShapePlugin}, + shapes, +}; use bevy_rapier2d::prelude::*; use indoc::indoc; use std::collections::HashMap; @@ -25,9 +32,9 @@ use std::collections::HashMap; /// w (zoom in) /// d (zoom out) -/// Custom PNG: bevy_rapier2d convex_polyline collider +/// Custom PNG: `bevy_rapier2d` `convex_polyline` collider /// from png path specified as cli argument -pub fn custom_png_spawn( +fn custom_png_spawn( mut commands: Commands, game_assets: Res, image_assets: Res>, @@ -76,9 +83,9 @@ pub struct Car { pub initial_xyz: Vec3, } -/// Car: bevy_rapier2d convex_polyline collider +/// Car: `bevy_rapier2d` `convex_polyline` collider /// from assets/sprite/car.png -pub fn car_spawn( +fn car_spawn( mut commands: Commands, game_assets: Res, image_assets: Res>, @@ -102,9 +109,9 @@ pub fn car_spawn( )); } -/// Terrain: bevy_rapier2d heightfield collider +/// Terrain: `bevy_rapier2d` heightfield collider /// from assets/sprite/terrain.png -pub fn terrain_spawn( +fn terrain_spawn( mut commands: Commands, game_assets: Res, image_assets: Res>, @@ -126,9 +133,9 @@ pub fn terrain_spawn( } /// Boulder: using groups of edge coordinates to create geometry to color fill -/// multiple bevy_rapier2d convex_polyline colliders +/// multiple `bevy_rapier2d` `convex_polyline` colliders /// from assets/sprite/boulders.png -pub fn boulders_spawn( +fn boulders_spawn( mut commands: Commands, game_assets: Res, image_assets: Res>, @@ -256,7 +263,7 @@ pub fn check_assets( return; } - state.set(AppState::Running) + state.set(AppState::Running); } pub fn camera_spawn(mut commands: Commands) { @@ -267,7 +274,7 @@ pub fn camera_movement( mut query: Query<(&Camera, &mut OrthographicProjection, &mut Transform)>, keys: Res>, ) { - for (_, mut projection, mut transform) in query.iter_mut() { + for (_, mut projection, mut transform) in &mut query { if keys.pressed(KeyCode::ArrowLeft) { transform.translation.x += 10.0; } @@ -375,7 +382,7 @@ pub fn controls_text_spawn(mut commands: Commands, game_assets: Res) } pub fn car_movement(mut query: Query<(&Car, &mut Transform)>, keys: Res>) { - for (car, mut transform) in query.iter_mut() { + for (car, mut transform) in &mut query { if keys.pressed(KeyCode::KeyD) { transform.translation.x += 5.0; } diff --git a/src/collider/avian2d.rs b/src/collider/avian2d.rs index ea46bfe..b462c52 100644 --- a/src/collider/avian2d.rs +++ b/src/collider/avian2d.rs @@ -11,6 +11,7 @@ use edges::Edges; /// Generate a single polyline collider from the image, /// coordinates translated to either side of (0, 0) +#[must_use] pub fn single_polyline_collider_translated(image: &Image) -> Collider { let e = Edges::from(image); Collider::polyline(e.single_image_edge_translated(), None) @@ -18,13 +19,15 @@ pub fn single_polyline_collider_translated(image: &Image) -> Collider { /// Generate a single polyline collider from the image, /// coordinates left alone and all in positive x and y +#[must_use] pub fn single_polyline_collider_raw(image: &Image) -> Collider { let e = Edges::from(image); Collider::polyline(e.single_image_edge_raw(), None) } -/// Generate a single convex_polyline collider from the image, +/// Generate a single `convex_polyline` collider from the image, /// coordinates translated to either side of (0, 0) +#[must_use] pub fn single_convex_polyline_collider_translated(image: &Image) -> Option { let e = Edges::from(image); let points = e @@ -35,8 +38,9 @@ pub fn single_convex_polyline_collider_translated(image: &Image) -> Option Option { let e = Edges::from(image); let points = e @@ -47,16 +51,18 @@ pub fn single_convex_polyline_collider_raw(image: &Image) -> Option { SharedShape::convex_polyline(points).map(Collider::from) } -/// Generate a single convex_hull collider from the image, +/// Generate a single `convex_hull` collider from the image, /// coordinates translated to either side of (0, 0) +#[must_use] pub fn single_convex_hull_collider_translated(image: &Image) -> Option { let e = Edges::from(image); let points = e.single_image_edge_translated(); Collider::convex_hull(points) } -/// Generate a single convex_hull collider from the image, +/// Generate a single `convex_hull` collider from the image, /// coordinates left alone and all in positive x and y +#[must_use] pub fn single_convex_hull_collider_raw(image: &Image) -> Option { let e = Edges::from(image); let points = e.single_image_edge_translated(); @@ -65,6 +71,7 @@ pub fn single_convex_hull_collider_raw(image: &Image) -> Option { /// Generate a single heightfield collider from the image, /// coordinates translated to either side of (0, 0) +#[must_use] pub fn single_heightfield_collider_translated(image: &Image) -> Collider { let e = Edges::from(image); heightfield_collider_from_points(&e.single_image_edge_translated()) @@ -72,6 +79,7 @@ pub fn single_heightfield_collider_translated(image: &Image) -> Collider { /// Generate a single heightfield collider from the image, /// coordinates left alone and all in positive x and y +#[must_use] pub fn single_heightfield_collider_raw(image: &Image) -> Collider { let e = Edges::from(image); heightfield_collider_from_points(&e.single_image_edge_raw()) @@ -79,6 +87,7 @@ pub fn single_heightfield_collider_raw(image: &Image) -> Collider { /// Generate as many polyline colliders as it can find in the image, /// coordinates translated to either side of (0, 0) +#[must_use] pub fn multi_polyline_collider_translated(image: &Image) -> Vec { let e = Edges::from(image); e.multi_image_edge_translated() @@ -89,6 +98,7 @@ pub fn multi_polyline_collider_translated(image: &Image) -> Vec { /// Generate as many polyline colliders as it can find in the image, /// coordinates left alone and all in positive x and y +#[must_use] pub fn multi_polyline_collider_raw(image: &Image) -> Vec { let e = Edges::from(image); e.multi_image_edges_raw() @@ -97,8 +107,9 @@ pub fn multi_polyline_collider_raw(image: &Image) -> Vec { .collect() } -/// Generate as many convex_polyline colliders as it can find in the image, +/// Generate as many `convex_polyline` colliders as it can find in the image, /// coordinates translated to either side of (0, 0) +#[must_use] pub fn multi_convex_polyline_collider_translated(image: &Image) -> Vec> { let e = Edges::from(image); e.multi_image_edge_translated() @@ -110,8 +121,9 @@ pub fn multi_convex_polyline_collider_translated(image: &Image) -> Vec Vec> { let e = Edges::from(image); e.multi_image_edges_raw() @@ -125,6 +137,7 @@ pub fn multi_convex_polyline_collider_raw(image: &Image) -> Vec /// Generate as many heightfield colliders as it can find in the image, /// coordinates translated to either side of (0, 0) +#[must_use] pub fn multi_heightfield_collider_translated(image: &Image) -> Vec { let e = Edges::from(image); e.multi_image_edge_translated() @@ -135,6 +148,7 @@ pub fn multi_heightfield_collider_translated(image: &Image) -> Vec { /// Generate as many heightfield colliders as it can find in the image, /// coordinates left alone and all in positive x and y +#[must_use] pub fn multi_heightfield_collider_raw(image: &Image) -> Vec { let e = Edges::from(image); e.multi_image_edges_raw() @@ -143,8 +157,9 @@ pub fn multi_heightfield_collider_raw(image: &Image) -> Vec { .collect() } -/// Generate as many convex_hull colliders as it can find in the image, +/// Generate as many `convex_hull` colliders as it can find in the image, /// coordinates translated to either side of (0, 0) +#[must_use] pub fn multi_convex_hull_collider_translated(image: &Image) -> Vec> { let e = Edges::from(image); e.multi_image_edge_translated() @@ -153,8 +168,9 @@ pub fn multi_convex_hull_collider_translated(image: &Image) -> Vec Vec> { let e = Edges::from(image); e.multi_image_edges_raw() @@ -176,15 +192,18 @@ fn heightfield_collider_from_points(v: &[Vec2]) -> Collider { fn heights_from_points(points: &[Vec2]) -> Vec { let mut heights: Vec = vec![]; - for p in points { - let elem = heights.iter().enumerate().find(|(_, e)| e.x == p.x); - if let Some((i, e)) = elem { - if e.y < p.y { + for &p in points { + if let Some((i, element)) = heights + .iter() + .enumerate() + .find(|(_, e)| (e.x - p.x).abs() <= f32::EPSILON) + { + if element.y < p.y { heights.remove(i); - heights.insert(i, *p); + heights.insert(i, p); } } else { - heights.push(*p); + heights.push(p); } } diff --git a/src/collider/rapier2d.rs b/src/collider/rapier2d.rs index e89404a..528a5f5 100644 --- a/src/collider/rapier2d.rs +++ b/src/collider/rapier2d.rs @@ -2,66 +2,75 @@ use bevy::prelude::{Image, Vec2}; use bevy_rapier2d::prelude::{Collider, Real}; use edges::Edges; -/// Generate a single bevy_rapier2d polyline collider from the image, +/// Generate a single `bevy_rapier2d` polyline collider from the image, /// coordinates translated to either side of (0, 0) +#[must_use] pub fn single_polyline_collider_translated(image: &Image) -> Collider { let e = Edges::from(image); Collider::polyline(e.single_image_edge_translated(), None) } -/// Generate a single bevy_rapier2d polyline collider from the image, +/// Generate a single `bevy_rapier2d` polyline collider from the image, /// coordinates left alone and all in positive x and y +#[must_use] pub fn single_polyline_collider_raw(image: &Image) -> Collider { let e = Edges::from(image); Collider::polyline(e.single_image_edge_raw(), None) } -/// Generate a single bevy_rapier2d convex_polyline collider from the image, +/// Generate a single `bevy_rapier2d` `convex_polyline` collider from the image, /// coordinates translated to either side of (0, 0) +#[must_use] pub fn single_convex_polyline_collider_translated(image: &Image) -> Option { let e = Edges::from(image); Collider::convex_polyline(e.single_image_edge_translated()) } -/// Generate a single bevy_rapier2d convex_polyline collider from the image, +/// Generate a single `bevy_rapier2d` `convex_polyline` collider from the image, /// coordinates left alone and all in positive x and y +#[must_use] pub fn single_convex_polyline_collider_raw(image: &Image) -> Option { let e = Edges::from(image); Collider::convex_polyline(e.single_image_edge_raw()) } -/// Generate a single bevy_rapier2d convex_hull collider from the image, +/// Generate a single `bevy_rapier2d` `convex_hull` collider from the image, /// coordinates translated to either side of (0, 0) +#[must_use] pub fn single_convex_hull_collider_translated(image: &Image) -> Option { let e = Edges::from(image); let points = e.single_image_edge_translated(); Collider::convex_hull(&points) } -/// Generate a single bevy_rapier2d convex_hull collider from the image, +/// Generate a single `bevy_rapier2d` `convex_hull` collider from the image, /// coordinates left alone and all in positive x and y +#[must_use] pub fn single_convex_hull_collider_raw(image: &Image) -> Option { let e = Edges::from(image); let points = e.single_image_edge_translated(); Collider::convex_hull(&points) } -/// Generate a single bevy_rapier2d heightfield collider from the image, +/// Generate a single `bevy_rapier2d` heightfield collider from the image, /// coordinates translated to either side of (0, 0) +#[must_use] pub fn single_heightfield_collider_translated(image: &Image) -> Collider { let e = Edges::from(image); heightfield_collider_from_points(&e.single_image_edge_translated()) } -/// Generate a single bevy_rapier2d heightfield collider from the image, +/// Generate a single `bevy_rapier2d` heightfield collider from the image, /// coordinates left alone and all in positive x and y +#[must_use] pub fn single_heightfield_collider_raw(image: &Image) -> Collider { let e = Edges::from(image); heightfield_collider_from_points(&e.single_image_edge_raw()) } -/// Generate as many bevy_rapier2d polyline colliders as it can find in the image, +/// Generate as many `bevy_rapier2d` polyline colliders as it can find in the image, /// coordinates translated to either side of (0, 0) +#[must_use] pub fn multi_polyline_collider_translated(image: &Image) -> Vec { let e = Edges::from(image); e.multi_image_edge_translated() @@ -70,8 +79,9 @@ pub fn multi_polyline_collider_translated(image: &Image) -> Vec { .collect() } -/// Generate as many bevy_rapier2d polyline colliders as it can find in the image, +/// Generate as many `bevy_rapier2d` polyline colliders as it can find in the image, /// coordinates left alone and all in positive x and y +#[must_use] pub fn multi_polyline_collider_raw(image: &Image) -> Vec { let e = Edges::from(image); e.multi_image_edges_raw() @@ -80,8 +90,9 @@ pub fn multi_polyline_collider_raw(image: &Image) -> Vec { .collect() } -/// Generate as many bevy_rapier2d convex_polyline colliders as it can find in the image, +/// Generate as many `bevy_rapier2d` `convex_polyline` colliders as it can find in the image, /// coordinates translated to either side of (0, 0) +#[must_use] pub fn multi_convex_polyline_collider_translated(image: &Image) -> Vec> { let e = Edges::from(image); e.multi_image_edge_translated() @@ -90,8 +101,9 @@ pub fn multi_convex_polyline_collider_translated(image: &Image) -> Vec Vec> { let e = Edges::from(image); e.multi_image_edges_raw() @@ -100,8 +112,9 @@ pub fn multi_convex_polyline_collider_raw(image: &Image) -> Vec .collect() } -/// Generate as many bevy_rapier2d heightfield colliders as it can find in the image, +/// Generate as many `bevy_rapier2d` heightfield colliders as it can find in the image, /// coordinates translated to either side of (0, 0) +#[must_use] pub fn multi_heightfield_collider_translated(image: &Image) -> Vec { let e = Edges::from(image); e.multi_image_edge_translated() @@ -110,8 +123,9 @@ pub fn multi_heightfield_collider_translated(image: &Image) -> Vec { .collect() } -/// Generate as many bevy_rapier2d heightfield colliders as it can find in the image, +/// Generate as many `bevy_rapier2d` heightfield colliders as it can find in the image, /// coordinates left alone and all in positive x and y +#[must_use] pub fn multi_heightfield_collider_raw(image: &Image) -> Vec { let e = Edges::from(image); e.multi_image_edges_raw() @@ -120,8 +134,9 @@ pub fn multi_heightfield_collider_raw(image: &Image) -> Vec { .collect() } -/// Generate as many bevy_rapier2d convex_hull colliders as it can find in the image, +/// Generate as many `bevy_rapier2d` `convex_hull` colliders as it can find in the image, /// coordinates translated to either side of (0, 0) +#[must_use] pub fn multi_convex_hull_collider_translated(image: &Image) -> Vec> { let e = Edges::from(image); e.multi_image_edge_translated() @@ -130,8 +145,9 @@ pub fn multi_convex_hull_collider_translated(image: &Image) -> Vec Vec> { let e = Edges::from(image); e.multi_image_edges_raw() @@ -141,26 +157,29 @@ pub fn multi_convex_hull_collider_raw(image: &Image) -> Vec> { } /// parses x,y points into y values at the top of the image (smallest y) and creates a -/// bevy_rapier2d heightfield collider +/// `bevy_rapier2d` heightfield collider fn heightfield_collider_from_points(v: &[Vec2]) -> Collider { let hf = heights_from_points(v); - let x_scale = hf.len() as f32 - 1.0; - Collider::heightfield(hf, Vec2::new(x_scale, 1.0)) + let x_scale = hf.len() - 1; + Collider::heightfield(hf, Vec2::new(x_scale as f32, 1.0)) } /// takes x,y points collects the y values at the top of the image (smallest y) fn heights_from_points(points: &[Vec2]) -> Vec { - let mut heights: Vec = vec![]; - - for p in points { - let elem = heights.iter().enumerate().find(|(_, e)| e.x == p.x); - if let Some((i, e)) = elem { - if e.y < p.y { + let mut heights: Vec = Vec::new(); + + for &p in points { + if let Some((i, element)) = heights + .iter() + .enumerate() + .find(|(_, e)| (e.x - p.x).abs() <= f32::EPSILON) + { + if element.y < p.y { heights.remove(i); - heights.insert(i, *p); + heights.insert(i, p); } } else { - heights.push(*p); + heights.push(p); } } From 8b12b5ed4ee2d21db54780cd048d1039fd4c132d Mon Sep 17 00:00:00 2001 From: salam Date: Mon, 11 Nov 2024 17:51:09 +0900 Subject: [PATCH 03/25] upd: thiserror dependency --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index f332183..861723c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ bevy = "0.14" bevy_rapier2d = { version = "0.27.0", optional = true } avian2d = { version = "0.1.0", optional = true } edges = { version = "0.3.4", features = ["bevy"] } -thiserror = "1.0.57" +thiserror = "2.0.3" [dev-dependencies] bevy_prototype_lyon = "0.12.0" From d2079cb293d6aad43588ef849539c2e885de3e0c Mon Sep 17 00:00:00 2001 From: salam Date: Mon, 11 Nov 2024 17:56:36 +0900 Subject: [PATCH 04/25] dependency `bevy` made dev and replaced with `bevy_math` and `bevy_render`. --- Cargo.toml | 10 +++++++++- src/collider/avian2d.rs | 3 ++- src/collider/rapier2d.rs | 3 ++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 861723c..1022faa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,13 +21,21 @@ avian2d = ["dep:avian2d"] rapier2d = ["dep:bevy_rapier2d"] [dependencies] -bevy = "0.14" bevy_rapier2d = { version = "0.27.0", optional = true } avian2d = { version = "0.1.0", optional = true } edges = { version = "0.3.4", features = ["bevy"] } thiserror = "2.0.3" +[dependencies.bevy_math] +version = "0.14" +default-features = false + +[dependencies.bevy_render] +version = "0.14" +default-features = false + [dev-dependencies] +bevy = "0.14" bevy_prototype_lyon = "0.12.0" indoc = "2.0.4" diff --git a/src/collider/avian2d.rs b/src/collider/avian2d.rs index b462c52..0aab602 100644 --- a/src/collider/avian2d.rs +++ b/src/collider/avian2d.rs @@ -6,7 +6,8 @@ use avian2d::{ }, prelude::Collider, }; -use bevy::prelude::{Image, Vec2}; +use bevy_math::prelude::Vec2; +use bevy_render::prelude::Image; use edges::Edges; /// Generate a single polyline collider from the image, diff --git a/src/collider/rapier2d.rs b/src/collider/rapier2d.rs index 528a5f5..c6da56e 100644 --- a/src/collider/rapier2d.rs +++ b/src/collider/rapier2d.rs @@ -1,5 +1,6 @@ -use bevy::prelude::{Image, Vec2}; +use bevy_math::prelude::Vec2; use bevy_rapier2d::prelude::{Collider, Real}; +use bevy_render::prelude::Image; use edges::Edges; /// Generate a single `bevy_rapier2d` polyline collider from the image, From 1019ba697f0c3b20a633eaa55af7446193ab6e9e Mon Sep 17 00:00:00 2001 From: salam Date: Mon, 11 Nov 2024 18:06:12 +0900 Subject: [PATCH 05/25] add: rayon dependency for faster --- Cargo.toml | 1 + src/collider/avian2d.rs | 33 ++++++++++++++++++++------------- src/collider/rapier2d.rs | 19 ++++++++++--------- 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1022faa..6b8c029 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ avian2d = ["dep:avian2d"] rapier2d = ["dep:bevy_rapier2d"] [dependencies] +rayon = "1.10.0" bevy_rapier2d = { version = "0.27.0", optional = true } avian2d = { version = "0.1.0", optional = true } edges = { version = "0.3.4", features = ["bevy"] } diff --git a/src/collider/avian2d.rs b/src/collider/avian2d.rs index 0aab602..184cab0 100644 --- a/src/collider/avian2d.rs +++ b/src/collider/avian2d.rs @@ -9,6 +9,7 @@ use avian2d::{ use bevy_math::prelude::Vec2; use bevy_render::prelude::Image; use edges::Edges; +use rayon::prelude::*; /// Generate a single polyline collider from the image, /// coordinates translated to either side of (0, 0) @@ -33,7 +34,7 @@ pub fn single_convex_polyline_collider_translated(image: &Image) -> Option>>(); SharedShape::convex_polyline(points).map(Collider::from) @@ -46,7 +47,7 @@ pub fn single_convex_polyline_collider_raw(image: &Image) -> Option { let e = Edges::from(image); let points = e .single_image_edge_raw() - .into_iter() + .into_par_iter() .map(Point::from) .collect::>>(); SharedShape::convex_polyline(points).map(Collider::from) @@ -92,7 +93,7 @@ pub fn single_heightfield_collider_raw(image: &Image) -> Collider { pub fn multi_polyline_collider_translated(image: &Image) -> Vec { let e = Edges::from(image); e.multi_image_edge_translated() - .into_iter() + .into_par_iter() .map(|v| Collider::polyline(v, None)) .collect() } @@ -103,7 +104,7 @@ pub fn multi_polyline_collider_translated(image: &Image) -> Vec { pub fn multi_polyline_collider_raw(image: &Image) -> Vec { let e = Edges::from(image); e.multi_image_edges_raw() - .into_iter() + .into_par_iter() .map(|v| Collider::polyline(v, None)) .collect() } @@ -114,9 +115,12 @@ pub fn multi_polyline_collider_raw(image: &Image) -> Vec { pub fn multi_convex_polyline_collider_translated(image: &Image) -> Vec> { let e = Edges::from(image); e.multi_image_edge_translated() - .into_iter() + .into_par_iter() .map(|v| { - let points = v.into_iter().map(Point::from).collect::>>(); + let points = v + .into_par_iter() + .map(Point::from) + .collect::>>(); SharedShape::convex_polyline(points).map(Collider::from) }) .collect() @@ -128,9 +132,12 @@ pub fn multi_convex_polyline_collider_translated(image: &Image) -> Vec Vec> { let e = Edges::from(image); e.multi_image_edges_raw() - .into_iter() + .into_par_iter() .map(|v| { - let points = v.into_iter().map(Point::from).collect::>>(); + let points = v + .into_par_iter() + .map(Point::from) + .collect::>>(); SharedShape::convex_polyline(points).map(Collider::from) }) .collect() @@ -142,7 +149,7 @@ pub fn multi_convex_polyline_collider_raw(image: &Image) -> Vec pub fn multi_heightfield_collider_translated(image: &Image) -> Vec { let e = Edges::from(image); e.multi_image_edge_translated() - .into_iter() + .into_par_iter() .map(|v| heightfield_collider_from_points(&v)) .collect() } @@ -153,7 +160,7 @@ pub fn multi_heightfield_collider_translated(image: &Image) -> Vec { pub fn multi_heightfield_collider_raw(image: &Image) -> Vec { let e = Edges::from(image); e.multi_image_edges_raw() - .into_iter() + .into_par_iter() .map(|v| heightfield_collider_from_points(&v)) .collect() } @@ -164,7 +171,7 @@ pub fn multi_heightfield_collider_raw(image: &Image) -> Vec { pub fn multi_convex_hull_collider_translated(image: &Image) -> Vec> { let e = Edges::from(image); e.multi_image_edge_translated() - .into_iter() + .into_par_iter() .map(Collider::convex_hull) .collect() } @@ -175,7 +182,7 @@ pub fn multi_convex_hull_collider_translated(image: &Image) -> Vec Vec> { let e = Edges::from(image); e.multi_image_edges_raw() - .into_iter() + .into_par_iter() .map(Collider::convex_hull) .collect() } @@ -208,5 +215,5 @@ fn heights_from_points(points: &[Vec2]) -> Vec { } } - heights.iter().map(|e| e.y).collect::>() + heights.into_par_iter().map(|e| e.y).collect::>() } diff --git a/src/collider/rapier2d.rs b/src/collider/rapier2d.rs index c6da56e..bd8ed14 100644 --- a/src/collider/rapier2d.rs +++ b/src/collider/rapier2d.rs @@ -2,6 +2,7 @@ use bevy_math::prelude::Vec2; use bevy_rapier2d::prelude::{Collider, Real}; use bevy_render::prelude::Image; use edges::Edges; +use rayon::prelude::*; /// Generate a single `bevy_rapier2d` polyline collider from the image, /// coordinates translated to either side of (0, 0) @@ -75,7 +76,7 @@ pub fn single_heightfield_collider_raw(image: &Image) -> Collider { pub fn multi_polyline_collider_translated(image: &Image) -> Vec { let e = Edges::from(image); e.multi_image_edge_translated() - .into_iter() + .into_par_iter() .map(|v| Collider::polyline(v, None)) .collect() } @@ -86,7 +87,7 @@ pub fn multi_polyline_collider_translated(image: &Image) -> Vec { pub fn multi_polyline_collider_raw(image: &Image) -> Vec { let e = Edges::from(image); e.multi_image_edges_raw() - .into_iter() + .into_par_iter() .map(|v| Collider::polyline(v, None)) .collect() } @@ -97,7 +98,7 @@ pub fn multi_polyline_collider_raw(image: &Image) -> Vec { pub fn multi_convex_polyline_collider_translated(image: &Image) -> Vec> { let e = Edges::from(image); e.multi_image_edge_translated() - .into_iter() + .into_par_iter() .map(Collider::convex_polyline) .collect() } @@ -108,7 +109,7 @@ pub fn multi_convex_polyline_collider_translated(image: &Image) -> Vec Vec> { let e = Edges::from(image); e.multi_image_edges_raw() - .into_iter() + .into_par_iter() .map(Collider::convex_polyline) .collect() } @@ -119,7 +120,7 @@ pub fn multi_convex_polyline_collider_raw(image: &Image) -> Vec pub fn multi_heightfield_collider_translated(image: &Image) -> Vec { let e = Edges::from(image); e.multi_image_edge_translated() - .into_iter() + .into_par_iter() .map(|v| heightfield_collider_from_points(&v)) .collect() } @@ -130,7 +131,7 @@ pub fn multi_heightfield_collider_translated(image: &Image) -> Vec { pub fn multi_heightfield_collider_raw(image: &Image) -> Vec { let e = Edges::from(image); e.multi_image_edges_raw() - .into_iter() + .into_par_iter() .map(|v| heightfield_collider_from_points(&v)) .collect() } @@ -141,7 +142,7 @@ pub fn multi_heightfield_collider_raw(image: &Image) -> Vec { pub fn multi_convex_hull_collider_translated(image: &Image) -> Vec> { let e = Edges::from(image); e.multi_image_edge_translated() - .into_iter() + .into_par_iter() .map(|v| Collider::convex_hull(&v)) .collect() } @@ -152,7 +153,7 @@ pub fn multi_convex_hull_collider_translated(image: &Image) -> Vec Vec> { let e = Edges::from(image); e.multi_image_edges_raw() - .into_iter() + .into_par_iter() .map(|v| Collider::convex_hull(&v)) .collect() } @@ -184,5 +185,5 @@ fn heights_from_points(points: &[Vec2]) -> Vec { } } - heights.iter().map(|v| v.y).collect::>() + heights.into_par_iter().map(|v| v.y).collect::>() } From e4c501fa701a47c9ac67bd17e805ede77ad6485a Mon Sep 17 00:00:00 2001 From: salam Date: Tue, 12 Nov 2024 22:27:05 +0900 Subject: [PATCH 06/25] updated `edges` version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 6b8c029..538943d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,9 +22,9 @@ rapier2d = ["dep:bevy_rapier2d"] [dependencies] rayon = "1.10.0" +edges = "0.4.0" bevy_rapier2d = { version = "0.27.0", optional = true } avian2d = { version = "0.1.0", optional = true } -edges = { version = "0.3.4", features = ["bevy"] } thiserror = "2.0.3" [dependencies.bevy_math] From 1ef84220ebe71d8c7110b722a605bd8dd3928878 Mon Sep 17 00:00:00 2001 From: salam Date: Tue, 12 Nov 2024 22:34:43 +0900 Subject: [PATCH 07/25] `initial_xyz` variable renamed to `INITIAL_POSITION` and makes const --- examples/avian2d_colliders.rs | 17 +++++++---------- examples/rapier2d_colliders.rs | 29 +++++++++++++++-------------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/examples/avian2d_colliders.rs b/examples/avian2d_colliders.rs index a73ceb2..166c757 100644 --- a/examples/avian2d_colliders.rs +++ b/examples/avian2d_colliders.rs @@ -61,11 +61,8 @@ fn custom_png_spawn( } } -/// for the movement system -#[derive(Component, Resource)] -pub struct Car { - pub initial_xyz: Vec3, -} +#[derive(Component)] +pub struct Car; /// Car: `convex_polyline` collider /// from assets/sprite/car.png @@ -88,7 +85,7 @@ fn car_spawn( transform: Transform::from_xyz(initial_xyz.x, initial_xyz.y, initial_xyz.z), ..default() }, - Car { initial_xyz }, + Car, RigidBody::Dynamic, DebugRender::default().with_collider_color(css::VIOLET.into()), )); @@ -363,10 +360,10 @@ pub fn controls_text_spawn(mut commands: Commands, game_assets: Res) } pub fn car_movement( - mut query: Query<(&Car, &mut LinearVelocity, &mut Transform)>, + mut query: Query<(&mut LinearVelocity, &mut Transform), With>, keys: Res>, ) { - for (car, mut linear_velocity, mut transform) in &mut query { + for (mut linear_velocity, mut transform) in &mut query { if keys.pressed(KeyCode::KeyD) { linear_velocity.x += 30.0; } @@ -378,8 +375,8 @@ pub fn car_movement( if keys.pressed(KeyCode::Digit1) { linear_velocity.x = 0.0; linear_velocity.y = 0.0; - *transform = - Transform::from_xyz(car.initial_xyz.x, car.initial_xyz.y, car.initial_xyz.z); + *transform = INITIAL_POSITION; } } } +const INITIAL_POSITION: Transform = Transform::from_xyz(-200.0, 2.0, 0.0); diff --git a/examples/rapier2d_colliders.rs b/examples/rapier2d_colliders.rs index 21bcf0b..be2951e 100644 --- a/examples/rapier2d_colliders.rs +++ b/examples/rapier2d_colliders.rs @@ -78,10 +78,8 @@ fn custom_png_spawn( } /// for the movement system -#[derive(Component, Resource)] -pub struct Car { - pub initial_xyz: Vec3, -} +#[derive(Component)] +pub struct Car; /// Car: `bevy_rapier2d` `convex_polyline` collider /// from assets/sprite/car.png @@ -90,7 +88,6 @@ fn car_spawn( game_assets: Res, image_assets: Res>, ) { - let initial_xyz = Vec3::new(-200.0, 2.0, 0.0); let sprite_handle = game_assets.image_handles.get("car_handle"); if sprite_handle.is_none() { return; @@ -100,12 +97,13 @@ fn car_spawn( commands.spawn(( collider, RigidBody::Dynamic, + Velocity::default(), SpriteBundle { texture: sprite_handle.unwrap().clone(), - transform: Transform::from_xyz(initial_xyz.x, initial_xyz.y, initial_xyz.z), + transform: INITIAL_POSITION, ..default() }, - Car { initial_xyz }, + Car, )); } @@ -381,19 +379,22 @@ pub fn controls_text_spawn(mut commands: Commands, game_assets: Res) }); } -pub fn car_movement(mut query: Query<(&Car, &mut Transform)>, keys: Res>) { - for (car, mut transform) in &mut query { +pub fn car_movement( + mut query: Query<(&mut Transform, &mut Velocity), With>, + keys: Res>, +) { + for (mut transform, mut velocity) in &mut query { + let linear_velocity = &mut velocity.linvel; if keys.pressed(KeyCode::KeyD) { - transform.translation.x += 5.0; + linear_velocity.x += 30.0; } if keys.pressed(KeyCode::KeyA) { - transform.translation.x -= 5.0; + linear_velocity.x -= 30.0; } - if keys.pressed(KeyCode::Digit1) { - *transform = - Transform::from_xyz(car.initial_xyz.x, car.initial_xyz.y, car.initial_xyz.z); + *transform = INITIAL_POSITION; } } } +const INITIAL_POSITION: Transform = Transform::from_xyz(-200.0, 2.0, 0.0); From 3a51cc0133d13571e323232077fba111b94e9e3d Mon Sep 17 00:00:00 2001 From: salam Date: Tue, 12 Nov 2024 22:37:01 +0900 Subject: [PATCH 08/25] `ImagePlugin` type changed to `default_nearest` --- examples/avian2d_colliders.rs | 1 + examples/rapier2d_colliders.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/examples/avian2d_colliders.rs b/examples/avian2d_colliders.rs index 166c757..d738f2a 100644 --- a/examples/avian2d_colliders.rs +++ b/examples/avian2d_colliders.rs @@ -174,6 +174,7 @@ fn main() { App::new() .add_plugins( DefaultPlugins + .set(ImagePlugin::default_nearest()) .set(WindowPlugin { primary_window: Some(Window { title: "colliders".to_string(), diff --git a/examples/rapier2d_colliders.rs b/examples/rapier2d_colliders.rs index be2951e..4a2f319 100644 --- a/examples/rapier2d_colliders.rs +++ b/examples/rapier2d_colliders.rs @@ -188,6 +188,7 @@ fn main() { App::new() .add_plugins( DefaultPlugins + .set(ImagePlugin::default_nearest()) .set(WindowPlugin { primary_window: Some(Window { title: "colliders".to_string(), From 43b2e2cc52f9348f693b6708afd2bf02a2829060 Mon Sep 17 00:00:00 2001 From: salam Date: Tue, 12 Nov 2024 22:40:02 +0900 Subject: [PATCH 09/25] changed: pixels per meter parameter from 1 to 100 for larger mass of objects --- examples/rapier2d_colliders.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/rapier2d_colliders.rs b/examples/rapier2d_colliders.rs index 4a2f319..7547169 100644 --- a/examples/rapier2d_colliders.rs +++ b/examples/rapier2d_colliders.rs @@ -213,7 +213,7 @@ fn main() { .insert_resource(ClearColor(Color::srgb(0.0, 0.0, 0.0))) .add_plugins(ShapePlugin) .add_plugins(WireframePlugin) - .add_plugins(RapierPhysicsPlugin::::pixels_per_meter(1.0)) + .add_plugins(RapierPhysicsPlugin::::pixels_per_meter(100.0)) .add_plugins(RapierDebugRenderPlugin { style: DebugRenderStyle { collider_fixed_color: [360., 100., 100., 1.], From 881b24d9749b873709e3ee27bda1a4ac002d4cd1 Mon Sep 17 00:00:00 2001 From: salam Date: Tue, 12 Nov 2024 22:43:00 +0900 Subject: [PATCH 10/25] inverted camera controls for convenience --- examples/avian2d_colliders.rs | 8 ++++---- examples/rapier2d_colliders.rs | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/avian2d_colliders.rs b/examples/avian2d_colliders.rs index d738f2a..13f3de5 100644 --- a/examples/avian2d_colliders.rs +++ b/examples/avian2d_colliders.rs @@ -255,18 +255,18 @@ pub fn camera_movement( ) { for (_, mut projection, mut transform) in &mut query { if keys.pressed(KeyCode::ArrowLeft) { - transform.translation.x += 10.0; + transform.translation.x -= 10.0; } if keys.pressed(KeyCode::ArrowRight) { - transform.translation.x -= 10.0; + transform.translation.x += 10.0; } if keys.pressed(KeyCode::ArrowUp) { - transform.translation.y -= 10.0; + transform.translation.y += 10.0; } if keys.pressed(KeyCode::ArrowDown) { - transform.translation.y += 10.0; + transform.translation.y -= 10.0; } if keys.pressed(KeyCode::KeyW) { diff --git a/examples/rapier2d_colliders.rs b/examples/rapier2d_colliders.rs index 7547169..6899820 100644 --- a/examples/rapier2d_colliders.rs +++ b/examples/rapier2d_colliders.rs @@ -275,18 +275,18 @@ pub fn camera_movement( ) { for (_, mut projection, mut transform) in &mut query { if keys.pressed(KeyCode::ArrowLeft) { - transform.translation.x += 10.0; + transform.translation.x -= 10.0; } if keys.pressed(KeyCode::ArrowRight) { - transform.translation.x -= 10.0; + transform.translation.x += 10.0; } if keys.pressed(KeyCode::ArrowUp) { - transform.translation.y -= 10.0; + transform.translation.y += 10.0; } if keys.pressed(KeyCode::ArrowDown) { - transform.translation.y += 10.0; + transform.translation.y -= 10.0; } if keys.pressed(KeyCode::KeyW) { From 554404b0386a8daac32f8485c89d9ae03b2ed407 Mon Sep 17 00:00:00 2001 From: salam Date: Tue, 12 Nov 2024 23:05:16 +0900 Subject: [PATCH 11/25] refactor: functions to generate colliders and its docs simplified, inner logic moved to utils --- src/avian2d.rs | 117 +++++++++++++++++++++ src/collider/avian2d.rs | 219 --------------------------------------- src/collider/mod.rs | 5 - src/collider/rapier2d.rs | 189 --------------------------------- src/lib.rs | 12 +-- src/rapier2d.rs | 117 +++++++++++++++++++++ src/utils.rs | 97 +++++++++++++++++ 7 files changed, 336 insertions(+), 420 deletions(-) create mode 100644 src/avian2d.rs delete mode 100644 src/collider/avian2d.rs delete mode 100644 src/collider/mod.rs delete mode 100644 src/collider/rapier2d.rs create mode 100644 src/rapier2d.rs create mode 100644 src/utils.rs diff --git a/src/avian2d.rs b/src/avian2d.rs new file mode 100644 index 0000000..ea30d2e --- /dev/null +++ b/src/avian2d.rs @@ -0,0 +1,117 @@ +use crate::utils::{ + avian2d::{convex_hull_collider, convex_polyline_collider, heightfield_collider, Collider}, + generate_collider, generate_multi_collider, +}; +use bevy_render::prelude::Image; + +/// Generate a single polyline collider from the image, +/// coordinates translated to either side of (0, 0) +#[must_use] +pub fn single_polyline_collider_translated(image: &Image) -> Collider { + generate_collider(image, |points| Collider::polyline(points, None), true) +} + +/// Generate a single polyline collider from the image, +/// coordinates left alone and all in positive x and y +#[must_use] +pub fn single_polyline_collider_raw(image: &Image) -> Collider { + generate_collider(image, |points| Collider::polyline(points, None), false) +} + +/// Generate a single `convex_polyline` collider from the image, +/// coordinates translated to either side of (0, 0) +#[must_use] +pub fn single_convex_polyline_collider_translated(image: &Image) -> Option { + generate_collider(image, convex_polyline_collider, true) +} + +/// Generate a single `convex_polyline` collider from the image, +/// coordinates left alone and all in positive x and y +#[must_use] +pub fn single_convex_polyline_collider_raw(image: &Image) -> Option { + generate_collider(image, convex_polyline_collider, false) +} + +/// Generate a single `convex_hull` collider from the image, +/// coordinates translated to either side of (0, 0) +#[must_use] +pub fn single_convex_hull_collider_translated(image: &Image) -> Option { + generate_collider(image, convex_hull_collider, true) +} + +/// Generate a single `convex_hull` collider from the image, +/// coordinates left alone and all in positive x and y +#[must_use] +pub fn single_convex_hull_collider_raw(image: &Image) -> Option { + generate_collider(image, convex_hull_collider, false) +} + +/// Generate a single heightfield collider from the image, +/// coordinates translated to either side of (0, 0) +#[must_use] +pub fn single_heightfield_collider_translated(image: &Image) -> Collider { + generate_collider(image, heightfield_collider, true) +} + +/// Generate a single heightfield collider from the image, +/// coordinates left alone and all in positive x and y +#[must_use] +pub fn single_heightfield_collider_raw(image: &Image) -> Collider { + generate_collider(image, heightfield_collider, false) +} + +/// Generate as many polyline colliders as it can find in the image, +/// coordinates translated to either side of (0, 0) +#[must_use] +pub fn multi_polyline_collider_translated(image: &Image) -> Vec { + generate_multi_collider(image, |points| Collider::polyline(points, None), true) +} + +/// Generate as many polyline colliders as it can find in the image, +/// coordinates left alone and all in positive x and y +#[must_use] +pub fn multi_polyline_collider_raw(image: &Image) -> Vec { + generate_multi_collider(image, |points| Collider::polyline(points, None), false) +} + +/// Generate as many `convex_polyline` colliders as it can find in the image, +/// coordinates translated to either side of (0, 0) +#[must_use] +pub fn multi_convex_polyline_collider_translated(image: &Image) -> Vec> { + generate_multi_collider(image, convex_polyline_collider, true) +} + +/// Generate as many `convex_polyline` colliders as it can find in the image, +/// coordinates left alone and all in positive x and y +#[must_use] +pub fn multi_convex_polyline_collider_raw(image: &Image) -> Vec> { + generate_multi_collider(image, convex_polyline_collider, false) +} + +/// Generate as many heightfield colliders as it can find in the image, +/// coordinates translated to either side of (0, 0) +#[must_use] +pub fn multi_heightfield_collider_translated(image: &Image) -> Vec { + generate_multi_collider(image, heightfield_collider, true) +} + +/// Generate as many heightfield colliders as it can find in the image, +/// coordinates left alone and all in positive x and y +#[must_use] +pub fn multi_heightfield_collider_raw(image: &Image) -> Vec { + generate_multi_collider(image, heightfield_collider, false) +} + +/// Generate as many `convex_hull` colliders as it can find in the image, +/// coordinates translated to either side of (0, 0) +#[must_use] +pub fn multi_convex_hull_collider_translated(image: &Image) -> Vec> { + generate_multi_collider(image, convex_hull_collider, true) +} + +/// Generate as many `convex_hull` colliders as it can find in the image, +/// coordinates left alone and all in positive x and y +#[must_use] +pub fn multi_convex_hull_collider_raw(image: &Image) -> Vec> { + generate_multi_collider(image, convex_hull_collider, false) +} diff --git a/src/collider/avian2d.rs b/src/collider/avian2d.rs deleted file mode 100644 index 184cab0..0000000 --- a/src/collider/avian2d.rs +++ /dev/null @@ -1,219 +0,0 @@ -use avian2d::{ - math::{Scalar, Vector, Vector2}, - parry::{ - math::{Point, Real}, - shape::SharedShape, - }, - prelude::Collider, -}; -use bevy_math::prelude::Vec2; -use bevy_render::prelude::Image; -use edges::Edges; -use rayon::prelude::*; - -/// Generate a single polyline collider from the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn single_polyline_collider_translated(image: &Image) -> Collider { - let e = Edges::from(image); - Collider::polyline(e.single_image_edge_translated(), None) -} - -/// Generate a single polyline collider from the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn single_polyline_collider_raw(image: &Image) -> Collider { - let e = Edges::from(image); - Collider::polyline(e.single_image_edge_raw(), None) -} - -/// Generate a single `convex_polyline` collider from the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn single_convex_polyline_collider_translated(image: &Image) -> Option { - let e = Edges::from(image); - let points = e - .single_image_edge_translated() - .into_par_iter() - .map(Point::from) - .collect::>>(); - SharedShape::convex_polyline(points).map(Collider::from) -} - -/// Generate a single `convex_polyline` collider from the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn single_convex_polyline_collider_raw(image: &Image) -> Option { - let e = Edges::from(image); - let points = e - .single_image_edge_raw() - .into_par_iter() - .map(Point::from) - .collect::>>(); - SharedShape::convex_polyline(points).map(Collider::from) -} - -/// Generate a single `convex_hull` collider from the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn single_convex_hull_collider_translated(image: &Image) -> Option { - let e = Edges::from(image); - let points = e.single_image_edge_translated(); - Collider::convex_hull(points) -} - -/// Generate a single `convex_hull` collider from the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn single_convex_hull_collider_raw(image: &Image) -> Option { - let e = Edges::from(image); - let points = e.single_image_edge_translated(); - Collider::convex_hull(points) -} - -/// Generate a single heightfield collider from the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn single_heightfield_collider_translated(image: &Image) -> Collider { - let e = Edges::from(image); - heightfield_collider_from_points(&e.single_image_edge_translated()) -} - -/// Generate a single heightfield collider from the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn single_heightfield_collider_raw(image: &Image) -> Collider { - let e = Edges::from(image); - heightfield_collider_from_points(&e.single_image_edge_raw()) -} - -/// Generate as many polyline colliders as it can find in the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn multi_polyline_collider_translated(image: &Image) -> Vec { - let e = Edges::from(image); - e.multi_image_edge_translated() - .into_par_iter() - .map(|v| Collider::polyline(v, None)) - .collect() -} - -/// Generate as many polyline colliders as it can find in the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn multi_polyline_collider_raw(image: &Image) -> Vec { - let e = Edges::from(image); - e.multi_image_edges_raw() - .into_par_iter() - .map(|v| Collider::polyline(v, None)) - .collect() -} - -/// Generate as many `convex_polyline` colliders as it can find in the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn multi_convex_polyline_collider_translated(image: &Image) -> Vec> { - let e = Edges::from(image); - e.multi_image_edge_translated() - .into_par_iter() - .map(|v| { - let points = v - .into_par_iter() - .map(Point::from) - .collect::>>(); - SharedShape::convex_polyline(points).map(Collider::from) - }) - .collect() -} - -/// Generate as many `convex_polyline` colliders as it can find in the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn multi_convex_polyline_collider_raw(image: &Image) -> Vec> { - let e = Edges::from(image); - e.multi_image_edges_raw() - .into_par_iter() - .map(|v| { - let points = v - .into_par_iter() - .map(Point::from) - .collect::>>(); - SharedShape::convex_polyline(points).map(Collider::from) - }) - .collect() -} - -/// Generate as many heightfield colliders as it can find in the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn multi_heightfield_collider_translated(image: &Image) -> Vec { - let e = Edges::from(image); - e.multi_image_edge_translated() - .into_par_iter() - .map(|v| heightfield_collider_from_points(&v)) - .collect() -} - -/// Generate as many heightfield colliders as it can find in the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn multi_heightfield_collider_raw(image: &Image) -> Vec { - let e = Edges::from(image); - e.multi_image_edges_raw() - .into_par_iter() - .map(|v| heightfield_collider_from_points(&v)) - .collect() -} - -/// Generate as many `convex_hull` colliders as it can find in the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn multi_convex_hull_collider_translated(image: &Image) -> Vec> { - let e = Edges::from(image); - e.multi_image_edge_translated() - .into_par_iter() - .map(Collider::convex_hull) - .collect() -} - -/// Generate as many `convex_hull` colliders as it can find in the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn multi_convex_hull_collider_raw(image: &Image) -> Vec> { - let e = Edges::from(image); - e.multi_image_edges_raw() - .into_par_iter() - .map(Collider::convex_hull) - .collect() -} - -/// parses x,y points into y values at the top of the image (smallest y) and creates a -/// heightfield collider -fn heightfield_collider_from_points(v: &[Vec2]) -> Collider { - let hf: Vec = heights_from_points(v); - let x_scale: Real = hf.len() as f32 - 1.0; - let scale: Vector = Vector2::new(x_scale, 1.0); - Collider::heightfield(hf, scale) -} - -/// takes x,y points collects the y values at the top of the image (smallest y) -fn heights_from_points(points: &[Vec2]) -> Vec { - let mut heights: Vec = vec![]; - - for &p in points { - if let Some((i, element)) = heights - .iter() - .enumerate() - .find(|(_, e)| (e.x - p.x).abs() <= f32::EPSILON) - { - if element.y < p.y { - heights.remove(i); - heights.insert(i, p); - } - } else { - heights.push(p); - } - } - - heights.into_par_iter().map(|e| e.y).collect::>() -} diff --git a/src/collider/mod.rs b/src/collider/mod.rs deleted file mode 100644 index 28de707..0000000 --- a/src/collider/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -#[cfg(feature = "avian2d")] -pub mod avian2d; - -#[cfg(feature = "rapier2d")] -pub mod rapier2d; diff --git a/src/collider/rapier2d.rs b/src/collider/rapier2d.rs deleted file mode 100644 index bd8ed14..0000000 --- a/src/collider/rapier2d.rs +++ /dev/null @@ -1,189 +0,0 @@ -use bevy_math::prelude::Vec2; -use bevy_rapier2d::prelude::{Collider, Real}; -use bevy_render::prelude::Image; -use edges::Edges; -use rayon::prelude::*; - -/// Generate a single `bevy_rapier2d` polyline collider from the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn single_polyline_collider_translated(image: &Image) -> Collider { - let e = Edges::from(image); - Collider::polyline(e.single_image_edge_translated(), None) -} - -/// Generate a single `bevy_rapier2d` polyline collider from the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn single_polyline_collider_raw(image: &Image) -> Collider { - let e = Edges::from(image); - Collider::polyline(e.single_image_edge_raw(), None) -} - -/// Generate a single `bevy_rapier2d` `convex_polyline` collider from the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn single_convex_polyline_collider_translated(image: &Image) -> Option { - let e = Edges::from(image); - Collider::convex_polyline(e.single_image_edge_translated()) -} - -/// Generate a single `bevy_rapier2d` `convex_polyline` collider from the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn single_convex_polyline_collider_raw(image: &Image) -> Option { - let e = Edges::from(image); - Collider::convex_polyline(e.single_image_edge_raw()) -} - -/// Generate a single `bevy_rapier2d` `convex_hull` collider from the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn single_convex_hull_collider_translated(image: &Image) -> Option { - let e = Edges::from(image); - let points = e.single_image_edge_translated(); - Collider::convex_hull(&points) -} - -/// Generate a single `bevy_rapier2d` `convex_hull` collider from the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn single_convex_hull_collider_raw(image: &Image) -> Option { - let e = Edges::from(image); - let points = e.single_image_edge_translated(); - Collider::convex_hull(&points) -} - -/// Generate a single `bevy_rapier2d` heightfield collider from the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn single_heightfield_collider_translated(image: &Image) -> Collider { - let e = Edges::from(image); - heightfield_collider_from_points(&e.single_image_edge_translated()) -} - -/// Generate a single `bevy_rapier2d` heightfield collider from the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn single_heightfield_collider_raw(image: &Image) -> Collider { - let e = Edges::from(image); - heightfield_collider_from_points(&e.single_image_edge_raw()) -} - -/// Generate as many `bevy_rapier2d` polyline colliders as it can find in the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn multi_polyline_collider_translated(image: &Image) -> Vec { - let e = Edges::from(image); - e.multi_image_edge_translated() - .into_par_iter() - .map(|v| Collider::polyline(v, None)) - .collect() -} - -/// Generate as many `bevy_rapier2d` polyline colliders as it can find in the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn multi_polyline_collider_raw(image: &Image) -> Vec { - let e = Edges::from(image); - e.multi_image_edges_raw() - .into_par_iter() - .map(|v| Collider::polyline(v, None)) - .collect() -} - -/// Generate as many `bevy_rapier2d` `convex_polyline` colliders as it can find in the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn multi_convex_polyline_collider_translated(image: &Image) -> Vec> { - let e = Edges::from(image); - e.multi_image_edge_translated() - .into_par_iter() - .map(Collider::convex_polyline) - .collect() -} - -/// Generate as many `bevy_rapier2d` `convex_polyline` colliders as it can find in the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn multi_convex_polyline_collider_raw(image: &Image) -> Vec> { - let e = Edges::from(image); - e.multi_image_edges_raw() - .into_par_iter() - .map(Collider::convex_polyline) - .collect() -} - -/// Generate as many `bevy_rapier2d` heightfield colliders as it can find in the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn multi_heightfield_collider_translated(image: &Image) -> Vec { - let e = Edges::from(image); - e.multi_image_edge_translated() - .into_par_iter() - .map(|v| heightfield_collider_from_points(&v)) - .collect() -} - -/// Generate as many `bevy_rapier2d` heightfield colliders as it can find in the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn multi_heightfield_collider_raw(image: &Image) -> Vec { - let e = Edges::from(image); - e.multi_image_edges_raw() - .into_par_iter() - .map(|v| heightfield_collider_from_points(&v)) - .collect() -} - -/// Generate as many `bevy_rapier2d` `convex_hull` colliders as it can find in the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn multi_convex_hull_collider_translated(image: &Image) -> Vec> { - let e = Edges::from(image); - e.multi_image_edge_translated() - .into_par_iter() - .map(|v| Collider::convex_hull(&v)) - .collect() -} - -/// Generate as many `bevy_rapier2d` `convex_hull` colliders as it can find in the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn multi_convex_hull_collider_raw(image: &Image) -> Vec> { - let e = Edges::from(image); - e.multi_image_edges_raw() - .into_par_iter() - .map(|v| Collider::convex_hull(&v)) - .collect() -} - -/// parses x,y points into y values at the top of the image (smallest y) and creates a -/// `bevy_rapier2d` heightfield collider -fn heightfield_collider_from_points(v: &[Vec2]) -> Collider { - let hf = heights_from_points(v); - let x_scale = hf.len() - 1; - Collider::heightfield(hf, Vec2::new(x_scale as f32, 1.0)) -} - -/// takes x,y points collects the y values at the top of the image (smallest y) -fn heights_from_points(points: &[Vec2]) -> Vec { - let mut heights: Vec = Vec::new(); - - for &p in points { - if let Some((i, element)) = heights - .iter() - .enumerate() - .find(|(_, e)| (e.x - p.x).abs() <= f32::EPSILON) - { - if element.y < p.y { - heights.remove(i); - heights.insert(i, p); - } - } else { - heights.push(p); - } - } - - heights.into_par_iter().map(|v| v.y).collect::>() -} diff --git a/src/lib.rs b/src/lib.rs index ea3f6f2..6ec6c32 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,11 +1,9 @@ #![doc = include_str!("../README.md")] -mod collider; - -#[cfg(feature = "rapier2d")] -pub use collider::rapier2d; +pub use edges::Edges; #[cfg(feature = "avian2d")] -pub use collider::avian2d; - -pub use ::edges::Edges; +pub mod avian2d; +#[cfg(feature = "rapier2d")] +pub mod rapier2d; +mod utils; diff --git a/src/rapier2d.rs b/src/rapier2d.rs new file mode 100644 index 0000000..0375fd8 --- /dev/null +++ b/src/rapier2d.rs @@ -0,0 +1,117 @@ +use crate::utils::{ + generate_collider, generate_multi_collider, + rapier2d::{convex_hull_collider, convex_polyline_collider, heightfield_collider, Collider}, +}; +use bevy_render::prelude::Image; + +/// Generate a single polyline collider from the image, +/// coordinates translated to either side of (0, 0) +#[must_use] +pub fn single_polyline_collider_translated(image: &Image) -> Collider { + generate_collider(image, |points| Collider::polyline(points, None), true) +} + +/// Generate a single polyline collider from the image, +/// coordinates left alone and all in positive x and y +#[must_use] +pub fn single_polyline_collider_raw(image: &Image) -> Collider { + generate_collider(image, |points| Collider::polyline(points, None), false) +} + +/// Generate a single `convex_polyline` collider from the image, +/// coordinates translated to either side of (0, 0) +#[must_use] +pub fn single_convex_polyline_collider_translated(image: &Image) -> Option { + generate_collider(image, convex_polyline_collider, true) +} + +/// Generate a single `convex_polyline` collider from the image, +/// coordinates left alone and all in positive x and y +#[must_use] +pub fn single_convex_polyline_collider_raw(image: &Image) -> Option { + generate_collider(image, convex_polyline_collider, false) +} + +/// Generate a single `convex_hull` collider from the image, +/// coordinates translated to either side of (0, 0) +#[must_use] +pub fn single_convex_hull_collider_translated(image: &Image) -> Option { + generate_collider(image, convex_hull_collider, true) +} + +/// Generate a single `convex_hull` collider from the image, +/// coordinates left alone and all in positive x and y +#[must_use] +pub fn single_convex_hull_collider_raw(image: &Image) -> Option { + generate_collider(image, convex_hull_collider, false) +} + +/// Generate a single heightfield collider from the image, +/// coordinates translated to either side of (0, 0) +#[must_use] +pub fn single_heightfield_collider_translated(image: &Image) -> Collider { + generate_collider(image, heightfield_collider, true) +} + +/// Generate a single heightfield collider from the image, +/// coordinates left alone and all in positive x and y +#[must_use] +pub fn single_heightfield_collider_raw(image: &Image) -> Collider { + generate_collider(image, heightfield_collider, false) +} + +/// Generate as many polyline colliders as it can find in the image, +/// coordinates translated to either side of (0, 0) +#[must_use] +pub fn multi_polyline_collider_translated(image: &Image) -> Vec { + generate_multi_collider(image, |points| Collider::polyline(points, None), true) +} + +/// Generate as many polyline colliders as it can find in the image, +/// coordinates left alone and all in positive x and y +#[must_use] +pub fn multi_polyline_collider_raw(image: &Image) -> Vec { + generate_multi_collider(image, |points| Collider::polyline(points, None), false) +} + +/// Generate as many `convex_polyline` colliders as it can find in the image, +/// coordinates translated to either side of (0, 0) +#[must_use] +pub fn multi_convex_polyline_collider_translated(image: &Image) -> Vec> { + generate_multi_collider(image, convex_polyline_collider, true) +} + +/// Generate as many `convex_polyline` colliders as it can find in the image, +/// coordinates left alone and all in positive x and y +#[must_use] +pub fn multi_convex_polyline_collider_raw(image: &Image) -> Vec> { + generate_multi_collider(image, convex_polyline_collider, false) +} + +/// Generate as many heightfield colliders as it can find in the image, +/// coordinates translated to either side of (0, 0) +#[must_use] +pub fn multi_heightfield_collider_translated(image: &Image) -> Vec { + generate_multi_collider(image, heightfield_collider, true) +} + +/// Generate as many heightfield colliders as it can find in the image, +/// coordinates left alone and all in positive x and y +#[must_use] +pub fn multi_heightfield_collider_raw(image: &Image) -> Vec { + generate_multi_collider(image, heightfield_collider, false) +} + +/// Generate as many `convex_hull` colliders as it can find in the image, +/// coordinates translated to either side of (0, 0) +#[must_use] +pub fn multi_convex_hull_collider_translated(image: &Image) -> Vec> { + generate_multi_collider(image, convex_hull_collider, true) +} + +/// Generate as many `convex_hull` colliders as it can find in the image, +/// coordinates left alone and all in positive x and y +#[must_use] +pub fn multi_convex_hull_collider_raw(image: &Image) -> Vec> { + generate_multi_collider(image, convex_hull_collider, false) +} diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..23044bf --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,97 @@ +use bevy_render::prelude::Image; +use edges::{Edges, Vec2}; +use rayon::prelude::*; + +#[cfg(feature = "avian2d")] +pub mod avian2d { + use super::{heights_and_scale, Vec2}; + + use avian2d::parry::{math::Point, shape::SharedShape}; + use rayon::prelude::*; + + pub use avian2d::prelude::Collider; + + /// Generate `convex_polyline` collider from the points, + pub fn convex_polyline_collider(points: Vec) -> Option { + SharedShape::convex_polyline(points.into_par_iter().map(Point::from).collect()) + .map(Collider::from) + } + + /// Generate `convex_hull` collider from the points, + pub fn convex_hull_collider(points: Vec) -> Option { + Collider::convex_hull(points) + } + + /// takes x,y points collects the y values at the top of the image (smallest y) + /// and creates a heightfield collider + pub fn heightfield_collider(v: Vec) -> Collider { + let (heights, scale) = heights_and_scale(v); + Collider::heightfield(heights, scale) + } +} + +#[cfg(feature = "rapier2d")] +pub mod rapier2d { + use super::{heights_and_scale, Vec2}; + + pub use bevy_rapier2d::prelude::Collider; + + /// Generate `convex_polyline` collider from the points, + pub fn convex_polyline_collider(points: Vec) -> Option { + Collider::convex_polyline(points) + } + + /// Generate `convex_hull` collider from the points, + #[allow(clippy::needless_pass_by_value)] + pub fn convex_hull_collider(points: Vec) -> Option { + Collider::convex_hull(&points) + } + + /// takes x,y points collects the y values at the top of the image (biggest y) + /// and creates a heightfield collider + pub fn heightfield_collider(v: Vec) -> Collider { + let (heights, scale) = heights_and_scale(v); + Collider::heightfield(heights, scale) + } +} + +/// takes x,y points collects the y values at the top of the image (biggest y) +fn heights_and_scale(mut points: Vec) -> (Vec, Vec2) { + points.sort_by(|p1, p2| p1.x.partial_cmp(&p2.x).unwrap()); + let heights = points + .par_chunk_by(|p1, p2| (p1.x - p2.x).abs() <= f32::EPSILON) + .map(|chunk| chunk.iter().map(|p| p.y).reduce(f32::max).unwrap()) + .collect::>(); + + let x_scale = heights.len() - 1; + (heights, Vec2::new(x_scale as f32, 1.0)) +} + +/// Generate colliders from the image based on the provided collider type and coordinate handling. +pub fn generate_collider(image: &Image, collider_fn: F, translated: bool) -> T +where + F: Fn(Vec) -> T, +{ + let edges = Edges::from(image); + collider_fn( + edges + .image_edges(translated) + .into_par_iter() + .flatten() + .collect(), + ) +} + +/// Generate multiple colliders from the image based on the provided collider type and coordinate handling. +pub fn generate_multi_collider(image: &Image, collider_fn: F, translated: bool) -> Vec +where + F: Fn(Vec) -> R + Send + Sync, + R: Send, +{ + let edges = Edges::from(image); + edges + .image_edges(translated) + .into_par_iter() + .map(collider_fn) + .collect() +} From 594e767586494e821009f18fe8cbd96fe1b3703e Mon Sep 17 00:00:00 2001 From: salam Date: Wed, 13 Nov 2024 02:47:29 +0900 Subject: [PATCH 12/25] add: `parallel` feature --- Cargo.toml | 14 +++++--------- src/utils.rs | 38 +++++++++++++++++++++++++++----------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 538943d..6b0db3b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,24 +16,20 @@ cast_precision_loss = { level = "allow", priority = 1 } pedantic = { level = "warn", priority = 0 } [features] -default = ["avian2d", "rapier2d"] +default = ["avian2d", "rapier2d", "parallel"] avian2d = ["dep:avian2d"] rapier2d = ["dep:bevy_rapier2d"] +parallel = ["dep:rayon"] [dependencies] -rayon = "1.10.0" edges = "0.4.0" bevy_rapier2d = { version = "0.27.0", optional = true } avian2d = { version = "0.1.0", optional = true } +bevy_math = { version = "0.14", default-features = false } +bevy_render = { version = "0.14", default-features = false } +rayon = { version = "1.10.0", optional = true } thiserror = "2.0.3" -[dependencies.bevy_math] -version = "0.14" -default-features = false - -[dependencies.bevy_render] -version = "0.14" -default-features = false [dev-dependencies] bevy = "0.14" diff --git a/src/utils.rs b/src/utils.rs index 23044bf..938f8b0 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,19 +1,33 @@ use bevy_render::prelude::Image; use edges::{Edges, Vec2}; + +#[cfg(feature = "parallel")] use rayon::prelude::*; +macro_rules! into_par_iter { + ($t: expr) => {{ + #[cfg(not(feature = "parallel"))] + let it = $t.into_iter(); + + #[cfg(feature = "parallel")] + let it = $t.into_par_iter(); + it + }}; +} + #[cfg(feature = "avian2d")] pub mod avian2d { use super::{heights_and_scale, Vec2}; use avian2d::parry::{math::Point, shape::SharedShape}; + #[cfg(feature = "parallel")] use rayon::prelude::*; pub use avian2d::prelude::Collider; /// Generate `convex_polyline` collider from the points, pub fn convex_polyline_collider(points: Vec) -> Option { - SharedShape::convex_polyline(points.into_par_iter().map(Point::from).collect()) + SharedShape::convex_polyline(into_par_iter!(points).map(Point::from).collect()) .map(Collider::from) } @@ -58,10 +72,16 @@ pub mod rapier2d { /// takes x,y points collects the y values at the top of the image (biggest y) fn heights_and_scale(mut points: Vec) -> (Vec, Vec2) { points.sort_by(|p1, p2| p1.x.partial_cmp(&p2.x).unwrap()); - let heights = points - .par_chunk_by(|p1, p2| (p1.x - p2.x).abs() <= f32::EPSILON) - .map(|chunk| chunk.iter().map(|p| p.y).reduce(f32::max).unwrap()) - .collect::>(); + let heights = { + #[cfg(not(feature = "parallel"))] + let chunk = points.chunk_by(|p1, p2| (p1.x - p2.x).abs() <= f32::EPSILON); + + #[cfg(feature = "parallel")] + let chunk = points.par_chunk_by(|p1, p2| (p1.x - p2.x).abs() <= f32::EPSILON); + chunk + } + .map(|chunk| chunk.iter().map(|p| p.y).reduce(f32::max).unwrap()) + .collect::>(); let x_scale = heights.len() - 1; (heights, Vec2::new(x_scale as f32, 1.0)) @@ -74,9 +94,7 @@ where { let edges = Edges::from(image); collider_fn( - edges - .image_edges(translated) - .into_par_iter() + into_par_iter!(edges.image_edges(translated)) .flatten() .collect(), ) @@ -89,9 +107,7 @@ where R: Send, { let edges = Edges::from(image); - edges - .image_edges(translated) - .into_par_iter() + into_par_iter!(edges.image_edges(translated)) .map(collider_fn) .collect() } From 42c750ecdd9b4d8f167a20e204a6692ea1cd6bee Mon Sep 17 00:00:00 2001 From: salam Date: Wed, 13 Nov 2024 02:52:02 +0900 Subject: [PATCH 13/25] removed `bevy_render` dependency --- Cargo.toml | 1 - src/avian2d.rs | 83 +++++++++++++++++++++++++++++++++++++++---------- src/rapier2d.rs | 83 +++++++++++++++++++++++++++++++++++++++---------- src/utils.rs | 9 +++--- 4 files changed, 137 insertions(+), 39 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6b0db3b..c1510ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,6 @@ edges = "0.4.0" bevy_rapier2d = { version = "0.27.0", optional = true } avian2d = { version = "0.1.0", optional = true } bevy_math = { version = "0.14", default-features = false } -bevy_render = { version = "0.14", default-features = false } rayon = { version = "1.10.0", optional = true } thiserror = "2.0.3" diff --git a/src/avian2d.rs b/src/avian2d.rs index ea30d2e..0383148 100644 --- a/src/avian2d.rs +++ b/src/avian2d.rs @@ -1,117 +1,166 @@ +use edges::Edges; + use crate::utils::{ avian2d::{convex_hull_collider, convex_polyline_collider, heightfield_collider, Collider}, generate_collider, generate_multi_collider, }; -use bevy_render::prelude::Image; /// Generate a single polyline collider from the image, /// coordinates translated to either side of (0, 0) #[must_use] -pub fn single_polyline_collider_translated(image: &Image) -> Collider { +pub fn single_polyline_collider_translated(image: I) -> Collider +where + Edges: From, +{ generate_collider(image, |points| Collider::polyline(points, None), true) } /// Generate a single polyline collider from the image, /// coordinates left alone and all in positive x and y #[must_use] -pub fn single_polyline_collider_raw(image: &Image) -> Collider { +pub fn single_polyline_collider_raw(image: I) -> Collider +where + Edges: From, +{ generate_collider(image, |points| Collider::polyline(points, None), false) } /// Generate a single `convex_polyline` collider from the image, /// coordinates translated to either side of (0, 0) #[must_use] -pub fn single_convex_polyline_collider_translated(image: &Image) -> Option { +pub fn single_convex_polyline_collider_translated(image: I) -> Option +where + Edges: From, +{ generate_collider(image, convex_polyline_collider, true) } /// Generate a single `convex_polyline` collider from the image, /// coordinates left alone and all in positive x and y #[must_use] -pub fn single_convex_polyline_collider_raw(image: &Image) -> Option { +pub fn single_convex_polyline_collider_raw(image: I) -> Option +where + Edges: From, +{ generate_collider(image, convex_polyline_collider, false) } /// Generate a single `convex_hull` collider from the image, /// coordinates translated to either side of (0, 0) #[must_use] -pub fn single_convex_hull_collider_translated(image: &Image) -> Option { +pub fn single_convex_hull_collider_translated(image: I) -> Option +where + Edges: From, +{ generate_collider(image, convex_hull_collider, true) } /// Generate a single `convex_hull` collider from the image, /// coordinates left alone and all in positive x and y #[must_use] -pub fn single_convex_hull_collider_raw(image: &Image) -> Option { +pub fn single_convex_hull_collider_raw(image: I) -> Option +where + Edges: From, +{ generate_collider(image, convex_hull_collider, false) } /// Generate a single heightfield collider from the image, /// coordinates translated to either side of (0, 0) #[must_use] -pub fn single_heightfield_collider_translated(image: &Image) -> Collider { +pub fn single_heightfield_collider_translated(image: I) -> Collider +where + Edges: From, +{ generate_collider(image, heightfield_collider, true) } /// Generate a single heightfield collider from the image, /// coordinates left alone and all in positive x and y #[must_use] -pub fn single_heightfield_collider_raw(image: &Image) -> Collider { +pub fn single_heightfield_collider_raw(image: I) -> Collider +where + Edges: From, +{ generate_collider(image, heightfield_collider, false) } /// Generate as many polyline colliders as it can find in the image, /// coordinates translated to either side of (0, 0) #[must_use] -pub fn multi_polyline_collider_translated(image: &Image) -> Vec { +pub fn multi_polyline_collider_translated(image: I) -> Vec +where + Edges: From, +{ generate_multi_collider(image, |points| Collider::polyline(points, None), true) } /// Generate as many polyline colliders as it can find in the image, /// coordinates left alone and all in positive x and y #[must_use] -pub fn multi_polyline_collider_raw(image: &Image) -> Vec { +pub fn multi_polyline_collider_raw(image: I) -> Vec +where + Edges: From, +{ generate_multi_collider(image, |points| Collider::polyline(points, None), false) } /// Generate as many `convex_polyline` colliders as it can find in the image, /// coordinates translated to either side of (0, 0) #[must_use] -pub fn multi_convex_polyline_collider_translated(image: &Image) -> Vec> { +pub fn multi_convex_polyline_collider_translated(image: I) -> Vec> +where + Edges: From, +{ generate_multi_collider(image, convex_polyline_collider, true) } /// Generate as many `convex_polyline` colliders as it can find in the image, /// coordinates left alone and all in positive x and y #[must_use] -pub fn multi_convex_polyline_collider_raw(image: &Image) -> Vec> { +pub fn multi_convex_polyline_collider_raw(image: I) -> Vec> +where + Edges: From, +{ generate_multi_collider(image, convex_polyline_collider, false) } /// Generate as many heightfield colliders as it can find in the image, /// coordinates translated to either side of (0, 0) #[must_use] -pub fn multi_heightfield_collider_translated(image: &Image) -> Vec { +pub fn multi_heightfield_collider_translated(image: I) -> Vec +where + Edges: From, +{ generate_multi_collider(image, heightfield_collider, true) } /// Generate as many heightfield colliders as it can find in the image, /// coordinates left alone and all in positive x and y #[must_use] -pub fn multi_heightfield_collider_raw(image: &Image) -> Vec { +pub fn multi_heightfield_collider_raw(image: I) -> Vec +where + Edges: From, +{ generate_multi_collider(image, heightfield_collider, false) } /// Generate as many `convex_hull` colliders as it can find in the image, /// coordinates translated to either side of (0, 0) #[must_use] -pub fn multi_convex_hull_collider_translated(image: &Image) -> Vec> { +pub fn multi_convex_hull_collider_translated(image: I) -> Vec> +where + Edges: From, +{ generate_multi_collider(image, convex_hull_collider, true) } /// Generate as many `convex_hull` colliders as it can find in the image, /// coordinates left alone and all in positive x and y #[must_use] -pub fn multi_convex_hull_collider_raw(image: &Image) -> Vec> { +pub fn multi_convex_hull_collider_raw(image: I) -> Vec> +where + Edges: From, +{ generate_multi_collider(image, convex_hull_collider, false) } diff --git a/src/rapier2d.rs b/src/rapier2d.rs index 0375fd8..bf7c80a 100644 --- a/src/rapier2d.rs +++ b/src/rapier2d.rs @@ -1,117 +1,166 @@ +use edges::Edges; + use crate::utils::{ generate_collider, generate_multi_collider, rapier2d::{convex_hull_collider, convex_polyline_collider, heightfield_collider, Collider}, }; -use bevy_render::prelude::Image; /// Generate a single polyline collider from the image, /// coordinates translated to either side of (0, 0) #[must_use] -pub fn single_polyline_collider_translated(image: &Image) -> Collider { +pub fn single_polyline_collider_translated(image: I) -> Collider +where + Edges: From, +{ generate_collider(image, |points| Collider::polyline(points, None), true) } /// Generate a single polyline collider from the image, /// coordinates left alone and all in positive x and y #[must_use] -pub fn single_polyline_collider_raw(image: &Image) -> Collider { +pub fn single_polyline_collider_raw(image: I) -> Collider +where + Edges: From, +{ generate_collider(image, |points| Collider::polyline(points, None), false) } /// Generate a single `convex_polyline` collider from the image, /// coordinates translated to either side of (0, 0) #[must_use] -pub fn single_convex_polyline_collider_translated(image: &Image) -> Option { +pub fn single_convex_polyline_collider_translated(image: I) -> Option +where + Edges: From, +{ generate_collider(image, convex_polyline_collider, true) } /// Generate a single `convex_polyline` collider from the image, /// coordinates left alone and all in positive x and y #[must_use] -pub fn single_convex_polyline_collider_raw(image: &Image) -> Option { +pub fn single_convex_polyline_collider_raw(image: I) -> Option +where + Edges: From, +{ generate_collider(image, convex_polyline_collider, false) } /// Generate a single `convex_hull` collider from the image, /// coordinates translated to either side of (0, 0) #[must_use] -pub fn single_convex_hull_collider_translated(image: &Image) -> Option { +pub fn single_convex_hull_collider_translated(image: I) -> Option +where + Edges: From, +{ generate_collider(image, convex_hull_collider, true) } /// Generate a single `convex_hull` collider from the image, /// coordinates left alone and all in positive x and y #[must_use] -pub fn single_convex_hull_collider_raw(image: &Image) -> Option { +pub fn single_convex_hull_collider_raw(image: I) -> Option +where + Edges: From, +{ generate_collider(image, convex_hull_collider, false) } /// Generate a single heightfield collider from the image, /// coordinates translated to either side of (0, 0) #[must_use] -pub fn single_heightfield_collider_translated(image: &Image) -> Collider { +pub fn single_heightfield_collider_translated(image: I) -> Collider +where + Edges: From, +{ generate_collider(image, heightfield_collider, true) } /// Generate a single heightfield collider from the image, /// coordinates left alone and all in positive x and y #[must_use] -pub fn single_heightfield_collider_raw(image: &Image) -> Collider { +pub fn single_heightfield_collider_raw(image: I) -> Collider +where + Edges: From, +{ generate_collider(image, heightfield_collider, false) } /// Generate as many polyline colliders as it can find in the image, /// coordinates translated to either side of (0, 0) #[must_use] -pub fn multi_polyline_collider_translated(image: &Image) -> Vec { +pub fn multi_polyline_collider_translated(image: I) -> Vec +where + Edges: From, +{ generate_multi_collider(image, |points| Collider::polyline(points, None), true) } /// Generate as many polyline colliders as it can find in the image, /// coordinates left alone and all in positive x and y #[must_use] -pub fn multi_polyline_collider_raw(image: &Image) -> Vec { +pub fn multi_polyline_collider_raw(image: I) -> Vec +where + Edges: From, +{ generate_multi_collider(image, |points| Collider::polyline(points, None), false) } /// Generate as many `convex_polyline` colliders as it can find in the image, /// coordinates translated to either side of (0, 0) #[must_use] -pub fn multi_convex_polyline_collider_translated(image: &Image) -> Vec> { +pub fn multi_convex_polyline_collider_translated(image: I) -> Vec> +where + Edges: From, +{ generate_multi_collider(image, convex_polyline_collider, true) } /// Generate as many `convex_polyline` colliders as it can find in the image, /// coordinates left alone and all in positive x and y #[must_use] -pub fn multi_convex_polyline_collider_raw(image: &Image) -> Vec> { +pub fn multi_convex_polyline_collider_raw(image: I) -> Vec> +where + Edges: From, +{ generate_multi_collider(image, convex_polyline_collider, false) } /// Generate as many heightfield colliders as it can find in the image, /// coordinates translated to either side of (0, 0) #[must_use] -pub fn multi_heightfield_collider_translated(image: &Image) -> Vec { +pub fn multi_heightfield_collider_translated(image: I) -> Vec +where + Edges: From, +{ generate_multi_collider(image, heightfield_collider, true) } /// Generate as many heightfield colliders as it can find in the image, /// coordinates left alone and all in positive x and y #[must_use] -pub fn multi_heightfield_collider_raw(image: &Image) -> Vec { +pub fn multi_heightfield_collider_raw(image: I) -> Vec +where + Edges: From, +{ generate_multi_collider(image, heightfield_collider, false) } /// Generate as many `convex_hull` colliders as it can find in the image, /// coordinates translated to either side of (0, 0) #[must_use] -pub fn multi_convex_hull_collider_translated(image: &Image) -> Vec> { +pub fn multi_convex_hull_collider_translated(image: I) -> Vec> +where + Edges: From, +{ generate_multi_collider(image, convex_hull_collider, true) } /// Generate as many `convex_hull` colliders as it can find in the image, /// coordinates left alone and all in positive x and y #[must_use] -pub fn multi_convex_hull_collider_raw(image: &Image) -> Vec> { +pub fn multi_convex_hull_collider_raw(image: I) -> Vec> +where + Edges: From, +{ generate_multi_collider(image, convex_hull_collider, false) } diff --git a/src/utils.rs b/src/utils.rs index 938f8b0..656b2b3 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,4 +1,3 @@ -use bevy_render::prelude::Image; use edges::{Edges, Vec2}; #[cfg(feature = "parallel")] @@ -88,9 +87,10 @@ fn heights_and_scale(mut points: Vec) -> (Vec, Vec2) { } /// Generate colliders from the image based on the provided collider type and coordinate handling. -pub fn generate_collider(image: &Image, collider_fn: F, translated: bool) -> T +pub fn generate_collider(image: I, collider_fn: F, translated: bool) -> R where - F: Fn(Vec) -> T, + F: Fn(Vec) -> R, + Edges: From, { let edges = Edges::from(image); collider_fn( @@ -101,10 +101,11 @@ where } /// Generate multiple colliders from the image based on the provided collider type and coordinate handling. -pub fn generate_multi_collider(image: &Image, collider_fn: F, translated: bool) -> Vec +pub fn generate_multi_collider(image: I, collider_fn: F, translated: bool) -> Vec where F: Fn(Vec) -> R + Send + Sync, R: Send, + Edges: From, { let edges = Edges::from(image); into_par_iter!(edges.image_edges(translated)) From 2f1f35b4f6275ad079b1fe76e1a976ba6a2c3b04 Mon Sep 17 00:00:00 2001 From: salam Date: Wed, 13 Nov 2024 02:53:58 +0900 Subject: [PATCH 14/25] removed `thiserror` dependency --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index c1510ab..5ea6a3d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,6 @@ bevy_rapier2d = { version = "0.27.0", optional = true } avian2d = { version = "0.1.0", optional = true } bevy_math = { version = "0.14", default-features = false } rayon = { version = "1.10.0", optional = true } -thiserror = "2.0.3" [dev-dependencies] From b60735895576a879dddc6247cd1ce5fbd814768e Mon Sep 17 00:00:00 2001 From: salam Date: Wed, 13 Nov 2024 18:37:18 +0900 Subject: [PATCH 15/25] fixed argument naming --- src/utils.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utils.rs b/src/utils.rs index 656b2b3..db6e017 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -37,8 +37,8 @@ pub mod avian2d { /// takes x,y points collects the y values at the top of the image (smallest y) /// and creates a heightfield collider - pub fn heightfield_collider(v: Vec) -> Collider { - let (heights, scale) = heights_and_scale(v); + pub fn heightfield_collider(points: Vec) -> Collider { + let (heights, scale) = heights_and_scale(points); Collider::heightfield(heights, scale) } } @@ -62,8 +62,8 @@ pub mod rapier2d { /// takes x,y points collects the y values at the top of the image (biggest y) /// and creates a heightfield collider - pub fn heightfield_collider(v: Vec) -> Collider { - let (heights, scale) = heights_and_scale(v); + pub fn heightfield_collider(points: Vec) -> Collider { + let (heights, scale) = heights_and_scale(points); Collider::heightfield(heights, scale) } } From 618b5f7d081744a9f1eafee10ce9c0d21b95e1a9 Mon Sep 17 00:00:00 2001 From: salam Date: Wed, 13 Nov 2024 20:42:32 +0900 Subject: [PATCH 16/25] replaced: small functions with long names --- examples/avian2d_colliders.rs | 16 +-- examples/rapier2d_colliders.rs | 16 +-- src/avian2d.rs | 241 +++++++++++---------------------- src/lib.rs | 10 +- src/rapier2d.rs | 187 +++++-------------------- src/utils.rs | 100 ++++---------- 6 files changed, 164 insertions(+), 406 deletions(-) diff --git a/examples/avian2d_colliders.rs b/examples/avian2d_colliders.rs index 13f3de5..be96edd 100644 --- a/examples/avian2d_colliders.rs +++ b/examples/avian2d_colliders.rs @@ -11,11 +11,9 @@ use bevy::{ }, }; use bevy_collider_gen::{ - avian2d::{ - multi_convex_polyline_collider_translated, single_convex_polyline_collider_translated, - single_heightfield_collider_translated, - }, - Edges, + avian2d::{multi_collider, single_collider}, + edges::Edges, + ColliderType, }; use bevy_prototype_lyon::{ prelude::{Fill, GeometryBuilder, ShapePlugin}, @@ -46,7 +44,7 @@ fn custom_png_spawn( } let sprite_image = image_assets.get(sprite_handle.unwrap()).unwrap(); - let colliders = multi_convex_polyline_collider_translated(sprite_image); + let colliders = multi_collider(sprite_image, ColliderType::ConvexPolyline, true); for collider in colliders { commands.spawn(( collider.unwrap(), @@ -77,7 +75,7 @@ fn car_spawn( return; } let sprite_image = image_assets.get(sprite_handle.unwrap()).unwrap(); - let collider = single_convex_polyline_collider_translated(sprite_image).unwrap(); + let collider = single_collider(sprite_image, ColliderType::ConvexPolyline, true).unwrap(); commands.spawn(( collider, SpriteBundle { @@ -103,7 +101,7 @@ fn terrain_spawn( return; } let sprite_image = image_assets.get(sprite_handle.unwrap()).unwrap(); - let collider = single_heightfield_collider_translated(sprite_image); + let collider = single_collider(sprite_image, ColliderType::Heightfield, true).unwrap(); commands.spawn(( collider, RigidBody::Static, @@ -131,7 +129,7 @@ fn boulders_spawn( let edges = Edges::from(sprite_image); let coord_group = edges.multi_image_edge_translated(); - let colliders = multi_convex_polyline_collider_translated(sprite_image); + let colliders = multi_collider(sprite_image, ColliderType::ConvexPolyline, true); for (coords, collider) in coord_group.iter().zip(colliders.into_iter()) { let shape = shapes::Polygon { diff --git a/examples/rapier2d_colliders.rs b/examples/rapier2d_colliders.rs index 6899820..6fcf5f6 100644 --- a/examples/rapier2d_colliders.rs +++ b/examples/rapier2d_colliders.rs @@ -9,11 +9,9 @@ use bevy::{ }, }; use bevy_collider_gen::{ - rapier2d::{ - multi_convex_polyline_collider_translated, single_convex_polyline_collider_translated, - single_heightfield_collider_translated, - }, - Edges, + edges::Edges, + rapier2d::{multi_collider, single_collider}, + ColliderType, }; use bevy_prototype_lyon::{ prelude::{Fill, GeometryBuilder, ShapePlugin}, @@ -45,7 +43,7 @@ fn custom_png_spawn( } let sprite_image = image_assets.get(sprite_handle.unwrap()).unwrap(); - let colliders = multi_convex_polyline_collider_translated(sprite_image); + let colliders = multi_collider(sprite_image, ColliderType::ConvexPolyline, true); for collider in colliders { commands.spawn(( collider.unwrap(), @@ -93,7 +91,7 @@ fn car_spawn( return; } let sprite_image = image_assets.get(sprite_handle.unwrap()).unwrap(); - let collider = single_convex_polyline_collider_translated(sprite_image).unwrap(); + let collider = single_collider(sprite_image, ColliderType::ConvexPolyline, true).unwrap(); commands.spawn(( collider, RigidBody::Dynamic, @@ -119,7 +117,7 @@ fn terrain_spawn( return; } let sprite_image = image_assets.get(sprite_handle.unwrap()).unwrap(); - let collider = single_heightfield_collider_translated(sprite_image); + let collider = single_collider(sprite_image, ColliderType::Heightfield, true).unwrap(); commands.spawn(( collider, RigidBody::Fixed, @@ -146,7 +144,7 @@ fn boulders_spawn( let edges = Edges::from(sprite_image); let coord_group = edges.multi_image_edge_translated(); - let colliders = multi_convex_polyline_collider_translated(sprite_image); + let colliders = multi_collider(sprite_image, ColliderType::ConvexPolyline, true); for (coords, collider) in coord_group.iter().zip(colliders.into_iter()) { let shape = shapes::Polygon { diff --git a/src/avian2d.rs b/src/avian2d.rs index 0383148..962f2a3 100644 --- a/src/avian2d.rs +++ b/src/avian2d.rs @@ -1,166 +1,85 @@ -use edges::Edges; - -use crate::utils::{ - avian2d::{convex_hull_collider, convex_polyline_collider, heightfield_collider, Collider}, - generate_collider, generate_multi_collider, +use avian2d::{ + parry::{math::Point, shape::SharedShape}, + prelude::Collider, }; +use edges::Edges; -/// Generate a single polyline collider from the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn single_polyline_collider_translated(image: I) -> Collider -where - Edges: From, -{ - generate_collider(image, |points| Collider::polyline(points, None), true) -} - -/// Generate a single polyline collider from the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn single_polyline_collider_raw(image: I) -> Collider -where - Edges: From, -{ - generate_collider(image, |points| Collider::polyline(points, None), false) -} - -/// Generate a single `convex_polyline` collider from the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn single_convex_polyline_collider_translated(image: I) -> Option -where - Edges: From, -{ - generate_collider(image, convex_polyline_collider, true) -} - -/// Generate a single `convex_polyline` collider from the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn single_convex_polyline_collider_raw(image: I) -> Option -where - Edges: From, -{ - generate_collider(image, convex_polyline_collider, false) -} - -/// Generate a single `convex_hull` collider from the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn single_convex_hull_collider_translated(image: I) -> Option -where - Edges: From, -{ - generate_collider(image, convex_hull_collider, true) -} - -/// Generate a single `convex_hull` collider from the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn single_convex_hull_collider_raw(image: I) -> Option -where - Edges: From, -{ - generate_collider(image, convex_hull_collider, false) -} - -/// Generate a single heightfield collider from the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn single_heightfield_collider_translated(image: I) -> Collider -where - Edges: From, -{ - generate_collider(image, heightfield_collider, true) -} - -/// Generate a single heightfield collider from the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn single_heightfield_collider_raw(image: I) -> Collider -where - Edges: From, -{ - generate_collider(image, heightfield_collider, false) -} - -/// Generate as many polyline colliders as it can find in the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn multi_polyline_collider_translated(image: I) -> Vec -where - Edges: From, -{ - generate_multi_collider(image, |points| Collider::polyline(points, None), true) -} - -/// Generate as many polyline colliders as it can find in the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn multi_polyline_collider_raw(image: I) -> Vec -where - Edges: From, -{ - generate_multi_collider(image, |points| Collider::polyline(points, None), false) -} - -/// Generate as many `convex_polyline` colliders as it can find in the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn multi_convex_polyline_collider_translated(image: I) -> Vec> -where - Edges: From, -{ - generate_multi_collider(image, convex_polyline_collider, true) -} - -/// Generate as many `convex_polyline` colliders as it can find in the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn multi_convex_polyline_collider_raw(image: I) -> Vec> -where - Edges: From, -{ - generate_multi_collider(image, convex_polyline_collider, false) -} - -/// Generate as many heightfield colliders as it can find in the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn multi_heightfield_collider_translated(image: I) -> Vec -where - Edges: From, -{ - generate_multi_collider(image, heightfield_collider, true) -} - -/// Generate as many heightfield colliders as it can find in the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn multi_heightfield_collider_raw(image: I) -> Vec -where - Edges: From, -{ - generate_multi_collider(image, heightfield_collider, false) -} +#[cfg(feature = "parallel")] +use rayon::prelude::*; -/// Generate as many `convex_hull` colliders as it can find in the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn multi_convex_hull_collider_translated(image: I) -> Vec> -where - Edges: From, -{ - generate_multi_collider(image, convex_hull_collider, true) -} +use crate::{ + utils::{generate_collider, generate_multi_collider, heights_and_scale}, + ColliderType, +}; -/// Generate as many `convex_hull` colliders as it can find in the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn multi_convex_hull_collider_raw(image: I) -> Vec> -where - Edges: From, -{ - generate_multi_collider(image, convex_hull_collider, false) +/// Generate a single collider from the image. +#[must_use] +pub fn single_collider( + image: I, + collider_type: ColliderType, + translated: bool, +) -> Option +where + Edges: From, +{ + let collider_fn = match collider_type { + ColliderType::Polyline => |vertices| Some(Collider::polyline(vertices, None)), + ColliderType::ConvexPolyline => |points: Vec<_>| { + SharedShape::convex_polyline( + { + #[cfg(not(feature = "parallel"))] + let iterator = points.into_iter(); + + #[cfg(feature = "parallel")] + let iterator = points.into_par_iter(); + iterator + } + .map(Point::from) + .collect(), + ) + .map(Collider::from) + }, + ColliderType::ConvexHull => |points| Collider::convex_hull(points), + ColliderType::Heightfield => |points| { + let (heights, scale) = heights_and_scale(points); + Some(Collider::heightfield(heights, scale)) + }, + }; + generate_collider(image, collider_fn, translated) +} + +/// Generate as many colliders as it can find in the image. +#[must_use] +pub fn multi_collider( + image: I, + collider_type: ColliderType, + translated: bool, +) -> Vec> +where + Edges: From, +{ + let collider_fn = match collider_type { + ColliderType::Polyline => |vertices| Some(Collider::polyline(vertices, None)), + ColliderType::ConvexPolyline => |points: Vec<_>| { + SharedShape::convex_polyline( + { + #[cfg(not(feature = "parallel"))] + let iterator = points.into_iter(); + + #[cfg(feature = "parallel")] + let iterator = points.into_par_iter(); + iterator + } + .map(Point::from) + .collect(), + ) + .map(Collider::from) + }, + ColliderType::ConvexHull => |points| Collider::convex_hull(points), + ColliderType::Heightfield => |points| { + let (heights, scale) = heights_and_scale(points); + Some(Collider::heightfield(heights, scale)) + }, + }; + generate_multi_collider(image, collider_fn, translated) } diff --git a/src/lib.rs b/src/lib.rs index 6ec6c32..9563215 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,17 @@ #![doc = include_str!("../README.md")] -pub use edges::Edges; +pub extern crate edges; #[cfg(feature = "avian2d")] pub mod avian2d; #[cfg(feature = "rapier2d")] pub mod rapier2d; mod utils; + +#[derive(Clone, Copy, Debug)] +pub enum ColliderType { + Polyline, + ConvexPolyline, + ConvexHull, + Heightfield, +} diff --git a/src/rapier2d.rs b/src/rapier2d.rs index bf7c80a..d411d97 100644 --- a/src/rapier2d.rs +++ b/src/rapier2d.rs @@ -1,166 +1,51 @@ +use bevy_rapier2d::prelude::Collider; use edges::Edges; -use crate::utils::{ - generate_collider, generate_multi_collider, - rapier2d::{convex_hull_collider, convex_polyline_collider, heightfield_collider, Collider}, +use crate::{ + utils::{generate_collider, generate_multi_collider, heights_and_scale}, + ColliderType, }; -/// Generate a single polyline collider from the image, -/// coordinates translated to either side of (0, 0) +/// Generate a single collider from the image. #[must_use] -pub fn single_polyline_collider_translated(image: I) -> Collider +pub fn single_collider( + image: I, + collider_type: ColliderType, + translate: bool, +) -> Option where Edges: From, { - generate_collider(image, |points| Collider::polyline(points, None), true) + let collider_fn = match collider_type { + ColliderType::Polyline => |vertices| Some(Collider::polyline(vertices, None)), + ColliderType::ConvexPolyline => |points| Collider::convex_polyline(points), + ColliderType::ConvexHull => |points: Vec<_>| Collider::convex_hull(&points), + ColliderType::Heightfield => |points| { + let (heights, scale) = heights_and_scale(points); + Some(Collider::heightfield(heights, scale)) + }, + }; + generate_collider(image, collider_fn, translate) } -/// Generate a single polyline collider from the image, -/// coordinates left alone and all in positive x and y +/// Generate as many colliders as it can find in the image. #[must_use] -pub fn single_polyline_collider_raw(image: I) -> Collider +pub fn multi_collider( + image: I, + collider_type: ColliderType, + translate: bool, +) -> Vec> where Edges: From, { - generate_collider(image, |points| Collider::polyline(points, None), false) -} - -/// Generate a single `convex_polyline` collider from the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn single_convex_polyline_collider_translated(image: I) -> Option -where - Edges: From, -{ - generate_collider(image, convex_polyline_collider, true) -} - -/// Generate a single `convex_polyline` collider from the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn single_convex_polyline_collider_raw(image: I) -> Option -where - Edges: From, -{ - generate_collider(image, convex_polyline_collider, false) -} - -/// Generate a single `convex_hull` collider from the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn single_convex_hull_collider_translated(image: I) -> Option -where - Edges: From, -{ - generate_collider(image, convex_hull_collider, true) -} - -/// Generate a single `convex_hull` collider from the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn single_convex_hull_collider_raw(image: I) -> Option -where - Edges: From, -{ - generate_collider(image, convex_hull_collider, false) -} - -/// Generate a single heightfield collider from the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn single_heightfield_collider_translated(image: I) -> Collider -where - Edges: From, -{ - generate_collider(image, heightfield_collider, true) -} - -/// Generate a single heightfield collider from the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn single_heightfield_collider_raw(image: I) -> Collider -where - Edges: From, -{ - generate_collider(image, heightfield_collider, false) -} - -/// Generate as many polyline colliders as it can find in the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn multi_polyline_collider_translated(image: I) -> Vec -where - Edges: From, -{ - generate_multi_collider(image, |points| Collider::polyline(points, None), true) -} - -/// Generate as many polyline colliders as it can find in the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn multi_polyline_collider_raw(image: I) -> Vec -where - Edges: From, -{ - generate_multi_collider(image, |points| Collider::polyline(points, None), false) -} - -/// Generate as many `convex_polyline` colliders as it can find in the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn multi_convex_polyline_collider_translated(image: I) -> Vec> -where - Edges: From, -{ - generate_multi_collider(image, convex_polyline_collider, true) -} - -/// Generate as many `convex_polyline` colliders as it can find in the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn multi_convex_polyline_collider_raw(image: I) -> Vec> -where - Edges: From, -{ - generate_multi_collider(image, convex_polyline_collider, false) -} - -/// Generate as many heightfield colliders as it can find in the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn multi_heightfield_collider_translated(image: I) -> Vec -where - Edges: From, -{ - generate_multi_collider(image, heightfield_collider, true) -} - -/// Generate as many heightfield colliders as it can find in the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn multi_heightfield_collider_raw(image: I) -> Vec -where - Edges: From, -{ - generate_multi_collider(image, heightfield_collider, false) -} - -/// Generate as many `convex_hull` colliders as it can find in the image, -/// coordinates translated to either side of (0, 0) -#[must_use] -pub fn multi_convex_hull_collider_translated(image: I) -> Vec> -where - Edges: From, -{ - generate_multi_collider(image, convex_hull_collider, true) -} - -/// Generate as many `convex_hull` colliders as it can find in the image, -/// coordinates left alone and all in positive x and y -#[must_use] -pub fn multi_convex_hull_collider_raw(image: I) -> Vec> -where - Edges: From, -{ - generate_multi_collider(image, convex_hull_collider, false) + let collider_fn = match collider_type { + ColliderType::Polyline => |vertices| Some(Collider::polyline(vertices, None)), + ColliderType::ConvexPolyline => |points| Collider::convex_polyline(points), + ColliderType::ConvexHull => |points: Vec<_>| Collider::convex_hull(&points), + ColliderType::Heightfield => |points| { + let (heights, scale) = heights_and_scale(points); + Some(Collider::heightfield(heights, scale)) + }, + }; + generate_multi_collider(image, collider_fn, translate) } diff --git a/src/utils.rs b/src/utils.rs index db6e017..f6102b6 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,75 +1,9 @@ use edges::{Edges, Vec2}; - #[cfg(feature = "parallel")] use rayon::prelude::*; -macro_rules! into_par_iter { - ($t: expr) => {{ - #[cfg(not(feature = "parallel"))] - let it = $t.into_iter(); - - #[cfg(feature = "parallel")] - let it = $t.into_par_iter(); - it - }}; -} - -#[cfg(feature = "avian2d")] -pub mod avian2d { - use super::{heights_and_scale, Vec2}; - - use avian2d::parry::{math::Point, shape::SharedShape}; - #[cfg(feature = "parallel")] - use rayon::prelude::*; - - pub use avian2d::prelude::Collider; - - /// Generate `convex_polyline` collider from the points, - pub fn convex_polyline_collider(points: Vec) -> Option { - SharedShape::convex_polyline(into_par_iter!(points).map(Point::from).collect()) - .map(Collider::from) - } - - /// Generate `convex_hull` collider from the points, - pub fn convex_hull_collider(points: Vec) -> Option { - Collider::convex_hull(points) - } - - /// takes x,y points collects the y values at the top of the image (smallest y) - /// and creates a heightfield collider - pub fn heightfield_collider(points: Vec) -> Collider { - let (heights, scale) = heights_and_scale(points); - Collider::heightfield(heights, scale) - } -} - -#[cfg(feature = "rapier2d")] -pub mod rapier2d { - use super::{heights_and_scale, Vec2}; - - pub use bevy_rapier2d::prelude::Collider; - - /// Generate `convex_polyline` collider from the points, - pub fn convex_polyline_collider(points: Vec) -> Option { - Collider::convex_polyline(points) - } - - /// Generate `convex_hull` collider from the points, - #[allow(clippy::needless_pass_by_value)] - pub fn convex_hull_collider(points: Vec) -> Option { - Collider::convex_hull(&points) - } - - /// takes x,y points collects the y values at the top of the image (biggest y) - /// and creates a heightfield collider - pub fn heightfield_collider(points: Vec) -> Collider { - let (heights, scale) = heights_and_scale(points); - Collider::heightfield(heights, scale) - } -} - /// takes x,y points collects the y values at the top of the image (biggest y) -fn heights_and_scale(mut points: Vec) -> (Vec, Vec2) { +pub fn heights_and_scale(mut points: Vec) -> (Vec, Vec2) { points.sort_by(|p1, p2| p1.x.partial_cmp(&p2.x).unwrap()); let heights = { #[cfg(not(feature = "parallel"))] @@ -87,28 +21,44 @@ fn heights_and_scale(mut points: Vec) -> (Vec, Vec2) { } /// Generate colliders from the image based on the provided collider type and coordinate handling. -pub fn generate_collider(image: I, collider_fn: F, translated: bool) -> R +pub fn generate_collider(image: I, collider_fn: F, translate: bool) -> R where F: Fn(Vec) -> R, Edges: From, { let edges = Edges::from(image); + let points = edges.image_edges(translate); collider_fn( - into_par_iter!(edges.image_edges(translated)) - .flatten() - .collect(), + { + #[cfg(not(feature = "parallel"))] + let iterator = points.into_iter(); + + #[cfg(feature = "parallel")] + let iterator = points.into_par_iter(); + iterator + } + .flatten() + .collect(), ) } /// Generate multiple colliders from the image based on the provided collider type and coordinate handling. -pub fn generate_multi_collider(image: I, collider_fn: F, translated: bool) -> Vec +pub fn generate_multi_collider(image: I, collider_fn: F, translate: bool) -> Vec where F: Fn(Vec) -> R + Send + Sync, R: Send, Edges: From, { let edges = Edges::from(image); - into_par_iter!(edges.image_edges(translated)) - .map(collider_fn) - .collect() + let points = edges.image_edges(translate); + { + #[cfg(not(feature = "parallel"))] + let iterator = points.into_iter(); + + #[cfg(feature = "parallel")] + let iterator = points.into_par_iter(); + iterator + } + .map(collider_fn) + .collect() } From f0001048d5000b34ef888fca76ccd26f3edeb3e9 Mon Sep 17 00:00:00 2001 From: salam Date: Fri, 15 Nov 2024 07:02:43 +0900 Subject: [PATCH 17/25] avian2d remove from default features --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 5ea6a3d..8a5b43c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ cast_precision_loss = { level = "allow", priority = 1 } pedantic = { level = "warn", priority = 0 } [features] -default = ["avian2d", "rapier2d", "parallel"] +default = ["rapier2d", "parallel"] avian2d = ["dep:avian2d"] rapier2d = ["dep:bevy_rapier2d"] parallel = ["dep:rayon"] From 783b3809634e84cd97afd4dd0c8827e44a63fe95 Mon Sep 17 00:00:00 2001 From: salam Date: Fri, 15 Nov 2024 07:04:03 +0900 Subject: [PATCH 18/25] default features of rapier2d and avian 2d disabled --- Cargo.toml | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8a5b43c..b238b4a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,15 +19,24 @@ pedantic = { level = "warn", priority = 0 } default = ["rapier2d", "parallel"] avian2d = ["dep:avian2d"] rapier2d = ["dep:bevy_rapier2d"] -parallel = ["dep:rayon"] +parallel = ["dep:rayon", "avian2d/parallel", "bevy_rapier2d/parallel"] [dependencies] edges = "0.4.0" -bevy_rapier2d = { version = "0.27.0", optional = true } -avian2d = { version = "0.1.0", optional = true } bevy_math = { version = "0.14", default-features = false } rayon = { version = "1.10.0", optional = true } +[dependencies.bevy_rapier2d] +version = "0.27" +optional = true +default-features = false +features = ["dim2"] + +[dependencies.avian2d] +version = "0.1" +optional = true +default-features = false +features = ["2d", "parry-f32"] [dev-dependencies] bevy = "0.14" @@ -37,9 +46,9 @@ indoc = "2.0.4" [[example]] name = "avian2d_colliders" path = "examples/avian2d_colliders.rs" -required-features = ["avian2d"] +required-features = ["avian2d", "avian2d/debug-plugin"] [[example]] name = "rapier2d_colliders" path = "examples/rapier2d_colliders.rs" -required-features = ["rapier2d"] +required-features = ["rapier2d", "bevy_rapier2d/debug-render-2d"] From 2798f0052dc1186309eb3901ff8b2b6cfb042d54 Mon Sep 17 00:00:00 2001 From: salam Date: Fri, 15 Nov 2024 07:05:37 +0900 Subject: [PATCH 19/25] add: doc for `ColliderType` --- src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 9563215..69818b7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,9 @@ pub mod avian2d; pub mod rapier2d; mod utils; +/// An enumeration representing the different types of colliders that can be created. +/// +/// This enum is used to specify the type of collider when generating colliders from images or other sources. #[derive(Clone, Copy, Debug)] pub enum ColliderType { Polyline, From afa1f9c94d060fe7cf54d3f5965b1d909e0ada97 Mon Sep 17 00:00:00 2001 From: salam Date: Fri, 15 Nov 2024 07:12:42 +0900 Subject: [PATCH 20/25] refactor: conversion to collider, moved outside of generation functions --- src/avian2d.rs | 85 ++++++++++++++++++++----------------------------- src/rapier2d.rs | 46 +++++++++++++------------- src/utils.rs | 2 +- 3 files changed, 58 insertions(+), 75 deletions(-) diff --git a/src/avian2d.rs b/src/avian2d.rs index 962f2a3..177c29f 100644 --- a/src/avian2d.rs +++ b/src/avian2d.rs @@ -2,7 +2,7 @@ use avian2d::{ parry::{math::Point, shape::SharedShape}, prelude::Collider, }; -use edges::Edges; +use edges::{Edges, Vec2}; #[cfg(feature = "parallel")] use rayon::prelude::*; @@ -12,7 +12,29 @@ use crate::{ ColliderType, }; -/// Generate a single collider from the image. +fn to_collider(collider_type: ColliderType, points: Vec) -> Option { + match collider_type { + ColliderType::Polyline => Some(Collider::polyline(points, None)), + ColliderType::ConvexPolyline => SharedShape::convex_polyline( + { + #[cfg(not(feature = "parallel"))] + let iterator = points.into_iter(); + #[cfg(feature = "parallel")] + let iterator = points.into_par_iter(); + iterator + } + .map(Point::from) + .collect(), + ) + .map(Collider::from), + ColliderType::ConvexHull => Collider::convex_hull(points), + ColliderType::Heightfield => { + let (heights, scale) = heights_and_scale(points); + Some(Collider::heightfield(heights, scale)) + } + } +} + #[must_use] pub fn single_collider( image: I, @@ -22,33 +44,13 @@ pub fn single_collider( where Edges: From, { - let collider_fn = match collider_type { - ColliderType::Polyline => |vertices| Some(Collider::polyline(vertices, None)), - ColliderType::ConvexPolyline => |points: Vec<_>| { - SharedShape::convex_polyline( - { - #[cfg(not(feature = "parallel"))] - let iterator = points.into_iter(); - - #[cfg(feature = "parallel")] - let iterator = points.into_par_iter(); - iterator - } - .map(Point::from) - .collect(), - ) - .map(Collider::from) - }, - ColliderType::ConvexHull => |points| Collider::convex_hull(points), - ColliderType::Heightfield => |points| { - let (heights, scale) = heights_and_scale(points); - Some(Collider::heightfield(heights, scale)) - }, - }; - generate_collider(image, collider_fn, translated) + crate::utils::generate_collider( + image, + |points| to_collider(collider_type, points), + translate, + ) } -/// Generate as many colliders as it can find in the image. #[must_use] pub fn multi_collider( image: I, @@ -58,28 +60,9 @@ pub fn multi_collider( where Edges: From, { - let collider_fn = match collider_type { - ColliderType::Polyline => |vertices| Some(Collider::polyline(vertices, None)), - ColliderType::ConvexPolyline => |points: Vec<_>| { - SharedShape::convex_polyline( - { - #[cfg(not(feature = "parallel"))] - let iterator = points.into_iter(); - - #[cfg(feature = "parallel")] - let iterator = points.into_par_iter(); - iterator - } - .map(Point::from) - .collect(), - ) - .map(Collider::from) - }, - ColliderType::ConvexHull => |points| Collider::convex_hull(points), - ColliderType::Heightfield => |points| { - let (heights, scale) = heights_and_scale(points); - Some(Collider::heightfield(heights, scale)) - }, - }; - generate_multi_collider(image, collider_fn, translated) + crate::utils::generate_colliders( + image, + |points| to_collider(collider_type, points), + translate, + ) } diff --git a/src/rapier2d.rs b/src/rapier2d.rs index d411d97..e2496f5 100644 --- a/src/rapier2d.rs +++ b/src/rapier2d.rs @@ -1,12 +1,23 @@ use bevy_rapier2d::prelude::Collider; -use edges::Edges; +use edges::{Edges, Vec2}; use crate::{ utils::{generate_collider, generate_multi_collider, heights_and_scale}, ColliderType, }; -/// Generate a single collider from the image. +fn to_collider(collider_type: ColliderType, points: Vec) -> Option { + match collider_type { + ColliderType::Polyline => Some(Collider::polyline(points, None)), + ColliderType::ConvexPolyline => Collider::convex_polyline(points), + ColliderType::ConvexHull => Collider::convex_hull(&points), + ColliderType::Heightfield => { + let (heights, scale) = heights_and_scale(points); + Some(Collider::heightfield(heights, scale)) + } + } +} + #[must_use] pub fn single_collider( image: I, @@ -16,19 +27,13 @@ pub fn single_collider( where Edges: From, { - let collider_fn = match collider_type { - ColliderType::Polyline => |vertices| Some(Collider::polyline(vertices, None)), - ColliderType::ConvexPolyline => |points| Collider::convex_polyline(points), - ColliderType::ConvexHull => |points: Vec<_>| Collider::convex_hull(&points), - ColliderType::Heightfield => |points| { - let (heights, scale) = heights_and_scale(points); - Some(Collider::heightfield(heights, scale)) - }, - }; - generate_collider(image, collider_fn, translate) + crate::utils::generate_collider( + image, + |points| to_collider(collider_type, points), + translate, + ) } -/// Generate as many colliders as it can find in the image. #[must_use] pub fn multi_collider( image: I, @@ -38,14 +43,9 @@ pub fn multi_collider( where Edges: From, { - let collider_fn = match collider_type { - ColliderType::Polyline => |vertices| Some(Collider::polyline(vertices, None)), - ColliderType::ConvexPolyline => |points| Collider::convex_polyline(points), - ColliderType::ConvexHull => |points: Vec<_>| Collider::convex_hull(&points), - ColliderType::Heightfield => |points| { - let (heights, scale) = heights_and_scale(points); - Some(Collider::heightfield(heights, scale)) - }, - }; - generate_multi_collider(image, collider_fn, translate) + crate::utils::generate_colliders( + image, + |points| to_collider(collider_type, points), + translate, + ) } diff --git a/src/utils.rs b/src/utils.rs index f6102b6..1bc0401 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -43,7 +43,7 @@ where } /// Generate multiple colliders from the image based on the provided collider type and coordinate handling. -pub fn generate_multi_collider(image: I, collider_fn: F, translate: bool) -> Vec +pub fn generate_colliders(image: I, collider_fn: F, translate: bool) -> Vec where F: Fn(Vec) -> R + Send + Sync, R: Send, From 56f3a2faebab3190c170ecf68e2067fa51b1ce1c Mon Sep 17 00:00:00 2001 From: salam Date: Fri, 15 Nov 2024 07:13:43 +0900 Subject: [PATCH 21/25] renamed public generate functions --- src/avian2d.rs | 9 +++------ src/rapier2d.rs | 9 +++------ 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/avian2d.rs b/src/avian2d.rs index 177c29f..95ad19c 100644 --- a/src/avian2d.rs +++ b/src/avian2d.rs @@ -7,10 +7,7 @@ use edges::{Edges, Vec2}; #[cfg(feature = "parallel")] use rayon::prelude::*; -use crate::{ - utils::{generate_collider, generate_multi_collider, heights_and_scale}, - ColliderType, -}; +use crate::{utils::heights_and_scale, ColliderType}; fn to_collider(collider_type: ColliderType, points: Vec) -> Option { match collider_type { @@ -36,7 +33,7 @@ fn to_collider(collider_type: ColliderType, points: Vec) -> Option( +pub fn generate_collider( image: I, collider_type: ColliderType, translated: bool, @@ -52,7 +49,7 @@ where } #[must_use] -pub fn multi_collider( +pub fn generate_colliders( image: I, collider_type: ColliderType, translated: bool, diff --git a/src/rapier2d.rs b/src/rapier2d.rs index e2496f5..7c450c0 100644 --- a/src/rapier2d.rs +++ b/src/rapier2d.rs @@ -1,10 +1,7 @@ use bevy_rapier2d::prelude::Collider; use edges::{Edges, Vec2}; -use crate::{ - utils::{generate_collider, generate_multi_collider, heights_and_scale}, - ColliderType, -}; +use crate::{utils::heights_and_scale, ColliderType}; fn to_collider(collider_type: ColliderType, points: Vec) -> Option { match collider_type { @@ -19,7 +16,7 @@ fn to_collider(collider_type: ColliderType, points: Vec) -> Option( +pub fn generate_collider( image: I, collider_type: ColliderType, translate: bool, @@ -35,7 +32,7 @@ where } #[must_use] -pub fn multi_collider( +pub fn generate_colliders( image: I, collider_type: ColliderType, translate: bool, From f8682d3cbb208a303ecdbefce53fba459659f673 Mon Sep 17 00:00:00 2001 From: salam Date: Fri, 15 Nov 2024 07:14:12 +0900 Subject: [PATCH 22/25] renamed `translate` argument --- examples/avian2d_colliders.rs | 10 +++++----- examples/rapier2d_colliders.rs | 10 +++++----- src/avian2d.rs | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/avian2d_colliders.rs b/examples/avian2d_colliders.rs index be96edd..c883e98 100644 --- a/examples/avian2d_colliders.rs +++ b/examples/avian2d_colliders.rs @@ -11,7 +11,7 @@ use bevy::{ }, }; use bevy_collider_gen::{ - avian2d::{multi_collider, single_collider}, + avian2d::{generate_collider, generate_colliders}, edges::Edges, ColliderType, }; @@ -44,7 +44,7 @@ fn custom_png_spawn( } let sprite_image = image_assets.get(sprite_handle.unwrap()).unwrap(); - let colliders = multi_collider(sprite_image, ColliderType::ConvexPolyline, true); + let colliders = generate_colliders(sprite_image, ColliderType::ConvexPolyline, true); for collider in colliders { commands.spawn(( collider.unwrap(), @@ -75,7 +75,7 @@ fn car_spawn( return; } let sprite_image = image_assets.get(sprite_handle.unwrap()).unwrap(); - let collider = single_collider(sprite_image, ColliderType::ConvexPolyline, true).unwrap(); + let collider = generate_collider(sprite_image, ColliderType::ConvexPolyline, true).unwrap(); commands.spawn(( collider, SpriteBundle { @@ -101,7 +101,7 @@ fn terrain_spawn( return; } let sprite_image = image_assets.get(sprite_handle.unwrap()).unwrap(); - let collider = single_collider(sprite_image, ColliderType::Heightfield, true).unwrap(); + let collider = generate_collider(sprite_image, ColliderType::Heightfield, true).unwrap(); commands.spawn(( collider, RigidBody::Static, @@ -129,7 +129,7 @@ fn boulders_spawn( let edges = Edges::from(sprite_image); let coord_group = edges.multi_image_edge_translated(); - let colliders = multi_collider(sprite_image, ColliderType::ConvexPolyline, true); + let colliders = generate_colliders(sprite_image, ColliderType::ConvexPolyline, true); for (coords, collider) in coord_group.iter().zip(colliders.into_iter()) { let shape = shapes::Polygon { diff --git a/examples/rapier2d_colliders.rs b/examples/rapier2d_colliders.rs index 6fcf5f6..3260e45 100644 --- a/examples/rapier2d_colliders.rs +++ b/examples/rapier2d_colliders.rs @@ -10,7 +10,7 @@ use bevy::{ }; use bevy_collider_gen::{ edges::Edges, - rapier2d::{multi_collider, single_collider}, + rapier2d::{generate_collider, generate_colliders}, ColliderType, }; use bevy_prototype_lyon::{ @@ -43,7 +43,7 @@ fn custom_png_spawn( } let sprite_image = image_assets.get(sprite_handle.unwrap()).unwrap(); - let colliders = multi_collider(sprite_image, ColliderType::ConvexPolyline, true); + let colliders = generate_colliders(sprite_image, ColliderType::ConvexPolyline, true); for collider in colliders { commands.spawn(( collider.unwrap(), @@ -91,7 +91,7 @@ fn car_spawn( return; } let sprite_image = image_assets.get(sprite_handle.unwrap()).unwrap(); - let collider = single_collider(sprite_image, ColliderType::ConvexPolyline, true).unwrap(); + let collider = generate_collider(sprite_image, ColliderType::ConvexPolyline, true).unwrap(); commands.spawn(( collider, RigidBody::Dynamic, @@ -117,7 +117,7 @@ fn terrain_spawn( return; } let sprite_image = image_assets.get(sprite_handle.unwrap()).unwrap(); - let collider = single_collider(sprite_image, ColliderType::Heightfield, true).unwrap(); + let collider = generate_collider(sprite_image, ColliderType::Heightfield, true).unwrap(); commands.spawn(( collider, RigidBody::Fixed, @@ -144,7 +144,7 @@ fn boulders_spawn( let edges = Edges::from(sprite_image); let coord_group = edges.multi_image_edge_translated(); - let colliders = multi_collider(sprite_image, ColliderType::ConvexPolyline, true); + let colliders = generate_colliders(sprite_image, ColliderType::ConvexPolyline, true); for (coords, collider) in coord_group.iter().zip(colliders.into_iter()) { let shape = shapes::Polygon { diff --git a/src/avian2d.rs b/src/avian2d.rs index 95ad19c..712a341 100644 --- a/src/avian2d.rs +++ b/src/avian2d.rs @@ -36,7 +36,7 @@ fn to_collider(collider_type: ColliderType, points: Vec) -> Option( image: I, collider_type: ColliderType, - translated: bool, + translate: bool, ) -> Option where Edges: From, @@ -52,7 +52,7 @@ where pub fn generate_colliders( image: I, collider_type: ColliderType, - translated: bool, + translate: bool, ) -> Vec> where Edges: From, From 5161d53140f29ec1be9c67ce02a109211c8c54d7 Mon Sep 17 00:00:00 2001 From: salam Date: Fri, 15 Nov 2024 07:15:12 +0900 Subject: [PATCH 23/25] add: doc for public functions --- src/avian2d.rs | 36 ++++++++++++++++++++++++++++++++++++ src/rapier2d.rs | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/src/avian2d.rs b/src/avian2d.rs index 712a341..8635958 100644 --- a/src/avian2d.rs +++ b/src/avian2d.rs @@ -32,6 +32,24 @@ fn to_collider(collider_type: ColliderType, points: Vec) -> Option` for `Edges`. +/// - `collider_type`: Specifies the type of collider to create (e.g., `Polyline`, `ConvexHull`, etc.). +/// - `translate`: A boolean flag indicating whether to apply translation during collider generation. +/// +/// # Returns +/// Returns an `Option`. If the collider is successfully generated, it returns `Some(Collider)`, +/// otherwise, it returns `None` if the generation fails. +/// +/// # Example +/// ``` +/// let collider = generate_collider(image, ColliderType::Polyline, true); +/// ``` #[must_use] pub fn generate_collider( image: I, @@ -48,6 +66,24 @@ where ) } +/// Generates multiple colliders from the provided image. +/// +/// This function processes the input image and creates a vector of colliders of the specified type. +/// Each collider can be translated based on the `translate` flag. +/// +/// # Parameters +/// - `image`: The input image from which to generate the colliders. The type `I` must implement `From` for `Edges`. +/// - `collider_type`: Specifies the type of colliders to create (e.g., `Polyline`, `ConvexHull`, etc.). +/// - `translate`: A boolean flag indicating whether to apply translation during collider generation. +/// +/// # Returns +/// Returns a `Vec>`, which is a vector of optional colliders. Each element may be `Some(Collider)` +/// if the collider is successfully generated, or `None` if the generation fails for that particular collider. +/// +/// # Example +/// ``` +/// let colliders = generate_colliders(image, ColliderType::Polyline, true); +/// ``` #[must_use] pub fn generate_colliders( image: I, diff --git a/src/rapier2d.rs b/src/rapier2d.rs index 7c450c0..7046797 100644 --- a/src/rapier2d.rs +++ b/src/rapier2d.rs @@ -15,6 +15,24 @@ fn to_collider(collider_type: ColliderType, points: Vec) -> Option` for `Edges`. +/// - `collider_type`: Specifies the type of collider to create (e.g., `Polyline`, `ConvexHull`, etc.). +/// - `translate`: A boolean flag indicating whether to apply translation during collider generation. +/// +/// # Returns +/// Returns an `Option`. If the collider is successfully generated, it returns `Some(Collider)`, +/// otherwise, it returns `None` if the generation fails. +/// +/// # Example +/// ``` +/// let collider = generate_collider(image, ColliderType::Polyline, true); +/// ``` #[must_use] pub fn generate_collider( image: I, @@ -31,6 +49,24 @@ where ) } +/// Generates multiple colliders from the provided image. +/// +/// This function processes the input image and creates a vector of colliders of the specified type. +/// Each collider can be translated based on the `translate` flag. +/// +/// # Parameters +/// - `image`: The input image from which to generate the colliders. The type `I` must implement `From` for `Edges`. +/// - `collider_type`: Specifies the type of colliders to create (e.g., `Polyline`, `ConvexHull`, etc.). +/// - `translate`: A boolean flag indicating whether to apply translation during collider generation. +/// +/// # Returns +/// Returns a `Vec>`, which is a vector of optional colliders. Each element may be `Some(Collider)` +/// if the collider is successfully generated, or `None` if the generation fails for that particular collider. +/// +/// # Example +/// ``` +/// let colliders = generate_colliders(image, ColliderType::Polyline, true); +/// ``` #[must_use] pub fn generate_colliders( image: I, From e1af25da7d4a73965a2801e8303d420d9a5795a4 Mon Sep 17 00:00:00 2001 From: salam Date: Fri, 15 Nov 2024 07:28:51 +0900 Subject: [PATCH 24/25] updated README.md --- README.md | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 7a9df72..9a4369a 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # bevy_collider_gen -[![Crates.io]()]() -[![Crates.io]()]() -[![MIT/Apache 2.0]()]() +[![Crates.io](https://img.shields.io/crates/v/bevy_collider_gen.svg)](https://crates.io/crates/bevy_collider_gen) +[![Crates.io](https://img.shields.io/crates/d/bevy_collider_gen.svg)](https://crates.io/crates/bevy_collider_gen) +[![MIT/Apache 2.0](https://img.shields.io/badge/license-MIT%2FApache-blue.svg)](https://github.com/shnewto/bevy_collider_gen#license) a library for generating 2d colliders, for bevy apps, from images with transparency @@ -16,8 +16,6 @@ but you'll probably only want to just use one of the physics engines supported s [dependencies.bevy_collider_gen] # replace "*" with the most recent version of bevy_collider_gen version = "*" -features = ["rapier2d"] -default-features = false ``` or this for `avian2d` @@ -26,13 +24,13 @@ or this for `avian2d` [dependencies.bevy_collider_gen] # replace "*" with the most recent version of bevy_collider_gen version = "*" -features = ["avian2d"] +features = ["avian2d", "parallel"] default-features = false ``` ## example -![example with a car, terrain, and boulders]() +![example with a car, terrain, and boulders](https://github.com/shnewto/bevy_collider_gen/blob/main/img/example-default.png?raw=true) to see this in action you can run the example, with no args it generates a scene with various colliders using pngs in the `assets/sprite` directory @@ -41,7 +39,7 @@ to see this in action you can run the example, with no args it generates a scene #### note that you must have the rapier2d feature enabled ```sh -cargo run --example rapier2d_colliders +cargo run --example rapier2d_colliders -F "bevy_rapier2d/debug-render-2d" ``` ### avian2d @@ -49,7 +47,7 @@ cargo run --example rapier2d_colliders #### note that you must have the avian2d feature enabled ```sh -cargo run --example avian2d_colliders +cargo run --example avian2d_colliders -F "avian2d, avian2d/debug-plugin" ``` you can also specify a path to an image yourself the example will attempt to generate one or more convex_polyline colliders for the objects it finds @@ -75,22 +73,22 @@ packaged up my approach here in case anyone else could benefit. ### convex polyline (bevy_raiper2d only) -![convex polyline collider on an upside down car sprite]() +![convex polyline collider on an upside down car sprite](https://github.com/shnewto/bevy_collider_gen/blob/main/img/convex-polyline.png?raw=true) ### polyline -![polyline collider on an upside down car sprite]() +![polyline collider on an upside down car sprite](https://github.com/shnewto/bevy_collider_gen/blob/main/img/polyline.png?raw=true) ### convex hull -![convex hull collider on an upside down car sprite]() +![convex hull collider on an upside down car sprite](https://github.com/shnewto/bevy_collider_gen/blob/main/img/convex-hull.png?raw=true) ### heightfield the current implementation does best if the image you're generating a heightfield from is either centered in the image or spans the entire width of the image... -![heightfield collider on an upside down car sprite]() +![heightfield collider on an upside down car sprite](https://github.com/shnewto/bevy_collider_gen/blob/main/img/heightfield.png?raw=true) ### convex decomposition @@ -115,7 +113,7 @@ for coords in edge_coordinate_groups { } ``` -![convex decomposition collider on a car sprite]() +![convex decomposition collider on a car sprite](https://github.com/shnewto/bevy_collider_gen/blob/main/img/convex-decomposition.png?raw=true) ## license From aba0383ed5dc7d20e7457a68c6905626ec19ca57 Mon Sep 17 00:00:00 2001 From: salam Date: Sat, 16 Nov 2024 02:22:39 +0900 Subject: [PATCH 25/25] fix: rapier2d build --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b238b4a..2b2caf7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ rayon = { version = "1.10.0", optional = true } version = "0.27" optional = true default-features = false -features = ["dim2"] +features = ["dim2", "headless"] [dependencies.avian2d] version = "0.1"