godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.16k stars 97 forks source link

Implement a way to import a glTF scene from string/byte array #3270

Closed RedSmarty closed 2 years ago

RedSmarty commented 3 years ago

Describe the project you are working on

I am working on a 3d game that supports heavy modding

Describe the problem or limitation you are having in your project

As heavy modding support is required, I am using the new PackedSceneGLTF to import 3d models. This approach, however, requires you to have a model accessible from file path.

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

I would like a feature that allows you to pass in a string (for gltf) or a byte array (for glb) to PackedSceneGLTF so that I can embed models in a binary file and pass the string/binary data of embedded model. This is also required to encrypt the models, as you can't load encrypted models directly, so I have to pass in a decrypted string.

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

It will just accept a string instead of a file path and parse that. PackSceneGltf.import_gltf_scene(String contents, int flags=0, float bake_fps=1000.0, GLTFState state=null)

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

I don't think its possible without modifying PackedSceneGLTF code itself.

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

There is no particular reason, but it would help people like me who want to make their game moddable and encrypt/protect their mods.

Calinou commented 3 years ago

cc @fire

fire commented 3 years ago

See https://github.com/godotengine/godot/pull/52501 where the general design is:

var gstate : GLTFState = GLTFState.new()
var gltf : GLTFDocument = GLTFDocument.new()
print(path);

var raw_f = File.new()
if raw_f.open(path, File.READ) != OK:
    return FAILED
var buffer : PackedByteArray = raw_f.get_buffer(raw_f.get_length())
var root_node : Node = gltf.import_buffer(buffer, 0, 30.0, gstate)

Edited for api changes.

RedSmarty commented 3 years ago

Thanks for taking your time to help me @fire and @Calinou. I have a few questions :-

  1. It works in runtime, right?
  2. How do I achieve the same result in gdnative (cpp)?
  3. What does pack scene method do?
Calinou commented 3 years ago

Godot 3.x does not support loading glTF scenes in exported projects, as the module is only compiled in editor builds. I don't think this will change in 4.0, so you have to use a custom build that enables glTF import functionality in export template binaries and make it not rely on the editor import system somehow. See https://github.com/godotengine/godot/pull/51383.

The above remark also applies to other 3D scene formats supported by Godot (Collada, FBX, OBJ). For OBJ however, you can find a few OBJ loaders written in GDScript on GitHub.

fire commented 3 years ago

For Godot 3 there's also import from regular gltf / glb. https://github.com/V-Sekai/godot-vrm/tree/godot3/addons/godot_gltf However, your question is not about runtime import but import from a buffer.

RedSmarty commented 3 years ago

Thanks for your time @fire and @Calinou , but I still have a few questions, do you by chance have discord, or any other social media/chat group where I can clarify if you don't mind?

fire commented 3 years ago

You probably want to discuss in #asset-pipeline @ https://chat.godotengine.org. I'm on discord too.

fire commented 3 years ago

Superseded by: https://github.com/godotengine/godot-proposals/issues/3273.

fire commented 2 years ago

Fixed by https://github.com/godotengine/godot/pull/52541.