From d39f41611a48963fc949ce36e8819f8c63d9753d Mon Sep 17 00:00:00 2001 From: Bourumir Wyngs Date: Sun, 8 Dec 2024 18:46:34 +0100 Subject: [PATCH] Added one more example. --- Cargo.toml | 5 +- README.md | 14 +- .../diverse_field_formats/doubles_ints.ply | Bin 0 -> 257 bytes .../diverse_field_formats/doubles_shorts.ply | Bin 0 -> 253 bytes .../diverse_field_formats/floats_ints.ply | Bin 0 -> 218 bytes .../diverse_field_formats/floats_shorts.ply | Bin 0 -> 214 bytes examples/read_diverse_field_types.rs | 122 ++++++++++++++++++ scripts/generate_diverse_field_types.py | 57 ++++++++ 8 files changed, 193 insertions(+), 5 deletions(-) create mode 100644 example_plys/diverse_field_formats/doubles_ints.ply create mode 100644 example_plys/diverse_field_formats/doubles_shorts.ply create mode 100644 example_plys/diverse_field_formats/floats_ints.ply create mode 100644 example_plys/diverse_field_formats/floats_shorts.ply create mode 100644 examples/read_diverse_field_types.rs create mode 100644 scripts/generate_diverse_field_types.py diff --git a/Cargo.toml b/Cargo.toml index 22a207f..5c39823 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ply-rs-bw" -version = "0.1.4" +version = "1.0.0" authors = ["Felice Serena ","Bourumir Wyngs{sfzO z=i?v~w8qJpg*7Qz6zH^(4yyZuqs0MTf)~bwGt@jpA85{?{nT27d6VQ#@?Ot$QXy3T z1#89xlj>yzv$hCB{R&4;e~2EX#>m-EpXWl>EIbyT3eSa?!fPQE-kJj=?Z|ub7d&`F ADF6Tf literal 0 HcmV?d00001 diff --git a/example_plys/diverse_field_formats/doubles_shorts.ply b/example_plys/diverse_field_formats/doubles_shorts.ply new file mode 100644 index 0000000000000000000000000000000000000000..c07a272f9d2891d17305950f59b637f18648d65a GIT binary patch literal 253 zcmZY3F%H5o3ku{6^;-Ppfo{Hxp6fez=u?^d@H*`2e A4gdfE literal 0 HcmV?d00001 diff --git a/example_plys/diverse_field_formats/floats_ints.ply b/example_plys/diverse_field_formats/floats_ints.ply new file mode 100644 index 0000000000000000000000000000000000000000..643173a7fd13f1e33fa86ce8769e044a7b506876 GIT binary patch literal 218 zcmZ9GQ3}E^5JXq~%a=#k6NtqFXipMiyP<(J32BtZuO7vtcodJ~d{rpygJG84ndGao zF^{J3-361Y_O28!T0-wk;O2Bz;$@Uj_$j%_%omk%Owg6Bk2svSM%@~(^@lZ`aP!}L vHx+(#gURgH2<;Hw$)r$14`O=BifFkK(G3F@@CG071=JE9+XDpcz#jYnLVQE| literal 0 HcmV?d00001 diff --git a/example_plys/diverse_field_formats/floats_shorts.ply b/example_plys/diverse_field_formats/floats_shorts.ply new file mode 100644 index 0000000000000000000000000000000000000000..4cf7c09b7f3da8dc5835cf78725edfd79149bfdb GIT binary patch literal 214 zcmZ9G!41MN3`Gsxa$*EefT$P%I!P2#M~##wkrPnEsiQCoqc94-08%AC$@KY$)knik2VZL-O>yuhVs|(y3N%rycqgtj<4I*sS@wo5Br(owp{<3-FT)v2*!}Op wmx?z#8pbjv{+4Jj^_Gf~H}ptmAXWg&82~Oa!Xi9{m+%iW&JfDLTn15(69-v9sr literal 0 HcmV?d00001 diff --git a/examples/read_diverse_field_types.rs b/examples/read_diverse_field_types.rs new file mode 100644 index 0000000..df85d84 --- /dev/null +++ b/examples/read_diverse_field_types.rs @@ -0,0 +1,122 @@ + +use ply_rs_bw::parser::Parser; +use ply_rs_bw::ply::{DefaultElement, Property}; +use std::fs::File; +use std::io::BufReader; + +/// Loads a mesh from a file, returning a list of vertices (x, y, z represented as `f32`) +/// and triangle indices (indices represented as `u32`). +/// +/// This example focuses on real-world scenarios where fields may be represented using +/// different types (e.g., `f32` vs `f64`, `u32` vs `i32`, etc.). To read PLY data +/// from various sources, the reader must adapt to the types used in the input. +pub fn read_mesh(ply_file_path: &str) -> (Vec<[f32; 3]>, Vec<[u32; 3]>) { + // Open the file + let file = + File::open(ply_file_path).expect(&format!("Could not open PLY file: {}", ply_file_path)); + let mut reader = BufReader::new(file); + + // Create a PLY parser and parse the header + let parser = Parser::::new(); + let ply = parser + .read_ply(&mut reader) + .expect(&format!("Could not parse PLY file: {}", ply_file_path)); + + // Extract vertices and faces from the PLY file + let mut vertices = Vec::new(); + let mut indices = Vec::new(); + + // PLY may have internally different types. + if let Some(vertices_elem) = ply.payload.get("vertex") { + for vertex in vertices_elem { + let x = match vertex.get("x").unwrap() { + Property::Float(val) => *val, + Property::Double(val) => *val as f32, + _ => panic!("Unexpected type for vertex x"), + }; + let y = match vertex.get("y").unwrap() { + Property::Float(val) => *val, + Property::Double(val) => *val as f32, + _ => panic!("Unexpected type for vertex y"), + }; + let z = match vertex.get("z").unwrap() { + Property::Float(val) => *val, + Property::Double(val) => *val as f32, + _ => panic!("Unexpected type for vertex z"), + }; + + vertices.push([x, y, z].into()); // Push vertex to the vertices list + } + } + + // Extract faces (indices) + fn extract_indices(indices_list: &[T], i: usize) -> [u32; 3] + where + T: TryInto + Copy, + >::Error: std::fmt::Debug, + { + if indices_list.len() < 3 { + panic!("Insufficient indices for a triangle in face {}", i); + } + const X: &'static str = "Failed to convert triangle index to u32"; + [ + indices_list[0].try_into().expect(X), + indices_list[1].try_into().expect(X), + indices_list[2].try_into().expect(X), + ] + } + + if let Some(faces_elem) = ply.payload.get("face") { + for (i, face) in faces_elem.iter().enumerate() { + match face.get("vertex_indices") { + Some(Property::ListUInt(indices_list)) => { + indices.push(extract_indices(indices_list, i).into()); + } + Some(Property::ListInt(indices_list)) => { + indices.push(extract_indices(indices_list, i).into()); + } + Some(Property::ListUShort(indices_list)) => { + indices.push(extract_indices(indices_list, i).into()); + } + Some(Property::ListShort(indices_list)) => { + indices.push(extract_indices(indices_list, i).into()); + } + Some(property) => { + panic!("Unexpected property type for face {}: {:?}", i, property); + } + None => { + panic!("Missing 'vertex_indices' for face {}", i); + } + } + } + } else { + panic!("No 'face' element in payload"); + } + + (vertices, indices) +} + +/// Helper function to print the results. Examples used only contain a single triangle. +/// Python script used for generating test data can be found in the folder 'scripts' +fn print_ply_data(data: (Vec<[f32; 3]>, Vec<[u32; 3]>)) { + let (vertices, indices) = data; + + println!("Vertices:"); + for (i, vertex) in vertices.iter().enumerate() { + println!(" {}: [{:.3}, {:.3}, {:.3}]", i, vertex[0], vertex[1], vertex[2]); + } + + println!("Indices:"); + for (i, index) in indices.iter().enumerate() { + println!(" {}: [{}, {}, {}]", i, index[0], index[1], index[2]); + } +} + + +fn main() { + // The output from four lines below must be identical. + print_ply_data(read_mesh("example_plys/diverse_field_formats/doubles_ints.ply")); + print_ply_data(read_mesh("example_plys/diverse_field_formats/doubles_shorts.ply")); + print_ply_data(read_mesh("example_plys/diverse_field_formats/floats_ints.ply")); + print_ply_data(read_mesh("example_plys/diverse_field_formats/floats_shorts.ply")); +} \ No newline at end of file diff --git a/scripts/generate_diverse_field_types.py b/scripts/generate_diverse_field_types.py new file mode 100644 index 0000000..27a358a --- /dev/null +++ b/scripts/generate_diverse_field_types.py @@ -0,0 +1,57 @@ +import struct + + +def write_ply(filename, vertex_format, index_format, vertices, face): + """ + Writes a PLY file with the given vertex and face formats. + + Args: + filename (str): Name of the output file. + vertex_format (str): Format string for vertex coordinates. + index_format (str): Format string for face indices. + vertices (list): List of vertices (tuples of coordinates). + face (list): Face data (count followed by vertex indices). + """ + # Map formats to PLY property declarations + vertex_properties = { + '