From 1a84bf2af34176508bdda8d0f2ad2e46dc5c4df9 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Sun, 16 May 2021 17:49:20 +0200 Subject: Replace Kiss3d by Bevy for the testbed renderer. --- src_testbed/objects/ball.rs | 76 ------ src_testbed/objects/box_node.rs | 76 ------ src_testbed/objects/capsule.rs | 77 ------ src_testbed/objects/cone.rs | 77 ------ src_testbed/objects/convex.rs | 96 ------- src_testbed/objects/cylinder.rs | 77 ------ src_testbed/objects/heightfield.rs | 128 --------- src_testbed/objects/mesh.rs | 111 -------- src_testbed/objects/mod.rs | 12 - src_testbed/objects/node.rs | 547 +++++++++++++++++++++++++++---------- src_testbed/objects/plane.rs | 132 --------- src_testbed/objects/polyline.rs | 67 ----- 12 files changed, 401 insertions(+), 1075 deletions(-) delete mode 100644 src_testbed/objects/ball.rs delete mode 100644 src_testbed/objects/box_node.rs delete mode 100644 src_testbed/objects/capsule.rs delete mode 100644 src_testbed/objects/cone.rs delete mode 100644 src_testbed/objects/convex.rs delete mode 100644 src_testbed/objects/cylinder.rs delete mode 100644 src_testbed/objects/heightfield.rs delete mode 100644 src_testbed/objects/mesh.rs delete mode 100644 src_testbed/objects/plane.rs delete 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 deleted file mode 100644 index df43341..0000000 --- a/src_testbed/objects/ball.rs +++ /dev/null @@ -1,76 +0,0 @@ -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, - delta: Isometry, -} - -impl Ball { - pub fn new( - collider: ColliderHandle, - delta: Isometry, - 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, - delta, - }; - - // 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, - &self.delta, - ); - } - - 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 deleted file mode 100644 index 0586d77..0000000 --- a/src_testbed/objects/box_node.rs +++ /dev/null @@ -1,76 +0,0 @@ -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, - delta: Isometry, -} - -impl Box { - pub fn new( - collider: ColliderHandle, - delta: Isometry, - 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, - delta, - }; - - 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, - &self.delta, - ); - } - - 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 deleted file mode 100644 index 3d3e88f..0000000 --- a/src_testbed/objects/capsule.rs +++ /dev/null @@ -1,77 +0,0 @@ -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, - delta: Isometry, -} - -impl Capsule { - pub fn new( - collider: ColliderHandle, - delta: Isometry, - 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, - delta: delta * capsule.transform_wrt_y(), - }; - - 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, - &self.delta, - ); - } - - 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/cone.rs b/src_testbed/objects/cone.rs deleted file mode 100644 index 7aa2039..0000000 --- a/src_testbed/objects/cone.rs +++ /dev/null @@ -1,77 +0,0 @@ -use crate::objects::node::{self, GraphicsNode}; -use kiss3d::window::Window; -use na::Point3; -use rapier::geometry::{ColliderHandle, ColliderSet}; -use rapier::math::Isometry; - -pub struct Cone { - color: Point3, - base_color: Point3, - gfx: GraphicsNode, - collider: ColliderHandle, - delta: Isometry, -} - -impl Cone { - pub fn new( - collider: ColliderHandle, - delta: Isometry, - half_height: f32, - radius: f32, - color: Point3, - window: &mut Window, - ) -> Cone { - #[cfg(feature = "dim2")] - let node = window.add_rectangle(radius, half_height); - #[cfg(feature = "dim3")] - let node = window.add_cone(radius, half_height * 2.0); - - let mut res = Cone { - color, - base_color: color, - gfx: node, - collider, - delta, - }; - - // 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, - &self.delta, - ); - } - - 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 deleted file mode 100644 index 95ef74a..0000000 --- a/src_testbed/objects/convex.rs +++ /dev/null @@ -1,96 +0,0 @@ -#![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, - delta: Isometry, -} - -impl Convex { - pub fn new( - body: ColliderHandle, - delta: Isometry, - vertices: Vec>, - #[cfg(feature = "dim3")] indices: Vec<[u32; 3]>, - 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 = { - use std::cell::RefCell; - use std::rc::Rc; - let mut mesh_vertices = Vec::new(); - let mut mesh_indices = Vec::new(); - for idx in indices { - let i = mesh_vertices.len() as u16; - mesh_vertices.push(vertices[idx[0] as usize]); - mesh_vertices.push(vertices[idx[1] as usize]); - mesh_vertices.push(vertices[idx[2] as usize]); - mesh_indices.push(Point3::new(i, i + 1, i + 2)); - } - - let mesh = kiss3d::resource::Mesh::new(mesh_vertices, mesh_indices, None, None, false); - window.add_mesh(Rc::new(RefCell::new(mesh)), na::Vector3::from_element(1.0)) - }; - - let mut res = Convex { - color, - base_color: color, - gfx: node, - body, - delta, - }; - - // 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, - &self.delta, - ); - } - - 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/cylinder.rs b/src_testbed/objects/cylinder.rs deleted file mode 100644 index ff4dc72..0000000 --- a/src_testbed/objects/cylinder.rs +++ /dev/null @@ -1,77 +0,0 @@ -use crate::objects::node::{self, GraphicsNode}; -use kiss3d::window::Window; -use na::Point3; -use rapier::geometry::{ColliderHandle, ColliderSet}; -use rapier::math::Isometry; - -pub struct Cylinder { - color: Point3, - base_color: Point3, - gfx: GraphicsNode, - collider: ColliderHandle, - delta: Isometry, -} - -impl Cylinder { - pub fn new( - collider: ColliderHandle, - delta: Isometry, - half_height: f32, - radius: f32, - color: Point3, - window: &mut Window, - ) -> Cylinder { - #[cfg(feature = "dim2")] - let node = window.add_rectangle(radius, half_height); - #[cfg(feature = "dim3")] - let node = window.add_cylinder(radius, half_height * 2.0); - - let mut res = Cylinder { - color, - base_color: color, - gfx: node, - collider, - delta, - }; - - // 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, - &self.delta, - ); - } - - 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/heightfield.rs b/src_testbed/objects/heightfield.rs deleted file mode 100644 index 913a732..0000000 --- a/src_testbed/objects/heightfield.rs +++ /dev/null @@ -1,128 +0,0 @@ -use kiss3d::window::Window; -use na::{self, Point3}; -use parry::shape; -use rapier::geometry::{ColliderHandle, ColliderSet}; -#[cfg(feature = "dim2")] -use rapier::math::Point; -#[cfg(feature = "dim3")] -use { - crate::objects::node::{self, GraphicsNode}, - kiss3d::resource::Mesh, - rapier::math::Vector, - std::cell::RefCell, -}; - -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 { - use std::rc::Rc; - - let (vertices, indices) = heightfield.to_trimesh(); - let indices = indices - .into_iter() - .map(|idx| Point3::new(idx[0] as u16, idx[1] as u16, idx[2] as u16)) - .collect(); - let mesh = Mesh::new(vertices, indices, None, None, false); - - let mut res = HeightField { - color, - base_color: color, - gfx: window.add_mesh(Rc::new(RefCell::new(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 deleted file mode 100644 index 5505de3..0000000 --- a/src_testbed/objects/mesh.rs +++ /dev/null @@ -1,111 +0,0 @@ -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<[u32; 3]>, - color: Point3, - window: &mut window::Window, - ) -> Mesh { - let vs = vertices; - let is = indices - .into_iter() - .map(|idx| Point3::new(idx[0] as u16, idx[1] as u16, idx[2] as u16)) - .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 index 8e12dbe..492bc84 100644 --- a/src_testbed/objects/mod.rs +++ b/src_testbed/objects/mod.rs @@ -1,13 +1 @@ -pub mod ball; -pub mod box_node; -pub mod capsule; -pub mod cone; -pub mod convex; -pub mod cylinder; -pub mod heightfield; -pub mod mesh; pub mod node; -pub mod polyline; -//pub mod plane; -//#[cfg(feature = "dim2")] -//pub mod polyline; diff --git a/src_testbed/objects/node.rs b/src_testbed/objects/node.rs index 1bc491f..be2fa71 100644 --- a/src_testbed/objects/node.rs +++ b/src_testbed/objects/node.rs @@ -1,177 +1,432 @@ -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 bevy::prelude::*; +use bevy::render::mesh::{Indices, VertexAttributeValues}; + //use crate::objects::plane::Plane; -use crate::objects::polyline::Polyline; -use kiss3d::window::Window; -use na::Point3; +use na::{Point3, Vector3}; +use std::collections::HashMap; -use crate::objects::cone::Cone; -use crate::objects::cylinder::Cylinder; -use rapier::geometry::{ColliderHandle, ColliderSet}; +use bevy::render::pipeline::PrimitiveTopology; +use bevy::render::wireframe::Wireframe; +use rapier::geometry::{ColliderHandle, ColliderSet, Shape, ShapeType}; +#[cfg(feature = "dim3")] +use rapier::geometry::{Cone, Cylinder}; 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), - Polyline(Polyline), - Mesh(Mesh), - Convex(Convex), - Cylinder(Cylinder), - Cone(Cone), +use { + na::{Point2, Vector2}, + rapier::geometry::{Ball, Cuboid}, +}; + +pub struct EntityWithGraphics { + pub entity: Entity, + pub color: Point3, + pub base_color: Point3, + pub collider: ColliderHandle, + pub delta: Isometry, + material: Handle, } -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(), - Node::Polyline(ref mut n) => n.select(), - Node::Mesh(ref mut n) => n.select(), - Node::Convex(ref mut n) => n.select(), - Node::Cylinder(ref mut n) => n.select(), - Node::Cone(ref mut n) => n.select(), +impl EntityWithGraphics { + pub fn spawn( + commands: &mut Commands, + meshes: &mut Assets, + materials: &mut Assets, + prefab_meshs: &HashMap>, + shape: &dyn Shape, + collider: ColliderHandle, + collider_pos: Isometry, + delta: Isometry, + color: Point3, + sensor: bool, + ) -> Self { + let entity = commands.spawn().id(); + + let scale = collider_mesh_scale(shape); + let mesh = prefab_meshs + .get(&shape.shape_type()) + .cloned() + .or_else(|| generate_collider_mesh(shape).map(|m| meshes.add(m))) + .expect("Could not build the collider's render mesh"); + + let bevy_color = Color::rgb(color.x, color.y, color.z); + let shape_pos = collider_pos * delta; + let mut transform = Transform::from_scale(scale); + transform.translation.x = shape_pos.translation.vector.x; + transform.translation.y = shape_pos.translation.vector.y; + #[cfg(feature = "dim3")] + { + transform.translation.z = shape_pos.translation.vector.z; + transform.rotation = Quat::from_xyzw( + shape_pos.rotation.i, + shape_pos.rotation.j, + shape_pos.rotation.k, + shape_pos.rotation.w, + ); + } + #[cfg(feature = "dim2")] + { + if sensor { + transform.translation.z = -10.0; + } + transform.rotation = Quat::from_rotation_z(shape_pos.rotation.angle()); + } + + let material = StandardMaterial { + metallic: 0.5, + roughness: 0.5, + double_sided: true, // TODO: this doesn't do anything? + ..StandardMaterial::from(bevy_color) + }; + let material_handle = materials.add(material); + let material_weak_handle = material_handle.clone_weak(); + let pbr = PbrBundle { + mesh, + material: material_handle, + transform, + ..Default::default() + }; + + let mut entity_commands = commands.entity(entity); + entity_commands.insert_bundle(pbr); + + if sensor { + entity_commands.insert(Wireframe); + } + + EntityWithGraphics { + entity, + color, + base_color: color, + collider, + delta, + material: material_weak_handle, } } - 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(), - Node::Polyline(ref mut n) => n.unselect(), - Node::Mesh(ref mut n) => n.unselect(), - Node::Convex(ref mut n) => n.unselect(), - Node::Cylinder(ref mut n) => n.unselect(), - Node::Cone(ref mut n) => n.unselect(), + pub fn select(&mut self, materials: &mut Assets) { + // NOTE: we don't just call `self.set_color` because that would + // overwrite self.base_color too. + self.color = Point3::new(1.0, 0.0, 0.0); + if let Some(material) = materials.get_mut(&self.material) { + material.base_color = Color::rgb(self.color.x, self.color.y, self.color.z); } } - 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), - Node::Polyline(ref mut n) => n.update(colliders), - Node::Mesh(ref mut n) => n.update(colliders), - Node::Convex(ref mut n) => n.update(colliders), - Node::Cylinder(ref mut n) => n.update(colliders), - Node::Cone(ref mut n) => n.update(colliders), + pub fn unselect(&mut self, materials: &mut Assets) { + self.set_color(materials, self.base_color); + } + + pub fn set_color(&mut self, materials: &mut Assets, color: Point3) { + if let Some(material) = materials.get_mut(&self.material) { + material.base_color = Color::rgb(color.x, color.y, color.z); } + self.color = color; + self.base_color = color; } - #[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), - _ => {} + pub fn update(&mut self, colliders: &ColliderSet, components: &mut Query<(&mut Transform,)>) { + if let Some(co) = colliders.get(self.collider) { + if let Ok(mut pos) = components.get_component_mut::(self.entity) { + let co_pos = co.position() * self.delta; + pos.translation.x = co_pos.translation.vector.x; + pos.translation.y = co_pos.translation.vector.y; + #[cfg(feature = "dim3")] + { + pos.translation.z = co_pos.translation.vector.z; + pos.rotation = Quat::from_xyzw( + co_pos.rotation.i, + co_pos.rotation.j, + co_pos.rotation.k, + co_pos.rotation.w, + ); + } + #[cfg(feature = "dim2")] + { + pos.rotation = Quat::from_rotation_z(co_pos.rotation.angle()); + } + } } } + pub fn object(&self) -> ColliderHandle { + self.collider + } + + #[cfg(feature = "dim2")] + pub fn gen_prefab_meshes( + out: &mut HashMap>, + meshes: &mut Assets, + ) { + // + // Cuboid mesh + // + let cuboid = bevy_mesh_from_polyline(Cuboid::new(Vector2::new(1.0, 1.0)).to_polyline()); + out.insert(ShapeType::Cuboid, meshes.add(cuboid)); + + // + // Ball mesh + // + let ball = bevy_mesh_from_polyline(Ball::new(1.0).to_polyline(30)); + out.insert(ShapeType::Ball, meshes.add(ball)); + } + #[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()), - Node::Cylinder(ref n) => Some(n.scene_node()), - Node::Cone(ref n) => Some(n.scene_node()), - Node::Polyline(_) => None, - #[cfg(feature = "dim2")] - Node::HeightField(_) => None, - } + pub fn gen_prefab_meshes( + out: &mut HashMap>, + meshes: &mut Assets, + ) { + // + // Cuboid mesh + // + let cuboid = Mesh::from(shape::Cube { size: 2.0 }); + out.insert(ShapeType::Cuboid, meshes.add(cuboid)); + + // + // Ball mesh + // + let ball = Mesh::from(shape::Icosphere { + subdivisions: 2, + radius: 1.0, + }); + out.insert(ShapeType::Ball, meshes.add(ball)); + + // + // Cylinder mesh + // + let cylinder = Cylinder::new(1.0, 1.0); + let mesh = bevy_mesh(cylinder.to_trimesh(20)); + out.insert(ShapeType::Cylinder, meshes.add(mesh.clone())); + out.insert(ShapeType::RoundCylinder, meshes.add(mesh)); + + // + // Cone mesh + // + let cone = Cone::new(1.0, 1.0); + let mesh = bevy_mesh(cone.to_trimesh(10)); + out.insert(ShapeType::Cone, meshes.add(mesh.clone())); + out.insert(ShapeType::RoundCone, meshes.add(mesh)); + + // + // Halfspace + // + let vertices = vec![ + Point3::new(-1000.0, 0.0, -1000.0), + Point3::new(1000.0, 0.0, -1000.0), + Point3::new(1000.0, 0.0, 1000.0), + Point3::new(-1000.0, 0.0, 1000.0), + ]; + let indices = vec![[0, 1, 2], [0, 2, 3]]; + let mesh = bevy_mesh((vertices, indices)); + out.insert(ShapeType::HalfSpace, meshes.add(mesh)); } +} - 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()), - Node::Cylinder(ref mut n) => Some(n.scene_node_mut()), - Node::Cone(ref mut n) => Some(n.scene_node_mut()), - Node::Polyline(_) => None, - #[cfg(feature = "dim2")] - Node::HeightField(_) => None, +#[cfg(feature = "dim2")] +fn bevy_mesh_from_polyline(vertices: Vec>) -> Mesh { + let n = vertices.len(); + let idx = (1..n as u32 - 1).map(|i| [0, i, i + 1]).collect(); + let vtx = vertices + .into_iter() + .map(|v| Point3::new(v.x, v.y, 0.0)) + .collect(); + bevy_mesh((vtx, idx)) +} + +#[cfg(feature = "dim2")] +fn bevy_polyline(buffers: (Vec>, Option>)) -> Mesh { + let (vtx, idx) = buffers; + // let mut normals: Vec<[f32; 3]> = vec![]; + let mut vertices: Vec<[f32; 3]> = vec![]; + + if let Some(idx) = idx { + for idx in idx { + let a = vtx[idx[0] as usize]; + let b = vtx[idx[1] as usize]; + + vertices.push([a.x, a.y, 0.0]); + vertices.push([b.x, b.y, 0.0]); } + } else { + vertices = vtx.iter().map(|v| [v.x, v.y, 0.0]).collect(); } - 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(), - Node::Polyline(ref n) => n.object(), - Node::Mesh(ref n) => n.object(), - Node::Convex(ref n) => n.object(), - Node::Cylinder(ref n) => n.object(), - Node::Cone(ref n) => n.object(), - } + let indices: Vec<_> = (0..vertices.len() as u32).collect(); + let uvs: Vec<_> = (0..vertices.len()).map(|_| [0.0, 0.0]).collect(); + let normals: Vec<_> = (0..vertices.len()).map(|_| [0.0, 0.0, 1.0]).collect(); + + // Generate the mesh + let mut mesh = Mesh::new(PrimitiveTopology::LineStrip); + mesh.set_attribute( + Mesh::ATTRIBUTE_POSITION, + VertexAttributeValues::from(vertices), + ); + mesh.set_attribute(Mesh::ATTRIBUTE_NORMAL, VertexAttributeValues::from(normals)); + mesh.set_attribute(Mesh::ATTRIBUTE_UV_0, VertexAttributeValues::from(uvs)); + mesh.set_indices(Some(Indices::U32(indices))); + mesh +} + +fn bevy_mesh(buffers: (Vec>, Vec<[u32; 3]>)) -> Mesh { + let (vtx, idx) = buffers; + let mut normals: Vec<[f32; 3]> = vec![]; + let mut vertices: Vec<[f32; 3]> = vec![]; + + for idx in idx { + let a = vtx[idx[0] as usize]; + let b = vtx[idx[1] as usize]; + let c = vtx[idx[2] as usize]; + + vertices.push(a.into()); + vertices.push(b.into()); + vertices.push(c.into()); } - 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), - 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), - Node::Cylinder(ref mut n) => n.set_color(color), - Node::Cone(ref mut n) => n.set_color(color), - } + for vtx in vertices.chunks(3) { + let a = Point3::from(vtx[0]); + let b = Point3::from(vtx[1]); + let c = Point3::from(vtx[2]); + let n = (b - a).cross(&(c - a)).normalize(); + normals.push(n.into()); + normals.push(n.into()); + normals.push(n.into()); } + + normals + .iter_mut() + .for_each(|n| *n = Vector3::from(*n).normalize().into()); + let indices: Vec<_> = (0..vertices.len() as u32).collect(); + let uvs: Vec<_> = (0..vertices.len()).map(|_| [0.0, 0.0]).collect(); + + // Generate the mesh + let mut mesh = Mesh::new(PrimitiveTopology::TriangleList); + mesh.set_attribute( + Mesh::ATTRIBUTE_POSITION, + VertexAttributeValues::from(vertices), + ); + mesh.set_attribute(Mesh::ATTRIBUTE_NORMAL, VertexAttributeValues::from(normals)); + mesh.set_attribute(Mesh::ATTRIBUTE_UV_0, VertexAttributeValues::from(uvs)); + mesh.set_indices(Some(Indices::U32(indices))); + mesh } -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(); +fn collider_mesh_scale(co_shape: &dyn Shape) -> Vec3 { + match co_shape.shape_type() { + #[cfg(feature = "dim2")] + ShapeType::Cuboid => { + let c = co_shape.as_cuboid().unwrap(); + Vec3::new(c.half_extents.x, c.half_extents.y, 1.0) + } + ShapeType::Ball => { + let b = co_shape.as_ball().unwrap(); + Vec3::new(b.radius, b.radius, b.radius) + } + #[cfg(feature = "dim3")] + ShapeType::Cuboid => { + let c = co_shape.as_cuboid().unwrap(); + Vec3::from_slice_unaligned(c.half_extents.as_slice()) + } + #[cfg(feature = "dim3")] + ShapeType::Cylinder => { + let c = co_shape.as_cylinder().unwrap(); + Vec3::new(c.radius, c.half_height, c.radius) + } + #[cfg(feature = "dim3")] + ShapeType::RoundCylinder => { + let c = &co_shape.as_round_cylinder().unwrap().base_shape; + Vec3::new(c.radius, c.half_height, c.radius) + } + #[cfg(feature = "dim3")] + ShapeType::Cone => { + let c = co_shape.as_cone().unwrap(); + Vec3::new(c.radius, c.half_height, c.radius) + } + #[cfg(feature = "dim3")] + ShapeType::RoundCone => { + let c = &co_shape.as_round_cone().unwrap().base_shape; + Vec3::new(c.radius, c.half_height, c.radius) + } + _ => Vec3::ONE, } } + +#[cfg(feature = "dim2")] +fn generate_collider_mesh(co_shape: &dyn Shape) -> Option { + let mesh = match co_shape.shape_type() { + ShapeType::Capsule => { + let capsule = co_shape.as_capsule().unwrap(); + bevy_mesh_from_polyline(capsule.to_polyline(10)) + } + ShapeType::Triangle => { + let tri = co_shape.as_triangle().unwrap(); + bevy_mesh_from_polyline(vec![tri.a, tri.b, tri.c]) + } + ShapeType::TriMesh => { + let trimesh = co_shape.as_trimesh().unwrap(); + let vertices = trimesh + .vertices() + .iter() + .map(|p| Point3::new(p.x, p.y, 0.0)) + .collect(); + bevy_mesh((vertices, trimesh.indices().to_vec())) + } + ShapeType::Polyline => { + let polyline = co_shape.as_polyline().unwrap(); + bevy_polyline(( + polyline.vertices().to_vec(), + Some(polyline.indices().to_vec()), + )) + } + ShapeType::HeightField => { + let heightfield = co_shape.as_heightfield().unwrap(); + let vertices: Vec<_> = heightfield + .segments() + .flat_map(|s| vec![s.a, s.b]) + .collect(); + bevy_polyline((vertices, None)) + } + ShapeType::ConvexPolygon => { + let poly = co_shape.as_convex_polygon().unwrap(); + bevy_mesh_from_polyline(poly.points().to_vec()) + } + ShapeType::RoundConvexPolygon => { + let poly = co_shape.as_round_convex_polygon().unwrap(); + bevy_mesh_from_polyline(poly.base_shape.points().to_vec()) + } + _ => return None, + }; + + Some(mesh) +} + +#[cfg(feature = "dim3")] +fn generate_collider_mesh(co_shape: &dyn Shape) -> Option { + let mesh = match co_shape.shape_type() { + ShapeType::Capsule => { + let capsule = co_shape.as_capsule().unwrap(); + bevy_mesh(capsule.to_trimesh(20, 10)) + } + ShapeType::Triangle => { + let tri = co_shape.as_triangle().unwrap(); + bevy_mesh((vec![tri.a, tri.b, tri.c], vec![[0, 1, 2], [0, 2, 1]])) + } + ShapeType::TriMesh => { + let trimesh = co_shape.as_trimesh().unwrap(); + bevy_mesh((trimesh.vertices().to_vec(), trimesh.indices().to_vec())) + } + ShapeType::HeightField => { + let heightfield = co_shape.as_heightfield().unwrap(); + bevy_mesh(heightfield.to_trimesh()) + } + ShapeType::ConvexPolyhedron => { + let poly = co_shape.as_convex_polyhedron().unwrap(); + bevy_mesh(poly.to_trimesh()) + } + ShapeType::RoundConvexPolyhedron => { + let poly = co_shape.as_round_convex_polyhedron().unwrap(); + bevy_mesh(poly.base_shape.to_trimesh()) + } + _ => return None, + }; + + Some(mesh) +} diff --git a/src_testbed/objects/plane.rs b/src_testbed/objects/plane.rs deleted file mode 100644 index 218e97a..0000000 --- a/src_testbed/objects/plane.rs +++ /dev/null @@ -1,132 +0,0 @@ -#[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 deleted file mode 100644 index 98a8f24..0000000 --- a/src_testbed/objects/polyline.rs +++ /dev/null @@ -1,67 +0,0 @@ -use kiss3d::window::Window; -use na::Point3; -use rapier::geometry::{ColliderHandle, ColliderSet}; -use rapier::math::{Isometry, Point}; - -pub struct Polyline { - color: Point3, - base_color: Point3, - vertices: Vec>, - indices: Vec<[u32; 2]>, - collider: ColliderHandle, - pos: Isometry, -} - -impl Polyline { - pub fn new( - collider: ColliderHandle, - vertices: Vec>, - indices: Vec<[u32; 2]>, - color: Point3, - ) -> Polyline { - Polyline { - color, - pos: Isometry::identity(), - base_color: color, - vertices, - indices, - collider, - } - } - - 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: &ColliderSet) { - self.pos = colliders - .get(self.collider) - .map(|c| *c.position()) - .unwrap_or(Isometry::identity()); - } - - pub fn object(&self) -> ColliderHandle { - self.collider - } - - pub fn draw(&mut self, window: &mut Window) { - for idx in &self.indices { - let p1 = self.pos * self.vertices[idx[0] as usize]; - let p2 = self.pos * self.vertices[idx[1] as usize]; - - #[cfg(feature = "dim2")] - window.draw_planar_line(&p1, &p2, &self.color); - #[cfg(feature = "dim3")] - window.draw_line(&p1, &p2, &self.color); - } - } -} -- cgit