Replace Kiss3d by Bevy for the testbed renderer.

This commit is contained in:
Crozet Sébastien
2021-05-16 17:49:20 +02:00
parent f350ac35d9
commit 1a84bf2af3
88 changed files with 2327 additions and 3940 deletions

View File

@@ -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<f32>,
base_color: Point3<f32>,
gfx: GraphicsNode,
collider: ColliderHandle,
delta: Isometry<f32>,
}
impl Ball {
pub fn new(
collider: ColliderHandle,
delta: Isometry<f32>,
radius: f32,
color: Point3<f32>,
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<f32>) {
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
}
}

View File

@@ -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<f32>,
base_color: Point3<f32>,
gfx: GraphicsNode,
collider: ColliderHandle,
delta: Isometry<f32>,
}
impl Box {
pub fn new(
collider: ColliderHandle,
delta: Isometry<f32>,
half_extents: Vector<f32>,
color: Point3<f32>,
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<f32>) {
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
}
}

View File

@@ -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<f32>,
base_color: Point3<f32>,
gfx: GraphicsNode,
collider: ColliderHandle,
delta: Isometry<f32>,
}
impl Capsule {
pub fn new(
collider: ColliderHandle,
delta: Isometry<f32>,
capsule: &geometry::Capsule,
color: Point3<f32>,
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<f32>) {
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
}
}

View File

@@ -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<f32>,
base_color: Point3<f32>,
gfx: GraphicsNode,
collider: ColliderHandle,
delta: Isometry<f32>,
}
impl Cone {
pub fn new(
collider: ColliderHandle,
delta: Isometry<f32>,
half_height: f32,
radius: f32,
color: Point3<f32>,
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<f32>) {
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
}
}

View File

@@ -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<f32>,
base_color: Point3<f32>,
gfx: GraphicsNode,
body: ColliderHandle,
delta: Isometry<f32>,
}
impl Convex {
pub fn new(
body: ColliderHandle,
delta: Isometry<f32>,
vertices: Vec<Point<f32>>,
#[cfg(feature = "dim3")] indices: Vec<[u32; 3]>,
color: Point3<f32>,
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<f32>) {
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
}
}

View File

@@ -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<f32>,
base_color: Point3<f32>,
gfx: GraphicsNode,
collider: ColliderHandle,
delta: Isometry<f32>,
}
impl Cylinder {
pub fn new(
collider: ColliderHandle,
delta: Isometry<f32>,
half_height: f32,
radius: f32,
color: Point3<f32>,
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<f32>) {
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
}
}

View File

@@ -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<f32>,
base_color: Point3<f32>,
#[cfg(feature = "dim2")]
vertices: Vec<Point<f32>>,
#[cfg(feature = "dim3")]
gfx: GraphicsNode,
collider: ColliderHandle,
}
impl HeightField {
#[cfg(feature = "dim2")]
pub fn new(
collider: ColliderHandle,
heightfield: &shape::HeightField,
color: Point3<f32>,
_: &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<f32>,
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<f32>) {
#[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)
}
}
}

View File

@@ -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<f32>,
base_color: Point3<f32>,
gfx: GraphicsNode,
collider: ColliderHandle,
}
impl Mesh {
pub fn new(
collider: ColliderHandle,
vertices: Vec<Point<f32>>,
indices: Vec<[u32; 3]>,
color: Point3<f32>,
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<f32>) {
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::<TriMesh<f32>>().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
}
}

View File

@@ -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;

View File

