@@ -4,6 +4,10 @@ use anyhow::{anyhow, Context};
44use ply_rs as ply;
55use ply_rs:: ply:: Property ;
66
7+ use splashsurf_lib:: mesh:: AttributeData ;
8+ use splashsurf_lib:: mesh:: MeshAttribute ;
9+ use splashsurf_lib:: mesh:: MeshWithData ;
10+ use splashsurf_lib:: mesh:: TriMesh3d ;
711use splashsurf_lib:: nalgebra:: Vector3 ;
812use splashsurf_lib:: Real ;
913
@@ -49,3 +53,139 @@ pub fn particles_from_ply<R: Real, P: AsRef<Path>>(
4953
5054 Ok ( particles)
5155}
56+
57+ /// Tries to read a surface mesh from the VTK file at the given path
58+ pub fn surface_mesh_from_ply < R : Real , P : AsRef < Path > > (
59+ ply_file : P ,
60+ ) -> Result < MeshWithData < R , TriMesh3d < R > > , anyhow:: Error > {
61+ let mut ply_file = std:: fs:: File :: open ( ply_file) . unwrap ( ) ;
62+ let parser = ply:: parser:: Parser :: < ply:: ply:: DefaultElement > :: new ( ) ;
63+
64+ let ply = parser
65+ . read_ply ( & mut ply_file)
66+ . context ( "Failed to read PLY file" ) ?;
67+ let vertices_normals = ply
68+ . payload
69+ . get ( "vertex" )
70+ . ok_or ( anyhow ! ( "PLY file is missing a 'vertex' element" ) ) ?;
71+
72+ let vertices_normals: Vec < ( Vector3 < _ > , Vector3 < _ > ) > = vertices_normals
73+ . into_iter ( )
74+ . map ( |e| {
75+ let vertex = (
76+ e. get ( "x" ) . unwrap ( ) ,
77+ e. get ( "y" ) . unwrap ( ) ,
78+ e. get ( "z" ) . unwrap ( ) ,
79+ e. get ( "nx" ) . unwrap ( ) ,
80+ e. get ( "ny" ) . unwrap ( ) ,
81+ e. get ( "nz" ) . unwrap ( ) ,
82+ ) ;
83+
84+ let v = match vertex {
85+ (
86+ Property :: Float ( x) ,
87+ Property :: Float ( y) ,
88+ Property :: Float ( z) ,
89+ Property :: Float ( nx) ,
90+ Property :: Float ( ny) ,
91+ Property :: Float ( nz) ,
92+ ) => (
93+ Vector3 :: new (
94+ R :: from_f32 ( * x) . unwrap ( ) ,
95+ R :: from_f32 ( * y) . unwrap ( ) ,
96+ R :: from_f32 ( * z) . unwrap ( ) ,
97+ ) ,
98+ Vector3 :: new (
99+ R :: from_f32 ( * nx) . unwrap ( ) ,
100+ R :: from_f32 ( * ny) . unwrap ( ) ,
101+ R :: from_f32 ( * nz) . unwrap ( ) ,
102+ ) ,
103+ ) ,
104+ _ => {
105+ return Err ( anyhow ! (
106+ "Vertex properties have wrong PLY data type (expected float)"
107+ ) )
108+ }
109+ } ;
110+
111+ Ok ( v)
112+ } )
113+ . map ( |vn| vn. unwrap ( ) )
114+ . collect ( ) ;
115+
116+ let vertices: Vec < Vector3 < _ > > = vertices_normals. iter ( ) . map ( |vn| vn. 0 . clone ( ) ) . collect ( ) ;
117+ let normals: Vec < Vector3 < _ > > = vertices_normals. iter ( ) . map ( |vn| vn. 1 . clone ( ) ) . collect ( ) ;
118+
119+ let faces = ply
120+ . payload
121+ . get ( "face" )
122+ . ok_or ( anyhow ! ( "PLY file is missing a 'face' element" ) ) ?;
123+
124+ let triangles = faces
125+ . into_iter ( )
126+ . map ( |e| {
127+ // This is as per what blender creates for a
128+ let indices = e. get ( "vertex_indices" ) ;
129+ if let Some ( indices) = indices {
130+ if let Property :: ListUInt ( indices) = indices {
131+ if indices. len ( ) == 3 {
132+ return Ok ( [
133+ indices[ 0 ] as usize ,
134+ indices[ 1 ] as usize ,
135+ indices[ 2 ] as usize ,
136+ ] ) ;
137+ } else {
138+ return Err ( anyhow ! (
139+ "Invalid number of vertex indices per cell: {}" ,
140+ indices. len( )
141+ ) ) ;
142+ }
143+ } else {
144+ return Err ( anyhow ! (
145+ "Index properties have wrong PLY data type (expected uint)"
146+ ) ) ;
147+ }
148+ } else {
149+ return Err ( anyhow ! (
150+ "Vertex properties have wrong PLY data type (expected uint)"
151+ ) ) ;
152+ }
153+ } )
154+ . map ( |e| e. unwrap ( ) )
155+ . collect ( ) ;
156+
157+ let normals = MeshAttribute :: new ( "normals" , AttributeData :: Vector3Real ( normals) ) ;
158+ Ok ( MeshWithData :: new ( TriMesh3d {
159+ vertices,
160+ triangles,
161+ } )
162+ . with_point_data ( normals) )
163+ }
164+
165+ #[ cfg( test) ]
166+ pub mod test {
167+ use super :: * ;
168+
169+ #[ test]
170+ fn test_convert_cube ( ) -> Result < ( ) , anyhow:: Error > {
171+ let input_file = Path :: new ( "../data/cube.ply" ) ;
172+
173+ let mesh: MeshWithData < f32 , _ > = surface_mesh_from_ply ( input_file) . with_context ( || {
174+ format ! (
175+ "Failed to load surface mesh from file \" {}\" " ,
176+ input_file. display( )
177+ )
178+ } ) ?;
179+
180+ assert_eq ! ( mesh. mesh. vertices. len( ) , 24 ) ;
181+ assert_eq ! ( mesh. mesh. triangles. len( ) , 12 ) ;
182+ let normals = mesh. point_attributes . iter ( ) . find ( |a| a. name == "normals" ) ;
183+ if let Some ( MeshAttribute { data, .. } ) = normals {
184+ if let AttributeData :: Vector3Real ( normals) = data {
185+ assert_eq ! ( normals. len( ) , 24 )
186+ }
187+ }
188+
189+ Ok ( ( ) )
190+ }
191+ }
0 commit comments