1-
2- #![ doc = " glTF 2.0 file format support for Mesh and Sketch objects" ]
1+ #![ doc = " glTF 2.0 file format support" ]
32#![ doc = "" ]
43#![ doc = " This module provides export functionality for glTF 2.0 files," ]
54#![ doc = " a modern, efficient, and widely supported 3D asset format." ]
65
76use crate :: float_types:: { tolerance, Real } ;
8- use crate :: mesh:: Mesh ;
9- use crate :: sketch:: Sketch ;
10- use geo:: CoordsIter ;
7+ use crate :: triangulated:: Triangulated3D ;
118use nalgebra:: { Point3 , Vector3 } ;
129use std:: fmt:: Debug ;
1310use std:: io:: Write ;
14-
1511use base64:: engine:: general_purpose:: STANDARD as BASE64_ENGINE ;
1612use base64:: Engine ;
1713
@@ -39,6 +35,26 @@ fn add_unique_vertex_gltf(
3935 ( vertices. len ( ) - 1 ) as u32
4036}
4137
38+ fn build_gltf_buffers < T : Triangulated3D > (
39+ shape : & T ,
40+ ) -> ( Vec < GltfVertex > , Vec < u32 > ) {
41+ let mut vertices = Vec :: < GltfVertex > :: new ( ) ;
42+ let mut indices = Vec :: < u32 > :: new ( ) ;
43+
44+ shape. visit_triangles ( |tri| {
45+ for v in tri {
46+ let idx = add_unique_vertex_gltf (
47+ & mut vertices,
48+ v. position ,
49+ v. normal ,
50+ ) ;
51+ indices. push ( idx) ;
52+ }
53+ } ) ;
54+
55+ ( vertices, indices)
56+ }
57+
4258/// Build a glTF 2.0 JSON document with a single mesh & single scene,
4359/// using POSITION and NORMAL attributes and UNSIGNED_INT indices.
4460///
@@ -159,63 +175,12 @@ fn gltf_from_vertices(
159175 json
160176}
161177
162- impl < S : Clone + Debug + Send + Sync > Mesh < S > {
163- #[ doc = " Export this Mesh to glTF 2.0 format as a string" ]
164- #[ doc = "" ]
165- #[ doc = " Creates a glTF 2.0 (.gltf) JSON file containing:" ]
166- #[ doc = " 1. All 3D polygons from `self.polygons` (tessellated to triangles)" ]
167- #[ doc = " 2. POSITION and NORMAL attributes and triangle indices" ]
168- #[ doc = " 3. A single mesh / single node / single scene" ]
169- #[ doc = "" ]
170- #[ doc = " The binary data is embedded as a base64 buffer in the JSON file." ]
171- #[ doc = "" ]
172- #[ doc = " # Arguments" ]
173- #[ doc = " * `object_name` - Name for the mesh object in the glTF file" ]
174- #[ doc = "" ]
175- #[ doc = " # Example" ]
176- #[ doc = " ```" ]
177- #[ doc = " use csgrs::mesh::Mesh;" ]
178- #[ doc = " let csg: Mesh<()> = Mesh::cube(10.0, None);" ]
179- #[ doc = " let gltf_content = csg.to_gltf(\" my_cube\" );" ]
180- #[ doc = " println!(\" {}\" , gltf_content);" ]
181- #[ doc = " ```" ]
178+ impl < S : Clone + Debug + Send + Sync > crate :: mesh:: Mesh < S > {
182179 pub fn to_gltf ( & self , object_name : & str ) -> String {
183- let mut vertices = Vec :: < GltfVertex > :: new ( ) ;
184- let mut indices = Vec :: < u32 > :: new ( ) ;
185-
186- for poly in & self . polygons {
187- let triangles = poly. triangulate ( ) ;
188- let normal = poly. plane . normal ( ) . normalize ( ) ;
189-
190- for triangle in triangles {
191- for vertex in triangle {
192- let idx =
193- add_unique_vertex_gltf ( & mut vertices, vertex. pos , normal) ;
194- indices. push ( idx) ;
195- }
196- }
197- }
198-
180+ let ( vertices, indices) = build_gltf_buffers ( self ) ;
199181 gltf_from_vertices ( & vertices, & indices, object_name)
200182 }
201183
202- #[ doc = " Export this Mesh to a glTF 2.0 file" ]
203- #[ doc = "" ]
204- #[ doc = " # Arguments" ]
205- #[ doc = " * `writer` - Where to write the glTF JSON data" ]
206- #[ doc = " * `object_name` - Name for the object in the glTF file" ]
207- #[ doc = "" ]
208- #[ doc = " # Example" ]
209- #[ doc = " ```" ]
210- #[ doc = " use csgrs::mesh::Mesh;" ]
211- #[ doc = " use std::fs::File;" ]
212- #[ doc = " # fn main() -> Result<(), Box<dyn std::error::Error>> {" ]
213- #[ doc = " let csg: Mesh<()> = Mesh::cube(10.0, None);" ]
214- #[ doc = " let mut file = File::create(\" stl/output.gltf\" )?;" ]
215- #[ doc = " csg.write_gltf(&mut file, \" my_mesh\" )?;" ]
216- #[ doc = " # Ok(())" ]
217- #[ doc = " # }" ]
218- #[ doc = " ```" ]
219184 pub fn write_gltf < W : Write > (
220185 & self ,
221186 writer : & mut W ,
@@ -226,68 +191,12 @@ impl<S: Clone + Debug + Send + Sync> Mesh<S> {
226191 }
227192}
228193
229- impl < S : Clone + Debug + Send + Sync > Sketch < S > {
230- #[ doc = " Export this Sketch to glTF 2.0 format as a string" ]
231- #[ doc = "" ]
232- #[ doc = " Creates a glTF 2.0 (.gltf) JSON file containing:" ]
233- #[ doc = " 1. All 2D polygons from `self.geometry` triangulated and placed at Z=0" ]
234- #[ doc = " 2. POSITION and NORMAL attributes and triangle indices" ]
235- #[ doc = " 3. A single mesh / single node / single scene" ]
236- #[ doc = "" ]
237- #[ doc = " The binary data is embedded as a base64 buffer in the JSON file." ]
238- #[ doc = "" ]
239- #[ doc = " # Arguments" ]
240- #[ doc = " * `object_name` - Name for the object in the glTF file" ]
241- #[ doc = "" ]
242- #[ doc = " # Example" ]
243- #[ doc = " ```" ]
244- #[ doc = " use csgrs::sketch::Sketch;" ]
245- #[ doc = " let sketch: Sketch<()> = Sketch::square(2.0, None);" ]
246- #[ doc = " let gltf_content = sketch.to_gltf(\" my_sketch\" );" ]
247- #[ doc = " println!(\" {}\" , gltf_content);" ]
248- #[ doc = " ```" ]
194+ impl < S : Clone + Debug + Send + Sync > crate :: sketch:: Sketch < S > {
249195 pub fn to_gltf ( & self , object_name : & str ) -> String {
250- let mut vertices = Vec :: < GltfVertex > :: new ( ) ;
251- let mut indices = Vec :: < u32 > :: new ( ) ;
252-
253- for geom in & self . geometry . 0 {
254- match geom {
255- geo:: Geometry :: Polygon ( poly2d) => {
256- self . add_2d_polygon_to_gltf ( poly2d, & mut vertices, & mut indices) ;
257- }
258- geo:: Geometry :: MultiPolygon ( mp) => {
259- for poly2d in & mp. 0 {
260- self . add_2d_polygon_to_gltf (
261- poly2d,
262- & mut vertices,
263- & mut indices,
264- ) ;
265- }
266- }
267- _ => { }
268- }
269- }
270-
196+ let ( vertices, indices) = build_gltf_buffers ( self ) ;
271197 gltf_from_vertices ( & vertices, & indices, object_name)
272198 }
273199
274- #[ doc = " Export this Sketch to a glTF 2.0 file" ]
275- #[ doc = "" ]
276- #[ doc = " # Arguments" ]
277- #[ doc = " * `writer` - Where to write the glTF JSON data" ]
278- #[ doc = " * `object_name` - Name for the object in the glTF file" ]
279- #[ doc = "" ]
280- #[ doc = " # Example" ]
281- #[ doc = " ```" ]
282- #[ doc = " use csgrs::sketch::Sketch;" ]
283- #[ doc = " use std::fs::File;" ]
284- #[ doc = " # fn main() -> Result<(), Box<dyn std::error::Error>> {" ]
285- #[ doc = " let sketch: Sketch<()> = Sketch::square(2.0, None);" ]
286- #[ doc = " let mut file = File::create(\" stl/output.gltf\" )?;" ]
287- #[ doc = " sketch.write_gltf(&mut file, \" my_sketch\" )?;" ]
288- #[ doc = " # Ok(())" ]
289- #[ doc = " # }" ]
290- #[ doc = " ```" ]
291200 pub fn write_gltf < W : Write > (
292201 & self ,
293202 writer : & mut W ,
@@ -296,38 +205,20 @@ impl<S: Clone + Debug + Send + Sync> Sketch<S> {
296205 let gltf_content = self . to_gltf ( object_name) ;
297206 writer. write_all ( gltf_content. as_bytes ( ) )
298207 }
208+ }
299209
300- fn add_2d_polygon_to_gltf (
301- & self ,
302- poly2d : & geo:: Polygon < Real > ,
303- vertices : & mut Vec < GltfVertex > ,
304- indices : & mut Vec < u32 > ,
305- ) {
306- let exterior: Vec < [ Real ; 2 ] > = poly2d
307- . exterior ( )
308- . coords_iter ( )
309- . map ( |c| [ c. x , c. y ] )
310- . collect ( ) ;
311-
312- let holes_vec: Vec < Vec < [ Real ; 2 ] > > = poly2d
313- . interiors ( )
314- . iter ( )
315- . map ( |ring| ring. coords_iter ( ) . map ( |c| [ c. x , c. y ] ) . collect ( ) )
316- . collect ( ) ;
317-
318- let hole_refs: Vec < & [ [ Real ; 2 ] ] > =
319- holes_vec. iter ( ) . map ( |h| & h[ ..] ) . collect ( ) ;
320-
321- let triangles_2d = Self :: triangulate_with_holes ( & exterior, & hole_refs) ;
322- let normal = Vector3 :: new ( 0.0 , 0.0 , 1.0 ) ;
210+ impl < S : Clone + Debug + Send + Sync > crate :: bmesh:: BMesh < S > {
211+ pub fn to_gltf ( & self , object_name : & str ) -> String {
212+ let ( vertices, indices) = build_gltf_buffers ( self ) ;
213+ gltf_from_vertices ( & vertices, & indices, object_name)
214+ }
323215
324- for triangle in triangles_2d {
325- for point in triangle {
326- let vertex_3d = Point3 :: new ( point. x , point. y , point. z ) ;
327- let idx =
328- add_unique_vertex_gltf ( vertices, vertex_3d, normal) ;
329- indices. push ( idx) ;
330- }
331- }
216+ pub fn write_gltf < W : Write > (
217+ & self ,
218+ writer : & mut W ,
219+ object_name : & str ,
220+ ) -> std:: io:: Result < ( ) > {
221+ let gltf_content = self . to_gltf ( object_name) ;
222+ writer. write_all ( gltf_content. as_bytes ( ) )
332223 }
333224}
0 commit comments