Yes, src:// instead of res:// is my fault, but the source of the problem was that the scenes directory didn’t exist in my file system. I thought that Godot should create it, but not… (Contributors, fix it plz)
So I made the working example with file saving
var editorRootScene
var isModelLoading = false
func _ready():
editorRootScene = plugin.get_editor_interface().get_edited_scene_root()
func _process(delta):
if isModelLoading and not editor_fs.is_scanning():
isModelLoading = false
self.loadModel()
func downloadModelSuccess(result, response_code, headers, body):
var file = FileAccess.open("res://scenes/model.glb", FileAccess.WRITE)
if file == null:
printt("FileAccess error: ", FileAccess.get_open_error())
file.store_buffer(body)
file.close()
editor_fs.scan_sources() # or scan()?
isModelLoading = true
func loadModel():
var glb_scene:PackedScene = load("res://scenes/model.glb")
var glb_model:Node3D = glb_scene.instantiate()
editorRootScene.add_child(glb_model)
glb_model.set_owner(editorRootScene)
glb_model.translate(Vector3(0.0, 0.0, -2.0))
...
And a few more questions:
Which is preferable in my case scan or scan_sources for importing my model? Maybe there is some better way to import assets?
Why do I need GLTFDocument, GLTFState from article above if I can implement loadModel other way (see the example)? Or it is only for loading without file saving (using appenf_from_buffer)?
Can we speed up the import of assets? I’m not trying to use appenf_from_buffer yet. Does it faster?
var doc = GLTFDocument.new()
var state = GLTFState.new()
var error = body == null ? doc.append_from_file("res://scenes/model.glb", state) : doc.append_from_buffer(body, "", state)
if error == OK:
for gltfMesh in state.get_meshes():
var glb_model = MeshInstance3D.new()
glb_model.mesh = gltfMesh.get_mesh().get_mesh()
editorRootScene.add_child(glb_model)
glb_model.set_owner(editorRootScene)
If I have body == null and imported glb-file inside the res://scenes/model.glb it works correct and I see the textured MeshInstance3D inside my scene.
If I use model data inside the body I see the mesh only without textures etc. Why append_from_file and append_from_buffer work differently?
Upd. Some how I knew that the ImporterMeshInstance3D (which is in the scene from the GLTFDocument) is replaced by the MeshInstance3D during the import process. But I don’t have an import process in case of reading GLB data from RAM. So how do you convert ImporterMeshInstance3D to MeshInstance3D? I’m able to use the mesh, but I’m losing materials, etc.
Short PoC for several ways how to load models from the internet.
Common code:
var editor_fs = EditorInterface.get_resource_filesystem()
var editorRootScene
var isModelLoading = false
func _ready():
editorRootScene = plugin.get_editor_interface().get_edited_scene_root()
# Download model by HTTP and run `downloadModelSuccess` if OK
func downloadModel():
var http_request = HTTPRequest.new()
add_child(http_request)
http_request.request_completed.connect(self.downloadModelSuccess)
var error = http_request.request("https://mysite/mymodel.glb")
if error != OK:
push_error("An error occurred in the HTTP request.")
func placeModelToEditorScene(model):
editorRootScene.add_child(model)
model.set_owner(editorRootScene)
model.translate(Vector3(0.0, 0.0, -1.0))
Using the model through the file (with “(Re) Import assets” progress dialog)
func _process(delta):
if isModelLoading and not editor_fs.is_scanning():
isModelLoading = false
self.loadModelFromFileAsScene()
#self.loadModelFromFileByGLTFDocument() # Use it instead of loadModelFromFileAsScene if you want to use GLTFDocument way
func downloadModelSuccess(result, response_code, headers, body):
extractModelToFile(body)
func extractModelToFile(body):
var file = FileAccess.open("res://scenes/model.glb", FileAccess.WRITE)
if file == null:
printt("FileAccess error: ", FileAccess.get_open_error())
file.store_buffer(body)
file.close()
editor_fs.scan_sources() # or scan()? # Extract textures
isModelLoading = true
func loadModelFromFileAsScene():
var glb_scene:PackedScene = load("res://scenes/model.glb")
var glb_model:Node3D = glb_scene.instantiate()
self.placeModelToEditorScene(glb_model)
func loadModelFromFileByGLTFDocument():
var doc = GLTFDocument.new()
var state = GLTFState.new()
# state.set_handle_binary_image(GLTFState.HANDLE_BINARY_EMBED_AS_UNCOMPRESSED) # setup if you want to use the model without scan resources and extract textures
var error = doc.append_from_file("res://scenes/model.glb", state)
if error == OK:
print("Found scene: ", state.get_scene_name(), ", uniques_names: ", state.get_unique_names())
var glb_scene: Node3D = doc.generate_scene(state)
var glb_importer_model: ImporterMeshInstance3D = glb_scene.get_child(0)
var glb_importer_model_mesh: ImporterMesh = glb_importer_model.get_mesh()
var glb_model: MeshInstance3D = MeshInstance3D.new()
#glb_model.name = glb_importer_model.get_name()
glb_model.mesh = glb_importer_model_mesh.get_mesh()
glb_model.material_override = glb_importer_model_mesh.get_surface_material(0)
self.placeModelToEditorScene(glb_model)
else:
print("Couldn't load glTF scene (error code: %s)." % error_string(error))
Using the model through the RAM buffer (faster)
func downloadModelSuccess(result, response_code, headers, body):
loadModelFromBufferByGLTFDocument(body)
func loadModelFromBufferByGLTFDocument(body):
var doc = GLTFDocument.new()
var state = GLTFState.new()
state.set_handle_binary_image(GLTFState.HANDLE_BINARY_EMBED_AS_BASISU) # Fixed in new Godot version (4.3 as I see) https://github.com/godotengine/godot/blob/17e7f85c06366b427e5068c5b3e2940e27ff5f1d/scene/resources/portable_compressed_texture.cpp#L116
var error = doc.append_from_buffer(body, "", state)
if error == OK:
var glb_importer_model: GLTFMesh = state.get_meshes()[0]
var glb_importer_model_mesh: ImporterMesh = glb_importer_model.get_mesh()
var glb_model: MeshInstance3D = MeshInstance3D.new()
glb_model.mesh = glb_importer_model_mesh.get_mesh()
glb_model.material_override = state.get_materials()[0]
self.placeModelToEditorScene(glb_model)
else:
print("Couldn't load glTF scene (error code: %s)." % error_string(error))