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

Import/export GLTF extras to node->meta and back #86183

Merged
merged 1 commit into from
Aug 30, 2024

Conversation

demolke
Copy link
Contributor

@demolke demolke commented Dec 15, 2023

This is useful for custom tagging of objects with properties (for example in Blender) and having this available in the editor for scripting.

  • Adds import logic to propagate the parsed GLTF extras all the way to the resulting Node->meta where it creates extras dictionary
  • Adds export logic to save Godot Object meta/extras dictionary into GLTF extras
  • Support nodes, meshes and materials (in GLTF sense of the words)

image

Closes: godotengine/godot-proposals#8271

@AThousandShips
Copy link
Member

Please open a proposal to discuss the need and use cases for this feature

@demolke demolke changed the title Propagate gltf extras during mesh import to node->meta Propagate gltf extras during object import to node->meta Dec 15, 2023
@demolke
Copy link
Contributor Author

demolke commented Dec 15, 2023

Thanks, looks like there is one in godotengine/godot-proposals#8271, so I'll try to reuse that one

@noidexe
Copy link
Contributor

noidexe commented Dec 16, 2023

I tested it with a sample scene and overall it works well but I noticed a few things:

  • materials don't get metadata
  • blender mesh objects with -colonly and -convcolonly lose the metadata (in my workaround I assign it to the resulting StaticBody3D)
  • metadata in mesh datablocks doesn't end in the corresponding ArrayMesh resource. It seems to be added to every MeshInstance3D using the mesh. This could create collisions if a meshinstance and its assigned mesh happen to have a custom property with the same name

@fire
Copy link
Member

fire commented Dec 16, 2023

We also worked on a similar pull request with meta here #39024 #40474

@demolke demolke force-pushed the extras branch 2 times, most recently from acfb4fc to d26cf93 Compare December 17, 2023 03:40
@demolke
Copy link
Contributor Author

demolke commented Dec 17, 2023

@noidexe I've uploaded new version

  • GLTF material extras gets set in Godot Material
  • collision node extras get set on StaticBody3D (does not support collider mesh extra CollisionShape3D)
  • MeshInstance3D gets the node extras and Mesh gets the mesh extra properties

@fire
Copy link
Member

fire commented Dec 17, 2023

Part of my goal is that meta import and export is symmetrical for gltf. Let me know if thats too much or you agree.

@demolke
Copy link
Contributor Author

demolke commented Dec 17, 2023

I was thinking the same thing. I wanted to add a test that creates a scene, serializes it to gltf, deserializes it and checks it has the right meta, but the fact the mesh re-generation is happening in ResourceImporterScene makes testing it hairy.

I also don't understand github too much, so thought I was not including it in this PR, but somehow my in-progress stuff got attached - ignore it for now, I'll try to figure out.

editor/import/resource_importer_scene.cpp Outdated Show resolved Hide resolved
editor/import/resource_importer_scene.cpp Outdated Show resolved Hide resolved
modules/gltf/gltf_document.cpp Outdated Show resolved Hide resolved
modules/gltf/tests/test_gltf_extras.h Outdated Show resolved Hide resolved
editor/import/resource_importer_scene.cpp Outdated Show resolved Hide resolved
modules/gltf/tests/data/extras.gltf Outdated Show resolved Hide resolved
modules/gltf/tests/test_gltf_extras.h Outdated Show resolved Hide resolved
@demolke
Copy link
Contributor Author

demolke commented Dec 17, 2023

I feel bad for having you review this, apologies. I meant to say in my last comment that it needs more work - especially the test change, which I did not want to attach at all.

I guess I should mark it as draft?

@demolke demolke marked this pull request as draft December 17, 2023 18:38
@demolke demolke force-pushed the extras branch 2 times, most recently from 5d47d41 to e59dac2 Compare December 18, 2023 02:22
@demolke demolke marked this pull request as ready for review December 18, 2023 02:23
@demolke
Copy link
Contributor Author

demolke commented Dec 18, 2023

I've added both import and export as discussed in #86183 (comment) and added a test it works as expected.

I haven't found any import/export testing to take inspiration from - it might be my unfamiliarity with Godot, but the test has to instantiate way more of Godot that I would like - the whole import process is extremely intertwined with Editor/Engine (and their subsequent dependencies).

It's also not possible to do this in-memory, so a number of files (.gltf, .bin, .scn) get written and subsequently read from disk during the test run, which I'm not happy about.

Please take a look, cheers

@aaronfranke
Copy link
Member

@demolke Please review the CI failure and resolve all issues until the CI turns green. Only then is it ready for human review.

@gomes042
Copy link

