Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Selectively Hiding Instances During Import #2103

Closed
Xaldew opened this issue Jan 8, 2024 · 5 comments
Closed

Selectively Hiding Instances During Import #2103

Xaldew opened this issue Jan 8, 2024 · 5 comments

Comments

@Xaldew
Copy link

Xaldew commented Jan 8, 2024

Is your feature request related to a problem? Please describe.

Importing glTF scenes with a significant number of instances may make Blender
practically unresponsive.

Describe the solution you'd like

Blender should remain responsive after loading a glTF scene, even if it is really large or contain
a large number of instances.

Describe alternatives you've considered

This is a follow-up to issues #2101 and #2102. Essentially, to combat the Blender UI
performance problem I was having in scenes with many instances, I created the
following glTF import extension to selectively hide a percentage of all
instances. This let me import really large scenes into Blender (e.g., "San
Miguel" and "Landscape" from #2101) while still having a fully responsive Blender UI.

    class InstanceControlProperties(bpy.types.PropertyGroup):
        """Properties used by this extension."""
    
        enabled: bpy.props.BoolProperty(
            name=bl_info["name"],
            description="Enable this extension while importing glTF file.",
            default=True
        )
    
        hide_viewport: bpy.props.FloatProperty(
            name="Viewport Instances",
            description="Hide a percentage of all mesh instances from the viewport.",
            default=0.5,
            min=0.0,
            max=1.0,
            step=1.0,
        )
    
    class InstanceImporter:
        """Class responsible for modifying imported instance attributes."""
    
        def __init__(self, properties):
            """Initialize the importer."""
            self.properties = properties
            self.mesh_counts = collections.defaultdict(int)
            self.mesh_hidden = collections.defaultdict(int)
            self.mesh_totals = collections.defaultdict(int)
    
        def __del__(self):
            """Free any necessary resources."""
    
        def import_instance(self, gltf_node, bl_object, gltf):
            """Import a glTF node and change the corresponding Blender object."""
            m = gltf_node.mesh
            if not m or m < 0:
                return
            self.mesh_counts[m] += self.properties.hide_viewport
            self.mesh_totals[m] += 1
            cnt = self.mesh_counts[m]
            tot = self.mesh_totals[m]
            if tot > 1 and cnt >= 1.0:
                mesh_name = gltf.data.meshes[m].name or ""
                log(f"Hiding '{gltf_node.name}' from viewport ('{mesh_name}').")
                bl_object.hide_viewport = True
                self.mesh_counts[m] -= 1.0
                self.mesh_hidden[m] += 1
    
        def report(self):
            """Create a final report over the number of hidden instances."""
            hidden = sum(self.mesh_hidden.values())
            total = sum(self.mesh_totals.values())
            log(f"Hid {hidden} / {total} instances.")
    
    
    class glTF2ImportUserExtension:
        """Custom override class to add new attributes to imported objects."""
    
        def __init__(self):
            """Initialize the glTF2 addon."""
            from io_scene_gltf2.io.com.gltf2_io_extensions import Extension
            self.properties = bpy.context.scene.InstanceControlProperties
            self.importer = InstanceImporter(self.properties)
            self.extensions = [Extension(name=glTF_extension_name, extension={}, required=False)]
            self.gather_import_node_after_hook = self.node_post_import_hook
            self.gather_import_scene_after_nodes_hook = self.post_import_hook
    
        def node_post_import_hook(self, vnode, gltf_node, bl_object, gltf_imp):
            """Node callback hook."""
            if self.properties.enabled:
                self.importer.import_instance(gltf_node, bl_object, gltf_imp)
    
        def post_import_hook(self, gltf_scene, blender_scene, gltf_imp):
            """Post import hook."""
            if self.properties.enabled:
                self.importer.report()

(There's a bit more stuff, but this shows the gist of it)

Is this something you think would be useful to a wider group of people? Or is
there an easier way to improve the Blender UI performance when handling such
large scenes?

Admittedly, I think the problem I encountered in issue #2102 needs to be solved
first before this is actually useful.

@julienduroure
Copy link
Collaborator

Hello,
You case is quite specific, and I can't see any reason to have it for all users.
This is the purpose of user extension to change the default behavior for anyone that need it.
I suggest you to upload your extension code somewhere on internet, and share it with people that need it.

@ghost
Copy link

ghost commented Jan 10, 2024 via email

@julienduroure
Copy link
Collaborator

@Balzx : I already answer you here 3 weeks ago : #2092 (comment)

@Xaldew
Copy link
Author

Xaldew commented Jan 19, 2024

Hello, You case is quite specific, and I can't see any reason to have it for all users. This is the purpose of user extension to change the default behavior for anyone that need it. I suggest you to upload your extension code somewhere on internet, and share it with people that need it.

That makes sense to me at least, I'll have to see what I'll do with it. That said, is there any existing/other mechanism for keeping Blender responsive for scenes like this? Even if my use-case is a bit obscure, I imagine this will come back eventually as "normal" scenes grow larger

@julienduroure
Copy link
Collaborator

is there any existing/other mechanism for keeping Blender responsive for scenes like this? Even if my use-case is a bit obscure, I imagine this will come back eventually as "normal" scenes grow larger

I suggest you to ask about it in some Blender forum/chat, as this is a Blender behavior, not linked to this addon.
https://devtalk.blender.org/ or https://blender.chat are probably the best place, as your request is not a really a bug.

Let's close this ticket

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants