From 2fcac97522dee91d8f444055b9a996fea7d36e40 Mon Sep 17 00:00:00 2001 From: Julien Duroure Date: Wed, 13 Jul 2022 12:15:28 +0200 Subject: glTF exporter: Manage all 4 types of Vertex Colors (corner/point - byte/float) --- io_scene_gltf2/__init__.py | 2 +- .../blender/exp/gltf2_blender_extract.py | 43 ++++++++++++++++------ .../gltf2_blender_gather_primitive_attributes.py | 20 ++++++---- 3 files changed, 46 insertions(+), 19 deletions(-) diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py index be8aa8ed..98210e82 100755 --- a/io_scene_gltf2/__init__.py +++ b/io_scene_gltf2/__init__.py @@ -4,7 +4,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": (3, 3, 16), + "version": (3, 3, 17), 'blender': (3, 3, 0), 'location': 'File > Import-Export', 'description': 'Import-Export as glTF 2.0', diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_extract.py b/io_scene_gltf2/blender/exp/gltf2_blender_extract.py index d4f34126..93947acb 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_extract.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_extract.py @@ -39,6 +39,18 @@ def extract_primitives(blender_mesh, uuid_for_skined_data, blender_vertex_groups if export_settings[gltf2_blender_export_keys.COLORS]: color_max = len(blender_mesh.vertex_colors) + colors_attributes = [] + rendered_color_idx = blender_mesh.attributes.render_color_index + + if color_max > 0: + colors_attributes.append(rendered_color_idx) + # Then find other ones + colors_attributes.extend([ + i for i in range(len(blender_mesh.color_attributes)) if i != rendered_color_idx \ + and blender_mesh.vertex_colors.find(blender_mesh.color_attributes[i].name) != -1 + ]) + + armature = None skin = None if blender_vertex_groups and export_settings[gltf2_blender_export_keys.SKINS]: @@ -110,7 +122,7 @@ def extract_primitives(blender_mesh, uuid_for_skined_data, blender_vertex_groups dot_fields += [('tx', np.float32), ('ty', np.float32), ('tz', np.float32), ('tw', np.float32)] for uv_i in range(tex_coord_max): dot_fields += [('uv%dx' % uv_i, np.float32), ('uv%dy' % uv_i, np.float32)] - for col_i in range(color_max): + for col_i, _ in enumerate(colors_attributes): dot_fields += [ ('color%dr' % col_i, np.float32), ('color%dg' % col_i, np.float32), @@ -163,8 +175,12 @@ def extract_primitives(blender_mesh, uuid_for_skined_data, blender_vertex_groups dots['uv%dy' % uv_i] = uvs[:, 1] del uvs - for col_i in range(color_max): - colors = __get_colors(blender_mesh, col_i) + colors_types = [] + for col_i, blender_col_i in enumerate(colors_attributes): + colors, colors_type, domain = __get_colors(blender_mesh, col_i, blender_col_i) + if domain == "POINT": + colors = colors[dots['vertex_index']] + colors_types.append(colors_type) dots['color%dr' % col_i] = colors[:, 0] dots['color%dg' % col_i] = colors[:, 1] dots['color%db' % col_i] = colors[:, 2] @@ -251,13 +267,16 @@ def extract_primitives(blender_mesh, uuid_for_skined_data, blender_vertex_groups uvs[:, 1] = prim_dots['uv%dy' % tex_coord_i] attributes['TEXCOORD_%d' % tex_coord_i] = uvs - for color_i in range(color_max): + for color_i, _ in enumerate(colors_attributes): colors = np.empty((len(prim_dots), 4), dtype=np.float32) colors[:, 0] = prim_dots['color%dr' % color_i] colors[:, 1] = prim_dots['color%dg' % color_i] colors[:, 2] = prim_dots['color%db' % color_i] colors[:, 3] = prim_dots['color%da' % color_i] - attributes['COLOR_%d' % color_i] = colors + attributes['COLOR_%d' % color_i] = {} + attributes['COLOR_%d' % color_i]["data"] = colors + + attributes['COLOR_%d' % color_i]["norm"] = colors_types[color_i] == "BYTE_COLOR" if skin: joints = [[] for _ in range(num_joint_sets)] @@ -525,13 +544,15 @@ def __get_uvs(blender_mesh, uv_i): return uvs -def __get_colors(blender_mesh, color_i): - colors = np.empty(len(blender_mesh.loops) * 4, dtype=np.float32) - layer = blender_mesh.vertex_colors[color_i] - blender_mesh.color_attributes[layer.name].data.foreach_get('color', colors) - colors = colors.reshape(len(blender_mesh.loops), 4) +def __get_colors(blender_mesh, color_i, blender_color_i): + if blender_mesh.color_attributes[blender_color_i].domain == "POINT": + colors = np.empty(len(blender_mesh.vertices) * 4, dtype=np.float32) #POINT + else: + colors = np.empty(len(blender_mesh.loops) * 4, dtype=np.float32) #CORNER + blender_mesh.color_attributes[blender_color_i].data.foreach_get('color', colors) + colors = colors.reshape(-1, 4) # colors are already linear, no need to switch color space - return colors + return colors, blender_mesh.color_attributes[blender_color_i].data_type, blender_mesh.color_attributes[blender_color_i].domain def __get_bone_data(blender_mesh, skin, blender_vertex_groups): diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitive_attributes.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitive_attributes.py index 72f0268c..f28a1f10 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitive_attributes.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitive_attributes.py @@ -124,28 +124,34 @@ def __gather_colors(blender_primitive, export_settings): color_index = 0 color_id = 'COLOR_' + str(color_index) while blender_primitive["attributes"].get(color_id) is not None: - colors = blender_primitive["attributes"][color_id] + colors = blender_primitive["attributes"][color_id]["data"] if type(colors) is not np.ndarray: colors = np.array(colors, dtype=np.float32) colors = colors.reshape(len(colors) // 4, 4) - # Convert to normalized ushorts - colors *= 65535 - colors += 0.5 # bias for rounding - colors = colors.astype(np.uint16) + if blender_primitive["attributes"][color_id]["norm"] is True: + comp_type = gltf2_io_constants.ComponentType.UnsignedShort + + # Convert to normalized ushorts + colors *= 65535 + colors += 0.5 # bias for rounding + colors = colors.astype(np.uint16) + + else: + comp_type = gltf2_io_constants.ComponentType.Float attributes[color_id] = gltf2_io.Accessor( buffer_view=gltf2_io_binary_data.BinaryData(colors.tobytes()), byte_offset=None, - component_type=gltf2_io_constants.ComponentType.UnsignedShort, + component_type=comp_type, count=len(colors), extensions=None, extras=None, max=None, min=None, name=None, - normalized=True, + normalized=blender_primitive["attributes"][color_id]["norm"], sparse=None, type=gltf2_io_constants.DataType.Vec4, ) -- cgit v1.2.3