use bevy::prelude::{Image, Vec2};
use bevy_xpbd_2d::{
math::Vector2,
parry::{
math::{Point, Real, Vector},
na::DVector,
shape::SharedShape,
},
prelude::Collider,
};
use edges::Edges;
pub fn single_polyline_collider_translated(image: &Image) -> Collider {
let e = Edges::from(image);
Collider::polyline(e.single_image_edge_translated(), None)
}
pub fn single_polyline_collider_raw(image: &Image) -> Collider {
let e = Edges::from(image);
Collider::polyline(e.single_image_edge_raw(), None)
}
pub fn single_convex_polyline_collider_translated(image: &Image) -> Option<Collider> {
let e = Edges::from(image);
let points = e
.single_image_edge_translated()
.into_iter()
.map(Point::from)
.collect::<Vec<Point<Real>>>();
SharedShape::convex_polyline(points).map(Collider::from)
}
pub fn single_convex_polyline_collider_raw(image: &Image) -> Option<Collider> {
let e = Edges::from(image);
let points = e
.single_image_edge_raw()
.into_iter()
.map(Point::from)
.collect::<Vec<Point<Real>>>();
SharedShape::convex_polyline(points).map(Collider::from)
}
pub fn single_convex_hull_collider_translated(image: &Image) -> Option<Collider> {
let e = Edges::from(image);
let points = e.single_image_edge_translated();
Collider::convex_hull(points)
}
pub fn single_convex_hull_collider_raw(image: &Image) -> Option<Collider> {
let e = Edges::from(image);
let points = e.single_image_edge_translated();
Collider::convex_hull(points)
}
pub fn single_heightfield_collider_translated(image: &Image) -> Collider {
let e = Edges::from(image);
heightfield_collider_from_points(&e.single_image_edge_translated())
}
pub fn single_heightfield_collider_raw(image: &Image) -> Collider {
let e = Edges::from(image);
heightfield_collider_from_points(&e.single_image_edge_raw())
}
pub fn multi_polyline_collider_translated(image: &Image) -> Vec<Collider> {
let e = Edges::from(image);
e.multi_image_edge_translated()
.into_iter()
.map(|v| Collider::polyline(v, None))
.collect()
}
pub fn multi_polyline_collider_raw(image: &Image) -> Vec<Collider> {
let e = Edges::from(image);
e.multi_image_edges_raw()
.into_iter()
.map(|v| Collider::polyline(v, None))
.collect()
}
pub fn multi_convex_polyline_collider_translated(image: &Image) -> Vec<Option<Collider>> {
let e = Edges::from(image);
e.multi_image_edge_translated()
.into_iter()
.map(|v| {
let points = v.into_iter().map(Point::from).collect::<Vec<Point<Real>>>();
SharedShape::convex_polyline(points).map(Collider::from)
})
.collect()
}
pub fn multi_convex_polyline_collider_raw(image: &Image) -> Vec<Option<Collider>> {
let e = Edges::from(image);
e.multi_image_edges_raw()
.into_iter()
.map(|v| {
let points = v.into_iter().map(Point::from).collect::<Vec<Point<Real>>>();
SharedShape::convex_polyline(points).map(Collider::from)
})
.collect()
}
pub fn multi_heightfield_collider_translated(image: &Image) -> Vec<Collider> {
let e = Edges::from(image);
e.multi_image_edge_translated()
.into_iter()
.map(|v| heightfield_collider_from_points(&v))
.collect()
}
pub fn multi_heightfield_collider_raw(image: &Image) -> Vec<Collider> {
let e = Edges::from(image);
e.multi_image_edges_raw()
.into_iter()
.map(|v| heightfield_collider_from_points(&v))
.collect()
}
pub fn multi_convex_hull_collider_translated(image: &Image) -> Vec<Option<Collider>> {
let e = Edges::from(image);
e.multi_image_edge_translated()
.into_iter()
.map(Collider::convex_hull)
.collect()
}
pub fn multi_convex_hull_collider_raw(image: &Image) -> Vec<Option<Collider>> {
let e = Edges::from(image);
e.multi_image_edges_raw()
.into_iter()
.map(Collider::convex_hull)
.collect()
}
fn heightfield_collider_from_points(v: &[Vec2]) -> Collider {
let hf: DVector<Real> = heights_from_points(v).into();
let x_scale: Real = hf.len() as f32 - 1.0;
let scale: Vector<Real> = Vector2::new(x_scale, 1.0).into();
Collider::from(SharedShape::heightfield(hf, scale))
}
fn heights_from_points(points: &[Vec2]) -> Vec<Real> {
let mut heights: Vec<Vec2> = 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 {
heights.remove(i);
heights.insert(i, *p);
}
} else {
heights.push(*p);
}
}
heights.iter().map(|e| e.y).collect::<Vec<Real>>()
}