@lgxm3z That will not be done. Extras will not be applied automatically. We already have a structured way to import lights, it's called KHR_lights_punctual. This is the data that will be applied automatically, not extras.

Please understand that the goal here goes beyond just making Godot understand Blender, or tailoring a model in Blender for Godot. The goal is to allow any GLTF file to come from anywhere and go anywhere. So you could not only use Blender, but any tool, and those assets could not only go to Godot, but any engine. The only way to do this is to standardize what that data looks like, which is what KHR_lights_punctual and other standards are for.

I understand what you mean, but from my perspective, the glTF format provides the possibility to include extra properties, and it is the engine's job to read this format and import it in the best possible way. Godot already does things like transforming specific names into certain nodes (e.g., -vehicle to VehicleWheel3D, -convcolonly to ConvexPolygonShape3D).

https://docs.godotengine.org/en/4.1/tutorials/assets_pipeline/importing_scenes.html#create-collisions-col-convcol-colonly-convcolonly

Not only Blender but any program can export such extra properties in a glTF file. From my perspective, it would be interesting for Godot to offer the possibility of using this to its advantage since it treats each property uniquely. However, I understand that this is a sensitive decision and may diverge from the principles that Godot upholds.

@aaronfranke
Copy link
Member

aaronfranke commented Jun 26, 2024

@lgxm3z Godot already does things like transforming specific names into certain nodes (e.g., -vehicle to VehicleWheel3D, -convcolonly to ConvexPolygonShape3D).

These are existing hacks that were "grandfathered in". Node name suffixes are not as flexible, and they're not standardized across engines, and they aren't something we want to add more of in the future. They aren't actually even part of Godot's GLTF code, they exist in the scene importer in general, for all scene-imported file types including GLTF, FBX, Collada, etc. EDIT: Also note, this means it only works in the editor, the suffixes don't work for runtime imports.

@gomes042
Copy link

@lgxm3z Godot already does things like transforming specific names into certain nodes (e.g., -vehicle to VehicleWheel3D, -convcolonly to ConvexPolygonShape3D).

These are existing hacks that were "grandfathered in". Node name suffixes are not as flexible, and they're not standardized across engines, and they aren't something we want to add more of in the future. They aren't actually even part of Godot's GLTF code, they exist in the scene importer in general, for all scene-imported file types including GLTF, FBX, Collada, etc.

Got it, and thanks for the explanation. I didn't know that Godot had 'changed its view' regarding these 'hacks'. It makes a lot of sense not to continue with these practices. Initially, I saw potential in this type of solution, but now I can see the problems it could cause and how certain features could be difficult to remove later.

@warcaninos
Copy link

Sorry i'm a beginner in all of this (github/source code) i want to try out this feature so i should probably compile godot from source but i still have to wait until it's merged right ?

@AThousandShips
Copy link
Member

See here for instructions

@lyuma
Copy link
Contributor

lyuma commented Aug 25, 2024

I already reviewed this, but Aaron asked me to take another look. I think it looks good. I'd be okay merging this in its current form and iterating on it if needed.

Some feedback on @lgxm3z 's comment.

One for enabling and disabling the copying of metadata from glTF files to nodes, materials

It's not that important: I think if the data is in the file it's okay to import it; and if it's in extras it's okay to export it.

Another for automatically identifying properties recognized by Godot and applying them

I would rather work on this as extensions: I see some value in supporting additional engine functionality, but it's also non-obvious behavior and given that most properties are supported as part of the gltf spec, it will be confusing to users which properties need to be specified using extras.

nodes, materials, etc

Finally, I'm confused which objects support extras. In glTF, just about anything can have extras. In this PR, it's implemented for all types of nodes, but only meshes and material resources? Should we also add it to skins, animations and textures? Or should we add it only to nodes, not resources?

@aaronfranke
Copy link
Member

Should we also add it to skins, animations and textures?

In general I think it makes sense to import/export extras everywhere, but it doesn't need to happen all at once. If we miss anything, we can add it in later in another PR. So we could add it in this PR, or not, I'm good either way.

@akien-mga
Copy link
Member

Needs rebase, I tried building it locally and it failed compiling the tests with:

In file included from ./core/templates/local_vector.h:35,
                 from ./core/object/message_queue.h:36,
                 from ./core/object/object.h:35,
                 from ./core/variant/binder_common.h:35,
                 from ./core/object/method_bind.h:34,
                 from ./core/object/class_db.h:34,
                 from ./editor/editor_paths.h:34,
                 from tests/test_main.cpp:36:
