diff options
author | Julien Duroure <julien.duroure@gmail.com> | 2021-02-25 21:08:53 +0300 |
---|---|---|
committer | Julien Duroure <julien.duroure@gmail.com> | 2021-02-25 21:08:53 +0300 |
commit | 8d24537a6e9c6e39f7d18d1bf3f4d162a85edd11 (patch) | |
tree | fb99c9635d5f902e4fb5b2853a143d0c2b6f8882 | |
parent | 37af7e130b99865575f1fa2315ef806f815b0f42 (diff) |
gltf exporter: new feature: export 'Loose Points' and 'Loose Edges'
-rwxr-xr-x | io_scene_gltf2/__init__.py | 41 | ||||
-rwxr-xr-x | io_scene_gltf2/blender/exp/gltf2_blender_extract.py | 86 | ||||
-rwxr-xr-x | io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives.py | 13 | ||||
-rw-r--r-- | io_scene_gltf2/io/exp/gltf2_io_draco_compression_extension.py | 6 |
4 files changed, 134 insertions, 12 deletions
diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py index 8d3ac965..352affa3 100755 --- a/io_scene_gltf2/__init__.py +++ b/io_scene_gltf2/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2018-2019 The glTF-Blender-IO authors. +# Copyright 2018-2021 The glTF-Blender-IO authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,7 +15,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": (1, 6, 4), + "version": (1, 6, 5), 'blender': (2, 91, 0), 'location': 'File > Import-Export', 'description': 'Import-Export as glTF 2.0', @@ -263,6 +263,22 @@ class ExportGLTF2_Base: default=True ) + use_mesh_edges: BoolProperty( + name='Loose Edges', + description=( + 'Export loose edges as lines, using the material from the first material slot' + ), + default=False, + ) + + use_mesh_vertices: BoolProperty( + name='Loose Points', + description=( + 'Export loose points as glTF points, using the material from the first material slot' + ), + default=False, + ) + export_cameras: BoolProperty( name='Cameras', description='Export cameras', @@ -444,10 +460,18 @@ class ExportGLTF2_Base: return ExportHelper.invoke(self, context, event) def save_settings(self, context): - # find all export_ props + # find all props to save + exceptional = [ + # options that don't start with 'export_' + 'use_selection', + 'use_mesh_edges', + 'use_mesh_vertices', + ] all_props = self.properties - export_props = {x: getattr(self, x) for x in dir(all_props) - if (x.startswith("export_") or x == "use_selection") and all_props.get(x) is not None} + export_props = { + x: getattr(self, x) for x in dir(all_props) + if (x.startswith("export_") or x in exceptional) and all_props.get(x) is not None + } context.scene[self.scene_key] = export_props @@ -479,6 +503,8 @@ class ExportGLTF2_Base: export_settings['gltf_texcoords'] = self.export_texcoords export_settings['gltf_normals'] = self.export_normals export_settings['gltf_tangents'] = self.export_tangents and self.export_normals + export_settings['gltf_loose_edges'] = self.use_mesh_edges + export_settings['gltf_loose_points'] = self.use_mesh_vertices if self.is_draco_available: export_settings['gltf_draco_mesh_compression'] = self.export_draco_mesh_compression_enable @@ -692,6 +718,11 @@ class GLTF_PT_export_geometry(bpy.types.Panel): col.active = operator.export_normals col.prop(operator, 'export_tangents') layout.prop(operator, 'export_colors') + + col = layout.column() + col.prop(operator, 'use_mesh_edges') + col.prop(operator, 'use_mesh_vertices') + layout.prop(operator, 'export_materials') col = layout.column() col.active = operator.export_materials == "EXPORT" diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_extract.py b/io_scene_gltf2/blender/exp/gltf2_blender_extract.py index 5a78ab04..0492c901 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_extract.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_extract.py @@ -1,4 +1,4 @@ -# Copyright 2018-2019 The glTF-Blender-IO authors. +# Copyright 2018-2021 The glTF-Blender-IO authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -283,6 +283,90 @@ def extract_primitives(glTF, blender_mesh, library, blender_object, blender_vert 'material': material_idx, }) + if export_settings['gltf_loose_edges']: + # Find loose edges + loose_edges = [e for e in blender_mesh.edges if e.is_loose] + blender_idxs = [vi for e in loose_edges for vi in e.vertices] + + if blender_idxs: + # Export one glTF vert per unique Blender vert in a loose edge + blender_idxs = np.array(blender_idxs, dtype=np.uint32) + blender_idxs, indices = np.unique(blender_idxs, return_inverse=True) + + attributes = {} + + attributes['POSITION'] = locs[blender_idxs] + + for morph_i, vs in enumerate(morph_locs): + attributes['MORPH_POSITION_%d' % morph_i] = vs[blender_idxs] + + if skin: + joints = [[] for _ in range(num_joint_sets)] + weights = [[] for _ in range(num_joint_sets)] + + for vi in blender_idxs: + bones = vert_bones[vi] + for j in range(0, 4 * num_joint_sets): + if j < len(bones): + joint, weight = bones[j] + else: + joint, weight = 0, 0.0 + joints[j//4].append(joint) + weights[j//4].append(weight) + + for i, (js, ws) in enumerate(zip(joints, weights)): + attributes['JOINTS_%d' % i] = js + attributes['WEIGHTS_%d' % i] = ws + + primitives.append({ + 'attributes': attributes, + 'indices': indices, + 'mode': 1, # LINES + 'material': 0, + }) + + if export_settings['gltf_loose_points']: + # Find loose points + verts_in_edge = set(vi for e in blender_mesh.edges for vi in e.vertices) + blender_idxs = [ + vi for vi, _ in enumerate(blender_mesh.vertices) + if vi not in verts_in_edge + ] + + if blender_idxs: + blender_idxs = np.array(blender_idxs, dtype=np.uint32) + + attributes = {} + + attributes['POSITION'] = locs[blender_idxs] + + for morph_i, vs in enumerate(morph_locs): + attributes['MORPH_POSITION_%d' % morph_i] = vs[blender_idxs] + + if skin: + joints = [[] for _ in range(num_joint_sets)] + weights = [[] for _ in range(num_joint_sets)] + + for vi in blender_idxs: + bones = vert_bones[vi] + for j in range(0, 4 * num_joint_sets): + if j < len(bones): + joint, weight = bones[j] + else: + joint, weight = 0, 0.0 + joints[j//4].append(joint) + weights[j//4].append(weight) + + for i, (js, ws) in enumerate(zip(joints, weights)): + attributes['JOINTS_%d' % i] = js + attributes['WEIGHTS_%d' % i] = ws + + primitives.append({ + 'attributes': attributes, + 'mode': 0, # POINTS + 'material': 0, + }) + print_console('INFO', 'Primitives created: %d' % len(primitives)) return primitives diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives.py index 8678db83..9f9b949a 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives.py @@ -1,4 +1,4 @@ -# Copyright 2018-2019 The glTF-Blender-IO authors. +# Copyright 2018-2021 The glTF-Blender-IO authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -54,7 +54,7 @@ def gather_primitives( material_idx = internal_primitive['material'] material = None - if export_settings['gltf_materials'] == "EXPORT": + if export_settings['gltf_materials'] == "EXPORT" and material_idx is not None: blender_material = None if material_names: i = material_idx if material_idx < len(material_names) else -1 @@ -73,7 +73,7 @@ def gather_primitives( extras=None, indices=internal_primitive['indices'], material=material, - mode=None, + mode=internal_primitive['mode'], targets=internal_primitive['targets'] ) primitives.append(primitive) @@ -101,7 +101,8 @@ def __gather_cache_primitives( primitive = { "attributes": __gather_attributes(internal_primitive, blender_mesh, modifiers, export_settings), "indices": __gather_indices(internal_primitive, blender_mesh, modifiers, export_settings), - "material": internal_primitive['material'], + "mode": internal_primitive.get('mode'), + "material": internal_primitive.get('material'), "targets": __gather_targets(internal_primitive, blender_mesh, modifiers, export_settings) } primitives.append(primitive) @@ -109,7 +110,9 @@ def __gather_cache_primitives( return primitives def __gather_indices(blender_primitive, blender_mesh, modifiers, export_settings): - indices = blender_primitive['indices'] + indices = blender_primitive.get('indices') + if indices is None: + return None # NOTE: Values used by some graphics APIs as "primitive restart" values are disallowed. # Specifically, the values 65535 (in UINT16) and 4294967295 (in UINT32) cannot be used as indices. diff --git a/io_scene_gltf2/io/exp/gltf2_io_draco_compression_extension.py b/io_scene_gltf2/io/exp/gltf2_io_draco_compression_extension.py index 0c6bfaf4..74dbfa03 100644 --- a/io_scene_gltf2/io/exp/gltf2_io_draco_compression_extension.py +++ b/io_scene_gltf2/io/exp/gltf2_io_draco_compression_extension.py @@ -1,4 +1,4 @@ -# Copyright 2018-2019 The glTF-Blender-IO authors. +# Copyright 2018-2021 The glTF-Blender-IO authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -85,6 +85,10 @@ def __encode_primitive(primitive, dll, export_settings): attributes = primitive.attributes indices = primitive.indices + # Only do TRIANGLES primitives + if primitive.mode not in [None, 4]: + return + if 'POSITION' not in attributes: print_console('WARNING', 'Draco encoder: Primitive without positions encountered. Skipping.') return |