@@ -28,16 +28,16 @@ export class FreeCADObject {
2828 public label : string
2929 public visibility : boolean
3030
31- public shape_file : string
31+ public brep : string
3232
3333 constructor ( public name : string , public type : string ) { }
3434
35- hasShapeBRep ( ) {
36- if ( this . shape_file ) {
35+ isVisible ( ) {
36+ if ( this . brep ) {
3737 return this . visibility === undefined || this . visibility
3838 } else {
3939 for ( const child of this . group || [ ] ) {
40- if ( child . hasShapeBRep ( ) ) {
40+ if ( child . isVisible ( ) ) {
4141 return true
4242 }
4343 }
@@ -56,36 +56,39 @@ function traverse(object: Object3D, material: MeshStandardMaterial) {
5656}
5757
5858export async function parseFCStdModel ( data : ReadableStream | BlobReader , brep2Glb : ( content : string ) => Promise < Uint8Array > ) {
59- const diffuse : { [ name : string ] : MeshStandardMaterial [ ] } = { }
59+ // Data stuctures
60+ const colors : { [ name : string ] : MeshStandardMaterial [ ] } = { }
6061 const breps : { [ name : string ] : Entry } = { }
62+ const gltfs : { [ name : string ] : GLTF } = { }
63+ // Main document
6164 let doc : FreeCADDocument
65+ // Read ZIP file
6266 const reader = new ZipReader ( data )
63- const parser = new DOMParser ( )
64- // Read files in ZIP archive
6567 const entries = await reader . getEntries ( )
6668 for ( const entry of entries ) {
67- //console.log(entry.filename)
68- // Check file type
6969 if ( entry . filename == 'Document.xml' ) {
70- // Parse XML file
70+ // Read main document
7171 const writer = new TextWriter ( )
7272 const content = await entry . getData ( writer )
73+ const parser = new DOMParser ( )
7374 const document = parser . parseFromString ( content , 'application/xml' )
7475 doc = parseFCStdDocument ( document )
7576 } else if ( entry . filename . startsWith ( 'DiffuseColor' ) ) {
77+ // Read color specification
7678 const writer = new Uint8ArrayWriter ( )
7779 const content = await entry . getData ( writer )
78- diffuse [ entry . filename ] = [ ]
80+ colors [ entry . filename ] = [ ]
7981 for ( let i = 1 ; i < content . length / 4 ; i ++ ) {
8082 const a = 1 - content [ i * 4 + 0 ] / 255
8183 const b = 1 - content [ i * 4 + 1 ] / 255
8284 const g = 1 - content [ i * 4 + 2 ] / 255
8385 const r = 1 - content [ i * 4 + 3 ] / 255
8486 const color = new Color ( r , g , b )
8587 const material = new MeshStandardMaterial ( { color, opacity : a } )
86- diffuse [ entry . filename ] . push ( material )
88+ colors [ entry . filename ] . push ( material )
8789 }
8890 } else if ( entry . filename . endsWith ( '.brp' ) ) {
91+ // Remember brep entry
8992 breps [ entry . filename ] = entry
9093 }
9194 }
@@ -96,57 +99,59 @@ export async function parseFCStdModel(data: ReadableStream | BlobReader, brep2Gl
9699 delete doc . objects [ object . name ]
97100 }
98101 }
99- // Log result
100- console . log ( doc )
101102 // Convert to THREEJS
102103 const model = new Group ( )
103104 model . name = doc . label
104105 model . rotateX ( - Math . PI / 2 )
105106 for ( const obj of Object . values ( doc . objects ) ) {
106- if ( obj . hasShapeBRep ( ) ) {
107- model . add ( await convertFCObject ( obj , diffuse , breps , brep2Glb ) )
107+ if ( obj . isVisible ( ) ) {
108+ model . add ( await convertFCObject ( obj , colors , breps , gltfs , brep2Glb ) )
108109 }
109110 }
110111 return model
111112}
112113
113- async function convertFCObject ( obj : FreeCADObject , diffuse : { [ name : string ] : MeshStandardMaterial [ ] } , breps : { [ name : string ] : Entry } , brep2Glb : ( content : string ) => Promise < Uint8Array > ) {
114+ async function convertFCObject ( obj : FreeCADObject , colors : { [ name : string ] : MeshStandardMaterial [ ] } , breps : { [ name : string ] : Entry } , gltfs : { [ name : string ] : GLTF } , brep2Glb : ( content : string ) => Promise < Uint8Array > ) {
114115 const container = new Group ( )
115116 container . name = obj . label
116-
117- if ( obj . shape_file ) {
117+ if ( obj . brep ) {
118118 try {
119- // Parse BRep file
120- const entry = breps [ obj . shape_file ]
121- const writer = new TextWriter ( )
122- const content = await entry . getData ( writer )
123- console . log ( 'Parsing' , entry . filename )
124- const glbFileData = await brep2Glb ( content )
125- const gltf = await new Promise < GLTF > ( ( resolve , reject ) => {
126- GLTF . parse ( glbFileData . buffer , undefined , resolve , reject )
127- } )
128- const clone = gltf . scene . clone ( true )
119+ const file = obj . brep
120+ // Parse brep
121+ if ( ! ( file in gltfs ) ) {
122+ const entry = breps [ obj . brep ]
123+ const writer = new TextWriter ( )
124+ const content = await entry . getData ( writer )
125+ console . log ( 'Converting' , file )
126+ const data = await brep2Glb ( content )
127+ console . log ( 'Parsing' , file )
128+ gltfs [ file ] = await new Promise < GLTF > ( ( resolve , reject ) => {
129+ GLTF . parse ( data . buffer , undefined , resolve , reject )
130+ } )
131+ }
132+ // Clone scene
133+ const face = gltfs [ file ] . scene . clone ( true )
134+ const wire = gltfs [ file ] . scene . clone ( true )
129135 // Update mesh materials
130- const other = entry . filename . replace ( 'PartShape' , 'DiffuseColor' ) . replace ( '.brp' , '' )
131- if ( other in diffuse ) {
132- const material = diffuse [ other ] [ 0 ]
133- traverse ( gltf . scene , material )
136+ const other = file . replace ( 'PartShape' , 'DiffuseColor' ) . replace ( '.brp' , '' )
137+ if ( other in colors ) {
138+ const material = colors [ other ] [ 0 ]
139+ traverse ( face , material )
134140 }
135- traverse ( clone , new MeshStandardMaterial ( { color : 'black' , wireframe : true } ) )
141+ traverse ( wire , new MeshStandardMaterial ( { color : 'black' , wireframe : true } ) )
136142 // Add scene objects
137- container . add ( clone )
138- container . add ( gltf . scene )
143+ container . add ( face )
144+ container . add ( wire )
139145 } catch ( e ) {
140146 console . log ( e )
141147 }
142148 } else if ( obj . group ) {
143149 for ( const child of obj . group ) {
144- if ( child . hasShapeBRep ( ) ) {
145- container . add ( await convertFCObject ( child , diffuse , breps , brep2Glb ) )
150+ if ( child . isVisible ( ) ) {
151+ container . add ( await convertFCObject ( child , colors , breps , gltfs , brep2Glb ) )
146152 }
147153 }
148154 }
149-
150155 return container
151156}
152157
@@ -226,7 +231,7 @@ function parseFCStdDocumentObjectProperty(data: Element, obj: FreeCADObject, doc
226231 } else if ( name == 'Shape' ) {
227232 if ( type == 'Part::PropertyPartShape' ) {
228233 const child = data . getElementsByTagName ( 'Part' ) [ 0 ]
229- obj . shape_file = child . getAttribute ( 'file' )
234+ obj . brep = child . getAttribute ( 'file' )
230235 } else if ( type == 'App::PropertyLink' ) {
231236 const child = data . getElementsByTagName ( 'LinkSub' ) [ 0 ]
232237 const other = doc . objects [ child . getAttribute ( 'value' ) ]
0 commit comments