Skip to content

Commit

Permalink
Add cylinder and cone primitives
Browse files Browse the repository at this point in the history
  • Loading branch information
HenryWConklin committed Nov 6, 2022
1 parent d607247 commit 2abf13f
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 3 deletions.
127 changes: 124 additions & 3 deletions blackjack_engine/src/mesh/halfedge/primitives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,17 @@ impl Quad {

pub struct Circle;
impl Circle {
pub fn build(center: Vec3, radius: f32, num_vertices: usize) -> HalfEdgeMesh {
pub fn make_verts(center: Vec3, radius: f32, num_vertices: usize) -> Vec<Vec3> {
let angle_delta = (2.0 * PI) / num_vertices as f32;
let verts = (0..num_vertices)
(0..num_vertices)
.map(|i| {
let q = Quat::from_rotation_y(angle_delta * i as f32);
q * (Vec3::Z * radius) + center
})
.collect_vec();
.collect_vec()
}
pub fn build(center: Vec3, radius: f32, num_vertices: usize) -> HalfEdgeMesh {
let verts = Self::make_verts(center, radius, num_vertices);
let polygon = (0..num_vertices).collect_vec();

HalfEdgeMesh::build_from_polygons(&verts, &[&polygon])
Expand Down Expand Up @@ -260,6 +263,80 @@ impl Polygon {
}
}

pub struct Cone;
impl Cone {
pub fn build(
center: Vec3,
top_radius: f32,
bottom_radius: f32,
height: f32,
num_vertices: usize,
) -> HalfEdgeMesh {
// Not using an epsilon, may be useful for to keep multiple verts at the point using small values.
if top_radius.abs() <= 1e-5 {
Self::build_cone(center, bottom_radius, height, num_vertices)
} else {
Self::build_truncated_cone(center, top_radius, bottom_radius, height, num_vertices)
}
}
pub fn build_cone(
center: Vec3,
bottom_radius: f32,
height: f32,
num_vertices: usize,
) -> HalfEdgeMesh {
let v_offset = Vec3::new(0.0, height / 2.0, 0.0);
let mut verts = Circle::make_verts(center - v_offset, bottom_radius, num_vertices);
verts.push(center + v_offset);

let side_faces = (0..num_vertices)
.map(|v| [v, (v + 1) % num_vertices, num_vertices])
.collect_vec();
let bottom_face = (0..num_vertices).rev().collect_vec();
let mut faces = vec![bottom_face.as_slice()];
faces.extend(side_faces.iter().map(|x| x.as_slice()));

HalfEdgeMesh::build_from_polygons(&verts, &faces)
.expect("Cone construction should not fail.")
}
pub fn build_truncated_cone(
center: Vec3,
top_radius: f32,
bottom_radius: f32,
height: f32,
num_vertices: usize,
) -> HalfEdgeMesh {
let v_offset = Vec3::new(0.0, height / 2.0, 0.0);
let mut verts = Circle::make_verts(center - v_offset, bottom_radius, num_vertices);
verts.extend(Circle::make_verts(
center + v_offset,
top_radius,
num_vertices,
));

let side_faces = (0..num_vertices)
.map(|v| {
let v2 = (v + 1) % num_vertices;
[v, v2, num_vertices + v2, num_vertices + v]
})
.collect_vec();
let bottom_face = (0..num_vertices).rev().collect_vec();
let top_face = (num_vertices..(2 * num_vertices)).collect_vec();
let mut faces = vec![bottom_face.as_slice(), top_face.as_slice()];
faces.extend(side_faces.iter().map(|x| x.as_slice()));

HalfEdgeMesh::build_from_polygons(&verts, &faces)
.expect("Truncated Cone construction should not fail.")
}
}

struct Cylinder;
impl Cylinder {
pub fn build(center: Vec3, radius: f32, height: f32, num_vertices: usize) -> HalfEdgeMesh {
Cone::build_truncated_cone(center, radius, radius, height, num_vertices)
}
}

#[blackjack_macros::blackjack_lua_module]
mod lua_api {
use super::*;
Expand All @@ -285,6 +362,31 @@ mod lua_api {
Circle::build_open(center.0, radius, num_vertices as usize)
}

/// Creates a truncated cone with the given `center`, `bottom_radius`, `top_radius`,
/// `height`, and `num_vertices` around its radius. A `top_radius` of 0 will make a standard cone.
#[lua(under = "Primitives")]
fn cone(
center: LVec3,
bottom_radius: f32,
top_radius: f32,
height: f32,
num_vertices: f32,
) -> HalfEdgeMesh {
Cone::build(
center.0,
top_radius,
bottom_radius,
height,
num_vertices as usize,
)
}

/// Creates a cylinder with the given `center`, `radius`, `height`, and `num_vertices around its radius`.
#[lua(under = "Primitives")]
fn cylinder(center: LVec3, radius: f32, height: f32, num_vertices: f32) -> HalfEdgeMesh {
Cylinder::build(center.0, radius, height, num_vertices as usize)
}

/// Creates a UV-sphere with given `center` and `radius`. The `rings` and
/// `segments` let you specify the specify the number of longitudinal
/// and vertical sections respectively.
Expand Down Expand Up @@ -312,3 +414,22 @@ mod lua_api {
Polygon::build_from_points(LVec3::cast_vector(points))
}
}

#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_cone() {
let cone = Cone::build(Vec3::ZERO, 0.0, 1.0, 1.0, 8);
assert_eq!(cone.read_connectivity().vertices.len(), 9);

Cone::build(Vec3::ZERO, 1.0, 2.0, 1.0, 8);
Cone::build_cone(Vec3::ZERO, 1.0, 1.0, 8);
Cone::build_truncated_cone(Vec3::ZERO, 1.0, 2.0, 1.0, 8);
}

#[test]
fn test_cylinder() {
Cylinder::build(Vec3::ZERO, 1.0, 1.0, 8);
}
}
40 changes: 40 additions & 0 deletions blackjack_lua/run/core_nodes.lua
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,46 @@ local primitives = {
},
returns = "out_mesh",
},
MakeCone = {
label = "Cone",
op = function (inputs)
return {
out_mesh = Primitives.cone(
inputs.center,
inputs.bottom_radius,
inputs.top_radius,
inputs.height,
inputs.num_vertices)
}
end,
inputs = {
P.v3("center", vector(0, 0, 0)),
P.scalar("bottom_radius", { default = 1.0, min = 0.0 }),
P.scalar("top_radius", { default = 0.0, min = 0.0 }),
P.scalar("height", { default = 1.0, min = 0.0 }),
P.scalar_int("num_vertices", { default = 8, min = 3, soft_max = 32 }),
},
outputs = {
P.mesh("out_mesh"),
},
returns = "out_mesh",
},
MakeCylinder = {
label = "Cylinder",
op = function (inputs)
return {out_mesh = Primitives.cylinder(inputs.center, inputs.radius, inputs.height, inputs.num_vertices)}
end,
inputs = {
P.v3("center", vector(0, 0, 0)),
P.scalar("radius", { default = 1.0, min = 0.0 }),
P.scalar("height", { default = 1.0, min = 0.0 }),
P.scalar_int("num_vertices", { default = 8, min = 3, soft_max = 32 }),
},
outputs = {
P.mesh("out_mesh"),
},
returns = "out_mesh"
},
}

local function parse_ch_key(s)
Expand Down

0 comments on commit 2abf13f

Please sign in to comment.