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

glTF - Replace modified scene tree parts with placeholders on re-import #11356

Open
RPicster opened this issue Dec 15, 2024 · 3 comments
Open

Comments

@RPicster
Copy link

Describe the project you are working on

PVKK: Planetenverteidigungskanonenkommandant, Dome Keeper, Engraving and others.

Describe the problem or limitation you are having in your project

This proposal contains a big wall of text to explain where my thoughts are coming from, so buckle your seat belts ;)
After talking with different people, I came to the conclusion that Godot is in a bad spot right now when it comes to a recommended workflow for importing 3D assets.
Almost every variant of working with imported gltf files has a flaw in one way or another.

The way that I would prefer to work with gltf files boils down to one of two variants:

    1. To be used directly as a mesh
    1. To be used in a way that respects / uses it's structure / data

Both points are flawed in one way or another right now from my point of view.

1) To be used directly as a mesh

Let's start with the simpler challenge in 1) that was also already discussed and can be solved with scripts.

I many scenarios, you want to import just a mesh. In many scenarios this could be solved via using obj, but not in all (requiring UV2 e.g.). You could also want to make use of the nice additional features a gltf import brings (autoLOD, materials, etc).
This is already discussed in #7494 and there is awareness for this. It can also be solved with a small post import script, here is a very straight forward example:

@tool
extends EditorScenePostImport

func _post_import(scene):
    iterate(scene)
    if first_mesh_instance:
        return first_mesh_instance
    else:
        return scene

var first_mesh_instance : MeshInstance3D
func iterate(node):
    if node != null:
        if node is MeshInstance3D and not first_mesh_instance:
            first_mesh_instance = node
            return
        for child in node.get_children():
            iterate(child)

2) To be used in a way that respects / uses it's structure / data

Let's say you have a gltf file that has a certain structure and/or additional information like an animations and you want to use this in Godot.
There are essentially two ways of handling this gracefully and one way that is a bit ugly.

  • 2.1) Place the imported gltf inside a new Scene and "make local"
  • 2.2) Place the imported gltf inside a new Scene and enable "editable children"
  • 2.3) Create an inherited Scene from the imported gltf

2.1) Place the imported gltf inside a new Scene and "make local"

This is the option that is reliable, but ugly. It has many, many flaws, some of which can be negated (meshes are being made local to the scene as text -> can be negated by saving each mesh as a resource in the import dialogue).
It will lose the link to the gltf file but has one advantage: It is reliable. No re-import of the gltf will alter the structure of this scene. It's still not a way that I would recommend.
This could be improved by #8750 .

2.2) Place the imported gltf inside a new Scene and enable "editable children"

To my knowledge this has the same problems and challenges compared to 2.3, so I will continue below.

2.3) Create an inherited Scene from the imported gltf

While this is generally a nice approach as the link to the gltf data is fully kept (re-importing the gltf will update meshes e.g.), it also has flaws.
The biggest problem I personally encounter and gave me a lot of headaches is that changing the node structure can result in a loss of work.
Let's say you have the following gltf imported:
Image

I want to modify the scene and add some new nodes:
Image

Next, I am back in Blender, renaming an object and changing the parenting of another object. Then I export and overwrite the old gltf. back in Godot, the following will happen:
Image

This is not great, but at least the nodes are still there. The problem is when I can't even remember where those new Nodes were attached to. It can even lead to nodes being renamed:
Image

Result after reimporting:
Image

Let's look into another example that is even more problematic. Changing the nodes properties and then re-importing.
Image
Image

I added three new Material Overrides, after changing things in Blender and re-importing:
Image
Image

These three materials are gone 😥

Of course one could argue that this is to be expected, but as it is, it makes it very hard to recommend this workflow as it connects logic with scene structure/naming from outside Godot. It's very prone to break things and has done so in many projects I worked on.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

I think some of the problems could be solved with creating placeholder nodes if a relevant discrepancy was detected between the node structure in the scene tree and the new structure.
I don't know how it could be technically solved, but to give an example:
This is the scene the user made:
Image

Now, "SomeNode" is renamed to "SomeRenamedNode" in Blender and re-imported in Godot:
Image

