//# meshx = { git = "https://github.com/elrnv/meshx" } //! The simplest way to generate all the assets is by running this file through cargo-play. //! //! The files generated by this script attempt to exhibit as many potential features that gltfgen //! may support, although not all are currently supported. These include //! - Animation (of positions but also all attributes) //! - Vertex attributes. //! - Face attributes. //! - Vertex-face attributes (which get remapped to vertex attributes during gltf creation) //! - Float and integer attribute types. //! - Conversion from vtk and obj file types. use meshx::attrib::*; use meshx::{ builder::{BoxBuilder, PlatonicSolidBuilder}, io, mesh::TriMesh, ops::*, topology::*, VertexPositions, }; fn generate_box_triangulated_asset() { let mesh = BoxBuilder::new().build_polymesh::(); let mut mesh = TriMesh::from(mesh); mesh.uniform_scale(0.5); // Face integer attribute. let f_ids = vec![0_i32; mesh.num_faces()]; // Vertex integer attribute. let v_ids = vec![1_i32; mesh.num_vertices()]; // Pressure float attrubute for vertices. let pressure = mesh.vertex_positions().iter().map(|p| p[1]).collect(); // UV (texture coordinates) attribute for vertex-faces (vertices in gltf). let pos = mesh.vertex_positions(); let uv = mesh .face_iter() .flat_map(|&[a, b, c]| { let [a, b, c] = [pos[a], pos[b], pos[c]]; let (x, y) = if a[0] == b[0] && b[0] == c[0] { (1, 2) // in yz plane } else if a[1] == b[1] && b[1] == c[1] { (0, 2) // in xz plane } else if a[2] == b[2] && b[2] == c[2] { (0, 1) // in xy plane } else { unreachable!("Invalid box"); }; vec![ [a[x] + 0.5, a[y] + 0.5, 0.0], [b[x] + 0.5, b[y] + 0.5, 0.0], [c[x] + 0.5, c[y] + 0.5, 0.0], ] .into_iter() }) .collect::>(); mesh.insert_attrib_data::<_, FaceIndex>("mtl_id", f_ids) .unwrap(); mesh.insert_attrib_data::<_, VertexIndex>("mtl_id", v_ids) .unwrap(); mesh.insert_attrib_data::<_, VertexIndex>("pressure", pressure) .unwrap(); mesh.insert_attrib_data::<_, FaceVertexIndex>("uv", uv) .unwrap(); io::save_mesh(&meshx::Mesh::from(mesh), "./box_triangulated.vtk").unwrap(); //let vtk = vtk::convert_polymesh_to_vtk_format(&meshx::PolyMesh::from(mesh), vtk::VTKPolyExportStyle::UnstructuredGrid).unwrap(); //vtk.export_be("./box_triangulated.vtk").unwrap(); } fn generate_box_rotate_assets() { // Generate box_rotate examples. let n_frames = 12; for i in 0..n_frames { let mut mesh = BoxBuilder::new().build_polymesh::(); mesh.uniform_scale(0.5); let ratio = i as f32 / (n_frames - 1) as f32; // Face integer attribute. let f_ids = vec![0_i32; mesh.num_faces()]; // Vertex integer attribute. let v_ids = vec![1_i32; mesh.num_vertices()]; // Pressure float attrubute for vertices. let pressure = mesh .vertex_positions() .iter() .map(|p| p[1] + ratio as f32) .collect(); // Color attribute for vertices. let color = mesh .vertex_positions() .iter() .map(|p| { let sec = (n_frames / 4) as f32; match 4 * i / n_frames { 0 => { let f = i as f32 / sec; [ if p[1] > 0.0 { 0.95 * f } else { 0.2 }, p[1] + 0.5, if p[1] > 0.0 { 0.1 - 0.1 * f } else { 1.0 }, ] } 1 => { let f = (i as f32 - 1.0 * sec) / sec; [ if p[1] > 0.0 { 0.95 + 0.05 * f } else { 0.2 }, p[1] + 0.5 - if p[1] > 0.0 { f } else { 0.0 }, if p[1] > 0.0 { 0.0 } else { 1.0 }, ] } 2 => { let f = (i as f32 - 2.0 * sec) / sec; [ if p[1] > 0.0 { 1.0 } else { 0.2 - 0.2 * f }, p[1] + 0.5 + if p[1] < 0.0 { 0.85 * f } else { -1.0 }, if p[1] > 0.0 { 0.0 } else { 1.0 }, ] } _ => { let f = (i as f32 - 3.0 * sec) / sec; [ if p[1] > 0.0 { 1.0 } else { 0.0 }, p[1] + 0.5 + if p[1] < 0.0 { 0.85 + 0.15 * f } else { -1.0 }, if p[1] > 0.0 { 0.0 } else { 1.0 - 0.9 * f }, ] } } }) .collect(); // UV (texture coordinates) attribute for vertex-faces (vertices in gltf). let pos = mesh.vertex_positions(); let mut uv = mesh .face_iter() .flat_map(|face| { let [a, b, c, d] = [pos[face[0]], pos[face[1]], pos[face[2]], pos[face[3]]]; let (x, y) = if a[0] == b[0] && b[0] == c[0] && c[0] == d[0] { (1, 2) // in yz plane } else if a[1] == b[1] && b[1] == c[1] && c[1] == d[1] { (0, 2) // in xz plane } else if a[2] == b[2] && b[2] == c[2] && c[2] == d[2] { (0, 1) // in xy plane } else { unreachable!("Invalid box"); }; vec![ [a[x] + 0.5, a[y] + 0.5, 0.0], [b[x] + 0.5, b[y] + 0.5, 0.0], [c[x] + 0.5, c[y] + 0.5, 0.0], [d[x] + 0.5, d[y] + 0.5, 0.0], ] .into_iter() }) .collect::>(); // Scale down uvs. uv.iter_mut().for_each(|uv| { uv[0] *= 0.5; uv[1] *= 0.5; }); // Place ends in a different uv place to avoid breaks in the output gltf due // to uv seam changes. uv.iter_mut().skip(16).for_each(|uv| { uv[1] += 1.0; }); // Stretch sides to make texture be always in proportion. uv.iter_mut().take(16).for_each(|uv| { uv[0] -= 0.25; uv[0] *= 1.0 + ratio; uv[0] += 0.25; }); // Normals let normals = mesh.vertex_positions().iter().map(|[x,y,z]| { let l = 1.0/(x*x + y*y + z*z).sqrt(); [x*l, y*l, z*l] }).collect::>(); // Transform mesh. mesh.scale([1.0 + ratio, 1.0, 1.0]); mesh.rotate_by_vector([0.0, ratio * std::f32::consts::PI, 0.0]); mesh.insert_attrib_data::<_, FaceIndex>("mtl_id", f_ids) .unwrap(); mesh.insert_attrib_data::<_, VertexIndex>("mtl_id", v_ids) .unwrap(); mesh.insert_attrib_data::<_, VertexIndex>("pressure", pressure) .unwrap(); mesh.insert_attrib_data::<_, VertexIndex>("Cd", color) .unwrap(); mesh.insert_attrib_data::<_, FaceVertexIndex>("uv", uv) .unwrap(); mesh.insert_attrib_data::<_, VertexIndex>("N", normals) .unwrap(); io::save_polymesh(&mesh, &format!("./box_rotate_{}.vtk", i + 1)).unwrap(); io::save_polymesh(&mesh, &format!("./box_rotate_{}.obj", i + 1)).unwrap(); } } fn generate_tet_assets() { let n_frames = 2; for i in 0..n_frames { let mut mesh = PlatonicSolidBuilder::default().build_tetrahedron::(); // Cell integer attribute. let f_ids = vec![0_i32; mesh.num_cells()]; // Pressure attribute for vertices. let pressure = mesh.vertex_positions().iter().map(|p| p[0]).collect(); // Transform mesh. mesh.scale([1.0, i as f32 + 1.0, 1.0]); mesh.insert_attrib_data::<_, CellIndex>("mtl_id", f_ids) .unwrap(); mesh.insert_attrib_data::<_, VertexIndex>("pressure", pressure) .unwrap(); io::save_tetmesh(&mesh, &format!("./tet_{}.vtk", i + 1)).unwrap(); } } fn main() { generate_tet_assets(); generate_box_rotate_assets(); generate_box_triangulated_asset(); }