From ac979078417e7093e1088b05e0065337d73816b3 Mon Sep 17 00:00:00 2001 From: Julien Duroure Date: Fri, 24 May 2024 09:28:53 +0200 Subject: [PATCH] glTF exporter: Fix UVMap export when is set from an attribute node --- .../addons_core/io_scene_gltf2/__init__.py | 2 +- ...gltf2_blender_gather_primitives_extract.py | 25 ++++++++++++++++--- .../gltf2_blender_gather_materials.py | 7 +++++- .../gltf2_blender_gather_texture_info.py | 3 +++ 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/scripts/addons_core/io_scene_gltf2/__init__.py b/scripts/addons_core/io_scene_gltf2/__init__.py index 4d040f8a5a8..877dd0a161c 100755 --- a/scripts/addons_core/io_scene_gltf2/__init__.py +++ b/scripts/addons_core/io_scene_gltf2/__init__.py @@ -5,7 +5,7 @@ bl_info = { 'name': 'glTF 2.0 format', 'author': 'Julien Duroure, Scurest, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors', - "version": (4, 2, 34), + "version": (4, 2, 35), 'blender': (4, 2, 0), 'location': 'File > Import-Export', 'description': 'Import-Export as glTF 2.0', diff --git a/scripts/addons_core/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py b/scripts/addons_core/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py index a4c92137bb9..c5f376e03c9 100644 --- a/scripts/addons_core/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py +++ b/scripts/addons_core/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py @@ -420,7 +420,8 @@ class PrimitiveCreator: new_prim_indices = {} self.additional_materials = [] # In case of UDIM - self.uvmap_attribute_list = [] # Initialize here, in case we don't have any triangle primitive + self.uvmap_attribute_lists = [] + self.uvmap_attribute_list = [] # For each material # Initialize here, in case we don't have any triangle primitive materials_use_vc = None warning_already_displayed = False @@ -431,6 +432,10 @@ class PrimitiveCreator: self.uvmap_attribute_list = list( set([i['value'] for i in material_info["uv_info"].values() if 'type' in i.keys() and i['type'] == "Attribute"])) + # Check that attributes are not regular UVMaps + self.uvmap_attribute_list = [ + i for i in self.uvmap_attribute_list if i not in self.blender_mesh.uv_layers.keys()] + additional_fields = [] for attr in self.uvmap_attribute_list: if attr + str(0) not in self.dots.dtype.names: # In case user exports custom attributes, we may have it already @@ -455,6 +460,8 @@ class PrimitiveCreator: data = data.reshape(-1, 3) data = data[:, :2] elif self.blender_mesh.attributes[attr].data_type == "FLOAT2": + # This case should not happen, because we are in CORNER domain / 2D Vector, + # So this attribute is an UVMap data = np.empty(len(self.blender_mesh.loops) * 2, gltf2_blender_conversion.get_numpy_type('FLOAT2')) self.blender_mesh.attributes[attr].data.foreach_get('vector', data) @@ -550,6 +557,7 @@ class PrimitiveCreator: if len(material_info['udim_info'].keys()) == 0: new_prim_indices[material_idx] = self.prim_indices[material_idx] + self.uvmap_attribute_lists.append(self.uvmap_attribute_list) self.additional_materials.append(None) continue @@ -571,12 +579,19 @@ class PrimitiveCreator: index_uvmap = get_active_uvmap_index(self.blender_mesh) uvmap_name = "TEXCOORD_" + str(index_uvmap) else: # Attribute - uvmap_name = material_info['uv_info'][tex]['value'] + # This can be a regular UVMap, or a custom attribute + index_uvmap = self.blender_mesh.uv_layers.find(material_info['uv_info'][tex]['value']) + if index_uvmap < 0: + # This is a custom attribute + uvmap_name = material_info['uv_info'][tex]['value'] + else: + uvmap_name = "TEXCOORD_" + str(index_uvmap) all_uvmaps[tex] = uvmap_name if len(set(all_uvmaps.values())) > 1: self.export_settings['log'].warning('We are not managing this case (multiple UVMap for UDIM)') new_prim_indices[material_idx] = self.prim_indices[material_idx] + self.uvmap_attribute_lists.append(self.uvmap_attribute_list) self.additional_materials.append(None) continue @@ -632,6 +647,7 @@ class PrimitiveCreator: new_triangle_indices.append(self.prim_indices[material_idx][idx + 1]) new_triangle_indices.append(self.prim_indices[material_idx][idx + 2]) new_prim_indices[new_material_index] = np.array(new_triangle_indices, dtype=np.uint32) + self.uvmap_attribute_lists.append(self.uvmap_attribute_list) new_material_index += 1 # Now we have to create a new material for this tile @@ -763,7 +779,8 @@ class PrimitiveCreator: def primitive_creation_not_shared(self): primitives = [] - for material_idx, dot_indices in self.prim_indices.items(): + for (material_idx, dot_indices), uvmap_attribute_list in zip( + self.prim_indices.items(), self.uvmap_attribute_lists): # Extract just dots used by this primitive, deduplicate them, and # calculate indices into this deduplicated list. self.prim_dots = self.dots[dot_indices] @@ -786,7 +803,7 @@ class PrimitiveCreator: next_texcoor_idx = self.tex_coord_max uvmap_attributes_index = {} - for attr in self.uvmap_attribute_list: + for attr in uvmap_attribute_list: res = np.empty((len(self.prim_dots), 2), dtype=gltf2_blender_conversion.get_numpy_type('FLOAT2')) for i in range(2): res[:, i] = self.prim_dots[attr + str(i)] diff --git a/scripts/addons_core/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials.py b/scripts/addons_core/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials.py index c1c423c79ec..47779a30571 100644 --- a/scripts/addons_core/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials.py +++ b/scripts/addons_core/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials.py @@ -561,7 +561,12 @@ def get_final_material(mesh, blender_material, attr_indices, base_material, uvma elif v['type'] == 'Active': indices[m] = get_active_uvmap_index(mesh) elif v['type'] == "Attribute": - indices[m] = attr_indices[v['value']] + # This can be a regular UVMap or a custom attribute + i = mesh.uv_layers.find(v['value']) + if i >= 0: + indices[m] = i + else: + indices[m] = attr_indices[v['value']] # Now we have all needed indices, let's create a set that can be used for # caching, so containing all possible textures diff --git a/scripts/addons_core/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_texture_info.py b/scripts/addons_core/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_texture_info.py index c8b32ca9487..248e7b9a664 100644 --- a/scripts/addons_core/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_texture_info.py +++ b/scripts/addons_core/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_texture_info.py @@ -259,6 +259,9 @@ def __gather_texture_transform_and_tex_coord(primary_socket, export_settings): elif node and node.node and node.node.type == 'ATTRIBUTE' \ and node.node.attribute_type == "GEOMETRY" \ and node.node.attribute_name: + # If this attribute is Face Corner / 2D Vector, this is a UV map + # So we can use it as a UV map Fixed + # But this will be checked later, when we know the mesh uvmap_info['type'] = 'Attribute' uvmap_info['value'] = node.node.attribute_name