A placeholder/mock version of the old Node was created by Godot, containing the original children in the same position in the scene tree as it was before.

This mock node should contain properties that were modified by the user, e.g. ,aterial overrides, layers or settings like visibility ranges.
This would offer the user an opportunity to copy these properties if they want to.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

see above

If this enhancement will not be used often, can it be worked around with a few lines of script?

Unfortunately, this can't be solved via a script to my knowledge.

Is there a reason why this should be core and not an add-on in the asset library?

It's a core problem to working with 3D assets right now.

@ATBrackeys
Copy link

Just wanted to give my 2 cents; I've been exploring 3D import workflows in Godot for a video I'm working on and have had the pleasure of having discussions with @RPicster about this.

It seems like discussions about the import pipeline is currently a bit spread out, but I think the description of this issue nicely summarizes the problems I've run into.

The documentation is also currently lacking on this subject. This is probably because it's hard to recommend a standard/common workflow since all of them currently have fairly large drawbacks. Of course it can be argued that the official docs shouldn't recommend a particular workflow, but to this I say:

A) To my knowledge it doesn't currently show any example workflows and highlight pros/cons.
B) Not recommending any workflows means that new users will stumble into one by accident.

Combine this with the fact that the UI is currently structured in such a way that most users a prompted with this modal window after trying to open a .gltf file:

Image

And I think we have a situation where a lot of new users are (unintentionally?) lead into a workflow based on inheriting a scene from the gltf and using that as a base.

The solution proposed by @RPicster here (using placeholder nodes to resolve discrepancies) would definitely improve the stability of this workflow and I think that as long as inherited scenes are part of the engine, it makes complete sense from a usability point of view.

I would however - and I know this is not the perfect place but seeing as its topical I will argue it here - also use the opportunity to talk about whether Godot should be leading people to this workflow or if something could/should be done (with documentation or UI) to promote other workflows.

So to perhaps start that discussion I've created an overview of the three workflows with my quick thoughts on pros/cons:

1) Inherited scenes (as discussed)

Pros:

  • Very common already.
  • Quick to iterate on.

Cons:

  • Currently unstable.
  • Rigid hierarchy.
  • Promotes unclear separation of visuals and logic.

2) Nested scenes

Pros:

  • Also common.
  • Safe.
  • Clear separation.
  • Quick to iterate on.

Cons:

3) Make local

Pros:

  • Very flexible.
  • Reduces node clutter.
  • Clear separation.
  • Could be even more performant(?)

Cons:


I'm still new with Godot and I am sure I have made many wrong assumptions, please correct me! Still, I wanted to just offer my perspective, since I do have some experience working with new users and teaching this sort of stuff to beginners and I thought that as easy Godot is to get started with, this is currently in a weird in-between place where fairly technical considerations must be had before deciding on a workflow.

TLDR; Thanks @RPicster for opening the issue. Would be great to see this solution implemented. Hope it can lead to a broader discussion on how best to work with imported 3D assets in Godot and how to let beginners know what's what.

PS: I'm new here, be nice to me ;)

@aXu-AP
Copy link

aXu-AP commented Dec 17, 2024

I think the editor could ask the user to relocate the nodes that went missing (with options for add placeholder and delete) 👀
In case you adjusted multiple properties of some node, it's still very cumbersome and error-prone to copy those by hand.
However, I think this proposal would definitely be a step to the right direction, and fairly easy to implement, I reckon.

@ATBrackeys I think nudging users toward specific workflow and make that workflow as good as possible would be in line with Godot's way of doing things as I understand it: workflows > absolute flexibility.

@RPicster
Copy link
Author

@ATBrackeys I think nudging users toward specific workflow and make that workflow as good as possible would be in line with Godot's way of doing things as I understand it: workflows > absolute flexibility.

I think this is a bit against what I heard of the Godot mindset from Juan at the GodotCon which would be that Godot offers many ways to achieve something and that different ways should work.

In this case I think I would fully agree. It could make sense to choose one way that covers 95% of the usecases and make it really good - trying to remove all pitfalls that make it not really usable in a bigger project

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

No branches or pull requests

4 participants