1 # SPDX-FileCopyrightText: 2018-2022 The glTF-Blender-IO authors
3 # SPDX-License-Identifier: Apache-2.0
5 from copy
import deepcopy
8 from ....io
.com
import gltf2_io
9 from ....io
.com
.gltf2_io_extensions
import Extension
10 from ....io
.exp
.gltf2_io_user_extensions
import export_user_extensions
11 from ...com
.gltf2_blender_extras
import generate_extras
12 from ..gltf2_blender_gather_cache
import cached
, cached_by_key
13 from . import gltf2_blender_gather_materials_unlit
14 from . import gltf2_blender_gather_texture_info
15 from . import gltf2_blender_gather_materials_pbr_metallic_roughness
16 from .extensions
.gltf2_blender_gather_materials_volume
import export_volume
17 from .extensions
.gltf2_blender_gather_materials_emission
import export_emission_factor
, \
18 export_emission_texture
, export_emission_strength_extension
19 from .extensions
.gltf2_blender_gather_materials_sheen
import export_sheen
20 from .extensions
.gltf2_blender_gather_materials_specular
import export_specular
21 from .extensions
.gltf2_blender_gather_materials_transmission
import export_transmission
22 from .extensions
.gltf2_blender_gather_materials_clearcoat
import export_clearcoat
23 from .extensions
.gltf2_blender_gather_materials_anisotropy
import export_anisotropy
24 from .extensions
.gltf2_blender_gather_materials_ior
import export_ior
25 from .gltf2_blender_search_node_tree
import \
26 has_image_node_from_socket
, \
27 get_socket_from_gltf_material_node
, \
35 def get_material_cache_key(blender_material
, export_settings
):
37 # Do not use bpy.types that can be unhashable
38 # Do not use material name, that can be not unique (when linked)
39 # We use here the id of original material as for apply modifier, the material has a new id
40 # So, when no modifier applied => original is the same id
41 # And when modifier applied => new one is different id, but original is still the same
43 (id(blender_material
.original
),),
46 @cached_by_key(key
=get_material_cache_key
)
47 def gather_material(blender_material
, export_settings
):
49 Gather the material used by the blender primitive.
51 :param blender_material: the blender material used in the glTF primitive
52 :param export_settings:
53 :return: a glTF material
55 if not __filter_material(blender_material
, export_settings
):
56 return None, {"uv_info": {}, "vc_info": {'color': None, 'alpha': None, 'color_type': None, 'alpha_type': None}, "udim_info": {}}
58 # Reset exported images / textures nodes
59 export_settings
['exported_texture_nodes'] = []
60 if blender_material
.node_tree
and blender_material
.use_nodes
:
61 nodes
= get_material_nodes(blender_material
.node_tree
, [blender_material
.node_tree
], bpy
.types
.ShaderNodeTexImage
)
65 if node
[0].get("used", None) is not None:
68 mat_unlit
, uvmap_info
, vc_info
, udim_info
= __export_unlit(blender_material
, export_settings
)
69 if mat_unlit
is not None:
70 export_user_extensions('gather_material_hook', export_settings
, mat_unlit
, blender_material
)
71 return mat_unlit
, {"uv_info": uvmap_info
, "vc_info": vc_info
, "udim_info": udim_info
}
73 orm_texture
= __gather_orm_texture(blender_material
, export_settings
)
75 emissive_factor
= __gather_emissive_factor(blender_material
, export_settings
)
76 emissive_texture
, uvmap_info_emissive
, udim_info_emissive
= __gather_emissive_texture(blender_material
, export_settings
)
77 extensions
, uvmap_info_extensions
, udim_info_extensions
= __gather_extensions(blender_material
, emissive_factor
, export_settings
)
78 normal_texture
, uvmap_info_normal
, udim_info_normal
= __gather_normal_texture(blender_material
, export_settings
)
79 occlusion_texture
, uvmap_info_occlusion
, udim_occlusion
= __gather_occlusion_texture(blender_material
, orm_texture
, export_settings
)
80 pbr_metallic_roughness
, uvmap_info_pbr_metallic_roughness
, vc_info
, udim_info_prb_mr
= __gather_pbr_metallic_roughness(blender_material
, orm_texture
, export_settings
)
82 if any([i
>1.0 for i
in emissive_factor
or []]) is True:
83 # Strength is set on extension
84 emission_strength
= max(emissive_factor
)
85 emissive_factor
= [f
/ emission_strength
for f
in emissive_factor
]
88 material
= gltf2_io
.Material(
89 alpha_cutoff
=__gather_alpha_cutoff(blender_material
, export_settings
),
90 alpha_mode
=__gather_alpha_mode(blender_material
, export_settings
),
91 double_sided
=__gather_double_sided(blender_material
, extensions
, export_settings
),
92 emissive_factor
=emissive_factor
,
93 emissive_texture
=emissive_texture
,
94 extensions
=extensions
,
95 extras
=__gather_extras(blender_material
, export_settings
),
96 name
=__gather_name(blender_material
, export_settings
),
97 normal_texture
=normal_texture
,
98 occlusion_texture
=occlusion_texture
,
99 pbr_metallic_roughness
=pbr_metallic_roughness
105 # Get all textures nodes that are not used in the material
106 if export_settings
['gltf_unused_textures'] is True:
107 if blender_material
.node_tree
and blender_material
.use_nodes
:
108 nodes
= get_material_nodes(blender_material
.node_tree
, [blender_material
.node_tree
], bpy
.types
.ShaderNodeTexImage
)
113 if node
[0].get("used", None) is not None:
117 s
= NodeSocket(node
[0].outputs
[0], node
[1])
118 tex
, uv_info_additional
, udim_info
, _
= gltf2_blender_gather_texture_info
.gather_texture_info(s
, (s
,), export_settings
)
120 export_settings
['exported_images'][node
[0].image
.name
] = 1 # Fully used
121 uvmap_infos
.update({'additional' + str(cpt_additional
): uv_info_additional
})
122 udim_infos
.update({'additional' + str(cpt_additional
): udim_info
})
124 export_settings
['additional_texture_export'].append(tex
)
127 if blender_material
.node_tree
and blender_material
.use_nodes
:
128 nodes
= get_material_nodes(blender_material
.node_tree
, [blender_material
.node_tree
], bpy
.types
.ShaderNodeTexImage
)
132 if node
[0].get("used", None) is not None:
135 uvmap_infos
.update(uvmap_info_emissive
)
136 uvmap_infos
.update(uvmap_info_extensions
)
137 uvmap_infos
.update(uvmap_info_normal
)
138 uvmap_infos
.update(uvmap_info_occlusion
)
139 uvmap_infos
.update(uvmap_info_pbr_metallic_roughness
)
142 udim_infos
.update(udim_info_prb_mr
)
143 udim_infos
.update(udim_info_normal
)
144 udim_infos
.update(udim_info_emissive
)
145 udim_infos
.update(udim_occlusion
)
146 udim_infos
.update(udim_info_extensions
)
149 # If emissive is set, from an emissive node (not PBR)
150 # We need to set manually default values for
151 # pbr_metallic_roughness.baseColor
152 if material
.emissive_factor
is not None and get_node_socket(blender_material
.node_tree
, bpy
.types
.ShaderNodeBsdfPrincipled
, "Base Color").socket
is None:
153 material
.pbr_metallic_roughness
= gltf2_blender_gather_materials_pbr_metallic_roughness
.get_default_pbr_for_emissive_node()
155 export_user_extensions('gather_material_hook', export_settings
, material
, blender_material
)
157 # Now we have exported the material itself, we need to store some additional data
158 # This will be used when trying to export some KHR_animation_pointer
160 if len(export_settings
['current_paths']) > 0:
161 export_settings
['KHR_animation_pointer']['materials'][id(blender_material
)] = {}
162 export_settings
['KHR_animation_pointer']['materials'][id(blender_material
)]['paths'] = export_settings
['current_paths'].copy()
163 export_settings
['KHR_animation_pointer']['materials'][id(blender_material
)]['glTF_material'] = material
165 export_settings
['current_paths'] = {}
167 return material
, {"uv_info": uvmap_infos
, "vc_info": vc_info
, "udim_info": udim_infos
}
170 def get_new_material_texture_shared(base
, node
):
173 if callable(node
) is True:
175 if node
.__str
__().startswith('__'):
177 if type(node
) in [gltf2_io
.TextureInfo
, gltf2_io
.MaterialOcclusionTextureInfoClass
, gltf2_io
.MaterialNormalTextureInfoClass
]:
178 node
.index
= base
.index
180 if hasattr(node
, '__dict__'):
181 for attr
, value
in node
.__dict
__.items():
182 get_new_material_texture_shared(getattr(base
, attr
), value
)
184 # For extensions (on a dict)
185 if type(node
).__name
__ == 'dict':
186 for i
in node
.keys():
187 get_new_material_texture_shared(base
[i
], node
[i
])
189 def __filter_material(blender_material
, export_settings
):
190 return export_settings
['gltf_materials']
193 def __gather_alpha_cutoff(blender_material
, export_settings
):
194 if blender_material
.blend_method
== 'CLIP':
198 path_
['path'] = "/materials/XXX/alphaCutoff"
199 export_settings
['current_paths']['alpha_threshold'] = path_
201 return blender_material
.alpha_threshold
205 def __gather_alpha_mode(blender_material
, export_settings
):
206 if blender_material
.blend_method
== 'CLIP':
208 elif blender_material
.blend_method
in ['BLEND', 'HASHED']:
213 def __gather_double_sided(blender_material
, extensions
, export_settings
):
215 # If user create a volume extension, we force double sided to False
216 if 'KHR_materials_volume' in extensions
:
219 if not blender_material
.use_backface_culling
:
224 def __gather_emissive_factor(blender_material
, export_settings
):
225 return export_emission_factor(blender_material
, export_settings
)
227 def __gather_emissive_texture(blender_material
, export_settings
):
228 return export_emission_texture(blender_material
, export_settings
)
231 def __gather_extensions(blender_material
, emissive_factor
, export_settings
):
237 # KHR_materials_clearcoat
238 clearcoat_extension
, uvmap_info
, udim_info_clearcoat
= export_clearcoat(blender_material
, export_settings
)
239 if clearcoat_extension
:
240 extensions
["KHR_materials_clearcoat"] = clearcoat_extension
241 uvmap_infos
.update(uvmap_info
)
242 udim_infos
.update(udim_info_clearcoat
)
244 # KHR_materials_transmission
246 transmission_extension
, uvmap_info
, udim_info_transmission
= export_transmission(blender_material
, export_settings
)
247 if transmission_extension
:
248 extensions
["KHR_materials_transmission"] = transmission_extension
249 uvmap_infos
.update(uvmap_info
)
250 udim_infos
.update(udim_info_transmission
)
252 # KHR_materials_emissive_strength
253 emissive_strength_extension
= export_emission_strength_extension(emissive_factor
, export_settings
)
254 if emissive_strength_extension
:
255 extensions
["KHR_materials_emissive_strength"] = emissive_strength_extension
257 # KHR_materials_volume
259 volume_extension
, uvmap_info
, udim_info
= export_volume(blender_material
, export_settings
)
261 extensions
["KHR_materials_volume"] = volume_extension
262 uvmap_infos
.update(uvmap_info
)
263 udim_infos
.update(udim_info
)
265 # KHR_materials_specular
266 specular_extension
, uvmap_info
, udim_info
= export_specular(blender_material
, export_settings
)
267 if specular_extension
:
268 extensions
["KHR_materials_specular"] = specular_extension
269 uvmap_infos
.update(uvmap_info
)
270 udim_infos
.update(udim_info
)
272 # KHR_materials_sheen
273 sheen_extension
, uvmap_info
, udim_info
= export_sheen(blender_material
, export_settings
)
275 extensions
["KHR_materials_sheen"] = sheen_extension
276 uvmap_infos
.update(uvmap_info
)
277 udim_infos
.update(udim_info
)
279 # KHR_materials_anisotropy
280 anisotropy_extension
, uvmap_info
, udim_info
= export_anisotropy(blender_material
, export_settings
)
281 if anisotropy_extension
:
282 extensions
["KHR_materials_anisotropy"] = anisotropy_extension
283 uvmap_infos
.update(uvmap_info
)
284 udim_infos
.update(udim_info
)
287 # Keep this extension at the end, because we export it only if some others are exported
288 ior_extension
= export_ior(blender_material
, extensions
, export_settings
)
290 extensions
["KHR_materials_ior"] = ior_extension
292 return extensions
, uvmap_infos
, udim_infos
295 def __gather_extras(blender_material
, export_settings
):
296 if export_settings
['gltf_extras']:
297 return generate_extras(blender_material
)
301 def __gather_name(blender_material
, export_settings
):
302 return blender_material
.name
305 def __gather_normal_texture(blender_material
, export_settings
):
306 normal
= get_socket(blender_material
.node_tree
, blender_material
.use_nodes
, "Normal")
307 normal_texture
, uvmap_info
, udim_info
, _
= gltf2_blender_gather_texture_info
.gather_material_normal_texture_info_class(
312 if len(export_settings
['current_texture_transform']) != 0:
313 for k
in export_settings
['current_texture_transform'].keys():
315 path_
['length'] = export_settings
['current_texture_transform'][k
]['length']
316 path_
['path'] = export_settings
['current_texture_transform'][k
]['path'].replace("YYY", "normalTexture/extensions")
317 path_
['vector_type'] = export_settings
['current_texture_transform'][k
]['vector_type']
318 export_settings
['current_paths'][k
] = path_
320 export_settings
['current_texture_transform'] = {}
322 if len(export_settings
['current_normal_scale']) != 0:
323 for k
in export_settings
['current_normal_scale'].keys():
325 path_
['length'] = export_settings
['current_normal_scale'][k
]['length']
326 path_
['path'] = export_settings
['current_normal_scale'][k
]['path'].replace("YYY", "normalTexture")
327 export_settings
['current_paths'][k
] = path_
329 export_settings
['current_normal_scale'] = {}
331 return normal_texture
, {"normalTexture" : uvmap_info
}, {'normalTexture': udim_info
} if len(udim_info
.keys()) > 0 else {}
334 def __gather_orm_texture(blender_material
, export_settings
):
335 # Check for the presence of Occlusion, Roughness, Metallic sharing a single image.
336 # If not fully shared, return None, so the images will be cached and processed separately.
338 occlusion
= get_socket(blender_material
.node_tree
, blender_material
.use_nodes
, "Occlusion")
339 if occlusion
.socket
is None or not has_image_node_from_socket(occlusion
, export_settings
):
340 occlusion
= get_socket_from_gltf_material_node(blender_material
.node_tree
, blender_material
.use_nodes
, "Occlusion")
341 if occlusion
.socket
is None or not has_image_node_from_socket(occlusion
, export_settings
):
344 metallic_socket
= get_socket(blender_material
.node_tree
, blender_material
.use_nodes
, "Metallic")
345 roughness_socket
= get_socket(blender_material
.node_tree
, blender_material
.use_nodes
, "Roughness")
347 hasMetal
= metallic_socket
.socket
is not None and has_image_node_from_socket(metallic_socket
, export_settings
)
348 hasRough
= roughness_socket
.socket
is not None and has_image_node_from_socket(roughness_socket
, export_settings
)
350 # Warning: for default socket, do not use NodeSocket object, because it will break cache
351 # Using directlty the Blender socket object
352 if not hasMetal
and not hasRough
:
353 metallic_roughness
= get_socket_from_gltf_material_node(blender_material
.node_tree
, blender_material
.use_nodes
, "MetallicRoughness")
354 if metallic_roughness
.socket
is None or not has_image_node_from_socket(metallic_roughness
, export_settings
):
356 result
= (occlusion
, metallic_roughness
)
358 result
= (occlusion
, roughness_socket
)
360 result
= (occlusion
, metallic_socket
)
362 result
= (occlusion
, roughness_socket
, metallic_socket
)
364 if not gltf2_blender_gather_texture_info
.check_same_size_images(result
, export_settings
):
365 export_settings
['log'].info(
366 "Occlusion and metal-roughness texture will be exported separately "
367 "(use same-sized images if you want them combined)"
371 # Double-check this will past the filter in texture_info
372 info
, _
, _
, _
= gltf2_blender_gather_texture_info
.gather_texture_info(result
[0], result
, export_settings
)
376 if len(export_settings
['current_texture_transform']) != 0:
377 for k
in export_settings
['current_texture_transform'].keys():
379 path_
['length'] = export_settings
['current_texture_transform'][k
]['length']
380 path_
['path'] = export_settings
['current_texture_transform'][k
]['path'].replace("YYY", "occlusionTexture/extensions")
381 path_
['vector_type'] = export_settings
['current_texture_transform'][k
]['vector_type']
382 export_settings
['current_paths'][k
] = path_
384 #This case can't happen because we are going to keep only 1 UVMap
385 export_settings
['log'].warning("This case should not happen, please report a bug")
386 for k
in export_settings
['current_texture_transform'].keys():
388 path_
['length'] = export_settings
['current_texture_transform'][k
]['length']
389 path_
['path'] = export_settings
['current_texture_transform'][k
]['path'].replace("YYY", "pbrMetallicRoughness/metallicRoughnessTexture/extensions")
390 path_
['vector_type'] = export_settings
['current_texture_transform'][k
]['vector_type']
391 export_settings
['current_paths'][k
] = path_
393 export_settings
['current_texture_transform'] = {}
397 def __gather_occlusion_texture(blender_material
, orm_texture
, export_settings
):
398 occlusion
= get_socket(blender_material
.node_tree
, blender_material
.use_nodes
, "Occlusion")
399 if occlusion
.socket
is None:
400 occlusion
= get_socket_from_gltf_material_node(blender_material
.node_tree
, blender_material
.use_nodes
, "Occlusion")
401 if occlusion
.socket
is None:
403 occlusion_texture
, uvmap_info
, udim_info
, _
= gltf2_blender_gather_texture_info
.gather_material_occlusion_texture_info_class(
405 orm_texture
or (occlusion
,),
408 if len(export_settings
['current_occlusion_strength']) != 0:
409 for k
in export_settings
['current_occlusion_strength'].keys():
411 path_
['length'] = export_settings
['current_occlusion_strength'][k
]['length']
412 path_
['path'] = export_settings
['current_occlusion_strength'][k
]['path']
413 path_
['reverse'] = export_settings
['current_occlusion_strength'][k
]['reverse']
414 export_settings
['current_paths'][k
] = path_
416 export_settings
['current_occlusion_strength'] = {}
418 if len(export_settings
['current_texture_transform']) != 0:
419 for k
in export_settings
['current_texture_transform'].keys():
421 path_
['length'] = export_settings
['current_texture_transform'][k
]['length']
422 path_
['path'] = export_settings
['current_texture_transform'][k
]['path'].replace("YYY", "occlusionTexture/extensions")
423 path_
['vector_type'] = export_settings
['current_texture_transform'][k
]['vector_type']
424 export_settings
['current_paths'][k
] = path_
426 export_settings
['current_texture_transform'] = {}
428 return occlusion_texture
, \
429 {"occlusionTexture" : uvmap_info
}, {'occlusionTexture': udim_info
} if len(udim_info
.keys()) > 0 else {}
432 def __gather_pbr_metallic_roughness(blender_material
, orm_texture
, export_settings
):
433 return gltf2_blender_gather_materials_pbr_metallic_roughness
.gather_material_pbr_metallic_roughness(
438 def __export_unlit(blender_material
, export_settings
):
439 gltf2_unlit
= gltf2_blender_gather_materials_unlit
441 info
= gltf2_unlit
.detect_shadeless_material(blender_material
.node_tree
, blender_material
.use_nodes
, export_settings
)
443 return None, {}, {"color": None, "alpha": None, "color_type": None, "alpha_type": None}, {}
445 base_color_texture
, uvmap_info
, udim_info
= gltf2_unlit
.gather_base_color_texture(info
, export_settings
)
447 vc_info
= get_vertex_color_info(info
.get('rgb_socket'), info
.get('alpha_socket'), export_settings
)
449 material
= gltf2_io
.Material(
450 alpha_cutoff
=__gather_alpha_cutoff(blender_material
, export_settings
),
451 alpha_mode
=__gather_alpha_mode(blender_material
, export_settings
),
452 double_sided
=__gather_double_sided(blender_material
, {}, export_settings
),
453 extensions
={"KHR_materials_unlit": Extension("KHR_materials_unlit", {}, required
=False)},
454 extras
=__gather_extras(blender_material
, export_settings
),
455 name
=__gather_name(blender_material
, export_settings
),
456 emissive_factor
=None,
457 emissive_texture
=None,
459 occlusion_texture
=None,
461 pbr_metallic_roughness
=gltf2_io
.MaterialPBRMetallicRoughness(
462 base_color_factor
=gltf2_unlit
.gather_base_color_factor(info
, export_settings
),
463 base_color_texture
=base_color_texture
,
465 roughness_factor
=0.9,
466 metallic_roughness_texture
=None,
472 export_user_extensions('gather_material_unlit_hook', export_settings
, material
, blender_material
)
474 # Now we have exported the material itself, we need to store some additional data
475 # This will be used when trying to export some KHR_animation_pointer
477 if len(export_settings
['current_paths']) > 0:
478 export_settings
['KHR_animation_pointer']['materials'][id(blender_material
)] = {}
479 export_settings
['KHR_animation_pointer']['materials'][id(blender_material
)]['paths'] = export_settings
['current_paths'].copy()
480 export_settings
['KHR_animation_pointer']['materials'][id(blender_material
)]['glTF_material'] = material
482 export_settings
['current_paths'] = {}
484 return material
, uvmap_info
, vc_info
, udim_info
486 def get_active_uvmap_index(blender_mesh
):
487 # retrieve active render UVMap
489 for i
in range(len(blender_mesh
.uv_layers
)):
490 if blender_mesh
.uv_layers
[i
].active_render
is True:
493 return active_uvmap_idx
496 def get_final_material(mesh
, blender_material
, attr_indices
, base_material
, uvmap_info
, export_settings
):
498 # First, we need to calculate all index of UVMap
501 additional_indices
= 0
503 for m
, v
in uvmap_info
.items():
505 if m
.startswith("additional") and additional_indices
<= int(m
[10:]):
506 additional_indices
= +1
508 if not 'type' in v
.keys():
511 if v
['type'] == 'Fixed':
512 i
= mesh
.uv_layers
.find(v
['value'])
517 indices
[m
] = get_active_uvmap_index(mesh
)
518 elif v
['type'] == 'Active':
519 indices
[m
] = get_active_uvmap_index(mesh
)
520 elif v
['type'] == "Attribute":
521 indices
[m
] = attr_indices
[v
['value']]
523 # Now we have all needed indices, let's create a set that can be used for caching, so containing all possible textures
524 all_textures
= get_all_textures(additional_indices
)
527 for tex
in all_textures
:
528 caching_indices
.append(indices
.get(tex
, None))
530 caching_indices
= [i
if i
!= 0 else None for i
in caching_indices
]
531 caching_indices
= tuple(caching_indices
)
533 material
= __get_final_material_with_indices(blender_material
, base_material
, caching_indices
, export_settings
)
539 def caching_material_tex_indices(blender_material
, material
, caching_indices
, export_settings
):
541 (id(blender_material
),),
545 @cached_by_key(key
=caching_material_tex_indices
)
546 def __get_final_material_with_indices(blender_material
, base_material
, caching_indices
, export_settings
):
548 if base_material
is None:
551 if all([i
is None for i
in caching_indices
]):
554 material
= deepcopy(base_material
)
555 get_new_material_texture_shared(base_material
, material
)
557 for tex
, ind
in zip(get_all_textures(len(caching_indices
) - len(get_all_textures())), caching_indices
):
562 # Need to check if texture is not None, because it can be the case for UDIM on non managed UDIM textures
563 if tex
== "emissiveTexture":
564 if material
.emissive_texture
: material
.emissive_texture
.tex_coord
= ind
565 elif tex
== "normalTexture":
566 if material
.normal_texture
: material
.normal_texture
.tex_coord
= ind
567 elif tex
== "occlusionTexture":
568 if material
.occlusion_texture
: material
.occlusion_texture
.tex_coord
= ind
569 elif tex
== "baseColorTexture":
570 if material
.pbr_metallic_roughness
.base_color_texture
: material
.pbr_metallic_roughness
.base_color_texture
.tex_coord
= ind
571 elif tex
== "metallicRoughnessTexture":
572 if material
.pbr_metallic_roughness
.metallic_roughness_texture
: material
.pbr_metallic_roughness
.metallic_roughness_texture
.tex_coord
= ind
573 elif tex
== "clearcoatTexture":
574 if material
.extensions
["KHR_materials_clearcoat"].extension
['clearcoatTexture']: material
.extensions
["KHR_materials_clearcoat"].extension
['clearcoatTexture'].tex_coord
= ind
575 elif tex
== "clearcoatRoughnessTexture":
576 if material
.extensions
["KHR_materials_clearcoat"].extension
['clearcoatRoughnessTexture']: material
.extensions
["KHR_materials_clearcoat"].extension
['clearcoatRoughnessTexture'].tex_coord
= ind
577 elif tex
== "clearcoatNormalTexture":
578 if material
.extensions
["KHR_materials_clearcoat"].extension
['clearcoatNormalTexture']: material
.extensions
["KHR_materials_clearcoat"].extension
['clearcoatNormalTexture'].tex_coord
= ind
579 elif tex
== "transmissionTexture":
580 if material
.extensions
["KHR_materials_transmission"].extension
['transmissionTexture']: material
.extensions
["KHR_materials_transmission"].extension
['transmissionTexture'].tex_coord
= ind
581 elif tex
== "specularTexture":
582 if material
.extensions
["KHR_materials_specular"].extension
['specularTexture']: material
.extensions
["KHR_materials_specular"].extension
['specularTexture'].tex_coord
= ind
583 elif tex
== "specularColorTexture":
584 if material
.extensions
["KHR_materials_specular"].extension
['specularColorTexture']: material
.extensions
["KHR_materials_specular"].extension
['specularColorTexture'].tex_coord
= ind
585 elif tex
== "sheenColorTexture":
586 if material
.extensions
["KHR_materials_sheen"].extension
['sheenColorTexture']: material
.extensions
["KHR_materials_sheen"].extension
['sheenColorTexture'].tex_coord
= ind
587 elif tex
== "sheenRoughnessTexture":
588 if material
.extensions
["KHR_materials_sheen"].extension
['sheenRoughnessTexture']: material
.extensions
["KHR_materials_sheen"].extension
['sheenRoughnessTexture'].tex_coord
= ind
589 elif tex
== "thicknessTexture":
590 if material
.extensions
["KHR_materials_volume"].extension
['thicknessTexture']: material
.extensions
["KHR_materials_volume"].extension
['thicknessTexture'].tex_ccord
= ind
591 elif tex
== "anisotropyTexture":
592 if material
.extensions
["KHR_materials_anisotropy"].extension
['anisotropyTexture']: material
.extensions
["KHR_materials_anisotropy"].extension
['anisotropyTexture'].tex_coord
= ind
593 elif tex
.startswith("additional"):
594 export_settings
['additional_texture_export'][export_settings
['additional_texture_export_current_idx'] + int(tex
[10:])].tex_coord
= ind
596 export_settings
['log'].error("some Textures tex coord are not managed")
598 export_settings
['additional_texture_export_current_idx'] = len(export_settings
['additional_texture_export'])
603 def get_material_from_idx(material_idx
, materials
, export_settings
):
605 if export_settings
['gltf_materials'] == "EXPORT" and material_idx
is not None:
607 i
= material_idx
if material_idx
< len(materials
) else -1
611 def get_base_material(material_idx
, materials
, export_settings
):
613 export_settings
['current_paths'] = {}
627 mat
= get_material_from_idx(material_idx
, materials
, export_settings
)
629 material
, material_info
= gather_material(
635 # If no material, the mesh can still have vertex color
637 material_info
["vc_info"] = {"color_type": "active", "alpha_type": "active"}
639 return material
, material_info
641 def get_all_textures(idx
=0):
642 # Make sure to have all texture here, always in same order
645 tab
.append("emissiveTexture")
646 tab
.append("normalTexture")
647 tab
.append("occlusionTexture")
648 tab
.append("baseColorTexture")
649 tab
.append("metallicRoughnessTexture")
650 tab
.append("clearcoatTexture")
651 tab
.append("clearcoatRoughnessTexture")
652 tab
.append("clearcoatNormalTexture")
653 tab
.append("transmissionTexture")
654 tab
.append("specularTexture")
655 tab
.append("specularColorTexture")
656 tab
.append("sheenColorTexture")
657 tab
.append("sheenRoughnessTexture")
658 tab
.append("thicknessTexture")
659 tab
.append("anisotropyTexture")
662 tab
.append("additional" + str(i
))