@@ -28,16 +28,16 @@ export class FreeCADObject {
28
28
public label : string
29
29
public visibility : boolean
30
30
31
- public shape_file : string
31
+ public brep : string
32
32
33
33
constructor ( public name : string , public type : string ) { }
34
34
35
- hasShapeBRep ( ) {
36
- if ( this . shape_file ) {
35
+ isVisible ( ) {
36
+ if ( this . brep ) {
37
37
return this . visibility === undefined || this . visibility
38
38
} else {
39
39
for ( const child of this . group || [ ] ) {
40
- if ( child . hasShapeBRep ( ) ) {
40
+ if ( child . isVisible ( ) ) {
41
41
return true
42
42
}
43
43
}
@@ -56,36 +56,39 @@ function traverse(object: Object3D, material: MeshStandardMaterial) {
56
56
}
57
57
58
58
export 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 [ ] } = { }
60
61
const breps : { [ name : string ] : Entry } = { }
62
+ const gltfs : { [ name : string ] : GLTF } = { }
63
+ // Main document
61
64
let doc : FreeCADDocument
65
+ // Read ZIP file
62
66
const reader = new ZipReader ( data )
63
- const parser = new DOMParser ( )
64
- // Read files in ZIP archive
65
67
const entries = await reader . getEntries ( )
66
68
for ( const entry of entries ) {
67
- //console.log(entry.filename)
68
- // Check file type
69
69
if ( entry . filename == 'Document.xml' ) {
70
- // Parse XML file
70
+ // Read main document
71
71
const writer = new TextWriter ( )
72
72
const content = await entry . getData ( writer )
73
+ const parser = new DOMParser ( )
73
74
const document = parser . parseFromString ( content , 'application/xml' )
74
75
doc = parseFCStdDocument ( document )
75
76
} else if ( entry . filename . startsWith ( 'DiffuseColor' ) ) {
77
+ // Read color specification
76
78
const writer = new Uint8ArrayWriter ( )
77
79
const content = await entry . getData ( writer )
78
- diffuse [ entry . filename ] = [ ]
80
+ colors [ entry . filename ] = [ ]
79
81
for ( let i = 1 ; i < content . length / 4 ; i ++ ) {
80
82
const a = 1 - content [ i * 4 + 0 ] / 255
81
83
const b = 1 - content [ i * 4 + 1 ] / 255
82
84
const g = 1 - content [ i * 4 + 2 ] / 255
83
85
const r = 1 - content [ i * 4 + 3 ] / 255
84
86
const color = new Color ( r , g , b )
85
87
const material = new MeshStandardMaterial ( { color, opacity : a } )
86
- diffuse [ entry . filename ] . push ( material )
88
+ colors [ entry . filename ] . push ( material )
87
89
}
88
90
} else if ( entry . filename . endsWith ( '.brp' ) ) {
91
+ // Remember brep entry
89
92
breps [ entry . filename ] = entry
90
93
}
91
94
}
@@ -96,57 +99,59 @@ export async function parseFCStdModel(data: ReadableStream | BlobReader, brep2Gl
96
99
delete doc . objects [ object . name ]
97
100
}
98
101
}
99
- // Log result
100
- console . log ( doc )
101
102
// Convert to THREEJS
102
103
const model = new Group ( )
103
104
model . name = doc . label
104
105
model . rotateX ( - Math . PI / 2 )
105
106
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 ) )
108
109
}
109
110
}
110
111
return model
111
112
}
112
113
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 > ) {
114
115
const container = new Group ( )
115
116
container . name = obj . label
116
-
117
- if ( obj . shape_file ) {
117
+ if ( obj . brep ) {
118
118
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 )
129
135
// 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 )
134
140
}
135
- traverse ( clone , new MeshStandardMaterial ( { color : 'black' , wireframe : true } ) )
141
+ traverse ( wire , new MeshStandardMaterial ( { color : 'black' , wireframe : true } ) )
136
142
// Add scene objects
137
- container . add ( clone )
138
- container . add ( gltf . scene )
143
+ container . add ( face )
144
+ container . add ( wire )
139
145
} catch ( e ) {
140
146
console . log ( e )
141
147
}
142
148
} else if ( obj . group ) {
143
149
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 ) )
146
152
}
147
153
}
148
154
}
149
-
150
155
return container
151
156
}
152
157
@@ -226,7 +231,7 @@ function parseFCStdDocumentObjectProperty(data: Element, obj: FreeCADObject, doc
226
231
} else if ( name == 'Shape' ) {
227
232
if ( type == 'Part::PropertyPartShape' ) {
228
233
const child = data . getElementsByTagName ( 'Part' ) [ 0 ]
229
- obj . shape_file = child . getAttribute ( 'file' )
234
+ obj . brep = child . getAttribute ( 'file' )
230
235
} else if ( type == 'App::PropertyLink' ) {
231
236
const child = data . getElementsByTagName ( 'LinkSub' ) [ 0 ]
232
237
const other = doc . objects [ child . getAttribute ( 'value' ) ]
0 commit comments