summaryrefslogtreecommitdiff
path: root/modules/gltf/gltf_document.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gltf/gltf_document.cpp')
-rw-r--r--modules/gltf/gltf_document.cpp175
1 files changed, 98 insertions, 77 deletions
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index 2c42879bd3..281f62c4ad 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -58,7 +58,6 @@
#include "core/variant/variant.h"
#include "core/version.h"
#include "drivers/png/png_driver_common.h"
-#include "editor/import/resource_importer_scene.h"
#include "scene/2d/node_2d.h"
#include "scene/3d/camera_3d.h"
#include "scene/3d/mesh_instance_3d.h"
@@ -66,6 +65,7 @@
#include "scene/3d/node_3d.h"
#include "scene/animation/animation_player.h"
#include "scene/resources/importer_mesh.h"
+#include "scene/resources/material.h"
#include "scene/resources/mesh.h"
#include "scene/resources/multimesh.h"
#include "scene/resources/surface_tool.h"
@@ -79,6 +79,10 @@
#include "modules/gridmap/grid_map.h"
#endif // MODULE_GRIDMAP_ENABLED
+// FIXME: Hardcoded to avoid editor dependency.
+#define GLTF_IMPORT_USE_NAMED_SKIN_BINDS 16
+#define GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS 32
+
#include <stdio.h>
#include <stdlib.h>
#include <cstdint>
@@ -254,8 +258,8 @@ Error GLTFDocument::_serialize_scenes(Ref<GLTFState> state) {
Error GLTFDocument::_parse_json(const String &p_path, Ref<GLTFState> state) {
Error err;
- FileAccessRef f = FileAccess::open(p_path, FileAccess::READ, &err);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
+ if (f.is_null()) {
return err;
}
@@ -276,7 +280,7 @@ Error GLTFDocument::_parse_json(const String &p_path, Ref<GLTFState> state) {
return OK;
}
-Error GLTFDocument::_parse_glb(FileAccess *f, Ref<GLTFState> state) {
+Error GLTFDocument::_parse_glb(Ref<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);
@@ -694,8 +698,8 @@ Error GLTFDocument::_encode_buffer_glb(Ref<GLTFState> state, const String &p_pat
String filename = p_path.get_basename().get_file() + itos(i) + ".bin";
String path = p_path.get_base_dir() + "/" + filename;
Error err;
- FileAccessRef f = FileAccess::open(path, FileAccess::WRITE, &err);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(path, FileAccess::WRITE, &err);
+ if (f.is_null()) {
return err;
}
if (buffer_data.size() == 0) {
@@ -703,7 +707,6 @@ Error GLTFDocument::_encode_buffer_glb(Ref<GLTFState> state, const String &p_pat
}
f->create(FileAccess::ACCESS_RESOURCES);
f->store_buffer(buffer_data.ptr(), buffer_data.size());
- f->close();
gltf_buffer["uri"] = filename;
gltf_buffer["byteLength"] = buffer_data.size();
buffers.push_back(gltf_buffer);
@@ -727,8 +730,8 @@ Error GLTFDocument::_encode_buffer_bins(Ref<GLTFState> state, const String &p_pa
String filename = p_path.get_basename().get_file() + itos(i) + ".bin";
String path = p_path.get_base_dir() + "/" + filename;
Error err;
- FileAccessRef f = FileAccess::open(path, FileAccess::WRITE, &err);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(path, FileAccess::WRITE, &err);
+ if (f.is_null()) {
return err;
}
if (buffer_data.size() == 0) {
@@ -736,7 +739,6 @@ Error GLTFDocument::_encode_buffer_bins(Ref<GLTFState> state, const String &p_pa
}
f->create(FileAccess::ACCESS_RESOURCES);
f->store_buffer(buffer_data.ptr(), buffer_data.size());
- f->close();
gltf_buffer["uri"] = filename;
gltf_buffer["byteLength"] = buffer_data.size();
buffers.push_back(gltf_buffer);
@@ -2907,34 +2909,43 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
}
array_copy = blend_surface_tool->commit_to_arrays();
+ // Enforce blend shape mask array format
+ for (int l = 0; l < Mesh::ARRAY_MAX; l++) {
+ if (!(Mesh::ARRAY_FORMAT_BLEND_SHAPE_MASK & (1 << l))) {
+ array_copy[l] = Variant();
+ }
+ }
+
morphs.push_back(array_copy);
}
}
- //just add it
-
Ref<BaseMaterial3D> mat;
- if (p.has("material")) {
- const int material = p["material"];
- ERR_FAIL_INDEX_V(material, state->materials.size(), ERR_FILE_CORRUPT);
- Ref<BaseMaterial3D> mat3d = state->materials[material];
- ERR_FAIL_NULL_V(mat3d, ERR_FILE_CORRUPT);
- if (has_vertex_color) {
- mat3d->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
- }
- mat = mat3d;
+ String mat_name;
+ if (!state->discard_meshes_and_materials) {
+ if (p.has("material")) {
+ const int material = p["material"];
+ ERR_FAIL_INDEX_V(material, state->materials.size(), ERR_FILE_CORRUPT);
+ Ref<BaseMaterial3D> mat3d = state->materials[material];
+ ERR_FAIL_NULL_V(mat3d, ERR_FILE_CORRUPT);
+ if (has_vertex_color) {
+ mat3d->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+ }
+ mat = mat3d;
- } else {
- Ref<StandardMaterial3D> mat3d;
- mat3d.instantiate();
- if (has_vertex_color) {
- mat3d->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+ } else {
+ Ref<StandardMaterial3D> mat3d;
+ mat3d.instantiate();
+ if (has_vertex_color) {
+ mat3d->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+ }
+ mat = mat3d;
}
- mat = mat3d;
+ ERR_FAIL_NULL_V(mat, ERR_FILE_CORRUPT);
+ mat_name = mat->get_name();
}
- ERR_FAIL_NULL_V(mat, ERR_FILE_CORRUPT);
import_mesh->add_surface(primitive, array, morphs,
- Dictionary(), mat, mat->get_name(), flags);
+ Dictionary(), mat, mat_name, flags);
}
Vector<float> blend_weights;
@@ -3012,7 +3023,7 @@ Error GLTFDocument::_serialize_images(Ref<GLTFState> state, const String &p_path
String texture_dir = "textures";
String path = p_path.get_base_dir();
String new_texture_dir = path + "/" + texture_dir;
- DirAccessRef da = DirAccess::open(path);
+ Ref<DirAccess> da = DirAccess::open(path);
if (!da->dir_exists(new_texture_dir)) {
da->make_dir(new_texture_dir);
}
@@ -3265,7 +3276,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
Dictionary mr;
{
Array arr;
- const Color c = material->get_albedo().to_linear();
+ const Color c = material->get_albedo().srgb_to_linear();
arr.push_back(c.r);
arr.push_back(c.g);
arr.push_back(c.b);
@@ -3466,7 +3477,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
}
if (material->get_feature(BaseMaterial3D::FEATURE_EMISSION)) {
- const Color c = material->get_emission().to_srgb();
+ const Color c = material->get_emission().linear_to_srgb();
Array arr;
arr.push_back(c.r);
arr.push_back(c.g);
@@ -3548,7 +3559,7 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) {
if (sgm.has("diffuseFactor")) {
const Array &arr = sgm["diffuseFactor"];
ERR_FAIL_COND_V(arr.size() != 4, ERR_PARSE_ERROR);
- const Color c = Color(arr[0], arr[1], arr[2], arr[3]).to_srgb();
+ const Color c = Color(arr[0], arr[1], arr[2], arr[3]).linear_to_srgb();
spec_gloss->diffuse_factor = c;
material->set_albedo(spec_gloss->diffuse_factor);
}
@@ -3579,7 +3590,7 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) {
if (mr.has("baseColorFactor")) {
const Array &arr = mr["baseColorFactor"];
ERR_FAIL_COND_V(arr.size() != 4, ERR_PARSE_ERROR);
- const Color c = Color(arr[0], arr[1], arr[2], arr[3]).to_srgb();
+ const Color c = Color(arr[0], arr[1], arr[2], arr[3]).linear_to_srgb();
material->set_albedo(c);
}
@@ -3646,7 +3657,7 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) {
if (d.has("emissiveFactor")) {
const Array &arr = d["emissiveFactor"];
ERR_FAIL_COND_V(arr.size() != 3, ERR_PARSE_ERROR);
- const Color c = Color(arr[0], arr[1], arr[2]).to_srgb();
+ const Color c = Color(arr[0], arr[1], arr[2]).linear_to_srgb();
material->set_feature(BaseMaterial3D::FEATURE_EMISSION, true);
material->set_emission(c);
@@ -3730,11 +3741,11 @@ void GLTFDocument::spec_gloss_to_rough_metal(Ref<GLTFSpecGloss> r_spec_gloss, Re
}
for (int32_t y = 0; y < r_spec_gloss->spec_gloss_img->get_height(); y++) {
for (int32_t x = 0; x < r_spec_gloss->spec_gloss_img->get_width(); x++) {
- const Color specular_pixel = r_spec_gloss->spec_gloss_img->get_pixel(x, y).to_linear();
+ const Color specular_pixel = r_spec_gloss->spec_gloss_img->get_pixel(x, y).srgb_to_linear();
Color specular = Color(specular_pixel.r, specular_pixel.g, specular_pixel.b);
specular *= r_spec_gloss->specular_factor;
Color diffuse = Color(1.0f, 1.0f, 1.0f);
- diffuse *= r_spec_gloss->diffuse_img->get_pixel(x, y).to_linear();
+ diffuse *= r_spec_gloss->diffuse_img->get_pixel(x, y).srgb_to_linear();
float metallic = 0.0f;
Color base_color;
spec_gloss_to_metal_base_color(specular, diffuse, base_color, metallic);
@@ -3751,7 +3762,7 @@ void GLTFDocument::spec_gloss_to_rough_metal(Ref<GLTFSpecGloss> r_spec_gloss, Re
mr.g = 1.0f - mr.g;
rm_img->set_pixel(x, y, mr);
if (r_spec_gloss->diffuse_img.is_valid()) {
- r_spec_gloss->diffuse_img->set_pixel(x, y, base_color.to_srgb());
+ r_spec_gloss->diffuse_img->set_pixel(x, y, base_color.linear_to_srgb());
}
}
}
@@ -4619,7 +4630,7 @@ Error GLTFDocument::_parse_lights(Ref<GLTFState> state) {
if (d.has("color")) {
const Array &arr = d["color"];
ERR_FAIL_COND_V(arr.size() != 3, ERR_PARSE_ERROR);
- const Color c = Color(arr[0], arr[1], arr[2]).to_srgb();
+ const Color c = Color(arr[0], arr[1], arr[2]).linear_to_srgb();
light->color = c;
}
if (d.has("intensity")) {
@@ -5741,7 +5752,7 @@ void GLTFDocument::_generate_skeleton_bone_node(Ref<GLTFState> state, Node *scen
}
template <class T>
-struct EditorSceneFormatImporterGLTFInterpolate {
+struct SceneFormatImporterGLTFInterpolate {
T lerp(const T &a, const T &b, float c) const {
return a + (b - a) * c;
}
@@ -5767,7 +5778,7 @@ struct EditorSceneFormatImporterGLTFInterpolate {
// thank you for existing, partial specialization
template <>
-struct EditorSceneFormatImporterGLTFInterpolate<Quaternion> {
+struct SceneFormatImporterGLTFInterpolate<Quaternion> {
Quaternion lerp(const Quaternion &a, const Quaternion &b, const float c) const {
ERR_FAIL_COND_V_MSG(!a.is_normalized(), Quaternion(), "The quaternion \"a\" must be normalized.");
ERR_FAIL_COND_V_MSG(!b.is_normalized(), Quaternion(), "The quaternion \"b\" must be normalized.");
@@ -5806,7 +5817,7 @@ T GLTFDocument::_interpolate_track(const Vector<real_t> &p_times, const Vector<T
idx++;
}
- EditorSceneFormatImporterGLTFInterpolate<T> interp;
+ SceneFormatImporterGLTFInterpolate<T> interp;
switch (p_interp) {
case GLTFAnimation::INTERP_LINEAR: {
@@ -6088,7 +6099,14 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap,
animation->set_length(length);
- ap->add_animation(name, animation);
+ Ref<AnimationLibrary> library;
+ if (!ap->has_animation_library("")) {
+ library.instantiate();
+ ap->add_animation_library("", library);
+ } else {
+ library = ap->get_animation_library("");
+ }
+ library->add_animation(name, animation);
}
void GLTFDocument::_convert_mesh_instances(Ref<GLTFState> state) {
@@ -6470,8 +6488,8 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
gltf_animation->get_tracks().insert(transform_track_i.key, track);
}
}
- } else if (String(orig_track_path).contains(":blend_shapes/")) {
- const Vector<String> node_suffix = String(orig_track_path).split(":blend_shapes/");
+ } else if (String(orig_track_path).contains(":") && animation->track_get_type(track_i) == Animation::TYPE_BLEND_SHAPE) {
+ const Vector<String> node_suffix = String(orig_track_path).split(":");
const NodePath path = node_suffix[0];
const String suffix = node_suffix[1];
Node *node = ap->get_parent()->get_node_or_null(path);
@@ -6579,9 +6597,9 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
}
}
-Error GLTFDocument::_parse(Ref<GLTFState> state, String p_path, FileAccess *f, int p_bake_fps) {
+Error GLTFDocument::_parse(Ref<GLTFState> state, String p_path, Ref<FileAccess> f, int p_bake_fps) {
Error err;
- if (!f) {
+ if (f.is_null()) {
return FAILED;
}
f->seek(0);
@@ -6605,7 +6623,6 @@ Error GLTFDocument::_parse(Ref<GLTFState> state, String p_path, FileAccess *f, i
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
state->json = json.get_data();
}
- f->close();
if (!state->json.has("asset")) {
return ERR_PARSE_ERROR;
@@ -6694,8 +6711,8 @@ Error GLTFDocument::_serialize_file(Ref<GLTFState> state, const String p_path) {
if (p_path.to_lower().ends_with("glb")) {
err = _encode_buffer_glb(state, p_path);
ERR_FAIL_COND_V(err != OK, err);
- FileAccessRef f = FileAccess::open(p_path, FileAccess::WRITE, &err);
- ERR_FAIL_COND_V(!f, FAILED);
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE, &err);
+ ERR_FAIL_COND_V(f.is_null(), FAILED);
String json = Variant(state->json).to_json_string();
@@ -6732,25 +6749,22 @@ Error GLTFDocument::_serialize_file(Ref<GLTFState> state, const String p_path) {
for (uint32_t pad_i = binary_data_length; pad_i < binary_chunk_length; pad_i++) {
f->store_8(0);
}
-
- f->close();
} else {
err = _encode_buffer_bins(state, p_path);
ERR_FAIL_COND_V(err != OK, err);
- FileAccessRef f = FileAccess::open(p_path, FileAccess::WRITE, &err);
- ERR_FAIL_COND_V(!f, FAILED);
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE, &err);
+ ERR_FAIL_COND_V(f.is_null(), FAILED);
f->create(FileAccess::ACCESS_RESOURCES);
String json = Variant(state->json).to_json_string();
f->store_string(json);
- f->close();
}
return err;
}
void GLTFDocument::_bind_methods() {
- 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_file", "path", "state", "flags", "bake_fps", "base_path"),
+ &GLTFDocument::append_from_file, DEFVAL(0), DEFVAL(30), DEFVAL(String()));
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"),
@@ -6898,8 +6912,8 @@ Node *GLTFDocument::generate_scene(Ref<GLTFState> state, int32_t p_bake_fps) {
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;
+ state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS;
+ state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS;
_convert_scene_node(state, p_node, -1, -1);
if (!state->buffers.size()) {
@@ -6918,9 +6932,11 @@ Error GLTFDocument::append_from_buffer(PackedByteArray p_bytes, String p_base_pa
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);
+ state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS;
+ state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS;
+
+ Ref<FileAccessMemory> file_access;
+ file_access.instantiate();
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);
@@ -6957,20 +6973,22 @@ Error GLTFDocument::_parse_gltf_state(Ref<GLTFState> state, const String &p_sear
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
- /* PARSE IMAGES */
- err = _parse_images(state, p_search_path);
+ if (!state->discard_meshes_and_materials) {
+ /* PARSE IMAGES */
+ err = _parse_images(state, p_search_path);
- ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
+ ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
- /* PARSE TEXTURES */
- err = _parse_textures(state);
+ /* PARSE TEXTURES */
+ err = _parse_textures(state);
- ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
+ ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
- /* PARSE TEXTURES */
- err = _parse_materials(state);
+ /* PARSE TEXTURES */
+ err = _parse_materials(state);
- ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
+ ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
+ }
/* PARSE SKINS */
err = _parse_skins(state);
@@ -7015,20 +7033,23 @@ Error GLTFDocument::_parse_gltf_state(Ref<GLTFState> state, const String &p_sear
return OK;
}
-Error GLTFDocument::append_from_file(String p_path, Ref<GLTFState> r_state, uint32_t p_flags, int32_t p_bake_fps) {
+Error GLTFDocument::append_from_file(String p_path, Ref<GLTFState> r_state, uint32_t p_flags, int32_t p_bake_fps, String p_base_path) {
// 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;
+ r_state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS;
+ r_state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS;
Error err;
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
+ Ref<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);
+ String base_path = p_base_path;
+ if (base_path.is_empty()) {
+ base_path = p_path.get_base_dir();
+ }
+ err = _parse(r_state, base_path, f, p_bake_fps);
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
return err;
}