@@ -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 rapier::math::Isometry;
#[cfg(feature = "dim2")]
pub type GraphicsNode = kiss3d::scene::PlanarSceneNode;
use bevy::render::pipeline::PrimitiveTopology;
use bevy::render::wireframe::Wireframe;
use rapier::geometry::{ColliderHandle, ColliderSet, Shape, ShapeType};
#[cfg(feature = "dim3")]
pub type GraphicsNode = kiss3d::scene::SceneNode;
use rapier::geometry::{Cone, Cylinder};
use rapier::math::Isometry;
#[cfg(feature = "dim2")]
use {
na::{Point2, Vector2},
rapier::geometry::{Ball, Cuboid},
};
pub enum Node {
// Plane(Plane),
Ball(Ball),
Box(Box),
HeightField(HeightField),
Capsule(Capsule),
Polyline(Polyline),
Mesh(Mesh),
Convex(Convex),
Cylinder(Cylinder),
Cone(Cone),
pub struct EntityWithGraphics {
pub entity: Entity,
pub color: Point3<f32>,
pub base_color: Point3<f32>,
pub collider: ColliderHandle,
pub delta: Isometry<f32>,
material: Handle<StandardMaterial>,
}
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<Mesh>,
materials: &mut Assets<StandardMaterial>,
prefab_meshs: &HashMap<ShapeType, Handle<Mesh>>,
shape: &dyn Shape,
collider: ColliderHandle,
collider_pos: Isometry<f32>,
delta: Isometry<f32>,
color: Point3<f32>,
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<StandardMaterial>) {
// 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<StandardMaterial>) {
self.set_color(materials, self.base_color);
}
pub fn set_color(&mut self, materials: &mut Assets<StandardMaterial>, color: Point3<f32>) {
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;
}
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::<Transform>(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 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 gen_prefab_meshes(
out: &mut HashMap<ShapeType, Handle<Mesh>>,
meshes: &mut Assets<Mesh>,
) {
//
// 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 gen_prefab_meshes(
out: &mut HashMap<ShapeType, Handle<Mesh>>,
meshes: &mut Assets<Mesh>,
) {
//
// Cuboid mesh
//
let cuboid = Mesh::from(shape::Cube { size: 2.0 });
out.insert(ShapeType::Cuboid, meshes.add(cuboid));
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,
}
}
//
// Ball mesh
//
let ball = Mesh::from(shape::Icosphere {
subdivisions: 2,
radius: 1.0,
});
out.insert(ShapeType::Ball, meshes.add(ball));
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,
}
}
//
// 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));
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(),
}
}
//
// 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));
pub fn set_color(&mut self, color: Point3<f32>) {
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),
}
//
// 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 update_scene_node(
node: &mut GraphicsNode,
colliders: &ColliderSet,
handle: ColliderHandle,
color: &Point3<f32>,
delta: &Isometry<f32>,
) {
if let Some(co) = colliders.get(handle) {
node.set_local_transformation(co.position() * delta);
node.set_color(color.x, color.y, color.z);
#[cfg(feature = "dim2")]
fn bevy_mesh_from_polyline(vertices: Vec<Point2<f32>>) -> 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<Point2<f32>>, Option<Vec<[u32; 2]>>)) -> 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 {
node.set_visible(false);
node.unlink();
vertices = vtx.iter().map(|v| [v.x, v.y, 0.0]).collect();
}
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<Point3<f32>>, 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());
}
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
}
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<Mesh> {
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<Mesh> {
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)
}

View File

@@ -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<f32>,
base_color: Point3<f32>,
position: Point<f32>,
normal: na::Unit<Vector<f32>>,
collider: DefaultColliderHandle,
}
impl Plane {
#[cfg(feature = "dim2")]
pub fn new(
collider: DefaultColliderHandle,
colliders: &DefaultColliderSet<f32>,
position: &Point<f32>,
normal: &Vector<f32>,
color: Point3<f32>,
_: &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<f32>,
world_pos: &Point3<f32>,
world_normal: &Vector3<f32>,
color: Point3<f32>,
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<f32>) {
// FIXME: atm we assume the plane does not move
}
#[cfg(feature = "dim3")]
pub fn set_color(&mut self, color: Point3<f32>) {
self.gfx.set_color(color.x, color.y, color.z);
}
#[cfg(feature = "dim2")]
pub fn set_color(&mut self, color: Point3<f32>) {
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,
);
}
}

View File

@@ -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<f32>,
base_color: Point3<f32>,
vertices: Vec<Point<f32>>,
indices: Vec<[u32; 2]>,
collider: ColliderHandle,
pos: Isometry<f32>,
}
impl Polyline {
pub fn new(
collider: ColliderHandle,
vertices: Vec<Point<f32>>,
indices: Vec<[u32; 2]>,
color: Point3<f32>,
) -> 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<f32>) {
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);
}
}
}