use bevy::{
asset::RenderAssetUsages, pbr::wireframe::{WireframeConfig, WireframePlugin}, prelude::*
};
use procedural_modelling::{extensions::bevy::*, mesh::MeshBuilder, prelude::*};
use std::f32::consts::PI;
fn vp(x: f32, y: f32, z: f32) -> BevyVertexPayload3d {
BevyVertexPayload3d::from_pos(Vec3::new(x, y, z))
}
fn cuboid_from_vertices(size: Vec3) -> BevyMesh3d {
let (x, y, z) = (size * 0.5).tuple();
let mut mesh = BevyMesh3d::new();
let (v0, v1) = mesh.add_isolated_edge_default(vp(x, y, z), vp(-x, y, z));
let v2 = mesh.add_vertex_via_vertex_default(v1, vp(-x, -y, z)).0;
let v3 = mesh.add_vertex_via_vertex_default(v2, vp(x, -y, z)).0;
mesh.close_face_vertices_default(v2, v3, v0, false);
let v4 = mesh.add_vertex_via_vertex_default(v1, vp(-x, y, -z)).0;
let v5 = mesh.add_vertex_via_vertex_default(v4, vp(-x, -y, -z)).0;
mesh.close_face_vertices_default(v4, v5, v2, false);
let v6 = mesh.add_vertex_via_vertex_default(v0, vp(x, y, -z)).0;
let v7 = mesh.add_vertex_via_vertex_default(v3, vp(x, -y, -z)).0;
mesh.close_face_vertices_default(v3, v7, v6, false);
mesh.close_face_vertices_default(v2, v5, v7, false);
mesh.close_face_vertices_default(v0, v6, v4, false);
mesh.close_hole_default(mesh.shared_edge(v6, v7).unwrap().id());
mesh
}
fn cuboid_from_edges(_size: Vec3) -> BevyMesh3d {
todo!("cuboid_from_edges")
}
fn cuboid_from_loft(size: Vec3) -> BevyMesh3d {
let p = size * 0.5;
let mut mesh = BevyMesh3d::new();
let vs = [
(-p.x(), -p.y()),
(p.x(), -p.y()),
(p.x(), p.y()),
(-p.x(), p.y()),
];
let bottom_edge = mesh.insert_polygon(vs.iter().map(|(x, y)| vp(*x, *y, -p.z())));
let top_edge = mesh.loft_polygon(bottom_edge, 2, 2, vs.iter().map(|(x, y)| vp(*x, *y, p.z())));
mesh.close_hole_default(top_edge);
mesh
}
fn cuboid_from_prism(size: Vec3) -> BevyMesh3d {
let p = size * 0.5;
BevyMesh3d::prism(
[
vp(-p.x(), -p.y(), -p.z()),
vp(p.x(), -p.y(), -p.z()),
vp(p.x(), p.y(), -p.z()),
vp(-p.x(), p.y(), -p.z()),
],
p.z() * 2.0,
)
}
fn cuboid_from_prism_generic<T: MeshTypeHalfEdge + MeshType3D>(size: T::Vec) -> T::Mesh
where
T::EP: DefaultEdgePayload,
T::FP: DefaultFacePayload,
T::Mesh: MakePrismatoid<T>,
{
let p = size * T::S::HALF;
let make = |x, y, z| T::VP::from_pos(T::Vec::from_xyz(x, y, z));
T::Mesh::prism(
[
make(-p.x(), -p.y(), -p.z()),
make(p.x(), -p.y(), -p.z()),
make(p.x(), p.y(), -p.z()),
make(-p.x(), p.y(), -p.z()),
],
p.z() * T::S::TWO,
)
}
fn cuboid_from_cuboid(size: Vec3) -> BevyMesh3d {
BevyMesh3d::cuboid(size)
}
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(WireframePlugin::default())
.insert_resource(WireframeConfig {
global: true,
default_color: Color::WHITE,
})
.add_systems(Startup, setup_camera_and_light)
.add_systems(Startup, setup_meshes)
.run();
}
fn setup_meshes(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
let size = Vec3::new(1.0, 1.0, 2.0);
let generated_meshes = [
cuboid_from_vertices(size),
cuboid_from_loft(size),
cuboid_from_prism(size),
cuboid_from_prism_generic::<BevyMeshType3d32>(size),
cuboid_from_cuboid(size),
];
println!("{:?}", generated_meshes[0]);
for (i, mesh) in generated_meshes.iter().enumerate() {
commands.spawn((
Mesh3d(meshes.add(mesh.to_bevy_ex(
RenderAssetUsages::all(),
TriangulationAlgorithm::Delaunay,
true,
))),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: Color::srgb(1.0, 0.0, 0.0),
..default()
})),
Transform::from_translation(Vec3::new(
(i as f32 - generated_meshes.len() as f32 / 2.0) * 1.5,
0.0,
0.0,
)),
Name::new("Generated Shape"),
));
}
}
fn setup_camera_and_light(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
commands.spawn((
Mesh3d(meshes.add(Mesh::from(Plane3d::new(Vec3::Y, Vec2::new(1.0, 1.0))))),
MeshMaterial3d(materials.add(StandardMaterial::default())),
Transform::from_translation(Vec3::new(0.0, -1.0, 0.0)).with_scale(Vec3::splat(10.0)),
Name::new("Floor"),
));
commands.insert_resource(GlobalAmbientLight::default());
commands.spawn((
DirectionalLight {
color: Color::WHITE,
shadows_enabled: true,
..default()
},
Transform {
translation: Vec3::new(0.0, 2.0, 0.0),
rotation: Quat::from_rotation_x(-PI / 4.),
..default()
},
));
commands.spawn((
Camera3d::default(),
Transform::from_xyz(3.0, 5.0, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
));
}