From 754a48b7ff6d8c58b1ee08651e60112900b60455 Mon Sep 17 00:00:00 2001 From: Sébastien Crozet Date: Tue, 25 Aug 2020 22:10:25 +0200 Subject: First public release of Rapier. --- src_testbed/objects/ball.rs | 73 +++++++++++++++++ src_testbed/objects/box_node.rs | 73 +++++++++++++++++ src_testbed/objects/capsule.rs | 74 +++++++++++++++++ src_testbed/objects/convex.rs | 77 +++++++++++++++++ src_testbed/objects/heightfield.rs | 120 +++++++++++++++++++++++++++ src_testbed/objects/mesh.rs | 108 ++++++++++++++++++++++++ src_testbed/objects/mod.rs | 10 +++ src_testbed/objects/node.rs | 164 +++++++++++++++++++++++++++++++++++++ src_testbed/objects/plane.rs | 132 +++++++++++++++++++++++++++++ src_testbed/objects/polyline.rs | 79 ++++++++++++++++++ 10 files changed, 910 insertions(+) create mode 100644 src_testbed/objects/ball.rs create mode 100644 src_testbed/objects/box_node.rs create mode 100644 src_testbed/objects/capsule.rs create mode 100644 src_testbed/objects/convex.rs create mode 100644 src_testbed/objects/heightfield.rs create mode 100644 src_testbed/objects/mesh.rs create mode 100644 src_testbed/objects/mod.rs create mode 100644 src_testbed/objects/node.rs create mode 100644 src_testbed/objects/plane.rs create mode 100644 src_testbed/objects/polyline.rs (limited to 'src_testbed/objects') diff --git a/src_testbed/objects/ball.rs b/src_testbed/objects/ball.rs new file mode 100644 index 0000000..f72c284 --- /dev/null +++ b/src_testbed/objects/ball.rs @@ -0,0 +1,73 @@ +use crate::objects::node::{self, GraphicsNode}; +use kiss3d::window::Window; +use na::Point3; +use rapier::geometry::{ColliderHandle, ColliderSet}; +use rapier::math::Isometry; + +pub struct Ball { + color: Point3, + base_color: Point3, + gfx: GraphicsNode, + collider: ColliderHandle, +} + +impl Ball { + pub fn new( + collider: ColliderHandle, + radius: f32, + color: Point3, + window: &mut Window, + ) -> Ball { + #[cfg(feature = "dim2")] + let node = window.add_circle(radius); + #[cfg(feature = "dim3")] + let node = window.add_sphere(radius); + + let mut res = Ball { + color, + base_color: color, + gfx: node, + collider, + }; + + // res.gfx.set_texture_from_file(&Path::new("media/kitten.png"), "kitten"); + res.gfx.set_color(color.x, color.y, color.z); + res + } + + pub fn select(&mut self) { + self.color = Point3::new(1.0, 0.0, 0.0); + } + + pub fn unselect(&mut self) { + self.color = self.base_color; + } + + pub fn set_color(&mut self, color: Point3) { + self.gfx.set_color(color.x, color.y, color.z); + self.color = color; + self.base_color = color; + } + + pub fn update(&mut self, colliders: &ColliderSet) { + node::update_scene_node( + &mut self.gfx, + colliders, + self.collider, + &self.color, + &Isometry::identity(), + ); + } + + pub fn scene_node(&self) -> &GraphicsNode { + &self.gfx + } + + pub fn scene_node_mut(&mut self) -> &mut GraphicsNode { + &mut self.gfx + } + + pub fn object(&self) -> ColliderHandle { + self.collider + } +} diff --git a/src_testbed/objects/box_node.rs b/src_testbed/objects/box_node.rs new file mode 100644 index 0000000..493ffba --- /dev/null +++ b/src_testbed/objects/box_node.rs @@ -0,0 +1,73 @@ +use crate::objects::node::{self, GraphicsNode}; +use kiss3d::window; +use na::Point3; +use rapier::geometry::{ColliderHandle, ColliderSet}; +use rapier::math::{Isometry, Vector}; + +pub struct Box { + color: Point3, + base_color: Point3, + gfx: GraphicsNode, + collider: ColliderHandle, +} + +impl Box { + pub fn new( + collider: ColliderHandle, + half_extents: Vector, + color: Point3, + window: &mut window::Window, + ) -> Box { + let extents = half_extents * 2.0; + #[cfg(feature = "dim2")] + let node = window.add_rectangle(extents.x, extents.y); + #[cfg(feature = "dim3")] + let node = window.add_cube(extents.x, extents.y, extents.z); + + let mut res = Box { + color, + base_color: color, + gfx: node, + collider, + }; + + res.gfx.set_color(color.x, color.y, color.z); + res + } + + pub fn select(&mut self) { + self.color = Point3::new(1.0, 0.0, 0.0); + } + + pub fn unselect(&mut self) { + self.color = self.base_color; + } + + pub fn set_color(&mut self, color: Point3) { + self.gfx.set_color(color.x, color.y, color.z); + self.color = color; + self.base_color = color; + } + + pub fn update(&mut self, colliders: &ColliderSet) { + node::update_scene_node( + &mut self.gfx, + colliders, + self.collider, + &self.color, + &Isometry::identity(), + ); + } + + pub fn scene_node(&self) -> &GraphicsNode { + &self.gfx + } + + pub fn scene_node_mut(&mut self) -> &mut GraphicsNode { + &mut self.gfx + } + + pub fn object(&self) -> ColliderHandle { + self.collider + } +} diff --git a/src_testbed/objects/capsule.rs b/src_testbed/objects/capsule.rs new file mode 100644 index 0000000..23160be --- /dev/null +++ b/src_testbed/objects/capsule.rs @@ -0,0 +1,74 @@ +use crate::objects::node::{self, GraphicsNode}; +use kiss3d::window; +use na::Point3; +use rapier::geometry::{self, ColliderHandle, ColliderSet}; +use rapier::math::Isometry; + +pub struct Capsule { + color: Point3, + base_color: Point3, + gfx: GraphicsNode, + collider: ColliderHandle, +} + +impl Capsule { + pub fn new( + collider: ColliderHandle, + capsule: &geometry::Capsule, + color: Point3, + window: &mut window::Window, + ) -> Capsule { + let r = capsule.radius; + let h = capsule.half_height() * 2.0; + #[cfg(feature = "dim2")] + let node = window.add_planar_capsule(r, h); + #[cfg(feature = "dim3")] + let node = window.add_capsule(r, h); + + let mut res = Capsule { + color, + base_color: color, + gfx: node, + collider, + }; + + res.gfx.set_color(color.x, color.y, color.z); + res + } + + pub fn select(&mut self) { + self.color = Point3::new(1.0, 0.0, 0.0); + } + + pub fn unselect(&mut self) { + self.color = self.base_color; + } + + pub fn update(&mut self, colliders: &ColliderSet) { + node::update_scene_node( + &mut self.gfx, + colliders, + self.collider, + &self.color, + &Isometry::identity(), + ); + } + + pub fn set_color(&mut self, color: Point3) { + self.gfx.set_color(color.x, color.y, color.z); + self.color = color; + self.base_color = color; + } + + pub fn scene_node(&self) -> &GraphicsNode { + &self.gfx + } + + pub fn scene_node_mut(&mut self) -> &mut GraphicsNode { + &mut self.gfx + } + + pub fn object(&self) -> ColliderHandle { + self.collider + } +} diff --git a/src_testbed/objects/convex.rs b/src_testbed/objects/convex.rs new file mode 100644 index 0000000..0347144 --- /dev/null +++ b/src_testbed/objects/convex.rs @@ -0,0 +1,77 @@ +#![allow(warnings)] // TODO: remove this. + +#[cfg(feature = "dim2")] +use crate::math::Vector; +use crate::math::{Isometry, Point}; +use crate::objects::node::{self, GraphicsNode}; +use kiss3d::window::Window; +use na::Point3; +use rapier::geometry::{ColliderHandle, ColliderSet}; + +pub struct Convex { + color: Point3, + base_color: Point3, + gfx: GraphicsNode, + body: ColliderHandle, +} + +impl Convex { + pub fn new( + body: ColliderHandle, + vertices: Vec>, + color: Point3, + window: &mut Window, + ) -> Convex { + #[cfg(feature = "dim2")] + let node = window.add_convex_polygon(vertices, Vector::from_element(1.0)); + #[cfg(feature = "dim3")] + let node = unimplemented!(); + + let mut res = Convex { + color, + base_color: color, + gfx: node, + body, + }; + + // res.gfx.set_texture_from_file(&Path::new("media/kitten.png"), "kitten"); + res.gfx.set_color(color.x, color.y, color.z); + res + } + + pub fn select(&mut self) { + self.color = Point3::new(1.0, 0.0, 0.0); + } + + pub fn unselect(&mut self) { + self.color = self.base_color; + } + + pub fn set_color(&mut self, color: Point3) { + self.gfx.set_color(color.x, color.y, color.z); + self.color = color; + self.base_color = color; + } + + pub fn update(&mut self, colliders: &ColliderSet) { + node::update_scene_node( + &mut self.gfx, + colliders, + self.body, + &self.color, + &Isometry::identity(), + ); + } + + pub fn scene_node(&self) -> &GraphicsNode { + &self.gfx + } + + pub fn scene_node_mut(&mut self) -> &mut GraphicsNode { + &mut self.gfx + } + + pub fn object(&self) -> ColliderHandle { + self.body + } +} diff --git a/src_testbed/objects/heightfield.rs b/src_testbed/objects/heightfield.rs new file mode 100644 index 0000000..0815592 --- /dev/null +++ b/src_testbed/objects/heightfield.rs @@ -0,0 +1,120 @@ +#[cfg(feature = "dim3")] +use crate::objects::node::{self, GraphicsNode}; +use kiss3d::window::Window; +use na::{self, Point3}; +use ncollide::shape; +#[cfg(feature = "dim3")] +use ncollide::transformation::ToTriMesh; +use rapier::geometry::{ColliderHandle, ColliderSet}; +#[cfg(feature = "dim2")] +use rapier::math::Point; +#[cfg(feature = "dim3")] +use rapier::math::Vector; + +pub struct HeightField { + color: Point3, + base_color: Point3, + #[cfg(feature = "dim2")] + vertices: Vec>, + #[cfg(feature = "dim3")] + gfx: GraphicsNode, + collider: ColliderHandle, +} + +impl HeightField { + #[cfg(feature = "dim2")] + pub fn new( + collider: ColliderHandle, + heightfield: &shape::HeightField, + color: Point3, + _: &mut Window, + ) -> HeightField { + let mut vertices = Vec::new(); + + for seg in heightfield.segments() { + vertices.push(seg.a); + vertices.push(seg.b); + } + + HeightField { + color, + base_color: color, + vertices, + collider, + } + } + + #[cfg(feature = "dim3")] + pub fn new( + collider: ColliderHandle, + heightfield: &shape::HeightField, + color: Point3, + window: &mut Window, + ) -> HeightField { + let mesh = heightfield.to_trimesh(()); + + let mut res = HeightField { + color, + base_color: color, + gfx: window.add_trimesh(mesh, Vector::repeat(1.0)), + collider: collider, + }; + + res.gfx.enable_backface_culling(false); + res.gfx.set_color(color.x, color.y, color.z); + + res + } + + pub fn select(&mut self) { + self.color = Point3::new(1.0, 0.0, 0.0); + } + + pub fn unselect(&mut self) { + self.color = self.base_color; + } + + pub fn set_color(&mut self, color: Point3) { + #[cfg(feature = "dim3")] + { + self.gfx.set_color(color.x, color.y, color.z); + } + self.color = color; + self.base_color = color; + } + + #[cfg(feature = "dim3")] + pub fn update(&mut self, colliders: &ColliderSet) { + node::update_scene_node( + &mut self.gfx, + colliders, + self.collider, + &self.color, + &na::Isometry::identity(), + ); + } + + #[cfg(feature = "dim2")] + pub fn update(&mut self, _colliders: &ColliderSet) {} + + #[cfg(feature = "dim3")] + pub fn scene_node(&self) -> &GraphicsNode { + &self.gfx + } + + #[cfg(feature = "dim3")] + pub fn scene_node_mut(&mut self) -> &mut GraphicsNode { + &mut self.gfx + } + + pub fn object(&self) -> ColliderHandle { + self.collider + } + + #[cfg(feature = "dim2")] + pub fn draw(&mut self, window: &mut Window) { + for vtx in self.vertices.chunks(2) { + window.draw_planar_line(&vtx[0], &vtx[1], &self.color) + } + } +} diff --git a/src_testbed/objects/mesh.rs b/src_testbed/objects/mesh.rs new file mode 100644 index 0000000..5187a8b --- /dev/null +++ b/src_testbed/objects/mesh.rs @@ -0,0 +1,108 @@ +use crate::objects::node::{self, GraphicsNode}; +use kiss3d::window; +use na::Point3; +use rapier::geometry::{ColliderHandle, ColliderSet}; +use rapier::math::{Isometry, Point}; +use std::cell::RefCell; +use std::rc::Rc; + +pub struct Mesh { + color: Point3, + base_color: Point3, + gfx: GraphicsNode, + collider: ColliderHandle, +} + +impl Mesh { + pub fn new( + collider: ColliderHandle, + vertices: Vec>, + indices: Vec>, + color: Point3, + window: &mut window::Window, + ) -> Mesh { + let vs = vertices; + let is = indices.into_iter().map(na::convert).collect(); + + let mesh; + let gfx; + + #[cfg(feature = "dim2")] + { + mesh = kiss3d::resource::PlanarMesh::new(vs, is, None, false); + gfx = window.add_planar_mesh( + Rc::new(RefCell::new(mesh)), + crate::math::Vector::from_element(1.0), + ); + } + + #[cfg(feature = "dim3")] + { + mesh = kiss3d::resource::Mesh::new(vs, is, None, None, false); + gfx = window.add_mesh(Rc::new(RefCell::new(mesh)), na::Vector3::from_element(1.0)); + } + + let mut res = Mesh { + color, + base_color: color, + gfx, + collider, + }; + + res.gfx.enable_backface_culling(false); + res.gfx.set_color(color.x, color.y, color.z); + res + } + + pub fn select(&mut self) { + self.color = Point3::new(1.0, 0.0, 0.0); + } + + pub fn unselect(&mut self) { + self.color = self.base_color; + } + + pub fn set_color(&mut self, color: Point3) { + self.gfx.set_color(color.x, color.y, color.z); + self.color = color; + self.base_color = color; + } + + pub fn update(&mut self, colliders: &ColliderSet) { + node::update_scene_node( + &mut self.gfx, + colliders, + self.collider, + &self.color, + &Isometry::identity(), + ); + + // // Update if some deformation occurred. + // // FIXME: don't update if it did not move. + // if let Some(c) = colliders.get(self.collider) { + // if let ColliderAnchor::OnDeformableBody { .. } = c.anchor() { + // let shape = c.shape().as_shape::>().unwrap(); + // let vtx = shape.points(); + // + // self.gfx.modify_vertices(&mut |vertices| { + // for (v, new_v) in vertices.iter_mut().zip(vtx.iter()) { + // *v = *new_v + // } + // }); + // self.gfx.recompute_normals(); + // } + // } + } + + pub fn scene_node(&self) -> &GraphicsNode { + &self.gfx + } + + pub fn scene_node_mut(&mut self) -> &mut GraphicsNode { + &mut self.gfx + } + + pub fn object(&self) -> ColliderHandle { + self.collider + } +} diff --git a/src_testbed/objects/mod.rs b/src_testbed/objects/mod.rs new file mode 100644 index 0000000..82895b3 --- /dev/null +++ b/src_testbed/objects/mod.rs @@ -0,0 +1,10 @@ +pub mod ball; +pub mod box_node; +pub mod capsule; +pub mod convex; +pub mod heightfield; +pub mod mesh; +pub mod node; +//pub mod plane; +//#[cfg(feature = "dim2")] +//pub mod polyline; diff --git a/src_testbed/objects/node.rs b/src_testbed/objects/node.rs new file mode 100644 index 0000000..93b5eac --- /dev/null +++ b/src_testbed/objects/node.rs @@ -0,0 +1,164 @@ +use crate::objects::ball::Ball; +use crate::objects::box_node::Box; +use crate::objects::capsule::Capsule; +use crate::objects::convex::Convex; +use crate::objects::heightfield::HeightField; +use crate::objects::mesh::Mesh; +//use crate::objects::plane::Plane; +//#[cfg(feature = "dim2")] +//use crate::objects::polyline::Polyline; +use kiss3d::window::Window; +use na::Point3; + +use rapier::geometry::{ColliderHandle, ColliderSet}; +use rapier::math::Isometry; + +#[cfg(feature = "dim2")] +pub type GraphicsNode = kiss3d::scene::PlanarSceneNode; +#[cfg(feature = "dim3")] +pub type GraphicsNode = kiss3d::scene::SceneNode; + +pub enum Node { + // Plane(Plane), + Ball(Ball), + Box(Box), + HeightField(HeightField), + Capsule(Capsule), + // #[cfg(feature = "dim2")] + // Polyline(Polyline), + Mesh(Mesh), + Convex(Convex), +} + +impl Node { + pub fn select(&mut self) { + match *self { + // Node::Plane(ref mut n) => n.select(), + Node::Ball(ref mut n) => n.select(), + Node::Box(ref mut n) => n.select(), + Node::Capsule(ref mut n) => n.select(), + Node::HeightField(ref mut n) => n.select(), + // #[cfg(feature = "dim2")] + // Node::Polyline(ref mut n) => n.select(), + Node::Mesh(ref mut n) => n.select(), + Node::Convex(ref mut n) => n.select(), + } + } + + pub fn unselect(&mut self) { + match *self { + // Node::Plane(ref mut n) => n.unselect(), + Node::Ball(ref mut n) => n.unselect(), + Node::Box(ref mut n) => n.unselect(), + Node::Capsule(ref mut n) => n.unselect(), + Node::HeightField(ref mut n) => n.unselect(), + // #[cfg(feature = "dim2")] + // Node::Polyline(ref mut n) => n.unselect(), + Node::Mesh(ref mut n) => n.unselect(), + Node::Convex(ref mut n) => n.unselect(), + } + } + + pub fn update(&mut self, colliders: &ColliderSet) { + match *self { + // Node::Plane(ref mut n) => n.update(colliders), + Node::Ball(ref mut n) => n.update(colliders), + Node::Box(ref mut n) => n.update(colliders), + Node::Capsule(ref mut n) => n.update(colliders), + Node::HeightField(ref mut n) => n.update(colliders), + // #[cfg(feature = "dim2")] + // Node::Polyline(ref mut n) => n.update(colliders), + Node::Mesh(ref mut n) => n.update(colliders), + Node::Convex(ref mut n) => n.update(colliders), + } + } + + #[cfg(feature = "dim2")] + pub fn draw(&mut self, window: &mut Window) { + match *self { + // Node::Polyline(ref mut n) => n.draw(_window), + Node::HeightField(ref mut n) => n.draw(window), + // Node::Plane(ref mut n) => n.draw(_window), + _ => {} + } + } + + #[cfg(feature = "dim3")] + pub fn draw(&mut self, _: &mut Window) {} + + pub fn scene_node(&self) -> Option<&GraphicsNode> { + match *self { + // #[cfg(feature = "dim3")] + // Node::Plane(ref n) => Some(n.scene_node()), + Node::Ball(ref n) => Some(n.scene_node()), + Node::Box(ref n) => Some(n.scene_node()), + Node::Capsule(ref n) => Some(n.scene_node()), + #[cfg(feature = "dim3")] + Node::HeightField(ref n) => Some(n.scene_node()), + Node::Mesh(ref n) => Some(n.scene_node()), + Node::Convex(ref n) => Some(n.scene_node()), + #[cfg(feature = "dim2")] + _ => None, + } + } + + pub fn scene_node_mut(&mut self) -> Option<&mut GraphicsNode> { + match *self { + // #[cfg(feature = "dim3")] + // Node::Plane(ref mut n) => Some(n.scene_node_mut()), + Node::Ball(ref mut n) => Some(n.scene_node_mut()), + Node::Box(ref mut n) => Some(n.scene_node_mut()), + Node::Capsule(ref mut n) => Some(n.scene_node_mut()), + #[cfg(feature = "dim3")] + Node::HeightField(ref mut n) => Some(n.scene_node_mut()), + Node::Mesh(ref mut n) => Some(n.scene_node_mut()), + Node::Convex(ref mut n) => Some(n.scene_node_mut()), + #[cfg(feature = "dim2")] + _ => None, + } + } + + pub fn collider(&self) -> ColliderHandle { + match *self { + // Node::Plane(ref n) => n.object(), + Node::Ball(ref n) => n.object(), + Node::Box(ref n) => n.object(), + Node::Capsule(ref n) => n.object(), + Node::HeightField(ref n) => n.object(), + // #[cfg(feature = "dim2")] + // Node::Polyline(ref n) => n.object(), + Node::Mesh(ref n) => n.object(), + Node::Convex(ref n) => n.object(), + } + } + + pub fn set_color(&mut self, color: Point3) { + match *self { + // Node::Plane(ref mut n) => n.set_color(color), + Node::Ball(ref mut n) => n.set_color(color), + Node::Box(ref mut n) => n.set_color(color), + Node::Capsule(ref mut n) => n.set_color(color), + Node::HeightField(ref mut n) => n.set_color(color), + // #[cfg(feature = "dim2")] + // Node::Polyline(ref mut n) => n.set_color(color), + Node::Mesh(ref mut n) => n.set_color(color), + Node::Convex(ref mut n) => n.set_color(color), + } + } +} + +pub fn update_scene_node( + node: &mut GraphicsNode, + colliders: &ColliderSet, + handle: ColliderHandle, + color: &Point3, + delta: &Isometry, +) { + if let Some(co) = colliders.get(handle) { + node.set_local_transformation(co.position() * delta); + node.set_color(color.x, color.y, color.z); + } else { + node.set_visible(false); + node.unlink(); + } +} diff --git a/src_testbed/objects/plane.rs b/src_testbed/objects/plane.rs new file mode 100644 index 0000000..218e97a --- /dev/null +++ b/src_testbed/objects/plane.rs @@ -0,0 +1,132 @@ +#[cfg(feature = "dim3")] +use crate::objects::node::GraphicsNode; +use kiss3d::window::Window; +use na::Point3; +#[cfg(feature = "dim3")] +use na::Vector3; +#[cfg(feature = "dim2")] +use nphysics::math::{Point, Vector}; +use nphysics::object::{DefaultColliderHandle, DefaultColliderSet}; +#[cfg(feature = "dim3")] +use num::Zero; + +#[cfg(feature = "dim3")] +pub struct Plane { + gfx: GraphicsNode, + collider: DefaultColliderHandle, +} + +#[cfg(feature = "dim2")] +pub struct Plane { + color: Point3, + base_color: Point3, + position: Point, + normal: na::Unit>, + collider: DefaultColliderHandle, +} + +impl Plane { + #[cfg(feature = "dim2")] + pub fn new( + collider: DefaultColliderHandle, + colliders: &DefaultColliderSet, + position: &Point, + normal: &Vector, + color: Point3, + _: &mut Window, + ) -> Plane { + let mut res = Plane { + color, + base_color: color, + position: *position, + normal: na::Unit::new_normalize(*normal), + collider, + }; + + res.update(colliders); + res + } + + #[cfg(feature = "dim3")] + pub fn new( + collider: DefaultColliderHandle, + colliders: &DefaultColliderSet, + world_pos: &Point3, + world_normal: &Vector3, + color: Point3, + window: &mut Window, + ) -> Plane { + let mut res = Plane { + gfx: window.add_quad(100.0, 100.0, 10, 10), + collider, + }; + + if colliders + .get(collider) + .unwrap() + .query_type() + .is_proximity_query() + { + res.gfx.set_surface_rendering_activation(false); + res.gfx.set_lines_width(1.0); + } + + res.gfx.set_color(color.x, color.y, color.z); + + let up = if world_normal.z.is_zero() && world_normal.y.is_zero() { + Vector3::z() + } else { + Vector3::x() + }; + + res.gfx + .reorient(world_pos, &(*world_pos + *world_normal), &up); + + res.update(colliders); + + res + } + + pub fn select(&mut self) {} + + pub fn unselect(&mut self) {} + + pub fn update(&mut self, _: &DefaultColliderSet) { + // FIXME: atm we assume the plane does not move + } + + #[cfg(feature = "dim3")] + pub fn set_color(&mut self, color: Point3) { + self.gfx.set_color(color.x, color.y, color.z); + } + + #[cfg(feature = "dim2")] + pub fn set_color(&mut self, color: Point3) { + self.color = color; + self.base_color = color; + } + + #[cfg(feature = "dim3")] + pub fn scene_node(&self) -> &GraphicsNode { + &self.gfx + } + + #[cfg(feature = "dim3")] + pub fn scene_node_mut(&mut self) -> &mut GraphicsNode { + &mut self.gfx + } + + pub fn object(&self) -> DefaultColliderHandle { + self.collider + } + + #[cfg(feature = "dim2")] + pub fn draw(&mut self, window: &mut Window) { + let orth = Vector::new(-self.normal.y, self.normal.x); + window.draw_planar_line( + &(self.position - orth * 50.0), + &(self.position + orth * 50.0), + &self.color, + ); + } +} diff --git a/src_testbed/objects/polyline.rs b/src_testbed/objects/polyline.rs new file mode 100644 index 0000000..77841ae --- /dev/null +++ b/src_testbed/objects/polyline.rs @@ -0,0 +1,79 @@ +use kiss3d::window::Window; +use na::{Isometry2, Point2, Point3}; +use ncollide2d::shape; +use nphysics2d::object::{ColliderAnchor, DefaultColliderHandle, DefaultColliderSet}; + +pub struct Polyline { + color: Point3, + base_color: Point3, + vertices: Vec>, + indices: Vec>, + collider: DefaultColliderHandle, + pos: Isometry2, +} + +impl Polyline { + pub fn new( + collider: DefaultColliderHandle, + colliders: &DefaultColliderSet, + _: Isometry2, + vertices: Vec>, + indices: Vec>, + color: Point3, + _: &mut Window, + ) -> Polyline { + let mut res = Polyline { + color, + pos: Isometry2::identity(), + base_color: color, + vertices, + indices, + collider, + }; + + res.update(colliders); + res + } + + pub fn select(&mut self) { + self.color = Point3::new(1.0, 0.0, 0.0); + } + + pub fn unselect(&mut self) { + self.color = self.base_color; + } + + pub fn set_color(&mut self, color: Point3) { + self.color = color; + self.base_color = color; + } + + pub fn update(&mut self, colliders: &DefaultColliderSet) { + // Update if some deformation occurred. + // FIXME: don't update if it did not move. + if let Some(c) = colliders.get(self.collider) { + self.pos = *c.position(); + if let ColliderAnchor::OnDeformableBody { .. } = c.anchor() { + let shape = c.shape().as_shape::>().unwrap(); + self.vertices = shape.points().to_vec(); + self.indices.clear(); + + for e in shape.edges() { + self.indices.push(e.indices); + } + } + } + } + + pub fn object(&self) -> DefaultColliderHandle { + self.collider + } + + pub fn draw(&mut self, window: &mut Window) { + for idx in &self.indices { + let p1 = self.pos * self.vertices[idx.x]; + let p2 = self.pos * self.vertices[idx.y]; + window.draw_planar_line(&p1, &p2, &self.color) + } + } +} -- cgit