From 217a5670988bb388901e98056dc086a5172ae88c Mon Sep 17 00:00:00 2001 From: Thierry Berger Date: Fri, 13 Sep 2024 10:38:44 +0200 Subject: [PATCH] Add an example for projection (#250) --- CHANGELOG.md | 3 +- crates/parry2d/examples/common_macroquad2d.rs | 109 +++++++++++++++ crates/parry2d/examples/point_in_poly2d.rs | 44 +----- .../examples/polygons_intersection2d.rs | 18 +-- crates/parry2d/examples/project_point2d.rs | 89 ++++++++++++ crates/parry2d/examples/raycasts_animated.rs | 23 +--- crates/parry3d/Cargo.toml | 5 + crates/parry3d/examples/common_macroquad3d.rs | 128 ++++++++++++++++++ crates/parry3d/examples/plane_intersection.rs | 94 ++----------- crates/parry3d/examples/project_point3d.rs | 86 ++++++++++++ src/transformation/mod.rs | 1 - .../to_trimesh/cuboid_to_trimesh.rs | 81 ++++++----- src/transformation/to_trimesh/mod.rs | 6 + 13 files changed, 494 insertions(+), 193 deletions(-) create mode 100644 crates/parry2d/examples/common_macroquad2d.rs create mode 100644 crates/parry2d/examples/project_point2d.rs create mode 100644 crates/parry3d/examples/common_macroquad3d.rs create mode 100644 crates/parry3d/examples/project_point3d.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index b1d56e7c..6c1cf5c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,8 @@ ### Added -- `TriMesh` now implements `Shape::feature_normal_at_point` to retrieve the normal of a face, when passing a `FeatureId::Face`. +- Implement `::to_trimesh` in 2d for `Cuboid` and `Aabb`. +- Implement `Shape::feature_normal_at_point` for `TriMesh` to retrieve the normal of a face, when passing a `FeatureId::Face`. ## v0.17.1 diff --git a/crates/parry2d/examples/common_macroquad2d.rs b/crates/parry2d/examples/common_macroquad2d.rs new file mode 100644 index 00000000..da74dd59 --- /dev/null +++ b/crates/parry2d/examples/common_macroquad2d.rs @@ -0,0 +1,109 @@ +use std::f32::consts::{FRAC_PI_2, FRAC_PI_4}; + +use macroquad::prelude::*; +use macroquad::{ + color::{Color, WHITE}, + math::Vec2, + shapes::draw_line, +}; +use nalgebra::Point2; +use parry2d::math::Real; +use parry2d::shape::TriMesh; + +#[allow(dead_code)] +fn main() { + println!( + "This module contains helper functions to use macroquad, + isolated from the rest of the examples for the sake of simplicity." + ); +} + +#[allow(dead_code)] +pub fn mquad_from_na(a: Point2) -> Vec2 { + Vec2::new(a.x, a.y) +} + +#[allow(dead_code)] +pub fn na_from_mquad(a: Vec2) -> Point2 { + Point2::new(a.x, a.y) +} + +#[allow(dead_code)] +pub fn draw_polyline(polygon: Vec<(Vec2, Vec2)>, color: Color) { + for i in 0..polygon.len() { + let a = polygon[i].0; + let b = polygon[i].1; + draw_line_2d(a, b, color); + } +} + +#[allow(dead_code)] +pub fn easy_draw_text(text: &str) { + macroquad::text::draw_text(text, 10.0, 48.0 + 18.0, 30.0, WHITE); +} + +#[allow(dead_code)] +pub fn lissajous_2d(t: f32) -> Vec2 { + // Some hardcoded parameters to have a pleasing lissajous trajectory. + let (a, b, delta_x, delta_y) = (3.0, 2.0, FRAC_PI_2, FRAC_PI_4); + + let x = (a * t + delta_x).sin(); + let y = (b * t + delta_y).sin(); + Vec2::new(x, y) * 0.75f32 +} + +#[allow(dead_code)] +pub fn draw_line_2d(a: Vec2, b: Vec2, color: Color) { + draw_line(a.x, a.y, b.x, b.y, 2f32, color); +} + +#[allow(dead_code)] +pub fn draw_trimesh2(trimesh: &TriMesh, offset: Vec2) { + let vertices = trimesh.vertices(); + for v in trimesh.indices() { + let v0 = mquad_from_na(vertices[v[0] as usize]) + offset; + let v1 = mquad_from_na(vertices[v[1] as usize]) + offset; + let v2 = mquad_from_na(vertices[v[2] as usize]) + offset; + + draw_line(v0.x, v0.y, v1.x, v1.y, 2f32, WHITE); + draw_line(v0.x, v0.y, v2.x, v2.y, 2f32, WHITE); + draw_line(v2.x, v2.y, v1.x, v1.y, 2f32, WHITE); + } +} + +#[allow(dead_code)] +pub fn draw_polygon(polygon: &[Point2], scale: f32, shift: Point2, color: Color) { + for i in 0..polygon.len() { + let a = polygon[i]; + let b = polygon[(i + 1) % polygon.len()]; + draw_line( + a.x * scale + shift.x, + a.y * scale + shift.y, + b.x * scale + shift.x, + b.y * scale + shift.y, + 2.0, + color, + ); + } +} + +#[allow(dead_code)] +pub fn draw_point(point: Point2, scale: f32, shift: Point2, color: Color) { + let edge_len = 0.15; + draw_line( + (point.x - edge_len) * scale + shift.x, + point.y * scale + shift.y, + (point.x + edge_len) * scale + shift.x, + point.y * scale + shift.y, + 2.0, + color, + ); + draw_line( + point.x * scale + shift.x, + (point.y - edge_len) * scale + shift.y, + point.x * scale + shift.x, + (point.y + edge_len) * scale + shift.y, + 2.0, + color, + ); +} diff --git a/crates/parry2d/examples/point_in_poly2d.rs b/crates/parry2d/examples/point_in_poly2d.rs index 6933c21e..99f28770 100644 --- a/crates/parry2d/examples/point_in_poly2d.rs +++ b/crates/parry2d/examples/point_in_poly2d.rs @@ -1,3 +1,6 @@ +mod common_macroquad2d; + +use common_macroquad2d::{draw_point, draw_polygon}; use macroquad::prelude::*; use nalgebra::{Point2, UnitComplex, Vector2}; use parry2d::utils::point_in_poly2d; @@ -15,14 +18,14 @@ async fn main() { loop { clear_background(BLACK); - /* - * Compute polygon intersections. - */ spikes .iter_mut() .for_each(|pt| *pt = animation_rotation * *pt); draw_polygon(&spikes, RENDER_SCALE, spikes_render_pos, BLUE); + /* + * Compute polygon intersections. + */ for point in &test_points { if point_in_poly2d(point, &spikes) { draw_point(*point, RENDER_SCALE, spikes_render_pos, RED); @@ -71,38 +74,3 @@ fn grid_points() -> Vec> { } pts } - -fn draw_polygon(polygon: &[Point2], scale: f32, shift: Point2, color: Color) { - for i in 0..polygon.len() { - let a = polygon[i]; - let b = polygon[(i + 1) % polygon.len()]; - draw_line( - a.x * scale + shift.x, - a.y * scale + shift.y, - b.x * scale + shift.x, - b.y * scale + shift.y, - 2.0, - color, - ); - } -} - -fn draw_point(point: Point2, scale: f32, shift: Point2, color: Color) { - let edge_len = 0.15; - draw_line( - (point.x - edge_len) * scale + shift.x, - point.y * scale + shift.y, - (point.x + edge_len) * scale + shift.x, - point.y * scale + shift.y, - 2.0, - color, - ); - draw_line( - point.x * scale + shift.x, - (point.y - edge_len) * scale + shift.y, - point.x * scale + shift.x, - (point.y + edge_len) * scale + shift.y, - 2.0, - color, - ); -} diff --git a/crates/parry2d/examples/polygons_intersection2d.rs b/crates/parry2d/examples/polygons_intersection2d.rs index 51d03079..604f86c5 100644 --- a/crates/parry2d/examples/polygons_intersection2d.rs +++ b/crates/parry2d/examples/polygons_intersection2d.rs @@ -1,3 +1,6 @@ +mod common_macroquad2d; + +use common_macroquad2d::draw_polygon; use macroquad::prelude::*; use nalgebra::{Point2, UnitComplex, Vector2}; use parry2d::shape::Ball; @@ -111,18 +114,3 @@ fn spikes_polygon() -> Vec> { polygon } - -fn draw_polygon(polygon: &[Point2], scale: f32, shift: Point2, color: Color) { - for i in 0..polygon.len() { - let a = polygon[i]; - let b = polygon[(i + 1) % polygon.len()]; - draw_line( - a.x * scale + shift.x, - a.y * scale + shift.y, - b.x * scale + shift.x, - b.y * scale + shift.y, - 2.0, - color, - ); - } -} diff --git a/crates/parry2d/examples/project_point2d.rs b/crates/parry2d/examples/project_point2d.rs new file mode 100644 index 00000000..fc2a9884 --- /dev/null +++ b/crates/parry2d/examples/project_point2d.rs @@ -0,0 +1,89 @@ +mod common_macroquad2d; + +use common_macroquad2d::{draw_line_2d, draw_trimesh2, lissajous_2d, mquad_from_na, na_from_mquad}; +use macroquad::prelude::*; +use nalgebra::{Point3, UnitComplex, Vector2}; +use parry2d::math::{Isometry, Translation}; +use parry2d::query::PointQuery; +use parry2d::shape::{Cuboid, TriMesh, TriMeshFlags}; + +#[macroquad::main("parry3d::query::PlaneIntersection")] +async fn main() { + // + // This is useful to test for https://github.com/dimforge/parry/pull/248 + let _points = vec![ + Point3::from([0.0, 0.0, 0.0]), + Point3::from([0.0, 0.0, 1.0]), + Point3::from([1.0, 0.0, 0.0]), + Point3::from([1.0, 0.0, 1.0]), + ]; + let _indices: Vec<[u32; 3]> = vec![[0, 1, 2], [1, 3, 2]]; + + let scale = 200f32; + let (points, indices) = Cuboid::new(Vector2::new(0.2 * scale, 0.5 * scale)).to_trimesh(); + + let trimesh = TriMesh::with_flags(points, indices, TriMeshFlags::ORIENTED); + for _i in 1.. { + clear_background(BLACK); + + let elapsed_time = get_time() as f32; + let slow_elapsed_time = elapsed_time / 3.0; + + let offset = Vec2::new(screen_width() / 2f32, screen_height() / 2f32); + + let point_to_project = lissajous_2d(slow_elapsed_time) * scale + offset; + let translation = Translation::new(offset.x, offset.y); + let rot = UnitComplex::identity(); + let projected_point = trimesh.project_point( + &Isometry::from_parts(translation, rot), + &na_from_mquad(point_to_project), + true, + ); + + /* + * + * Render the projection + * + */ + let color = if projected_point.is_inside { + RED + } else { + YELLOW + }; + + draw_line_2d( + point_to_project, + mquad_from_na(projected_point.point), + color, + ); + draw_circle(point_to_project.x, point_to_project.y, 10f32, color); + + draw_line_2d( + point_to_project, + mquad_from_na(projected_point.point), + color, + ); + + // fixed local point inside the shape + let point_to_project = Vec2::ZERO; + let projected_point = trimesh.project_local_point(&na_from_mquad(point_to_project), true); + let color = if projected_point.is_inside { + RED + } else { + YELLOW + }; + // convert to "world" space + let point_to_project = point_to_project * scale + offset; + draw_circle(point_to_project.x, point_to_project.y, 10f32, color); + + draw_line_2d( + point_to_project, + mquad_from_na(projected_point.point) * scale + offset, + color, + ); + // Mesh is rendered in the back, so we can see the other graphics elements + draw_trimesh2(&trimesh, offset); + + next_frame().await + } +} diff --git a/crates/parry2d/examples/raycasts_animated.rs b/crates/parry2d/examples/raycasts_animated.rs index 09aa4bd4..ddd8fcb4 100644 --- a/crates/parry2d/examples/raycasts_animated.rs +++ b/crates/parry2d/examples/raycasts_animated.rs @@ -1,3 +1,6 @@ +mod common_macroquad2d; + +use common_macroquad2d::draw_point; use macroquad::prelude::*; use nalgebra::{Isometry2, Point2, UnitComplex, Vector2}; use parry2d::math::Isometry; @@ -99,26 +102,6 @@ fn draw_polygon( } } -fn draw_point(point: Point2, scale: f32, shift: Point2, color: Color) { - let edge_len = 0.15; - draw_line( - (point.x - edge_len) * scale + shift.x, - point.y * scale + shift.y, - (point.x + edge_len) * scale + shift.x, - point.y * scale + shift.y, - 2.0, - color, - ); - draw_line( - point.x * scale + shift.x, - (point.y - edge_len) * scale + shift.y, - point.x * scale + shift.x, - (point.y + edge_len) * scale + shift.y, - 2.0, - color, - ); -} - fn drawline_from_to( from: Point2, to: Point2, diff --git a/crates/parry3d/Cargo.toml b/crates/parry3d/Cargo.toml index 65078c26..abcc5369 100644 --- a/crates/parry3d/Cargo.toml +++ b/crates/parry3d/Cargo.toml @@ -173,6 +173,11 @@ name = "plane3d" path = "examples/plane3d.rs" doc-scrape-examples = true +[[example]] +name = "plane_intersection" +path = "examples/plane_intersection.rs" +doc-scrape-examples = true + [[example]] name = "polyline3d" path = "examples/polyline3d.rs" diff --git a/crates/parry3d/examples/common_macroquad3d.rs b/crates/parry3d/examples/common_macroquad3d.rs new file mode 100644 index 00000000..45aeb50e --- /dev/null +++ b/crates/parry3d/examples/common_macroquad3d.rs @@ -0,0 +1,128 @@ +#[allow(unused, dead_code)] +use std::f32::consts::{FRAC_PI_2, FRAC_PI_4, FRAC_PI_6}; + +use macroquad::{ + color::{Color, WHITE}, + math::{Vec2, Vec3, Vec4}, + models::{draw_line_3d, Mesh}, + ui::Vertex, +}; +use nalgebra::Point3; +use parry3d::math::Real; + +#[allow(dead_code)] +fn main() { + println!( + "This module contains helper functions to use macroquad, + isolated from the rest of the examples for the sake of simplicity." + ); +} + +#[allow(dead_code)] +pub fn mquad_from_na(a: Point3) -> Vec3 { + Vec3::new(a.x, a.y, a.z) +} + +#[allow(dead_code)] +pub fn na_from_mquad(a: Vec3) -> Point3 { + Point3::new(a.x, a.y, a.z) +} + +#[allow(dead_code)] +pub fn lissajous_3d(t: f32) -> Vec3 { + // Some hardcoded parameters to have a pleasing lissajous trajectory. + let (a, b, c, delta_x, delta_y, delta_z) = (3.0, 2.0, 1.0, FRAC_PI_2, FRAC_PI_4, FRAC_PI_6); + + let x = (a * t + delta_x).sin(); + let y = (b * t + delta_y).sin(); + let z = (c * t + delta_z).sin(); + Vec3::new(x, y, z) * 0.75f32 +} + +#[allow(dead_code)] +pub fn draw_polyline(polygon: Vec<(Vec3, Vec3)>, color: Color) { + for i in 0..polygon.len() { + let a = polygon[i].0; + let b = polygon[i].1; + draw_line_3d(a, b, color); + } +} + +#[allow(dead_code)] +pub fn easy_draw_text(text: &str) { + macroquad::text::draw_text(text, 10.0, 48.0 + 18.0, 30.0, WHITE); +} + +#[allow(dead_code)] +pub fn mquad_mesh_from_points( + trimesh: &(Vec>, Vec<[u32; 3]>), + light_pos: Vec3, + color: Color, +) -> Mesh { + let (points, indices) = trimesh; + // Transform the parry mesh into a mquad Mesh + let (mquad_points, mquad_indices) = ( + points + .iter() + .map(|p| Vertex { + position: mquad_from_na(*p), + uv: Vec2::new(p.x, p.y), + color: color.into(), + normal: Vec4::ZERO, + }) + .collect(), + indices.iter().flatten().map(|v| *v as u16).collect(), + ); + + // Macroquad does support adding normals to vertices, but we´d have to provide shaders for them. + // so we're baking a color into these vertices. + // See https://github.com/not-fl3/macroquad/issues/321. + + // Compute the normal of each vertex, making them unique + let vertices: Vec = + mquad_compute_normals_and_bake_light(&mquad_points, &mquad_indices, light_pos); + // Regenerate the index for each vertex. + let indices: Vec = (0..vertices.len() * 3) + .into_iter() + .map(|i| i as u16) + .collect(); + let mesh = Mesh { + vertices, + indices, + texture: None, + }; + mesh +} + +#[allow(dead_code)] +pub fn mquad_compute_normals_and_bake_light( + points: &Vec, + indices: &Vec, + light_pos: Vec3, +) -> Vec { + let mut vertices: Vec = Vec::::new(); + for indices in indices.chunks(3) { + let v0 = &points[indices[0] as usize]; + let v1 = &points[indices[1] as usize]; + let v2 = &points[indices[2] as usize]; + let normal = (v0.position - v2.position) + .cross(v1.position - v2.position) + .normalize(); + let brightness_mod = 0.4 + (0.6 / 2.) * (normal.dot(light_pos) + 1.); + + for &i in indices.iter() { + let mut color = points[i as usize].color; + color[0] = (color[0] as f32 * brightness_mod) as u8; + color[1] = (color[1] as f32 * brightness_mod) as u8; + color[2] = (color[2] as f32 * brightness_mod) as u8; + + vertices.push(Vertex { + position: points[i as usize].position, + uv: Vec2::ZERO, + color: color, + normal: Vec4::ZERO, + }); + } + } + vertices +} diff --git a/crates/parry3d/examples/plane_intersection.rs b/crates/parry3d/examples/plane_intersection.rs index c80fc0e5..47f45e69 100644 --- a/crates/parry3d/examples/plane_intersection.rs +++ b/crates/parry3d/examples/plane_intersection.rs @@ -1,17 +1,19 @@ -use macroquad::models::Vertex; use macroquad::prelude::*; -use nalgebra::{Point3, UnitVector3, Vector3}; -use parry3d::math::Real; +use nalgebra::{UnitVector3, Vector3}; use parry3d::query::IntersectResult; use parry3d::shape::{Cuboid, TriMesh}; +mod common_macroquad3d; +use common_macroquad3d::*; + #[macroquad::main("parry3d::query::PlaneIntersection")] async fn main() { let trimesh = Cuboid::new(Vector3::repeat(1.0)).to_trimesh(); + let light_pos = Vec3::new(-1f32, 3.5f32, -3f32); let camera_pos = Vec3::new(-1.5f32, 2.5f32, -3f32); - let mesh = mquad_mesh_from_points(&trimesh, camera_pos); + let mesh = mquad_mesh_from_points(&trimesh, light_pos, DARKGRAY); let trimesh = TriMesh::new(trimesh.0, trimesh.1); for _ in 1.. { @@ -64,95 +66,17 @@ async fn main() { Color::new(0f32, 1f32, 0f32, 1f32), ); set_default_camera(); - draw_text("Intersection found!"); + easy_draw_text("Intersection found!"); } IntersectResult::Negative => { set_default_camera(); - draw_text("No intersection found, the shape is below the plane."); + easy_draw_text("No intersection found, the shape is below the plane."); } IntersectResult::Positive => { set_default_camera(); - draw_text("No intersection found, the shape is above the plane."); + easy_draw_text("No intersection found, the shape is above the plane."); } } next_frame().await } } - -fn mquad_mesh_from_points(trimesh: &(Vec>, Vec<[u32; 3]>), camera_pos: Vec3) -> Mesh { - let (points, indices) = trimesh; - // Transform the parry mesh into a mquad Mesh - let (mquad_points, mquad_indices) = ( - points - .iter() - .map(|p| Vertex { - position: mquad_from_na(*p), - uv: Vec2::new(p.x, p.y), - color: DARKGRAY.into(), - normal: Vec4::ZERO, - }) - .collect(), - indices.iter().flatten().map(|v| *v as u16).collect(), - ); - - // Macroquad doesn´t support adding normals to vertices, so we'll bake a color into these vertices. - // See https://github.com/not-fl3/macroquad/issues/321. - - // Compute the normal of each vertex, making them unique - let vertices: Vec = mquad_compute_normals(&mquad_points, &mquad_indices, camera_pos); - // Regenerate the index for each vertex. - let indices: Vec = (0..vertices.len() * 3) - .into_iter() - .map(|i| i as u16) - .collect(); - let mesh = Mesh { - vertices, - indices, - texture: None, - }; - mesh -} - -fn mquad_compute_normals(points: &Vec, indices: &Vec, cam_pos: Vec3) -> Vec { - let mut vertices: Vec = Vec::::new(); - for indices in indices.chunks(3) { - let v0 = &points[indices[0] as usize]; - let v1 = &points[indices[1] as usize]; - let v2 = &points[indices[2] as usize]; - let normal = (v0.position - v2.position) - .cross(v1.position - v2.position) - .normalize(); - let brightness_mod = 0.2 + (0.8 / 2.) * (normal.dot(cam_pos) + 1.); - - for &i in indices.iter() { - let mut color = points[i as usize].color; - color[0] = (color[0] as f32 * brightness_mod) as u8; - color[1] = (color[1] as f32 * brightness_mod) as u8; - color[2] = (color[2] as f32 * brightness_mod) as u8; - - vertices.push(Vertex { - position: points[i as usize].position, - uv: Vec2::ZERO, - color: color, - normal: Vec4::ZERO, - }); - } - } - vertices -} - -fn draw_polyline(polygon: Vec<(Vec3, Vec3)>, color: Color) { - for i in 0..polygon.len() { - let a = polygon[i].0; - let b = polygon[i].1; - draw_line_3d(a, b, color); - } -} - -fn mquad_from_na(a: Point3) -> Vec3 { - Vec3::new(a.x, a.y, a.z) -} - -fn draw_text(text: &str) { - macroquad::text::draw_text(text, 10.0, 48.0 + 18.0, 30.0, WHITE); -} diff --git a/crates/parry3d/examples/project_point3d.rs b/crates/parry3d/examples/project_point3d.rs new file mode 100644 index 00000000..31e745a6 --- /dev/null +++ b/crates/parry3d/examples/project_point3d.rs @@ -0,0 +1,86 @@ +use macroquad::prelude::*; +use nalgebra::Vector3; +use parry3d::query::PointQuery; +use parry3d::shape::{Cuboid, TriMesh, TriMeshFlags}; + +mod common_macroquad3d; +use common_macroquad3d::*; + +#[macroquad::main("parry3d::query::PlaneIntersection")] +async fn main() { + let trimesh = Cuboid::new(Vector3::new(0.2, 0.5, 1.0)).to_trimesh(); + + let mesh = mquad_mesh_from_points( + &trimesh, + Vec3::new(1f32, 3f32, 3f32), + Color::from_rgba(200, 200, 200, 150), + ); + let (points, indices) = trimesh; + let trimesh = TriMesh::with_flags(points, indices, TriMeshFlags::ORIENTED); + for _i in 1.. { + clear_background(BLACK); + + let elapsed_time = get_time() as f32; + let slow_elapsed_time = elapsed_time / 3.0; + + let point_to_project = lissajous_3d(slow_elapsed_time); + let projected_point = trimesh.project_local_point(&na_from_mquad(point_to_project), true); + + let slow_elapsed_time = slow_elapsed_time * 0.7; + // Setup 3D camera. + set_camera(&Camera3D { + position: Vec3::new( + slow_elapsed_time.sin() * 3.0, + slow_elapsed_time.sin(), + slow_elapsed_time.cos() * 3.0, + ), + up: Vec3::Y, + target: Vec3::ZERO, + ..Default::default() + }); + + /* + * + * Render the projection + * + */ + let color = if projected_point.is_inside { + RED + } else { + YELLOW + }; + + draw_line_3d( + point_to_project, + mquad_from_na(projected_point.point), + color, + ); + draw_sphere(point_to_project, 0.1, None, color); + + draw_line_3d( + point_to_project, + mquad_from_na(projected_point.point), + color, + ); + + // fixed point inside the shape + let point_to_project = Vec3::ZERO; + let projected_point = trimesh.project_local_point(&na_from_mquad(point_to_project), true); + let color = if projected_point.is_inside { + RED + } else { + YELLOW + }; + draw_sphere(point_to_project, 0.1, None, color); + + draw_line_3d( + point_to_project, + mquad_from_na(projected_point.point), + color, + ); + // Mesh is rendered in the back, so we can see the other graphics elements + draw_mesh(&mesh); + + next_frame().await + } +} diff --git a/src/transformation/mod.rs b/src/transformation/mod.rs index be7e8348..7b29e427 100644 --- a/src/transformation/mod.rs +++ b/src/transformation/mod.rs @@ -36,7 +36,6 @@ mod mesh_intersection; mod to_outline; #[cfg(feature = "dim2")] mod to_polyline; -#[cfg(feature = "dim3")] mod to_trimesh; pub mod utils; diff --git a/src/transformation/to_trimesh/cuboid_to_trimesh.rs b/src/transformation/to_trimesh/cuboid_to_trimesh.rs index 1c763a22..5132cf17 100644 --- a/src/transformation/to_trimesh/cuboid_to_trimesh.rs +++ b/src/transformation/to_trimesh/cuboid_to_trimesh.rs @@ -1,12 +1,11 @@ use crate::bounding_volume::Aabb; -use crate::math::Real; +use crate::math::{Point, Real}; use crate::shape::Cuboid; use crate::transformation::utils; -use na::{self, Point3}; impl Aabb { /// Discretize the boundary of this Aabb as a triangle-mesh. - pub fn to_trimesh(&self) -> (Vec>, Vec<[u32; 3]>) { + pub fn to_trimesh(&self) -> (Vec>, Vec<[u32; 3]>) { let center = self.center(); let half_extents = self.half_extents(); let mut cube_mesh = Cuboid::new(half_extents).to_trimesh(); @@ -17,47 +16,63 @@ impl Aabb { impl Cuboid { /// Discretize the boundary of this cuboid as a triangle-mesh. - pub fn to_trimesh(&self) -> (Vec>, Vec<[u32; 3]>) { + pub fn to_trimesh(&self) -> (Vec>, Vec<[u32; 3]>) { let (vtx, idx) = unit_cuboid(); (utils::scaled(vtx, self.half_extents * 2.0), idx) } } -/** - * Generates a cuboid shape with a split index buffer. - * - * The cuboid is centered at the origin, and has its half extents set to 0.5. - */ -fn unit_cuboid() -> (Vec>, Vec<[u32; 3]>) { - let mut coords = Vec::with_capacity(8); - let mut faces = Vec::with_capacity(12); +/// Generates a cuboid shape with a split index buffer. +/// +/// The cuboid is centered at the origin, and has its half extents set to 0.5. +fn unit_cuboid() -> (Vec>, Vec<[u32; 3]>) { + #[cfg(feature = "dim3")] + { + let mut coords = Vec::with_capacity(8); + let mut faces = Vec::with_capacity(12); - coords.push(Point3::new(-0.5, -0.5, 0.5)); - coords.push(Point3::new(-0.5, -0.5, -0.5)); - coords.push(Point3::new(0.5, -0.5, -0.5)); - coords.push(Point3::new(0.5, -0.5, 0.5)); - coords.push(Point3::new(-0.5, 0.5, 0.5)); - coords.push(Point3::new(-0.5, 0.5, -0.5)); - coords.push(Point3::new(0.5, 0.5, -0.5)); - coords.push(Point3::new(0.5, 0.5, 0.5)); + coords.push(Point::new(-0.5, -0.5, 0.5)); + coords.push(Point::new(-0.5, -0.5, -0.5)); + coords.push(Point::new(0.5, -0.5, -0.5)); + coords.push(Point::new(0.5, -0.5, 0.5)); + coords.push(Point::new(-0.5, 0.5, 0.5)); + coords.push(Point::new(-0.5, 0.5, -0.5)); + coords.push(Point::new(0.5, 0.5, -0.5)); + coords.push(Point::new(0.5, 0.5, 0.5)); - faces.push([4, 5, 0]); - faces.push([5, 1, 0]); + faces.push([4, 5, 0]); + faces.push([5, 1, 0]); - faces.push([5, 6, 1]); - faces.push([6, 2, 1]); + faces.push([5, 6, 1]); + faces.push([6, 2, 1]); - faces.push([6, 7, 3]); - faces.push([2, 6, 3]); + faces.push([6, 7, 3]); + faces.push([2, 6, 3]); - faces.push([7, 4, 0]); - faces.push([3, 7, 0]); + faces.push([7, 4, 0]); + faces.push([3, 7, 0]); - faces.push([0, 1, 2]); - faces.push([3, 0, 2]); + faces.push([0, 1, 2]); + faces.push([3, 0, 2]); - faces.push([7, 6, 5]); - faces.push([4, 7, 5]); + faces.push([7, 6, 5]); + faces.push([4, 7, 5]); - (coords, faces) + (coords, faces) + } + #[cfg(feature = "dim2")] + { + let mut coords = Vec::with_capacity(8); + let mut faces = Vec::with_capacity(12); + + coords.push(Point::new(-0.5, -0.5)); + coords.push(Point::new(0.5, -0.5)); + coords.push(Point::new(-0.5, 0.5)); + coords.push(Point::new(0.5, 0.5)); + + faces.push([0, 1, 2]); + faces.push([2, 1, 3]); + + (coords, faces) + } } diff --git a/src/transformation/to_trimesh/mod.rs b/src/transformation/to_trimesh/mod.rs index 6c730f12..60dc33a7 100644 --- a/src/transformation/to_trimesh/mod.rs +++ b/src/transformation/to_trimesh/mod.rs @@ -1,7 +1,13 @@ +#[cfg(feature = "dim3")] mod ball_to_trimesh; +#[cfg(feature = "dim3")] mod capsule_to_trimesh; +#[cfg(feature = "dim3")] mod cone_to_trimesh; +#[cfg(feature = "dim3")] mod convex_polyhedron_to_trimesh; mod cuboid_to_trimesh; +#[cfg(feature = "dim3")] mod cylinder_to_trimesh; +#[cfg(feature = "dim3")] mod heightfield_to_trimesh;