mirror of
https://github.com/godotengine/godot.git
synced 2024-11-27 09:16:35 +08:00
Merge pull request #52541 from V-Sekai/gltf-load-scene-buffer
Add gltf import buffer.
This commit is contained in:
commit
5ce54ce142
@ -3,30 +3,57 @@
|
||||
<brief_description>
|
||||
</brief_description>
|
||||
<description>
|
||||
Append a glTF2 3d format from a file, buffer or scene and then write to the filesystem, buffer or scene.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="import_scene">
|
||||
<return type="Node" />
|
||||
<argument index="0" name="path" type="String" />
|
||||
<argument index="1" name="flags" type="int" default="0" />
|
||||
<argument index="2" name="bake_fps" type="int" default="30" />
|
||||
<argument index="3" name="state" type="GLTFState" default="null" />
|
||||
<method name="append_from_buffer">
|
||||
<return type="int" enum="Error" />
|
||||
<argument index="0" name="bytes" type="PackedByteArray" />
|
||||
<argument index="1" name="base_path" type="String" />
|
||||
<argument index="2" name="state" type="GLTFState" />
|
||||
<argument index="3" name="flags" type="int" default="0" />
|
||||
<argument index="4" name="bake_fps" type="int" default="30" />
|
||||
<description>
|
||||
Import a scene from glTF2 ".gltf" or ".glb" file.
|
||||
</description>
|
||||
</method>
|
||||
<method name="save_scene">
|
||||
<method name="append_from_file">
|
||||
<return type="int" enum="Error" />
|
||||
<argument index="0" name="path" type="String" />
|
||||
<argument index="1" name="state" type="GLTFState" />
|
||||
<argument index="2" name="flags" type="int" default="0" />
|
||||
<argument index="3" name="bake_fps" type="int" default="30" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="append_from_scene">
|
||||
<return type="int" enum="Error" />
|
||||
<argument index="0" name="node" type="Node" />
|
||||
<argument index="1" name="path" type="String" />
|
||||
<argument index="2" name="src_path" type="String" />
|
||||
<argument index="3" name="flags" type="int" default="0" />
|
||||
<argument index="4" name="bake_fps" type="float" default="30" />
|
||||
<argument index="5" name="state" type="GLTFState" default="null" />
|
||||
<argument index="1" name="state" type="GLTFState" />
|
||||
<argument index="2" name="flags" type="int" default="0" />
|
||||
<argument index="3" name="bake_fps" type="int" default="30" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="generate_buffer">
|
||||
<return type="PackedByteArray" />
|
||||
<argument index="0" name="state" type="GLTFState" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="generate_scene">
|
||||
<return type="Node" />
|
||||
<argument index="0" name="state" type="GLTFState" />
|
||||
<argument index="1" name="bake_fps" type="int" default="30" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="write_to_filesystem">
|
||||
<return type="int" enum="Error" />
|
||||
<argument index="0" name="state" type="GLTFState" />
|
||||
<argument index="1" name="path" type="String" />
|
||||
<description>
|
||||
Save a scene as a glTF2 ".glb" or ".gltf" file.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "core/templates/vector.h"
|
||||
#include "editor/editor_file_system.h"
|
||||
#include "gltf_document.h"
|
||||
#include "gltf_state.h"
|
||||
#include "scene/3d/mesh_instance_3d.h"
|
||||
#include "scene/gui/check_box.h"
|
||||
#include "scene/main/node.h"
|
||||
@ -75,7 +76,15 @@ void SceneExporterGLTFPlugin::_gltf2_dialog_action(String p_file) {
|
||||
List<String> deps;
|
||||
Ref<GLTFDocument> doc;
|
||||
doc.instantiate();
|
||||
Error err = doc->save_scene(root, p_file, p_file, 0, 30.0f, Ref<GLTFState>());
|
||||
Ref<GLTFState> state;
|
||||
state.instantiate();
|
||||
int32_t flags = 0;
|
||||
flags |= EditorSceneFormatImporter::IMPORT_USE_NAMED_SKIN_BINDS;
|
||||
Error err = doc->append_from_scene(root, state, flags, 30.0f);
|
||||
if (err != OK) {
|
||||
ERR_PRINT(vformat("glTF2 save scene error %s.", itos(err)));
|
||||
}
|
||||
err = doc->write_to_filesystem(state, p_file);
|
||||
if (err != OK) {
|
||||
ERR_PRINT(vformat("glTF2 save scene error %s.", itos(err)));
|
||||
}
|
||||
|
@ -53,7 +53,15 @@ Node *EditorSceneFormatImporterGLTF::import_scene(const String &p_path,
|
||||
Error *r_err) {
|
||||
Ref<GLTFDocument> doc;
|
||||
doc.instantiate();
|
||||
return doc->import_scene_gltf(p_path, p_flags, p_bake_fps, Ref<GLTFState>(), r_missing_deps, r_err);
|
||||
Ref<GLTFState> state;
|
||||
state.instantiate();
|
||||
Error err = doc->append_from_file(p_path, state, p_flags, p_bake_fps);
|
||||
if (err != OK) {
|
||||
*r_err = err;
|
||||
return nullptr;
|
||||
}
|
||||
Node *root = doc->generate_scene(state, p_bake_fps);
|
||||
return root;
|
||||
}
|
||||
|
||||
Ref<Animation> EditorSceneFormatImporterGLTF::import_animation(const String &p_path,
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "core/error/error_macros.h"
|
||||
#include "core/io/dir_access.h"
|
||||
#include "core/io/file_access.h"
|
||||
#include "core/io/file_access_memory.h"
|
||||
#include "core/io/json.h"
|
||||
#include "core/math/disjoint_set.h"
|
||||
#include "core/math/vector2.h"
|
||||
@ -62,6 +63,7 @@
|
||||
#include "scene/3d/camera_3d.h"
|
||||
#include "scene/3d/mesh_instance_3d.h"
|
||||
#include "scene/3d/multimesh_instance_3d.h"
|
||||
#include "scene/3d/node_3d.h"
|
||||
#include "scene/animation/animation_player.h"
|
||||
#include "scene/resources/importer_mesh.h"
|
||||
#include "scene/resources/mesh.h"
|
||||
@ -82,13 +84,7 @@
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
Error GLTFDocument::serialize(Ref<GLTFState> state, Node *p_root, const String &p_path) {
|
||||
uint64_t begin_time = OS::get_singleton()->get_ticks_usec();
|
||||
|
||||
state->skeleton3d_to_gltf_skeleton.clear();
|
||||
state->skin_and_skeleton3d_to_gltf_skin.clear();
|
||||
|
||||
_convert_scene_node(state, p_root, -1, -1);
|
||||
Error GLTFDocument::_serialize(Ref<GLTFState> state, const String &p_path) {
|
||||
if (!state->buffers.size()) {
|
||||
state->buffers.push_back(Vector<uint8_t>());
|
||||
}
|
||||
@ -184,16 +180,6 @@ Error GLTFDocument::serialize(Ref<GLTFState> state, Node *p_root, const String &
|
||||
return Error::FAILED;
|
||||
}
|
||||
|
||||
/* STEP 17 SERIALIZE FILE */
|
||||
err = _serialize_file(state, p_path);
|
||||
if (err != OK) {
|
||||
return Error::FAILED;
|
||||
}
|
||||
uint64_t elapsed = OS::get_singleton()->get_ticks_usec() - begin_time;
|
||||
float elapsed_sec = double(elapsed) / 1000000.0;
|
||||
elapsed_sec = Math::snapped(elapsed_sec, 0.01f);
|
||||
print_verbose("glTF: Export time elapsed seconds " + rtos(elapsed_sec).pad_decimals(2));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -255,18 +241,14 @@ Error GLTFDocument::_parse_json(const String &p_path, Ref<GLTFState> state) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
Error GLTFDocument::_parse_glb(const String &p_path, Ref<GLTFState> state) {
|
||||
Error err;
|
||||
FileAccessRef f = FileAccess::open(p_path, FileAccess::READ, &err);
|
||||
if (!f) {
|
||||
return err;
|
||||
}
|
||||
|
||||
Error GLTFDocument::_parse_glb(FileAccess *f, Ref<GLTFState> state) {
|
||||
ERR_FAIL_NULL_V(f, ERR_INVALID_PARAMETER);
|
||||
ERR_FAIL_NULL_V(state, ERR_INVALID_PARAMETER);
|
||||
ERR_FAIL_COND_V(f->get_position() != 0, ERR_FILE_CANT_READ);
|
||||
uint32_t magic = f->get_32();
|
||||
ERR_FAIL_COND_V(magic != 0x46546C67, ERR_FILE_UNRECOGNIZED); //glTF
|
||||
f->get_32(); // version
|
||||
f->get_32(); // length
|
||||
|
||||
uint32_t chunk_length = f->get_32();
|
||||
uint32_t chunk_type = f->get_32();
|
||||
|
||||
@ -280,9 +262,9 @@ Error GLTFDocument::_parse_glb(const String &p_path, Ref<GLTFState> state) {
|
||||
text.parse_utf8((const char *)json_data.ptr(), json_data.size());
|
||||
|
||||
JSON json;
|
||||
err = json.parse(text);
|
||||
Error err = json.parse(text);
|
||||
if (err != OK) {
|
||||
_err_print_error("", p_path.utf8().get_data(), json.get_error_line(), json.get_error_message().utf8().get_data(), false, ERR_HANDLER_SCRIPT);
|
||||
_err_print_error("", "", json.get_error_line(), json.get_error_message().utf8().get_data(), false, ERR_HANDLER_SCRIPT);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -753,6 +735,8 @@ Error GLTFDocument::_parse_buffers(Ref<GLTFState> state, const String &p_base_pa
|
||||
}
|
||||
buffer_data = _parse_base64_uri(uri);
|
||||
} else { // Relative path to an external image file.
|
||||
ERR_FAIL_COND_V(p_base_path.is_empty(), ERR_INVALID_PARAMETER);
|
||||
uri = uri.uri_decode();
|
||||
uri = p_base_path.plus_file(uri).replace("\\", "/"); // Fix for Windows.
|
||||
buffer_data = FileAccess::get_file_as_array(uri);
|
||||
ERR_FAIL_COND_V_MSG(buffer.size() == 0, ERR_PARSE_ERROR, "glTF: Couldn't load binary file as an array: " + uri);
|
||||
@ -2952,7 +2936,7 @@ Error GLTFDocument::_serialize_images(Ref<GLTFState> state, const String &p_path
|
||||
Ref<Image> image = state->images[i]->get_image();
|
||||
ERR_CONTINUE(image.is_null());
|
||||
|
||||
if (p_path.to_lower().ends_with("glb")) {
|
||||
if (p_path.to_lower().ends_with("glb") || p_path.is_empty()) {
|
||||
GLTFBufferViewIndex bvi;
|
||||
|
||||
Ref<GLTFBufferView> bv;
|
||||
@ -2981,6 +2965,7 @@ Error GLTFDocument::_serialize_images(Ref<GLTFState> state, const String &p_path
|
||||
d["bufferView"] = bvi;
|
||||
d["mimeType"] = "image/png";
|
||||
} else {
|
||||
ERR_FAIL_COND_V(p_path.is_empty(), ERR_INVALID_PARAMETER);
|
||||
String name = state->images[i]->get_name();
|
||||
if (name.is_empty()) {
|
||||
name = itos(i);
|
||||
@ -2988,13 +2973,14 @@ Error GLTFDocument::_serialize_images(Ref<GLTFState> state, const String &p_path
|
||||
name = _gen_unique_name(state, name);
|
||||
name = name.pad_zeros(3) + ".png";
|
||||
String texture_dir = "textures";
|
||||
String new_texture_dir = p_path.get_base_dir() + "/" + texture_dir;
|
||||
DirAccessRef da = DirAccess::open(p_path.get_base_dir());
|
||||
String path = p_path.get_base_dir();
|
||||
String new_texture_dir = path + "/" + texture_dir;
|
||||
DirAccessRef da = DirAccess::open(path);
|
||||
if (!da->dir_exists(new_texture_dir)) {
|
||||
da->make_dir(new_texture_dir);
|
||||
}
|
||||
image->save_png(new_texture_dir.plus_file(name));
|
||||
d["uri"] = texture_dir.plus_file(name);
|
||||
d["uri"] = texture_dir.plus_file(name).uri_encode();
|
||||
}
|
||||
images.push_back(d);
|
||||
}
|
||||
@ -3010,6 +2996,7 @@ Error GLTFDocument::_serialize_images(Ref<GLTFState> state, const String &p_path
|
||||
}
|
||||
|
||||
Error GLTFDocument::_parse_images(Ref<GLTFState> state, const String &p_base_path) {
|
||||
ERR_FAIL_NULL_V(state, ERR_INVALID_PARAMETER);
|
||||
if (!state->json.has("images")) {
|
||||
return OK;
|
||||
}
|
||||
@ -3069,6 +3056,7 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> state, const String &p_base_pat
|
||||
}
|
||||
}
|
||||
} else { // Relative path to an external image file.
|
||||
ERR_FAIL_COND_V(p_base_path.is_empty(), ERR_INVALID_PARAMETER);
|
||||
uri = uri.uri_decode();
|
||||
uri = p_base_path.plus_file(uri).replace("\\", "/"); // Fix for Windows.
|
||||
// ResourceLoader will rely on the file extension to use the relevant loader.
|
||||
@ -5099,7 +5087,7 @@ GLTFMeshIndex GLTFDocument::_convert_mesh_to_gltf(Ref<GLTFState> state, MeshInst
|
||||
return mesh_i;
|
||||
}
|
||||
|
||||
ImporterMeshInstance3D *GLTFDocument::_generate_mesh_instance(Ref<GLTFState> state, Node *parent_node, const GLTFNodeIndex node_index) {
|
||||
ImporterMeshInstance3D *GLTFDocument::_generate_mesh_instance(Ref<GLTFState> state, const GLTFNodeIndex node_index) {
|
||||
Ref<GLTFNode> gltf_node = state->nodes[node_index];
|
||||
|
||||
ERR_FAIL_INDEX_V(gltf_node->mesh, state->meshes.size(), nullptr);
|
||||
@ -5119,7 +5107,7 @@ ImporterMeshInstance3D *GLTFDocument::_generate_mesh_instance(Ref<GLTFState> sta
|
||||
return mi;
|
||||
}
|
||||
|
||||
Node3D *GLTFDocument::_generate_light(Ref<GLTFState> state, Node *scene_parent, const GLTFNodeIndex node_index) {
|
||||
Node3D *GLTFDocument::_generate_light(Ref<GLTFState> state, const GLTFNodeIndex node_index) {
|
||||
Ref<GLTFNode> gltf_node = state->nodes[node_index];
|
||||
|
||||
ERR_FAIL_INDEX_V(gltf_node->light, state->lights.size(), nullptr);
|
||||
@ -5171,7 +5159,7 @@ Node3D *GLTFDocument::_generate_light(Ref<GLTFState> state, Node *scene_parent,
|
||||
return memnew(Node3D);
|
||||
}
|
||||
|
||||
Camera3D *GLTFDocument::_generate_camera(Ref<GLTFState> state, Node *scene_parent, const GLTFNodeIndex node_index) {
|
||||
Camera3D *GLTFDocument::_generate_camera(Ref<GLTFState> state, const GLTFNodeIndex node_index) {
|
||||
Ref<GLTFNode> gltf_node = state->nodes[node_index];
|
||||
|
||||
ERR_FAIL_INDEX_V(gltf_node->camera, state->cameras.size(), nullptr);
|
||||
@ -5249,7 +5237,7 @@ void GLTFDocument::_convert_spatial(Ref<GLTFState> state, Node3D *p_spatial, Ref
|
||||
p_node->position = xform.origin;
|
||||
}
|
||||
|
||||
Node3D *GLTFDocument::_generate_spatial(Ref<GLTFState> state, Node *scene_parent, const GLTFNodeIndex node_index) {
|
||||
Node3D *GLTFDocument::_generate_spatial(Ref<GLTFState> state, const GLTFNodeIndex node_index) {
|
||||
Ref<GLTFNode> gltf_node = state->nodes[node_index];
|
||||
|
||||
Node3D *spatial = memnew(Node3D);
|
||||
@ -5616,19 +5604,18 @@ void GLTFDocument::_generate_scene_node(Ref<GLTFState> state, Node *scene_parent
|
||||
scene_parent = bone_attachment;
|
||||
}
|
||||
if (gltf_node->mesh >= 0) {
|
||||
current_node = _generate_mesh_instance(state, scene_parent, node_index);
|
||||
current_node = _generate_mesh_instance(state, node_index);
|
||||
} else if (gltf_node->camera >= 0) {
|
||||
current_node = _generate_camera(state, scene_parent, node_index);
|
||||
current_node = _generate_camera(state, node_index);
|
||||
} else if (gltf_node->light >= 0) {
|
||||
current_node = _generate_light(state, scene_parent, node_index);
|
||||
current_node = _generate_light(state, node_index);
|
||||
}
|
||||
|
||||
// We still have not managed to make a node.
|
||||
if (!current_node) {
|
||||
current_node = _generate_spatial(state, scene_parent, node_index);
|
||||
current_node = _generate_spatial(state, node_index);
|
||||
}
|
||||
|
||||
scene_parent->add_child(current_node, true);
|
||||
scene_parent->add_child(current_node);
|
||||
if (current_node != scene_root) {
|
||||
current_node->set_owner(scene_root);
|
||||
}
|
||||
@ -5699,11 +5686,11 @@ void GLTFDocument::_generate_skeleton_bone_node(Ref<GLTFState> state, Node *scen
|
||||
|
||||
// We still have not managed to make a node
|
||||
if (gltf_node->mesh >= 0) {
|
||||
current_node = _generate_mesh_instance(state, scene_parent, node_index);
|
||||
current_node = _generate_mesh_instance(state, node_index);
|
||||
} else if (gltf_node->camera >= 0) {
|
||||
current_node = _generate_camera(state, scene_parent, node_index);
|
||||
current_node = _generate_camera(state, node_index);
|
||||
} else if (gltf_node->light >= 0) {
|
||||
current_node = _generate_light(state, scene_parent, node_index);
|
||||
current_node = _generate_light(state, node_index);
|
||||
}
|
||||
|
||||
scene_parent->add_child(current_node, true);
|
||||
@ -6084,7 +6071,9 @@ void GLTFDocument::_convert_mesh_instances(Ref<GLTFState> state) {
|
||||
continue;
|
||||
}
|
||||
MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(mi_element->get());
|
||||
ERR_CONTINUE(!mi);
|
||||
if (!mi) {
|
||||
continue;
|
||||
}
|
||||
Transform3D mi_xform = mi->get_transform();
|
||||
node->scale = mi_xform.basis.get_scale();
|
||||
node->rotation = mi_xform.basis.get_rotation_quaternion();
|
||||
@ -6282,39 +6271,8 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> state
|
||||
ERR_CONTINUE(err != OK);
|
||||
p_track.rotation_track.values.write[key_i] = rotation;
|
||||
}
|
||||
} else if (path.find(":transform") != -1) {
|
||||
p_track.position_track.times = times;
|
||||
p_track.position_track.interpolation = gltf_interpolation;
|
||||
p_track.rotation_track.times = times;
|
||||
p_track.rotation_track.interpolation = gltf_interpolation;
|
||||
p_track.scale_track.times = times;
|
||||
p_track.scale_track.interpolation = gltf_interpolation;
|
||||
|
||||
p_track.scale_track.values.resize(key_count);
|
||||
p_track.scale_track.interpolation = gltf_interpolation;
|
||||
p_track.position_track.values.resize(key_count);
|
||||
p_track.position_track.interpolation = gltf_interpolation;
|
||||
p_track.rotation_track.values.resize(key_count);
|
||||
p_track.rotation_track.interpolation = gltf_interpolation;
|
||||
for (int32_t key_i = 0; key_i < key_count; key_i++) {
|
||||
Transform3D xform = p_animation->track_get_key_value(p_track_i, key_i);
|
||||
p_track.position_track.values.write[key_i] = xform.get_origin();
|
||||
p_track.rotation_track.values.write[key_i] = xform.basis.get_rotation_quaternion();
|
||||
p_track.scale_track.values.write[key_i] = xform.basis.get_scale();
|
||||
}
|
||||
} else if (track_type == Animation::TYPE_VALUE) {
|
||||
if (path.find("/rotation_quat") != -1) {
|
||||
p_track.rotation_track.times = times;
|
||||
p_track.rotation_track.interpolation = gltf_interpolation;
|
||||
|
||||
p_track.rotation_track.values.resize(key_count);
|
||||
p_track.rotation_track.interpolation = gltf_interpolation;
|
||||
|
||||
for (int32_t key_i = 0; key_i < key_count; key_i++) {
|
||||
Quaternion rotation_track = p_animation->track_get_key_value(p_track_i, key_i);
|
||||
p_track.rotation_track.values.write[key_i] = rotation_track;
|
||||
}
|
||||
} else if (path.find(":position") != -1) {
|
||||
if (path.find(":position") != -1) {
|
||||
p_track.position_track.times = times;
|
||||
p_track.position_track.interpolation = gltf_interpolation;
|
||||
|
||||
@ -6589,142 +6547,57 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
|
||||
}
|
||||
}
|
||||
|
||||
Error GLTFDocument::parse(Ref<GLTFState> state, String p_path, bool p_read_binary) {
|
||||
Error GLTFDocument::_parse(Ref<GLTFState> state, String p_path, FileAccess *f, int p_bake_fps) {
|
||||
Error err;
|
||||
FileAccessRef f = FileAccess::open(p_path, FileAccess::READ, &err);
|
||||
if (!f) {
|
||||
return err;
|
||||
return FAILED;
|
||||
}
|
||||
f->seek(0);
|
||||
uint32_t magic = f->get_32();
|
||||
if (magic == 0x46546C67) {
|
||||
//binary file
|
||||
//text file
|
||||
err = _parse_glb(p_path, state);
|
||||
if (err) {
|
||||
return FAILED;
|
||||
f->seek(0);
|
||||
err = _parse_glb(f, state);
|
||||
if (err != OK) {
|
||||
return err;
|
||||
}
|
||||
} else {
|
||||
//text file
|
||||
err = _parse_json(p_path, state);
|
||||
if (err) {
|
||||
return FAILED;
|
||||
f->seek(0);
|
||||
String text = f->get_as_utf8_string();
|
||||
JSON json;
|
||||
err = json.parse(text);
|
||||
if (err != OK) {
|
||||
_err_print_error("", "", json.get_error_line(), json.get_error_message().utf8().get_data(), false, ERR_HANDLER_SCRIPT);
|
||||
}
|
||||
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
|
||||
state->json = json.get_data();
|
||||
}
|
||||
f->close();
|
||||
|
||||
// get file's name, use for scene name if none
|
||||
state->filename = p_path.get_file().get_slice(".", 0);
|
||||
|
||||
ERR_FAIL_COND_V(!state->json.has("asset"), Error::FAILED);
|
||||
if (!state->json.has("asset")) {
|
||||
return ERR_PARSE_ERROR;
|
||||
}
|
||||
|
||||
Dictionary asset = state->json["asset"];
|
||||
|
||||
ERR_FAIL_COND_V(!asset.has("version"), Error::FAILED);
|
||||
if (!asset.has("version")) {
|
||||
return ERR_PARSE_ERROR;
|
||||
}
|
||||
|
||||
String version = asset["version"];
|
||||
|
||||
state->major_version = version.get_slice(".", 0).to_int();
|
||||
state->minor_version = version.get_slice(".", 1).to_int();
|
||||
|
||||
/* STEP 0 PARSE SCENE */
|
||||
err = _parse_scenes(state);
|
||||
if (err != OK) {
|
||||
return Error::FAILED;
|
||||
for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
|
||||
Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
|
||||
ERR_CONTINUE(ext.is_null());
|
||||
err = ext->import_preflight(this);
|
||||
ERR_FAIL_COND_V(err != OK, FAILED);
|
||||
}
|
||||
|
||||
/* STEP 1 PARSE NODES */
|
||||
err = _parse_nodes(state);
|
||||
if (err != OK) {
|
||||
return Error::FAILED;
|
||||
}
|
||||
|
||||
/* STEP 2 PARSE BUFFERS */
|
||||
err = _parse_buffers(state, p_path.get_base_dir());
|
||||
if (err != OK) {
|
||||
return Error::FAILED;
|
||||
}
|
||||
|
||||
/* STEP 3 PARSE BUFFER VIEWS */
|
||||
err = _parse_buffer_views(state);
|
||||
if (err != OK) {
|
||||
return Error::FAILED;
|
||||
}
|
||||
|
||||
/* STEP 4 PARSE ACCESSORS */
|
||||
err = _parse_accessors(state);
|
||||
if (err != OK) {
|
||||
return Error::FAILED;
|
||||
}
|
||||
|
||||
/* STEP 5 PARSE IMAGES */
|
||||
err = _parse_images(state, p_path.get_base_dir());
|
||||
if (err != OK) {
|
||||
return Error::FAILED;
|
||||
}
|
||||
|
||||
/* STEP 6 PARSE TEXTURES */
|
||||
err = _parse_textures(state);
|
||||
if (err != OK) {
|
||||
return Error::FAILED;
|
||||
}
|
||||
|
||||
/* STEP 7 PARSE TEXTURES */
|
||||
err = _parse_materials(state);
|
||||
if (err != OK) {
|
||||
return Error::FAILED;
|
||||
}
|
||||
|
||||
/* STEP 9 PARSE SKINS */
|
||||
err = _parse_skins(state);
|
||||
if (err != OK) {
|
||||
return Error::FAILED;
|
||||
}
|
||||
|
||||
/* STEP 10 DETERMINE SKELETONS */
|
||||
err = _determine_skeletons(state);
|
||||
if (err != OK) {
|
||||
return Error::FAILED;
|
||||
}
|
||||
|
||||
/* STEP 11 CREATE SKELETONS */
|
||||
err = _create_skeletons(state);
|
||||
if (err != OK) {
|
||||
return Error::FAILED;
|
||||
}
|
||||
|
||||
/* STEP 12 CREATE SKINS */
|
||||
err = _create_skins(state);
|
||||
if (err != OK) {
|
||||
return Error::FAILED;
|
||||
}
|
||||
|
||||
/* STEP 13 PARSE MESHES (we have enough info now) */
|
||||
err = _parse_meshes(state);
|
||||
if (err != OK) {
|
||||
return Error::FAILED;
|
||||
}
|
||||
|
||||
/* STEP 14 PARSE LIGHTS */
|
||||
err = _parse_lights(state);
|
||||
if (err != OK) {
|
||||
return Error::FAILED;
|
||||
}
|
||||
|
||||
/* STEP 15 PARSE CAMERAS */
|
||||
err = _parse_cameras(state);
|
||||
if (err != OK) {
|
||||
return Error::FAILED;
|
||||
}
|
||||
|
||||
/* STEP 16 PARSE ANIMATIONS */
|
||||
err = _parse_animations(state);
|
||||
if (err != OK) {
|
||||
return Error::FAILED;
|
||||
}
|
||||
|
||||
/* STEP 17 ASSIGN SCENE NAMES */
|
||||
_assign_scene_names(state);
|
||||
|
||||
err = _parse_gltf_state(state, p_path, p_bake_fps);
|
||||
ERR_FAIL_COND_V(err != OK, err);
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -6843,89 +6716,20 @@ Error GLTFDocument::_serialize_file(Ref<GLTFState> state, const String p_path) {
|
||||
return err;
|
||||
}
|
||||
|
||||
Error GLTFDocument::save_scene(Node *p_node, const String &p_path,
|
||||
const String &p_src_path, uint32_t p_flags,
|
||||
float p_bake_fps, Ref<GLTFState> r_state) {
|
||||
ERR_FAIL_NULL_V(p_node, ERR_INVALID_PARAMETER);
|
||||
|
||||
Ref<GLTFDocument> gltf_document;
|
||||
gltf_document.instantiate();
|
||||
for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
|
||||
Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
|
||||
ERR_CONTINUE(ext.is_null());
|
||||
Error err = ext->export_preflight(this, p_node);
|
||||
ERR_FAIL_COND_V(err != OK, err);
|
||||
}
|
||||
|
||||
if (r_state == Ref<GLTFState>()) {
|
||||
r_state.instantiate();
|
||||
}
|
||||
Error err = gltf_document->serialize(r_state, p_node, p_path);
|
||||
ERR_FAIL_COND_V(err != OK, err);
|
||||
for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
|
||||
Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
|
||||
ERR_CONTINUE(ext.is_null());
|
||||
err = ext->export_post(this);
|
||||
ERR_FAIL_COND_V(err != OK, err);
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
Node *GLTFDocument::import_scene_gltf(const String &p_path, uint32_t p_flags, int32_t p_bake_fps, Ref<GLTFState> r_state, List<String> *r_missing_deps, Error *r_err) {
|
||||
// TODO Add missing texture and missing .bin file paths to r_missing_deps 2021-09-10 fire
|
||||
if (r_state == Ref<GLTFState>()) {
|
||||
r_state.instantiate();
|
||||
}
|
||||
r_state->use_named_skin_binds =
|
||||
p_flags & EditorSceneFormatImporter::IMPORT_USE_NAMED_SKIN_BINDS;
|
||||
|
||||
Ref<GLTFDocument> gltf_document;
|
||||
gltf_document.instantiate();
|
||||
for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
|
||||
Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
|
||||
ERR_CONTINUE(ext.is_null());
|
||||
Error err = ext->import_preflight(this);
|
||||
if (r_err) {
|
||||
*r_err = err;
|
||||
}
|
||||
ERR_FAIL_COND_V(err != OK, nullptr);
|
||||
}
|
||||
Error err = gltf_document->parse(r_state, p_path);
|
||||
if (r_err) {
|
||||
*r_err = err;
|
||||
}
|
||||
ERR_FAIL_COND_V(err != Error::OK, nullptr);
|
||||
|
||||
Node3D *root = memnew(Node3D);
|
||||
for (int32_t root_i = 0; root_i < r_state->root_nodes.size(); root_i++) {
|
||||
gltf_document->_generate_scene_node(r_state, root, root, r_state->root_nodes[root_i]);
|
||||
}
|
||||
gltf_document->_process_mesh_instances(r_state, root);
|
||||
if (r_state->animations.size()) {
|
||||
AnimationPlayer *ap = memnew(AnimationPlayer);
|
||||
root->add_child(ap, true);
|
||||
ap->set_owner(root);
|
||||
for (int i = 0; i < r_state->animations.size(); i++) {
|
||||
gltf_document->_import_animation(r_state, ap, i, p_bake_fps);
|
||||
}
|
||||
}
|
||||
for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
|
||||
Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
|
||||
ERR_CONTINUE(ext.is_null());
|
||||
err = ext->import_post(this, root);
|
||||
if (r_err) {
|
||||
*r_err = err;
|
||||
}
|
||||
ERR_FAIL_COND_V(err != OK, nullptr);
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
void GLTFDocument::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("save_scene", "node", "path", "src_path", "flags", "bake_fps", "state"),
|
||||
&GLTFDocument::save_scene, DEFVAL(0), DEFVAL(30), DEFVAL(Ref<GLTFState>()));
|
||||
ClassDB::bind_method(D_METHOD("import_scene", "path", "flags", "bake_fps", "state"),
|
||||
&GLTFDocument::import_scene, DEFVAL(0), DEFVAL(30), DEFVAL(Ref<GLTFState>()));
|
||||
ClassDB::bind_method(D_METHOD("append_from_file", "path", "state", "flags", "bake_fps"),
|
||||
&GLTFDocument::append_from_file, DEFVAL(0), DEFVAL(30));
|
||||
ClassDB::bind_method(D_METHOD("append_from_buffer", "bytes", "base_path", "state", "flags", "bake_fps"),
|
||||
&GLTFDocument::append_from_buffer, DEFVAL(0), DEFVAL(30));
|
||||
ClassDB::bind_method(D_METHOD("append_from_scene", "node", "state", "flags", "bake_fps"),
|
||||
&GLTFDocument::append_from_scene, DEFVAL(0), DEFVAL(30));
|
||||
ClassDB::bind_method(D_METHOD("generate_scene", "state", "bake_fps"),
|
||||
&GLTFDocument::generate_scene, DEFVAL(30));
|
||||
ClassDB::bind_method(D_METHOD("generate_buffer", "state"),
|
||||
&GLTFDocument::generate_buffer);
|
||||
ClassDB::bind_method(D_METHOD("write_to_filesystem", "state", "path"),
|
||||
&GLTFDocument::write_to_filesystem);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_extensions", "extensions"),
|
||||
&GLTFDocument::set_extensions);
|
||||
ClassDB::bind_method(D_METHOD("get_extensions"),
|
||||
@ -6950,16 +6754,6 @@ void GLTFDocument::_build_parent_hierachy(Ref<GLTFState> state) {
|
||||
}
|
||||
}
|
||||
|
||||
Node *GLTFDocument::import_scene(const String &p_path, uint32_t p_flags, int32_t p_bake_fps, Ref<GLTFState> r_state) {
|
||||
Error err = FAILED;
|
||||
List<String> deps;
|
||||
Node *node = import_scene_gltf(p_path, p_flags, p_bake_fps, r_state, &deps, &err);
|
||||
if (err != OK) {
|
||||
return nullptr;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
void GLTFDocument::set_extensions(TypedArray<GLTFDocumentExtension> p_extensions) {
|
||||
document_extensions = p_extensions;
|
||||
}
|
||||
@ -6977,3 +6771,226 @@ GLTFDocument::GLTFDocument() {
|
||||
extension_editor.instantiate();
|
||||
document_extensions.push_back(extension_editor);
|
||||
}
|
||||
|
||||
PackedByteArray GLTFDocument::_serialize_glb_buffer(Ref<GLTFState> state, Error *r_err) {
|
||||
Error err = _encode_buffer_glb(state, "");
|
||||
if (r_err) {
|
||||
*r_err = err;
|
||||
}
|
||||
ERR_FAIL_COND_V(err != OK, PackedByteArray());
|
||||
String json = Variant(state->json).to_json_string();
|
||||
|
||||
const uint32_t magic = 0x46546C67; // GLTF
|
||||
const int32_t header_size = 12;
|
||||
const int32_t chunk_header_size = 8;
|
||||
|
||||
for (int32_t pad_i = 0; pad_i < (chunk_header_size + json.utf8().length()) % 4; pad_i++) {
|
||||
json += " ";
|
||||
}
|
||||
CharString cs = json.utf8();
|
||||
const uint32_t text_chunk_length = cs.length();
|
||||
|
||||
const uint32_t text_chunk_type = 0x4E4F534A; //JSON
|
||||
int32_t binary_data_length = 0;
|
||||
if (state->buffers.size()) {
|
||||
binary_data_length = state->buffers[0].size();
|
||||
}
|
||||
const int32_t binary_chunk_length = binary_data_length;
|
||||
const int32_t binary_chunk_type = 0x004E4942; //BIN
|
||||
|
||||
Ref<StreamPeerBuffer> buffer;
|
||||
buffer.instantiate();
|
||||
buffer->put_32(magic);
|
||||
buffer->put_32(state->major_version); // version
|
||||
buffer->put_32(header_size + chunk_header_size + text_chunk_length + chunk_header_size + binary_data_length); // length
|
||||
buffer->put_32(text_chunk_length);
|
||||
buffer->put_32(text_chunk_type);
|
||||
buffer->put_data((uint8_t *)&cs[0], cs.length());
|
||||
if (binary_chunk_length) {
|
||||
buffer->put_32(binary_chunk_length);
|
||||
buffer->put_32(binary_chunk_type);
|
||||
buffer->put_data(state->buffers[0].ptr(), binary_data_length);
|
||||
}
|
||||
return buffer->get_data_array();
|
||||
}
|
||||
|
||||
PackedByteArray GLTFDocument::generate_buffer(Ref<GLTFState> state) {
|
||||
ERR_FAIL_NULL_V(state, PackedByteArray());
|
||||
Error err = _serialize(state, "");
|
||||
ERR_FAIL_COND_V(err != OK, PackedByteArray());
|
||||
PackedByteArray bytes = _serialize_glb_buffer(state, &err);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
Error GLTFDocument::write_to_filesystem(Ref<GLTFState> state, const String &p_path) {
|
||||
ERR_FAIL_NULL_V(state, ERR_INVALID_PARAMETER);
|
||||
|
||||
Error err = _serialize(state, p_path);
|
||||
if (err != OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = _serialize_file(state, p_path);
|
||||
if (err != OK) {
|
||||
return Error::FAILED;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
Node *GLTFDocument::generate_scene(Ref<GLTFState> state, int32_t p_bake_fps) {
|
||||
ERR_FAIL_INDEX_V(0, state->root_nodes.size(), nullptr);
|
||||
GLTFNodeIndex gltf_root = state->root_nodes.write[0];
|
||||
Node *gltf_root_node = state->get_scene_node(gltf_root);
|
||||
Node *root = gltf_root_node->get_parent();
|
||||
ERR_FAIL_NULL_V(root, nullptr);
|
||||
_process_mesh_instances(state, root);
|
||||
if (state->animations.size()) {
|
||||
AnimationPlayer *ap = memnew(AnimationPlayer);
|
||||
root->add_child(ap);
|
||||
ap->set_owner(root);
|
||||
for (int i = 0; i < state->animations.size(); i++) {
|
||||
_import_animation(state, ap, i, p_bake_fps);
|
||||
}
|
||||
}
|
||||
|
||||
for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
|
||||
Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
|
||||
ERR_CONTINUE(ext.is_null());
|
||||
Error err = ext->import_post(this, root);
|
||||
ERR_FAIL_COND_V(err != OK, nullptr);
|
||||
}
|
||||
ERR_FAIL_NULL_V(root, nullptr);
|
||||
return root;
|
||||
}
|
||||
|
||||
Error GLTFDocument::append_from_scene(Node *p_node, Ref<GLTFState> state, uint32_t p_flags, int32_t p_bake_fps) {
|
||||
ERR_FAIL_COND_V(state.is_null(), FAILED);
|
||||
state->use_named_skin_binds =
|
||||
p_flags & EditorSceneFormatImporter::IMPORT_USE_NAMED_SKIN_BINDS;
|
||||
|
||||
_convert_scene_node(state, p_node, -1, -1);
|
||||
if (!state->buffers.size()) {
|
||||
state->buffers.push_back(Vector<uint8_t>());
|
||||
}
|
||||
|
||||
/* STEP 1 CONVERT MESH INSTANCES */
|
||||
_convert_mesh_instances(state);
|
||||
|
||||
/* STEP 2 CREATE SKINS */
|
||||
Error err = _serialize_skins(state);
|
||||
return err;
|
||||
}
|
||||
|
||||
Error GLTFDocument::append_from_buffer(PackedByteArray p_bytes, String p_base_path, Ref<GLTFState> state, uint32_t p_flags, int32_t p_bake_fps) {
|
||||
ERR_FAIL_COND_V(state.is_null(), FAILED);
|
||||
// TODO Add missing texture and missing .bin file paths to r_missing_deps 2021-09-10 fire
|
||||
Error err = FAILED;
|
||||
state->use_named_skin_binds =
|
||||
p_flags & EditorSceneFormatImporter::IMPORT_USE_NAMED_SKIN_BINDS;
|
||||
FileAccessMemory *file_access = memnew(FileAccessMemory);
|
||||
file_access->open_custom(p_bytes.ptr(), p_bytes.size());
|
||||
err = _parse(state, p_base_path.get_base_dir(), file_access, p_bake_fps);
|
||||
ERR_FAIL_COND_V(err != OK, FAILED);
|
||||
return OK;
|
||||
}
|
||||
|
||||
Error GLTFDocument::_parse_gltf_state(Ref<GLTFState> state, const String &p_search_path, float p_bake_fps) {
|
||||
Error err;
|
||||
/* STEP 0 PARSE SCENE */
|
||||
err = _parse_scenes(state);
|
||||
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
|
||||
|
||||
/* STEP 1 PARSE NODES */
|
||||
err = _parse_nodes(state);
|
||||
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
|
||||
|
||||
/* STEP 2 PARSE BUFFERS */
|
||||
err = _parse_buffers(state, p_search_path);
|
||||
|
||||
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
|
||||
|
||||
/* STEP 3 PARSE BUFFER VIEWS */
|
||||
err = _parse_buffer_views(state);
|
||||
|
||||
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
|
||||
|
||||
/* STEP 4 PARSE ACCESSORS */
|
||||
err = _parse_accessors(state);
|
||||
|
||||
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
|
||||
|
||||
/* STEP 5 PARSE IMAGES */
|
||||
err = _parse_images(state, p_search_path);
|
||||
|
||||
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
|
||||
|
||||
/* STEP 6 PARSE TEXTURES */
|
||||
err = _parse_textures(state);
|
||||
|
||||
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
|
||||
|
||||
/* STEP 7 PARSE TEXTURES */
|
||||
err = _parse_materials(state);
|
||||
|
||||
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
|
||||
|
||||
/* STEP 9 PARSE SKINS */
|
||||
err = _parse_skins(state);
|
||||
|
||||
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
|
||||
|
||||
/* STEP 10 DETERMINE SKELETONS */
|
||||
err = _determine_skeletons(state);
|
||||
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
|
||||
|
||||
/* STEP 11 CREATE SKELETONS */
|
||||
err = _create_skeletons(state);
|
||||
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
|
||||
|
||||
/* STEP 12 CREATE SKINS */
|
||||
err = _create_skins(state);
|
||||
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
|
||||
|
||||
/* STEP 13 PARSE MESHES (we have enough info now) */
|
||||
err = _parse_meshes(state);
|
||||
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
|
||||
|
||||
/* STEP 14 PARSE LIGHTS */
|
||||
err = _parse_lights(state);
|
||||
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
|
||||
|
||||
/* STEP 15 PARSE CAMERAS */
|
||||
err = _parse_cameras(state);
|
||||
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
|
||||
|
||||
/* STEP 16 PARSE ANIMATIONS */
|
||||
err = _parse_animations(state);
|
||||
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
|
||||
|
||||
/* STEP 17 ASSIGN SCENE NAMES */
|
||||
_assign_scene_names(state);
|
||||
|
||||
Node3D *root = memnew(Node3D);
|
||||
for (int32_t root_i = 0; root_i < state->root_nodes.size(); root_i++) {
|
||||
_generate_scene_node(state, root, root, state->root_nodes[root_i]);
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
Error GLTFDocument::append_from_file(String p_path, Ref<GLTFState> r_state, uint32_t p_flags, int32_t p_bake_fps) {
|
||||
// TODO Add missing texture and missing .bin file paths to r_missing_deps 2021-09-10 fire
|
||||
if (r_state == Ref<GLTFState>()) {
|
||||
r_state.instantiate();
|
||||
}
|
||||
r_state->filename = p_path.get_file().get_basename();
|
||||
r_state->use_named_skin_binds =
|
||||
p_flags & EditorSceneFormatImporter::IMPORT_USE_NAMED_SKIN_BINDS;
|
||||
Error err;
|
||||
FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
|
||||
ERR_FAIL_COND_V(err != OK, ERR_FILE_CANT_OPEN);
|
||||
ERR_FAIL_NULL_V(f, ERR_FILE_CANT_OPEN);
|
||||
|
||||
err = _parse(r_state, p_path.get_base_dir(), f, p_bake_fps);
|
||||
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
|
||||
return err;
|
||||
}
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
#include "gltf_animation.h"
|
||||
|
||||
#include "core/error/error_list.h"
|
||||
#include "core/variant/dictionary.h"
|
||||
#include "core/variant/variant.h"
|
||||
#include "gltf_document_extension_convert_importer_mesh.h"
|
||||
@ -120,11 +121,6 @@ protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
Node *import_scene(const String &p_path, uint32_t p_flags, int32_t p_bake_fps, Ref<GLTFState> r_state);
|
||||
Node *import_scene_gltf(const String &p_path, uint32_t p_flags, int32_t p_bake_fps, Ref<GLTFState> r_state, List<String> *r_missing_deps, Error *r_err = nullptr);
|
||||
Error save_scene(Node *p_node, const String &p_path,
|
||||
const String &p_src_path, uint32_t p_flags,
|
||||
float p_bake_fps, Ref<GLTFState> r_state);
|
||||
void set_extensions(TypedArray<GLTFDocumentExtension> p_extensions);
|
||||
TypedArray<GLTFDocumentExtension> get_extensions() const;
|
||||
|
||||
@ -200,7 +196,7 @@ private:
|
||||
Ref<Texture2D> _get_texture(Ref<GLTFState> state,
|
||||
const GLTFTextureIndex p_texture);
|
||||
Error _parse_json(const String &p_path, Ref<GLTFState> state);
|
||||
Error _parse_glb(const String &p_path, Ref<GLTFState> state);
|
||||
Error _parse_glb(FileAccess *f, Ref<GLTFState> state);
|
||||
void _compute_node_heights(Ref<GLTFState> state);
|
||||
Error _parse_buffers(Ref<GLTFState> state, const String &p_base_path);
|
||||
Error _parse_buffer_views(Ref<GLTFState> state);
|
||||
@ -287,10 +283,10 @@ private:
|
||||
Skeleton3D *skeleton,
|
||||
const GLTFNodeIndex node_index,
|
||||
const GLTFNodeIndex bone_index);
|
||||
ImporterMeshInstance3D *_generate_mesh_instance(Ref<GLTFState> state, Node *parent_node, const GLTFNodeIndex node_index);
|
||||
Camera3D *_generate_camera(Ref<GLTFState> state, Node *parent_node, const GLTFNodeIndex node_index);
|
||||
Node3D *_generate_light(Ref<GLTFState> state, Node *parent_node, const GLTFNodeIndex node_index);
|
||||
Node3D *_generate_spatial(Ref<GLTFState> state, Node *parent_node, const GLTFNodeIndex node_index);
|
||||
ImporterMeshInstance3D *_generate_mesh_instance(Ref<GLTFState> state, const GLTFNodeIndex node_index);
|
||||
Camera3D *_generate_camera(Ref<GLTFState> state, const GLTFNodeIndex node_index);
|
||||
Node3D *_generate_light(Ref<GLTFState> state, const GLTFNodeIndex node_index);
|
||||
Node3D *_generate_spatial(Ref<GLTFState> state, const GLTFNodeIndex node_index);
|
||||
void _assign_scene_names(Ref<GLTFState> state);
|
||||
template <class T>
|
||||
T _interpolate_track(const Vector<real_t> &p_times, const Vector<T> &p_values,
|
||||
@ -361,6 +357,7 @@ private:
|
||||
GLTFNodeIndex p_node_i);
|
||||
Error _encode_buffer_bins(Ref<GLTFState> state, const String &p_path);
|
||||
Error _encode_buffer_glb(Ref<GLTFState> state, const String &p_path);
|
||||
PackedByteArray _serialize_glb_buffer(Ref<GLTFState> state, Error *r_err);
|
||||
Dictionary _serialize_texture_transform_uv1(Ref<BaseMaterial3D> p_material);
|
||||
Dictionary _serialize_texture_transform_uv2(Ref<BaseMaterial3D> p_material);
|
||||
Error _serialize_version(Ref<GLTFState> state);
|
||||
@ -384,6 +381,17 @@ private:
|
||||
static float get_max_component(const Color &p_color);
|
||||
|
||||
public:
|
||||
Error append_from_file(String p_path, Ref<GLTFState> r_state, uint32_t p_flags = 0, int32_t p_bake_fps = 30);
|
||||
Error append_from_buffer(PackedByteArray p_bytes, String p_base_path, Ref<GLTFState> r_state, uint32_t p_flags = 0, int32_t p_bake_fps = 30);
|
||||
Error append_from_scene(Node *p_node, Ref<GLTFState> r_state, uint32_t p_flags = 0, int32_t p_bake_fps = 30);
|
||||
|
||||
public:
|
||||
Node *generate_scene(Ref<GLTFState> state, int32_t p_bake_fps = 30.0f);
|
||||
PackedByteArray generate_buffer(Ref<GLTFState> state);
|
||||
Error write_to_filesystem(Ref<GLTFState> state, const String &p_path);
|
||||
|
||||
public:
|
||||
Error _parse_gltf_state(Ref<GLTFState> state, const String &p_search_path, float p_bake_fps);
|
||||
void _process_mesh_instances(Ref<GLTFState> state, Node *scene_root);
|
||||
void _generate_scene_node(Ref<GLTFState> state, Node *scene_parent,
|
||||
Node3D *scene_root,
|
||||
@ -447,8 +455,8 @@ public:
|
||||
MeshInstance3D *p_mesh_instance);
|
||||
void _convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
|
||||
String p_animation_track_name);
|
||||
Error serialize(Ref<GLTFState> state, Node *p_root, const String &p_path);
|
||||
Error parse(Ref<GLTFState> state, String p_paths, bool p_read_binary = false);
|
||||
Error _serialize(Ref<GLTFState> state, const String &p_path);
|
||||
Error _parse(Ref<GLTFState> state, String p_path, FileAccess *f, int p_bake_fps);
|
||||
};
|
||||
|
||||
#endif // GLTF_DOCUMENT_H
|
||||
|
Loading…
Reference in New Issue
Block a user