1
1
import type { ParsedModel } from '.' ;
2
- import { texture } from '../models' ;
2
+ import { Material , texture } from '../models' ;
3
3
4
4
function parseNumbers ( row : string , skip : number ) {
5
5
const result = row . trim ( ) . split ( ' ' ) ;
@@ -9,11 +9,14 @@ function parseNumbers(row: string, skip: number) {
9
9
. map ( ( item ) => parseFloat ( item ) ) ;
10
10
}
11
11
12
- let materials = { } ;
12
+ let materials : Record < string , [ Material [ ] , texture ] > = { } ;
13
13
export async function OBJParser (
14
14
file : string ,
15
15
path : string
16
16
) : Promise < ParsedModel > {
17
+ let activeMaterial : Material = undefined ;
18
+ const materialsList : Record < string , Material > = { } ;
19
+
17
20
const lines = file . split ( '\n' ) ;
18
21
const basepath = path . substring ( 0 , path . lastIndexOf ( '/' ) + 1 ) ;
19
22
const positions : Array < number [ ] > = [ [ 0 , 0 , 0 ] ] ;
@@ -23,6 +26,7 @@ export async function OBJParser(
23
26
normals : [ ] ,
24
27
texcoords : [ ] ,
25
28
vertexes : [ ] ,
29
+ colors : [ ] ,
26
30
} ;
27
31
28
32
const sourceMap = {
@@ -56,6 +60,23 @@ export async function OBJParser(
56
60
}
57
61
}
58
62
}
63
+
64
+ // Add the respsective color
65
+ if ( activeMaterial ) {
66
+ const r =
67
+ activeMaterial . diffuse [ 0 ] * activeMaterial . shininess ;
68
+ const g =
69
+ activeMaterial . diffuse [ 1 ] * activeMaterial . shininess ;
70
+
71
+ const b =
72
+ activeMaterial . diffuse [ 2 ] * activeMaterial . shininess ;
73
+
74
+ result . colors . push (
75
+ Math . min ( r , 255.0 ) ,
76
+ Math . min ( g , 255.0 ) ,
77
+ Math . min ( b , 255.0 )
78
+ ) ;
79
+ }
59
80
}
60
81
}
61
82
}
@@ -87,6 +108,11 @@ export async function OBJParser(
87
108
continue ;
88
109
}
89
110
111
+ case 'usemtl' : {
112
+ activeMaterial = materialsList [ parts [ 1 ] ] ;
113
+ continue ;
114
+ }
115
+
90
116
case 'vt' : {
91
117
// Texture position
92
118
texcoords . push ( parseNumbers ( line , 1 ) ) ;
@@ -107,16 +133,24 @@ export async function OBJParser(
107
133
materials [ parts [ 1 ] ] = parseMtl ( mtlfile , basepath ) ;
108
134
}
109
135
110
- result . texture = materials [ parts [ 1 ] ] ;
136
+ result . texture = materials [ parts [ 1 ] ] [ 1 ] ;
137
+
138
+ // Create a materials list
139
+ for ( const mtl of materials [ parts [ 1 ] ] [ 0 ] ) {
140
+ materialsList [ mtl . name ] = mtl ;
141
+ }
111
142
}
112
143
}
113
144
}
114
145
115
146
return result ;
116
147
}
117
148
118
- function parseMtl ( file : string , basepath : string ) : texture {
149
+ function parseMtl ( file : string , basepath : string ) : [ Material [ ] , texture ] {
119
150
const lines = file . split ( '\n' ) ;
151
+ const materials : Material [ ] = [ ] ;
152
+ let mtl : Material = undefined ;
153
+
120
154
const result : texture = {
121
155
uri : '' ,
122
156
repeat_horizontal : 'clamp_to_edge' ,
@@ -131,13 +165,83 @@ function parseMtl(file: string, basepath: string): texture {
131
165
. map ( ( item ) => item . trim ( ) ) ;
132
166
133
167
switch ( parts [ 0 ] ) {
168
+ case 'newmtl' : {
169
+ if ( mtl ) {
170
+ materials . push ( Object . assign ( { } , mtl ) ) ;
171
+ }
172
+
173
+ mtl = {
174
+ name : parts [ 1 ] ,
175
+ } ;
176
+ continue ;
177
+ }
178
+ case 'Ka' : {
179
+ mtl . ambient = [
180
+ parseFloat ( parts [ 1 ] ) ,
181
+ parseFloat ( parts [ 2 ] ) ,
182
+ parseFloat ( parts [ 3 ] ) ,
183
+ ] ;
184
+ continue ;
185
+ }
186
+
187
+ case 'Ns' : {
188
+ mtl . shininess = parseFloat ( parts [ 1 ] ) ;
189
+ continue ;
190
+ }
191
+
192
+ case 'Kd' : {
193
+ mtl . diffuse = [
194
+ parseFloat ( parts [ 1 ] ) ,
195
+ parseFloat ( parts [ 2 ] ) ,
196
+ parseFloat ( parts [ 3 ] ) ,
197
+ ] ;
198
+ continue ;
199
+ }
200
+
201
+ case 'Ks' : {
202
+ mtl . specular = [
203
+ parseFloat ( parts [ 1 ] ) ,
204
+ parseFloat ( parts [ 2 ] ) ,
205
+ parseFloat ( parts [ 3 ] ) ,
206
+ ] ;
207
+ continue ;
208
+ }
209
+
210
+ case 'Ke' : {
211
+ mtl . emissive = [
212
+ parseFloat ( parts [ 1 ] ) ,
213
+ parseFloat ( parts [ 2 ] ) ,
214
+ parseFloat ( parts [ 3 ] ) ,
215
+ ] ;
216
+ continue ;
217
+ }
218
+
219
+ case 'd' : {
220
+ mtl . opacity = parseFloat ( parts [ 1 ] ) ;
221
+ continue ;
222
+ }
223
+
224
+ case 'Ni' : {
225
+ mtl . opticalDensity = parseFloat ( parts [ 1 ] ) ;
226
+ continue ;
227
+ }
228
+
229
+ case 'illum' : {
230
+ mtl . illum = parseInt ( parts [ 1 ] ) ;
231
+ continue ;
232
+ }
233
+
134
234
case 'map_Kd' : {
135
235
result . uri = basepath + parts [ 1 ] ;
136
236
continue ;
137
237
}
138
238
}
139
239
}
140
240
141
- if ( result . uri . length === 0 ) return undefined ;
142
- return result ;
241
+ if ( mtl ) {
242
+ materials . push ( Object . assign ( { } , mtl ) ) ;
243
+ }
244
+
245
+ if ( result . uri . length === 0 ) return [ materials , undefined ] ;
246
+ return [ materials , result ] ;
143
247
}
0 commit comments