./modules/gltf/tests/test_gltf_extras.h: In function 'Node* TestGltfExtras::_gltf_export_then_import(Node*, String&)':
./modules/gltf/tests/test_gltf_extras.h:62: error: no matching function for call to 'ResourceImporterScene::ResourceImporterScene(bool, bool)'
   62 |         Ref<ResourceImporterScene> import_scene = memnew(ResourceImporterScene(false, true));
./core/os/memory.h:125:51: note: in definition of macro 'memnew'
  125 | #define memnew(m_class) _post_initialize(new ("") m_class)
      |                                                   ^~~~~~~
In file included from ./modules/gltf/tests/test_gltf_extras.h:39,
                 from ./modules/modules_tests.gen.h:42,
                 from tests/test_main.cpp:162:
./editor/import/3d/resource_importer_scene.h:309: note: candidate: 'ResourceImporterScene::ResourceImporterScene(const String&, bool)'
  309 |         ResourceImporterScene(const String &p_scene_import_type = "PackedScene", bool p_singleton = false);
./editor/import/3d/resource_importer_scene.h:309: note:   no known conversion for argument 1 from 'bool' to 'const String&'

(implies building with scons tests=yes)

This is useful for custom tagging of objects with properties (for example in Blender) and having this available in the editor for scripting.

- Adds import logic to propagate the parsed GLTF extras all the way to the resulting Node->meta
- Adds export logic to save Godot Object meta into GLTF extras
- Supports `nodes`, `meshes` and `materials` (in GLTF sense of the words)
@demolke
Copy link
Contributor Author

demolke commented Aug 29, 2024

Needs rebase, I tried building it locally and it failed compiling the tests with:

Done, thanks for taking a look.

Finally, I'm confused which objects support extras. In glTF, just about anything can have extras. In this PR, it's implemented for all types of nodes, but only meshes and material resources? Should we also add it to skins, animations and textures? Or should we add it only to nodes, not resources?

I think eventually yes, all the resources should have extras supported - adding it to node vs adding it to mesh (or other resource) are distinctly different use cases. You could put generic information on the "enemy" mesh re-used everywhere and have specific extras on the node.

Once this get submitted I would like to get consensus on the bones PR #87150 and then I can look into the other types.

@akien-mga akien-mga merged commit d538549 into godotengine:master Aug 30, 2024
19 checks passed
@akien-mga
Copy link
Member

Thanks!

@demolke demolke deleted the extras branch August 30, 2024 19:11
@warcaninos
Copy link

Great work i've tested it and it just works™ i just have one question, when i import a .blend there is a root node that is made with the name of the .blend, what is this root node in blender ?
I've tried adding custom properties to the : workspace, collection, scene and none of those correspond to the root node.

@fire
Copy link
Member

fire commented Sep 14, 2024

we force the name of the blend file into the root node name

@warcaninos
Copy link

So it does not correspond to anything on the blender side ? Then i should open a proposal to at least have the root node inherit the custom properties of the scene, because in an exported gltf you already have this data available.

@aaronfranke
Copy link
Member

@warcaninos That root node corresponds to the Blender scene itself. Blender scenes allow multiple root nodes, which is incompatible with Godot scenes that have exactly one root node.

The "proper" fix for this is to add a feature to Blender to allow it to optionally flag scenes as having a single root node. This is implemented in Godot here, it just needs Blender to add support for it. Meaning, you should open a proposal to Blender, not a proposal to Godot.

@warcaninos
Copy link

Unless there is something i missunderstood, when you export a gltf scene from godot it doesn't get the metadata as extra.

@aaronfranke
Copy link
Member

@warcaninos It only gets metadata named extras, not all metadata.

@warcaninos
Copy link

I've tried metadata with the name "extras" wich automatically get called "Extras" with values of type
string: test - Does not show up in the gltf
dictionary: string: Node, string: MeshInstance3D; Does not show up in the gltf
Array of dictionary with the same dictionary up here and it still does not show up in the gltf.
I've searched in the documentation but since this is a feature that is still in a dev branch there is nothing.

@aaronfranke
Copy link
Member

@warcaninos Are you using the master branch of Godot (what will become Godot 4.4)? It's not in Godot 4.3.

@warcaninos
Copy link

@aaronfranke I'm using 4.4 dev2 import extras does work so i assume exporting should work too.

@warcaninos
Copy link

Should i open an issue about this ?

@aaronfranke
Copy link
Member

@warcaninos I can't reproduce the problem. The scene in Godot:

Screenshot 2024-10-18 at 12 48 11 PM

The exported file (formatted with Prettier):

Screenshot 2024-10-18 at 12 49 40 PM

@warcaninos
Copy link

I switched to 4.4 dev 3 and i do not have this problem anymore. Thanks for your time.

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

Successfully merging this pull request may close these issues.

Import custom glTF properties as node metadata