@@ -14,8 +14,6 @@ class USDZExporter {
1414
1515 const materials = { } ;
1616 const textures = { } ;
17- const materialsWithColor = new Set ( ) ;
18- const coloredTextures = new Map ( ) ; // material -> diffuse map file name
1917
2018 scene . traverseVisible ( ( object ) => {
2119
@@ -36,20 +34,6 @@ class USDZExporter {
3634 if ( ! ( material . uuid in materials ) ) {
3735
3836 materials [ material . uuid ] = material ;
39- // note: material.colorWhite dows not work (always true for some reason)
40- const materialIsNotWhite = material . color . r != 1 || material . color . g != 1 || material . color . b != 1 ;
41- if ( material . map !== null ) {
42- if ( materialIsNotWhite ) {
43- materialsWithColor . add ( material ) ;
44- } else {
45- textures [ material . map . uuid ] = material . map ;
46- }
47- }
48- if ( material . normalMap !== null ) textures [ material . normalMap . uuid ] = material . normalMap ;
49- if ( material . aoMap !== null ) textures [ material . aoMap . uuid ] = material . aoMap ;
50- if ( material . roughnessMap !== null ) textures [ material . roughnessMap . uuid ] = material . roughnessMap ;
51- if ( material . metalnessMap !== null ) textures [ material . metalnessMap . uuid ] = material . metalnessMap ;
52- if ( material . emissiveMap !== null ) textures [ material . emissiveMap . uuid ] = material . emissiveMap ;
5337
5438 }
5539
@@ -59,34 +43,19 @@ class USDZExporter {
5943
6044 } ) ;
6145
62- for ( const material of materialsWithColor ) {
63- const color256 = {
64- r : Math . floor ( material . color . r * 256 ) ,
65- g : Math . floor ( material . color . g * 256 ) ,
66- b : Math . floor ( material . color . b * 256 ) ,
67- } ;
68- const textureSignature = `${ material . map . id } _${ color256 . r } _${ color256 . g } _${ color256 . b } ` ;
69- const texturePath = `textures/Texture_${ textureSignature } .jpg` ;
70-
71- if ( ! files [ texturePath ] ) {
72- files [ texturePath ] = await imgToU8 ( material . map . image , color256 ) ;
73- }
74-
75- coloredTextures . set ( material , textureSignature ) ;
76- }
77-
78- output += buildMaterials ( materials , coloredTextures ) ;
46+ output += buildMaterials ( materials , textures ) ;
7947
8048 files [ modelFileName ] = fflate . strToU8 ( output ) ;
8149 output = null ;
8250
83- for ( const uuid in textures ) {
51+ for ( const id in textures ) {
8452
85- const texture = textures [ uuid ] ;
86- files [ 'textures/Texture_' + texture . id + '.jpg' ] = await imgToU8 ( texture . image ) ;
53+ const texture = textures [ id ] ;
54+ const color = id . split ( '_' ) [ 1 ] ;
8755
88- }
56+ files [ 'textures/Texture_' + id + '.jpg' ] = await imgToU8 ( texture . image , color ) ;
8957
58+ }
9059
9160 // 64 byte alignment
9261 // https://github.com/101arrowz/fflate/issues/39#issuecomment-777263109
@@ -115,12 +84,7 @@ class USDZExporter {
11584
11685 }
11786
118- return await new Promise ( ( resolve , reject ) => {
119- fflate . zip ( files , { level : 0 } , ( err , zipped ) => {
120- if ( err ) reject ( err ) ;
121- else resolve ( zipped ) ;
122- } ) ;
123- } ) ;
87+ return fflate . zipSync ( files , { level : 0 } ) ;
12488
12589 }
12690
@@ -142,10 +106,12 @@ async function imgToU8( image, color ) {
142106 const context = canvas . getContext ( '2d' ) ;
143107 context . drawImage ( image , 0 , 0 , canvas . width , canvas . height ) ;
144108
145- if ( ! ! color ) {
146- context . globalCompositeOperation = "multiply" ;
147- context . fillStyle = `rgb(${ color . r } , ${ color . g } , ${ color . b } )` ;
148- context . fillRect ( 0 , 0 , image . width , image . height ) ;
109+ if ( color !== undefined ) {
110+
111+ context . globalCompositeOperation = 'multiply' ;
112+ context . fillStyle = `#${ color } ` ;
113+ context . fillRect ( 0 , 0 , canvas . width , canvas . height ) ;
114+
149115 }
150116
151117 const blob = await new Promise ( resolve => canvas . toBlob ( resolve , 'image/jpeg' , 1 ) ) ;
@@ -330,15 +296,15 @@ function buildVector2Array( attribute, count ) {
330296
331297// Materials
332298
333- function buildMaterials ( materials , coloredTextures ) {
299+ function buildMaterials ( materials , textures ) {
334300
335301 const array = [ ] ;
336302
337303 for ( const uuid in materials ) {
338304
339305 const material = materials [ uuid ] ;
340306
341- array . push ( buildMaterial ( material , coloredTextures ) ) ;
307+ array . push ( buildMaterial ( material , textures ) ) ;
342308
343309 }
344310
@@ -351,17 +317,20 @@ ${ array.join( '' ) }
351317
352318}
353319
354- function buildMaterial ( material , coloredTextures ) {
320+ function buildMaterial ( material , textures ) {
355321
356322 // https://graphics.pixar.com/usd/docs/UsdPreviewSurface-Proposal.html
357323
358324 const pad = ' ' ;
359- const parameters = [ ] ;
360- const textures = [ ] ;
325+ const inputs = [ ] ;
326+ const samplers = [ ] ;
327+
328+ function buildTexture ( texture , mapType , color ) {
329+
330+ const id = texture . id + ( color ? '_' + color . getHexString ( ) : '' ) ;
361331
362- function buildTexture ( texture , mapType , textureSignature ) {
332+ textures [ id ] = texture ;
363333
364- const textureId = textureSignature || texture . id ;
365334 return `
366335 def Shader "Transform2d_${ mapType } " (
367336 sdrMetadata = {
@@ -379,7 +348,7 @@ function buildMaterial( material, coloredTextures ) {
379348 def Shader "Texture_${ texture . id } _${ mapType } "
380349 {
381350 uniform token info:id = "UsdUVTexture"
382- asset inputs:file = @textures/Texture_${ textureId } .jpg@
351+ asset inputs:file = @textures/Texture_${ id } .jpg@
383352 float2 inputs:st.connect = </Materials/Material_${ material . id } /Transform2d_${ mapType } .outputs:result>
384353 token inputs:wrapS = "repeat"
385354 token inputs:wrapT = "repeat"
@@ -393,95 +362,95 @@ function buildMaterial( material, coloredTextures ) {
393362
394363 if ( material . map !== null ) {
395364
396- parameters . push ( `${ pad } color3f inputs:diffuseColor.connect = </Materials/Material_${ material . id } /Texture_${ material . map . id } _diffuse.outputs:rgb>` ) ;
365+ inputs . push ( `${ pad } color3f inputs:diffuseColor.connect = </Materials/Material_${ material . id } /Texture_${ material . map . id } _diffuse.outputs:rgb>` ) ;
397366
398- textures . push ( buildTexture ( material . map , 'diffuse' , coloredTextures . get ( material ) ) ) ;
367+ samplers . push ( buildTexture ( material . map , 'diffuse' , material . color ) ) ;
399368
400369 } else {
401370
402- parameters . push ( `${ pad } color3f inputs:diffuseColor = ${ buildColor ( material . color ) } ` ) ;
371+ inputs . push ( `${ pad } color3f inputs:diffuseColor = ${ buildColor ( material . color ) } ` ) ;
403372
404373 }
405374
406375 if ( material . emissiveMap !== null ) {
407376
408- parameters . push ( `${ pad } color3f inputs:emissiveColor.connect = </Materials/Material_${ material . id } /Texture_${ material . emissiveMap . id } _emissive.outputs:rgb>` ) ;
377+ inputs . push ( `${ pad } color3f inputs:emissiveColor.connect = </Materials/Material_${ material . id } /Texture_${ material . emissiveMap . id } _emissive.outputs:rgb>` ) ;
409378
410- textures . push ( buildTexture ( material . emissiveMap , 'emissive' ) ) ;
379+ samplers . push ( buildTexture ( material . emissiveMap , 'emissive' ) ) ;
411380
412381 } else if ( material . emissive . getHex ( ) > 0 ) {
413382
414- parameters . push ( `${ pad } color3f inputs:emissiveColor = ${ buildColor ( material . emissive ) } ` ) ;
383+ inputs . push ( `${ pad } color3f inputs:emissiveColor = ${ buildColor ( material . emissive ) } ` ) ;
415384
416385 }
417386
418387 if ( material . normalMap !== null ) {
419388
420- parameters . push ( `${ pad } normal3f inputs:normal.connect = </Materials/Material_${ material . id } /Texture_${ material . normalMap . id } _normal.outputs:rgb>` ) ;
389+ inputs . push ( `${ pad } normal3f inputs:normal.connect = </Materials/Material_${ material . id } /Texture_${ material . normalMap . id } _normal.outputs:rgb>` ) ;
421390
422- textures . push ( buildTexture ( material . normalMap , 'normal' ) ) ;
391+ samplers . push ( buildTexture ( material . normalMap , 'normal' ) ) ;
423392
424393 }
425394
426395 if ( material . aoMap !== null ) {
427396
428- parameters . push ( `${ pad } float inputs:occlusion.connect = </Materials/Material_${ material . id } /Texture_${ material . aoMap . id } _occlusion.outputs:r>` ) ;
397+ inputs . push ( `${ pad } float inputs:occlusion.connect = </Materials/Material_${ material . id } /Texture_${ material . aoMap . id } _occlusion.outputs:r>` ) ;
429398
430- textures . push ( buildTexture ( material . aoMap , 'occlusion' ) ) ;
399+ samplers . push ( buildTexture ( material . aoMap , 'occlusion' ) ) ;
431400
432401 }
433402
434403 if ( material . roughnessMap !== null ) {
435404
436- parameters . push ( `${ pad } float inputs:roughness.connect = </Materials/Material_${ material . id } /Texture_${ material . roughnessMap . id } _roughness.outputs:g>` ) ;
405+ inputs . push ( `${ pad } float inputs:roughness.connect = </Materials/Material_${ material . id } /Texture_${ material . roughnessMap . id } _roughness.outputs:g>` ) ;
437406
438- textures . push ( buildTexture ( material . roughnessMap , 'roughness' ) ) ;
407+ samplers . push ( buildTexture ( material . roughnessMap , 'roughness' ) ) ;
439408
440409 } else {
441410
442- parameters . push ( `${ pad } float inputs:roughness = ${ material . roughness } ` ) ;
411+ inputs . push ( `${ pad } float inputs:roughness = ${ material . roughness } ` ) ;
443412
444413 }
445414
446415 if ( material . metalnessMap !== null ) {
447416
448- parameters . push ( `${ pad } float inputs:metallic.connect = </Materials/Material_${ material . id } /Texture_${ material . metalnessMap . id } _metallic.outputs:b>` ) ;
417+ inputs . push ( `${ pad } float inputs:metallic.connect = </Materials/Material_${ material . id } /Texture_${ material . metalnessMap . id } _metallic.outputs:b>` ) ;
449418
450- textures . push ( buildTexture ( material . metalnessMap , 'metallic' ) ) ;
419+ samplers . push ( buildTexture ( material . metalnessMap , 'metallic' ) ) ;
451420
452421 } else {
453422
454- parameters . push ( `${ pad } float inputs:metallic = ${ material . metalness } ` ) ;
423+ inputs . push ( `${ pad } float inputs:metallic = ${ material . metalness } ` ) ;
455424
456425 }
457426
458- parameters . push ( `${ pad } float inputs:opacity = ${ material . opacity } ` ) ;
427+ inputs . push ( `${ pad } float inputs:opacity = ${ material . opacity } ` ) ;
459428
460429 return `
461- def Material "Material_${ material . id } "
462- {
463- def Shader "PreviewSurface"
464- {
465- uniform token info:id = "UsdPreviewSurface"
466- ${ parameters . join ( '\n' ) }
467- int inputs:useSpecularWorkflow = 0
468- token outputs:surface
469- }
430+ def Material "Material_${ material . id } "
431+ {
432+ def Shader "PreviewSurface"
433+ {
434+ uniform token info:id = "UsdPreviewSurface"
435+ ${ inputs . join ( '\n' ) }
436+ int inputs:useSpecularWorkflow = 0
437+ token outputs:surface
438+ }
470439
471- token outputs:surface.connect = </Materials/Material_${ material . id } /PreviewSurface.outputs:surface>
472- token inputs:frame:stPrimvarName = "st"
440+ token outputs:surface.connect = </Materials/Material_${ material . id } /PreviewSurface.outputs:surface>
441+ token inputs:frame:stPrimvarName = "st"
473442
474- def Shader "uvReader_st"
475- {
476- uniform token info:id = "UsdPrimvarReader_float2"
477- token inputs:varname.connect = </Materials/Material_${ material . id } .inputs:frame:stPrimvarName>
478- float2 inputs:fallback = (0.0, 0.0)
479- float2 outputs:result
480- }
443+ def Shader "uvReader_st"
444+ {
445+ uniform token info:id = "UsdPrimvarReader_float2"
446+ token inputs:varname.connect = </Materials/Material_${ material . id } .inputs:frame:stPrimvarName>
447+ float2 inputs:fallback = (0.0, 0.0)
448+ float2 outputs:result
449+ }
481450
482- ${ textures . join ( '\n' ) }
451+ ${ samplers . join ( '\n' ) }
483452
484- }
453+ }
485454` ;
486455
487456}
0 commit comments