From c6429749970236059f5b7931eea03165d857be33 Mon Sep 17 00:00:00 2001 From: mitchellhansen Date: Wed, 21 Feb 2024 21:18:19 -0800 Subject: [PATCH] logic transfer --- src/lib.rs | 220 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 src/lib.rs diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..1360013 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,220 @@ + + +#[derive(Component)] +struct FjSolidWrapper{ + handle: fj_core::storage::Handle, +} + +#[derive(Component)] +struct FjConvertedFlag; + + +use fj_core::{ + algorithms::sweep::Sweep, + objects::{Region, Sketch, Solid}, + operations::{BuildRegion, BuildSketch, Insert, UpdateSketch}, + services::Services, + storage::Handle, +}; +use fj_core::algorithms::approx::Tolerance; +use fj_core::algorithms::bounding_volume::BoundingVolume; +use fj_core::algorithms::triangulate::Triangulate; +use fj_core::objects::{Cycle, Shell}; +use fj_core::operations::{BuildCycle, Reverse, UpdateRegion}; +use fj_interop::mesh::Mesh; +use fj_math::{Aabb, Point, Scalar, Vector}; +use std::ops::Deref; + +use bevy::prelude::Mesh; +use bevy::render::mesh::{Indices, PrimitiveTopology}; +use fj_interop::mesh::Mesh as FjMesh; +use fj_math::Point; + +fn generate_uv_mapping(fj_mesh: &FjMesh>) -> Vec<[f32; 2]> { + let mut uvs = Vec::new(); + + for vertex in fj_mesh.vertices() { + let x = vertex.coords.x.into_f32(); + let y = vertex.coords.y.into_f32(); + // Here we're using x and y coordinates as u and v + uvs.push([x, y]); + uvs.push([x, y]); + uvs.push([x, y]); + uvs.push([x, y]); + uvs.push([x, y]); + uvs.push([x, y]); + } + + uvs +} + +fn generate_normals(fj_mesh: &FjMesh>) -> Vec<[f32; 3]> { + let mut normals = Vec::new(); + for triangle in fj_mesh.triangles() { + let normal = triangle.inner.normal(); + normals.push([normal.x.into_f32(), normal.y.into_f32(), normal.z.into_f32()]); + normals.push([normal.x.into_f32(), normal.y.into_f32(), normal.z.into_f32()]); + normals.push([normal.x.into_f32(), normal.y.into_f32(), normal.z.into_f32()]); + } + normals +} + +fn generate_positions(fj_mesh: &FjMesh>) -> Vec<[f32; 3]> { + let mut positions = Vec::new(); + + // Iterate through each triangle + for triangle in fj_mesh.triangles() { + // For each vertex index in the triangle + for vertex_index in triangle.inner.points() { + positions.push([vertex_index.x.into_f32(), vertex_index.y.into_f32(), vertex_index.z.into_f32()]); + } + } + + positions +} + +fn generate_indices(fj_mesh: &FjMesh>) -> Vec { + let mut num_positions = 0; + + // Count the total number of positions (3 per triangle) + for triangle in fj_mesh.triangles() { + num_positions += 3; + } + + // Generate the indices [0, 1, 2, ..., num_positions-1] + (0..num_positions as u32).collect() +} + +// Need to take a solid, and return all the data needed to create a Bevy Mesh from scratch +pub fn convert_mesh(fj_mesh: &FjMesh>) -> Mesh { + let mut mesh = Mesh::new(PrimitiveTopology::TriangleList); + mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, generate_positions(&fj_mesh)); + mesh.insert_attribute(Mesh::ATTRIBUTE_NORMAL, generate_normals(&fj_mesh)); + // mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, generate_uv_mapping(&fj_mesh)); + mesh.set_indices(Some(Indices::U32(generate_indices(&fj_mesh)))); + mesh +} + + +fn model(x: f64, y: f64, z: f64, services: &mut Services) -> Handle { + let sketch = Sketch::empty() + .add_region( + Region::polygon( + [ + [-x / 2., -y / 2.], + [x / 2., -y / 2.], + [x / 2., y / 2.], + [-x / 2., y / 2.], + ], + services, + ) + .add_interiors( + [ + Cycle::polygon( + [ + [0.1, 0.1], + [0.1, 2.0], + [2.0, 2.0], + [2.0, 0.1], + ], + services, + ).insert(services), + // Cycle::circle([0.1,0.75], 0.05, services).reverse(services).insert(services), + // MinnesotaCycle::circle([0.1,0.75], 0.05, services).reverse(services).insert(services) + ] + ) + .insert(services), + ) + // .add_region( + // Region::polygon( + // [ + // [1.5, 2.25], + // [3.0, 2.25], + // [3.0, 4.5], + // [1.5, 4.5], + // ], + // services, + // ).insert(services) + // ) + .insert(services); + + let surface = services.objects.surfaces.xy_plane(); + + + + let path = Vector::from([0., 0., z]); + + // let mut iter = sketch.faces(surface, services).into_iter(); + // let face = iter.next().unwrap(); + // let face = iter.next().unwrap(); + + // services.drop_and_validate(); + + // face.sweep(path, services) + + // let surface = services.objects.surfaces.xy_plane(); + + (sketch, surface).sweep(path, services) +} + + +pub fn build_mesh() -> (Mesh>, Handle) { + + let mut services = Services::new(); + + let model = model(4., 8., (1.0 / 12.0 * 0.75), &mut services); + let aabb = model.aabb().unwrap_or(Aabb { + min: Point::origin(), + max: Point::origin(), + }); + + println!("{:?}", model); + + let mut min_extent = Scalar::MAX; + for extent in aabb.size().components { + if extent > Scalar::ZERO && extent < min_extent { + min_extent = extent; + } + } + let tolerance = min_extent / Scalar::from_f64(1000.); + let tolerance = Tolerance::from_scalar(tolerance).unwrap(); + + ((model.deref(), tolerance).triangulate(), model) +} + +fn update_fj_model_system( + mut commands: Commands, + query: Query<(Entity, &FjSolidWrapper), Without>, + mut meshes: ResMut>, + mut materials: ResMut>, +) { + for (entity, solid) in &query { + + let (mesh, fj_model) = fornjot_stuff::build_mesh(); + let bevy_mesh = fornjot_convert_mesh::convert_mesh(&mesh); + commands.entity(entity).insert( + ( + PbrBundle { + mesh: meshes.add(Mesh::from(bevy_mesh.clone())), + material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()), + transform: Transform::from_xyz(0.0, 0.0, 0.0), + ..default() + }, + FjMeshWrapper { data: mesh, data2: fj_model }, + FjConvertedFlag + + )); + } +} + + +pub struct FjRenderPlugin; + +impl Plugin for FjRenderPlugin { + fn build(&self, app: &mut App) { + app + .add_systems(Update, update_fj_model_system); + } +} + +