Created
December 5, 2020 19:16
-
-
Save Miouyouyou/7843e81effb22770b8a1b7411e18fd6f to your computer and use it in GitHub Desktop.
GLTF Document changes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- gltf_document.cpp 2020-12-05 20:03:10.357261955 +0100 | |
+++ ../godot/modules/gltf/gltf_document.cpp 2020-12-05 19:55:20.862232677 +0100 | |
@@ -45,11 +45,12 @@ | |
#include "thirdparty/misc/rjm_texbleed.h" | |
-#include "core/bind/core_bind.h" | |
+#include "core/core_bind.h" | |
#include "core/crypto/crypto_core.h" | |
#include "core/io/json.h" | |
#include "core/math/disjoint_set.h" | |
#include "core/os/file_access.h" | |
+#include "core/variant/typed_array.h" | |
#include "core/version.h" | |
#include "core/version_hash.gen.h" | |
#include "drivers/png/png_driver_common.h" | |
@@ -58,18 +59,17 @@ | |
#include "modules/gridmap/grid_map.h" | |
#include "modules/regex/regex.h" | |
#include "scene/2d/node_2d.h" | |
-#include "scene/3d/bone_attachment.h" | |
-#include "scene/3d/camera.h" | |
-#include "scene/3d/mesh_instance.h" | |
-#include "scene/3d/multimesh_instance.h" | |
-#include "scene/3d/skeleton.h" | |
-#include "scene/3d/spatial.h" | |
+#include "scene/3d/bone_attachment_3d.h" | |
+#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/3d/skeleton_3d.h" | |
#include "scene/animation/animation_player.h" | |
#include "scene/resources/surface_tool.h" | |
#include <limits> | |
Error GLTFDocument::serialize(Ref<GLTFState> state, const String &p_path) { | |
- | |
uint64_t begin_time = OS::get_singleton()->get_ticks_usec(); | |
if (!state->buffers.size()) { | |
@@ -215,7 +215,6 @@ | |
} | |
Error GLTFDocument::_parse_json(const String &p_path, Ref<GLTFState> state) { | |
- | |
Error err; | |
FileAccessRef f = FileAccess::open(p_path, FileAccess::READ, &err); | |
if (!f) { | |
@@ -244,7 +243,7 @@ | |
Error GLTFDocument::_serialize_bone_attachment(Ref<GLTFState> state) { | |
for (int skeleton_i = 0; skeleton_i < state->skeletons.size(); skeleton_i++) { | |
for (int attachment_i = 0; attachment_i < state->skeletons[skeleton_i]->bone_attachments.size(); attachment_i++) { | |
- BoneAttachment *bone_attachment = state->skeletons[skeleton_i]->bone_attachments[attachment_i]; | |
+ BoneAttachment3D *bone_attachment = state->skeletons[skeleton_i]->bone_attachments[attachment_i]; | |
String bone_name = bone_attachment->get_bone_name(); | |
bone_name = _sanitize_bone_name(bone_name); | |
int32_t bone = state->skeletons[skeleton_i]->godot_skeleton->find_bone(bone_name); | |
@@ -266,7 +265,6 @@ | |
} | |
Error GLTFDocument::_parse_glb(const String &p_path, Ref<GLTFState> state) { | |
- | |
Error err; | |
FileAccessRef f = FileAccess::open(p_path, FileAccess::READ, &err); | |
if (!f) { | |
@@ -447,7 +445,6 @@ | |
} | |
String GLTFDocument::_gen_unique_name(Ref<GLTFState> state, const String &p_name) { | |
- | |
const String s_name = _sanitize_scene_name(p_name); | |
String name; | |
@@ -491,7 +488,6 @@ | |
} | |
String GLTFDocument::_gen_unique_bone_name(Ref<GLTFState> state, const GLTFSkeletonIndex skel_i, const String &p_name) { | |
- | |
String s_name = _sanitize_bone_name(p_name); | |
if (s_name.empty()) { | |
s_name = "bone"; | |
@@ -516,7 +512,6 @@ | |
} | |
Error GLTFDocument::_parse_scenes(Ref<GLTFState> state) { | |
- | |
ERR_FAIL_COND_V(!state->json.has("scenes"), ERR_FILE_CORRUPT); | |
const Array &scenes = state->json["scenes"]; | |
int loaded_scene = 0; | |
@@ -546,11 +541,9 @@ | |
} | |
Error GLTFDocument::_parse_nodes(Ref<GLTFState> state) { | |
- | |
ERR_FAIL_COND_V(!state->json.has("nodes"), ERR_FILE_CORRUPT); | |
const Array &nodes = state->json["nodes"]; | |
for (int i = 0; i < nodes.size(); i++) { | |
- | |
Ref<GLTFNode> node; | |
node.instance(); | |
const Dictionary &n = nodes[i]; | |
@@ -570,7 +563,6 @@ | |
if (n.has("matrix")) { | |
node->xform = _arr_to_xform(n["matrix"]); | |
} else { | |
- | |
if (n.has("translation")) { | |
node->translation = _arr_to_vec3(n["translation"]); | |
} | |
@@ -608,7 +600,6 @@ | |
// build the hierarchy | |
for (GLTFNodeIndex node_i = 0; node_i < state->nodes.size(); node_i++) { | |
- | |
for (int j = 0; j < state->nodes[node_i]->children.size(); j++) { | |
GLTFNodeIndex child_i = state->nodes[node_i]->children[j]; | |
@@ -625,7 +616,6 @@ | |
} | |
void GLTFDocument::_compute_node_heights(Ref<GLTFState> state) { | |
- | |
state->root_nodes.clear(); | |
for (GLTFNodeIndex node_i = 0; node_i < state->nodes.size(); ++node_i) { | |
Ref<GLTFNode> node = state->nodes[node_i]; | |
@@ -647,7 +637,6 @@ | |
} | |
static Vector<uint8_t> _parse_base64_uri(const String &uri) { | |
- | |
int start = uri.find(","); | |
ERR_FAIL_COND_V(start == -1, Vector<uint8_t>()); | |
@@ -666,7 +655,6 @@ | |
return buf; | |
} | |
Error GLTFDocument::_encode_buffer_glb(Ref<GLTFState> state, const String &p_path) { | |
- | |
print_verbose("glTF: Total buffers: " + itos(state->buffers.size())); | |
if (!state->buffers.size()) { | |
@@ -707,7 +695,6 @@ | |
} | |
Error GLTFDocument::_encode_buffer_bins(Ref<GLTFState> state, const String &p_path) { | |
- | |
print_verbose("glTF: Total buffers: " + itos(state->buffers.size())); | |
if (!state->buffers.size()) { | |
@@ -741,30 +728,32 @@ | |
} | |
Error GLTFDocument::_parse_buffers(Ref<GLTFState> state, const String &p_base_path) { | |
- | |
- if (!state->json.has("buffers")) | |
+ if (!state->json.has("buffers")) { | |
return OK; | |
+ } | |
const Array &buffers = state->json["buffers"]; | |
for (GLTFBufferIndex i = 0; i < buffers.size(); i++) { | |
- | |
if (i == 0 && state->glb_data.size()) { | |
state->buffers.push_back(state->glb_data); | |
+ | |
} else { | |
const Dictionary &buffer = buffers[i]; | |
if (buffer.has("uri")) { | |
- | |
Vector<uint8_t> buffer_data; | |
String uri = buffer["uri"]; | |
- if (uri.findn("data:application/octet-stream;base64") == 0) { | |
- //embedded data | |
+ if (uri.begins_with("data:")) { // Embedded data using base64. | |
+ // Validate data MIME types and throw an error if it's one we don't know/support. | |
+ if (!uri.begins_with("data:application/octet-stream;base64") && | |
+ !uri.begins_with("data:application/gltf-buffer;base64")) { | |
+ ERR_PRINT("glTF: Got buffer with an unknown URI data type: " + uri); | |
+ } | |
buffer_data = _parse_base64_uri(uri); | |
- } else { | |
- | |
- uri = p_base_path.plus_file(uri).replace("\\", "/"); //fix for windows | |
+ } else { // Relative path to an external image file. | |
+ uri = p_base_path.plus_file(uri).replace("\\", "/"); // Fix for Windows. | |
buffer_data = FileAccess::get_file_as_array(uri); | |
- ERR_FAIL_COND_V(buffer.size() == 0, ERR_PARSE_ERROR); | |
+ ERR_FAIL_COND_V_MSG(buffer.size() == 0, ERR_PARSE_ERROR, "glTF: Couldn't load binary file as an array: " + uri); | |
} | |
ERR_FAIL_COND_V(!buffer.has("byteLength"), ERR_PARSE_ERROR); | |
@@ -781,10 +770,8 @@ | |
} | |
Error GLTFDocument::_encode_buffer_views(Ref<GLTFState> state) { | |
- | |
Array buffers; | |
for (GLTFBufferViewIndex i = 0; i < state->buffer_views.size(); i++) { | |
- | |
Dictionary d; | |
Ref<GLTFBufferView> buffer_view = state->buffer_views[i]; | |
@@ -811,11 +798,9 @@ | |
} | |
Error GLTFDocument::_parse_buffer_views(Ref<GLTFState> state) { | |
- | |
ERR_FAIL_COND_V(!state->json.has("bufferViews"), ERR_FILE_CORRUPT); | |
const Array &buffers = state->json["bufferViews"]; | |
for (GLTFBufferViewIndex i = 0; i < buffers.size(); i++) { | |
- | |
const Dictionary &d = buffers[i]; | |
Ref<GLTFBufferView> buffer_view; | |
@@ -848,10 +833,8 @@ | |
} | |
Error GLTFDocument::_encode_accessors(Ref<GLTFState> state) { | |
- | |
Array accessors; | |
for (GLTFAccessorIndex i = 0; i < state->accessors.size(); i++) { | |
- | |
Dictionary d; | |
Ref<GLTFAccessor> accessor = state->accessors[i]; | |
@@ -904,7 +887,6 @@ | |
} | |
String GLTFDocument::_get_accessor_type_name(const GLTFDocument::GLTFType p_type) { | |
- | |
if (p_type == GLTFDocument::TYPE_SCALAR) { | |
return "SCALAR"; | |
} | |
@@ -931,7 +913,6 @@ | |
} | |
GLTFDocument::GLTFType GLTFDocument::_get_type_from_str(const String &p_string) { | |
- | |
if (p_string == "SCALAR") | |
return GLTFDocument::TYPE_SCALAR; | |
@@ -953,11 +934,9 @@ | |
} | |
Error GLTFDocument::_parse_accessors(Ref<GLTFState> state) { | |
- | |
ERR_FAIL_COND_V(!state->json.has("accessors"), ERR_FILE_CORRUPT); | |
const Array &accessors = state->json["accessors"]; | |
for (GLTFAccessorIndex i = 0; i < accessors.size(); i++) { | |
- | |
const Dictionary &d = accessors[i]; | |
Ref<GLTFAccessor> accessor; | |
@@ -1024,7 +1003,6 @@ | |
} | |
String GLTFDocument::_get_component_type_name(const uint32_t p_component) { | |
- | |
switch (p_component) { | |
case GLTFDocument::COMPONENT_TYPE_BYTE: | |
return "Byte"; | |
@@ -1044,7 +1022,6 @@ | |
} | |
String GLTFDocument::_get_type_name(const GLTFType p_component) { | |
- | |
static const char *names[] = { | |
"float", | |
"vec2", | |
@@ -1059,7 +1036,6 @@ | |
} | |
Error GLTFDocument::_encode_buffer_view(Ref<GLTFState> state, const double *src, const int count, const GLTFType type, const int component_type, const bool normalized, const int byte_offset, const bool for_vertex, GLTFBufferViewIndex &r_accessor) { | |
- | |
const int component_count_for_type[7] = { | |
1, 2, 3, 4, 4, 9, 16 | |
}; | |
@@ -1074,7 +1050,6 @@ | |
switch (component_type) { | |
case COMPONENT_TYPE_BYTE: | |
case COMPONENT_TYPE_UNSIGNED_BYTE: { | |
- | |
if (type == TYPE_MAT2) { | |
skip_every = 2; | |
skip_bytes = 2; | |
@@ -1258,7 +1233,6 @@ | |
} | |
Error GLTFDocument::_decode_buffer_view(Ref<GLTFState> state, double *dst, const GLTFBufferViewIndex p_buffer_view, const int skip_every, const int skip_bytes, const int element_size, const int count, const GLTFType type, const int component_count, const int component_type, const int component_size, const bool normalized, const int byte_offset, const bool for_vertex) { | |
- | |
const Ref<GLTFBufferView> bv = state->buffer_views[p_buffer_view]; | |
int stride = element_size; | |
@@ -1287,11 +1261,9 @@ | |
//fill everything as doubles | |
for (int i = 0; i < count; i++) { | |
- | |
const uint8_t *src = &bufptr[offset + i * stride]; | |
for (int j = 0; j < component_count; j++) { | |
- | |
if (skip_every && j > 0 && (j % skip_every) == 0) { | |
src += skip_bytes; | |
} | |
@@ -1348,7 +1320,6 @@ | |
} | |
int GLTFDocument::_get_component_type_size(const int component_type) { | |
- | |
switch (component_type) { | |
case COMPONENT_TYPE_BYTE: | |
case COMPONENT_TYPE_UNSIGNED_BYTE: | |
@@ -1372,7 +1343,6 @@ | |
} | |
Vector<double> GLTFDocument::_decode_accessor(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { | |
- | |
//spec, for reference: | |
//https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#data-alignment | |
@@ -1395,7 +1365,6 @@ | |
switch (a->component_type) { | |
case COMPONENT_TYPE_BYTE: | |
case COMPONENT_TYPE_UNSIGNED_BYTE: { | |
- | |
if (a->type == TYPE_MAT2) { | |
skip_every = 2; | |
skip_bytes = 2; | |
@@ -1424,7 +1393,6 @@ | |
double *dst = dst_buffer.ptrw(); | |
if (a->buffer_view >= 0) { | |
- | |
ERR_FAIL_INDEX_V(a->buffer_view, state->buffer_views.size(), Vector<double>()); | |
const Error err = _decode_buffer_view(state, dst, a->buffer_view, skip_every, skip_bytes, element_size, a->count, a->type, component_count, a->component_type, component_size, a->normalized, a->byte_offset, p_for_vertex); | |
@@ -1466,7 +1434,6 @@ | |
} | |
GLTFAccessorIndex GLTFDocument::_encode_accessor_as_ints(Ref<GLTFState> state, const Vector<int32_t> p_attribs, const bool p_for_vertex) { | |
- | |
if (p_attribs.size() == 0) { | |
return -1; | |
} | |
@@ -1513,7 +1480,6 @@ | |
} | |
Vector<int> GLTFDocument::_decode_accessor_as_ints(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { | |
- | |
const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); | |
Vector<int> ret; | |
@@ -1532,7 +1498,6 @@ | |
} | |
Vector<float> GLTFDocument::_decode_accessor_as_floats(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { | |
- | |
const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); | |
Vector<float> ret; | |
@@ -1551,7 +1516,6 @@ | |
} | |
GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec2(Ref<GLTFState> state, const Vector<Vector2> p_attribs, const bool p_for_vertex) { | |
- | |
if (p_attribs.size() == 0) { | |
return -1; | |
} | |
@@ -1611,7 +1575,6 @@ | |
} | |
GLTFAccessorIndex GLTFDocument::_encode_accessor_as_color(Ref<GLTFState> state, const Vector<Color> p_attribs, const bool p_for_vertex) { | |
- | |
if (p_attribs.size() == 0) { | |
return -1; | |
} | |
@@ -1684,7 +1647,6 @@ | |
} | |
GLTFAccessorIndex GLTFDocument::_encode_accessor_as_weights(Ref<GLTFState> state, const Vector<Color> p_attribs, const bool p_for_vertex) { | |
- | |
if (p_attribs.size() == 0) { | |
return -1; | |
} | |
@@ -1760,7 +1722,6 @@ | |
} | |
GLTFAccessorIndex GLTFDocument::_encode_accessor_as_joints(Ref<GLTFState> state, const Vector<Color> p_attribs, const bool p_for_vertex) { | |
- | |
if (p_attribs.size() == 0) { | |
return -1; | |
} | |
@@ -1834,7 +1795,6 @@ | |
} | |
GLTFAccessorIndex GLTFDocument::_encode_accessor_as_quats(Ref<GLTFState> state, const Vector<Quat> p_attribs, const bool p_for_vertex) { | |
- | |
if (p_attribs.size() == 0) { | |
return -1; | |
} | |
@@ -1909,7 +1869,6 @@ | |
} | |
Vector<Vector2> GLTFDocument::_decode_accessor_as_vec2(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { | |
- | |
const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); | |
Vector<Vector2> ret; | |
@@ -1977,7 +1936,6 @@ | |
} | |
GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec3(Ref<GLTFState> state, const Vector<Vector3> p_attribs, const bool p_for_vertex) { | |
- | |
if (p_attribs.size() == 0) { | |
return -1; | |
} | |
@@ -2197,7 +2155,6 @@ | |
} | |
Vector<Vector3> GLTFDocument::_decode_accessor_as_vec3(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { | |
- | |
const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); | |
Vector<Vector3> ret; | |
@@ -2217,7 +2174,6 @@ | |
} | |
Vector<Color> GLTFDocument::_decode_accessor_as_color(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { | |
- | |
const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); | |
Vector<Color> ret; | |
@@ -2243,7 +2199,6 @@ | |
return ret; | |
} | |
Vector<Quat> GLTFDocument::_decode_accessor_as_quat(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { | |
- | |
const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); | |
Vector<Quat> ret; | |
@@ -2262,7 +2217,6 @@ | |
return ret; | |
} | |
Vector<Transform2D> GLTFDocument::_decode_accessor_as_xform2d(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { | |
- | |
const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); | |
Vector<Transform2D> ret; | |
@@ -2279,7 +2233,6 @@ | |
} | |
Vector<Basis> GLTFDocument::_decode_accessor_as_basis(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { | |
- | |
const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); | |
Vector<Basis> ret; | |
@@ -2297,7 +2250,6 @@ | |
} | |
Vector<Transform> GLTFDocument::_decode_accessor_as_xform(Ref<GLTFState> state, const GLTFAccessorIndex p_accessor, const bool p_for_vertex) { | |
- | |
const Vector<double> attribs = _decode_accessor(state, p_accessor, p_for_vertex); | |
Vector<Transform> ret; | |
@@ -2318,7 +2270,6 @@ | |
Error GLTFDocument::_serialize_meshes(Ref<GLTFState> state) { | |
Array meshes; | |
for (GLTFMeshIndex gltf_mesh_i = 0; gltf_mesh_i < state->meshes.size(); gltf_mesh_i++) { | |
- | |
print_verbose("glTF: Serializing mesh: " + itos(gltf_mesh_i)); | |
Ref<Mesh> godot_mesh = state->meshes.write[gltf_mesh_i]->mesh; | |
if (godot_mesh.is_null()) { | |
@@ -2411,7 +2362,6 @@ | |
{ | |
Vector<Vector2> a = array[Mesh::ARRAY_TEX_UV2]; | |
if (a.size()) { | |
- | |
attributes["TEXCOORD_1"] = _encode_accessor_as_vec2(state, a, true); | |
} | |
} | |
@@ -2501,7 +2451,6 @@ | |
//blend shapes | |
print_verbose("glTF: Mesh has targets"); | |
if (godot_mesh->get_blend_shape_count()) { | |
- | |
Array array_morphs = godot_mesh->surface_get_blend_shape_arrays(surface_i); | |
for (int morph_i = 0; morph_i < array_morphs.size(); morph_i++) { | |
target_names.push_back(godot_mesh->get_blend_shape_name(morph_i)); | |
@@ -2593,13 +2542,11 @@ | |
return OK; | |
} | |
Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { | |
- | |
if (!state->json.has("meshes")) | |
return OK; | |
Array meshes = state->json["meshes"]; | |
for (GLTFMeshIndex i = 0; i < meshes.size(); i++) { | |
- | |
print_verbose("glTF: Parsing mesh: " + itos(i)); | |
Dictionary d = meshes[i]; | |
@@ -2611,7 +2558,6 @@ | |
const Dictionary &extras = d.has("extras") ? (Dictionary)d["extras"] : Dictionary(); | |
for (int j = 0; j < primitives.size(); j++) { | |
- | |
Dictionary p = primitives[j]; | |
Array array; | |
@@ -2763,7 +2709,6 @@ | |
} | |
for (int k = 0; k < targets.size(); k++) { | |
- | |
const Dictionary &t = targets[k]; | |
Array array_copy; | |
@@ -2781,7 +2726,6 @@ | |
const int size = src_varr.size(); | |
ERR_FAIL_COND_V(size == 0, ERR_PARSE_ERROR); | |
{ | |
- | |
const int max_idx = varr.size(); | |
varr.resize(size); | |
@@ -2822,13 +2766,11 @@ | |
Vector<float> tangents_v4; | |
{ | |
- | |
int max_idx = tangents_v3.size(); | |
int size4 = src_tangents.size(); | |
tangents_v4.resize(size4); | |
for (int l = 0; l < size4 / 4; l++) { | |
- | |
if (l < max_idx) { | |
tangents_v4.write[l * 4 + 0] = tangents_v3[l].x + src_tangents[l * 4 + 0]; | |
tangents_v4.write[l * 4 + 1] = tangents_v3[l].y + src_tangents[l * 4 + 1]; | |
@@ -2868,9 +2810,9 @@ | |
array_mesh->surface_set_material(array_mesh->get_surface_count() - 1, mat); | |
} else { | |
- Ref<SpatialMaterial> mat; | |
+ Ref<StandardMaterial3D> mat; | |
mat.instance(); | |
- mat->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); | |
+ mat->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); | |
array_mesh->surface_set_material(array_mesh->get_surface_count() - 1, mat); | |
} | |
@@ -2905,10 +2847,8 @@ | |
} | |
Error GLTFDocument::_serialize_images(Ref<GLTFState> state, const String &p_path) { | |
- | |
Array images; | |
for (int i = 0; i < state->images.size(); i++) { | |
- | |
Dictionary d; | |
ERR_CONTINUE(state->images[i].is_null()); | |
@@ -2927,13 +2867,13 @@ | |
bv->byte_offset = state->buffers[bi].size(); | |
ERR_FAIL_INDEX_V(bi, state->buffers.size(), ERR_PARAMETER_RANGE_ERROR); | |
- PoolVector<uint8_t> buffer; | |
+ Vector<uint8_t> buffer; | |
Error err = PNGDriverCommon::image_to_png(image, buffer); | |
ERR_FAIL_COND_V_MSG(err, err, "Can't convert image to PNG."); | |
bv->byte_length = buffer.size(); | |
state->buffers.write[bi].resize(state->buffers[bi].size() + bv->byte_length); | |
- copymem(&state->buffers.write[bi].write[bv->byte_offset], buffer.write().ptr(), buffer.size()); | |
+ copymem(&state->buffers.write[bi].write[bv->byte_offset], buffer.ptr(), buffer.size()); | |
ERR_FAIL_COND_V(bv->byte_offset + bv->byte_length > state->buffers[bi].size(), ERR_FILE_CORRUPT); | |
state->buffer_views.push_back(bv); | |
@@ -2973,48 +2913,94 @@ | |
} | |
Error GLTFDocument::_parse_images(Ref<GLTFState> state, const String &p_base_path) { | |
- | |
- if (!state->json.has("images")) | |
+ if (!state->json.has("images")) { | |
return OK; | |
+ } | |
+ | |
+ // Ref: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#images | |
const Array &images = state->json["images"]; | |
for (int i = 0; i < images.size(); i++) { | |
- | |
const Dictionary &d = images[i]; | |
+ // glTF 2.0 supports PNG and JPEG types, which can be specified as (from spec): | |
+ // "- a URI to an external file in one of the supported images formats, or | |
+ // - a URI with embedded base64-encoded data, or | |
+ // - a reference to a bufferView; in that case mimeType must be defined." | |
+ // Since mimeType is optional for external files and base64 data, we'll have to | |
+ // fall back on letting Godot parse the data to figure out if it's PNG or JPEG. | |
+ | |
+ // We'll assume that we use either URI or bufferView, so let's warn the user | |
+ // if their image somehow uses both. And fail if it has neither. | |
+ ERR_CONTINUE_MSG(!d.has("uri") && !d.has("bufferView"), "Invalid image definition in glTF file, it should specific an 'uri' or 'bufferView'."); | |
+ if (d.has("uri") && d.has("bufferView")) { | |
+ WARN_PRINT("Invalid image definition in glTF file using both 'uri' and 'bufferView'. 'bufferView' will take precedence."); | |
+ } | |
+ | |
String mimetype; | |
- if (d.has("mimeType")) { | |
+ if (d.has("mimeType")) { // Should be "image/png" or "image/jpeg". | |
mimetype = d["mimeType"]; | |
} | |
Vector<uint8_t> data; | |
- const uint8_t *data_ptr = NULL; | |
+ const uint8_t *data_ptr = nullptr; | |
int data_size = 0; | |
if (d.has("uri")) { | |
+ // Handles the first two bullet points from the spec (embedded data, or external file). | |
String uri = d["uri"]; | |
- if (uri.findn("data:application/octet-stream;base64") == 0 || | |
- uri.findn("data:" + mimetype + ";base64") == 0) { | |
- //embedded data | |
+ if (uri.begins_with("data:")) { // Embedded data using base64. | |
+ // Validate data MIME types and throw a warning if it's one we don't know/support. | |
+ if (!uri.begins_with("data:application/octet-stream;base64") && | |
+ !uri.begins_with("data:application/gltf-buffer;base64") && | |
+ !uri.begins_with("data:image/png;base64") && | |
+ !uri.begins_with("data:image/jpeg;base64")) { | |
+ WARN_PRINT(vformat("glTF: Image index '%d' uses an unsupported URI data type: %s. Skipping it.", i, uri)); | |
+ state->images.push_back(Ref<Texture2D>()); // Placeholder to keep count. | |
+ continue; | |
+ } | |
data = _parse_base64_uri(uri); | |
data_ptr = data.ptr(); | |
data_size = data.size(); | |
- } else { | |
- | |
- uri = p_base_path.plus_file(uri).replace("\\", "/"); //fix for windows | |
- Ref<Texture> texture = ResourceLoader::load(uri); | |
- state->images.push_back(texture); | |
- continue; | |
+ // mimeType is optional, but if we have it defined in the URI, let's use it. | |
+ if (mimetype.empty()) { | |
+ if (uri.begins_with("data:image/png;base64")) { | |
+ mimetype = "image/png"; | |
+ } else if (uri.begins_with("data:image/jpeg;base64")) { | |
+ mimetype = "image/jpeg"; | |
+ } | |
+ } | |
+ } else { // Relative path to an external image file. | |
+ uri = p_base_path.plus_file(uri).replace("\\", "/"); // Fix for Windows. | |
+ // The spec says that if mimeType is defined, we should enforce it. | |
+ // So we should only rely on ResourceLoader::load if mimeType is not defined, | |
+ // otherwise we should use the same logic as for buffers. | |
+ if (mimetype == "image/png" || mimetype == "image/jpeg") { | |
+ // Load data buffer and rely on PNG and JPEG-specific logic below to load the image. | |
+ // This makes it possible to load a file with a wrong extension but correct MIME type, | |
+ // e.g. "foo.jpg" containing PNG data and with MIME type "image/png". ResourceLoader would fail. | |
+ data = FileAccess::get_file_as_array(uri); | |
+ ERR_FAIL_COND_V_MSG(data.size() == 0, ERR_PARSE_ERROR, "glTF: Couldn't load image file as an array: " + uri); | |
+ data_ptr = data.ptr(); | |
+ data_size = data.size(); | |
+ } else { | |
+ // Good old ResourceLoader will rely on file extension. | |
+ Ref<Texture2D> texture = ResourceLoader::load(uri); | |
+ state->images.push_back(texture); | |
+ continue; | |
+ } | |
} | |
- } | |
+ } else if (d.has("bufferView")) { | |
+ // Handles the third bullet point from the spec (bufferView). | |
+ ERR_FAIL_COND_V_MSG(mimetype.empty(), ERR_FILE_CORRUPT, | |
+ vformat("glTF: Image index '%d' specifies 'bufferView' but no 'mimeType', which is invalid.", i)); | |
- if (d.has("bufferView")) { | |
const GLTFBufferViewIndex bvi = d["bufferView"]; | |
ERR_FAIL_INDEX_V(bvi, state->buffer_views.size(), ERR_PARAMETER_RANGE_ERROR); | |
- const Ref<GLTFBufferView> bv = state->buffer_views[bvi]; | |
+ Ref<GLTFBufferView> bv = state->buffer_views[bvi]; | |
const GLTFBufferIndex bi = bv->buffer; | |
ERR_FAIL_INDEX_V(bi, state->buffers.size(), ERR_PARAMETER_RANGE_ERROR); | |
@@ -3025,51 +3011,42 @@ | |
data_size = bv->byte_length; | |
} | |
- ERR_FAIL_COND_V(mimetype == "", ERR_FILE_CORRUPT); | |
+ Ref<Image> img; | |
- if (mimetype.findn("png") != -1) { | |
- //is a png | |
- ERR_FAIL_COND_V(Image::_png_mem_loader_func == NULL, ERR_UNAVAILABLE); | |
- | |
- const Ref<Image> img = Image::_png_mem_loader_func(data_ptr, data_size); | |
- | |
- ERR_FAIL_COND_V(img.is_null(), ERR_FILE_CORRUPT); | |
- | |
- Ref<ImageTexture> t; | |
- t.instance(); | |
- t->create_from_image(img); | |
- | |
- state->images.push_back(t); | |
- continue; | |
+ if (mimetype == "image/png") { // Load buffer as PNG. | |
+ ERR_FAIL_COND_V(Image::_png_mem_loader_func == nullptr, ERR_UNAVAILABLE); | |
+ img = Image::_png_mem_loader_func(data_ptr, data_size); | |
+ } else if (mimetype == "image/jpeg") { // Loader buffer as JPEG. | |
+ ERR_FAIL_COND_V(Image::_jpg_mem_loader_func == nullptr, ERR_UNAVAILABLE); | |
+ img = Image::_jpg_mem_loader_func(data_ptr, data_size); | |
+ } else { | |
+ // We can land here if we got an URI with base64-encoded data with application/* MIME type, | |
+ // and the optional mimeType property was not defined to tell us how to handle this data (or was invalid). | |
+ // So let's try PNG first, then JPEG. | |
+ ERR_FAIL_COND_V(Image::_png_mem_loader_func == nullptr, ERR_UNAVAILABLE); | |
+ img = Image::_png_mem_loader_func(data_ptr, data_size); | |
+ if (img.is_null()) { | |
+ ERR_FAIL_COND_V(Image::_jpg_mem_loader_func == nullptr, ERR_UNAVAILABLE); | |
+ img = Image::_jpg_mem_loader_func(data_ptr, data_size); | |
+ } | |
} | |
- if (mimetype.findn("jpeg") != -1) { | |
- ERR_FAIL_COND_V(Image::_jpg_mem_loader_func == NULL, ERR_UNAVAILABLE); | |
- | |
- //is a jpg | |
- const Ref<Image> img = Image::_jpg_mem_loader_func(data_ptr, data_size); | |
- | |
- ERR_FAIL_COND_V(img.is_null(), ERR_FILE_CORRUPT); | |
+ ERR_FAIL_COND_V_MSG(img.is_null(), ERR_FILE_CORRUPT, | |
+ vformat("glTF: Couldn't load image index '%d' with its given mimetype: %s.", i, mimetype)); | |
- Ref<ImageTexture> t; | |
- t.instance(); | |
- t->create_from_image(img); | |
- | |
- state->images.push_back(t); | |
- | |
- continue; | |
- } | |
+ Ref<ImageTexture> t; | |
+ t.instance(); | |
+ t->create_from_image(img); | |
- ERR_FAIL_V(ERR_FILE_CORRUPT); | |
+ state->images.push_back(t); | |
} | |
- print_verbose("Total images: " + itos(state->images.size())); | |
+ print_verbose("glTF: Total images: " + itos(state->images.size())); | |
return OK; | |
} | |
Error GLTFDocument::_serialize_textures(Ref<GLTFState> state) { | |
- | |
if (!state->textures.size()) { | |
return OK; | |
} | |
@@ -3088,13 +3065,11 @@ | |
} | |
Error GLTFDocument::_parse_textures(Ref<GLTFState> state) { | |
- | |
if (!state->json.has("textures")) | |
return OK; | |
const Array &textures = state->json["textures"]; | |
for (GLTFTextureIndex i = 0; i < textures.size(); i++) { | |
- | |
const Dictionary &d = textures[i]; | |
ERR_FAIL_COND_V(!d.has("source"), ERR_PARSE_ERROR); | |
@@ -3108,7 +3083,7 @@ | |
return OK; | |
} | |
-GLTFTextureIndex GLTFDocument::_set_texture(Ref<GLTFState> state, Ref<Texture> p_texture) { | |
+GLTFTextureIndex GLTFDocument::_set_texture(Ref<GLTFState> state, Ref<Texture2D> p_texture) { | |
ERR_FAIL_COND_V(p_texture.is_null(), -1); | |
Ref<GLTFTexture> gltf_texture; | |
gltf_texture.instance(); | |
@@ -3136,7 +3111,6 @@ | |
int32_t width = target_image->get_size().x; | |
const int32_t bytes_in_pixel = 4; | |
pixels.resize(height * width * bytes_in_pixel); | |
- target_image->lock(); | |
for (int32_t y = 0; y < height; y++) { | |
for (int32_t x = 0; x < width; x++) { | |
int32_t pixel_index = x + (width * y); | |
@@ -3148,9 +3122,7 @@ | |
pixels.write[index + 3] = uint8_t(pixel.a * 255.0); | |
} | |
} | |
- target_image->unlock(); | |
rjm_texbleed(pixels.ptrw(), width, height, 3, bytes_in_pixel, bytes_in_pixel * width); | |
- target_image->lock(); | |
for (int32_t y = 0; y < height; y++) { | |
for (int32_t x = 0; x < width; x++) { | |
Color pixel; | |
@@ -3163,18 +3135,16 @@ | |
target_image->set_pixel(x, y, pixel); | |
} | |
} | |
- target_image->unlock(); | |
target_image->generate_mipmaps(); | |
return target_image; | |
} | |
Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { | |
- | |
Array materials; | |
for (int32_t i = 0; i < state->materials.size(); i++) { | |
Dictionary d; | |
- Ref<SpatialMaterial> material = state->materials[i]; | |
+ Ref<StandardMaterial3D> material = state->materials[i]; | |
if (material.is_null()) { | |
materials.push_back(d); | |
continue; | |
@@ -3195,7 +3165,7 @@ | |
} | |
{ | |
Dictionary bct; | |
- Ref<Texture> albedo_texture = material->get_texture(SpatialMaterial::TEXTURE_ALBEDO); | |
+ Ref<Texture2D> albedo_texture = material->get_texture(StandardMaterial3D::TEXTURE_ALBEDO); | |
Dictionary texture_transform = _serialize_texture_transform_uv1(material); | |
GLTFTextureIndex gltf_texture_index = -1; | |
@@ -3212,17 +3182,17 @@ | |
mr["metallicFactor"] = material->get_metallic(); | |
mr["roughnessFactor"] = material->get_roughness(); | |
- bool has_roughness = material->get_texture(SpatialMaterial::TEXTURE_ROUGHNESS).is_valid() && material->get_texture(SpatialMaterial::TEXTURE_ROUGHNESS)->get_data().is_valid(); | |
- bool has_ao = material->get_feature(SpatialMaterial::FEATURE_AMBIENT_OCCLUSION) && material->get_texture(SpatialMaterial::TEXTURE_AMBIENT_OCCLUSION).is_valid(); | |
- bool has_metalness = material->get_texture(SpatialMaterial::TEXTURE_METALLIC).is_valid() && material->get_texture(SpatialMaterial::TEXTURE_METALLIC)->get_data().is_valid(); | |
+ bool has_roughness = material->get_texture(StandardMaterial3D::TEXTURE_ROUGHNESS).is_valid() && material->get_texture(StandardMaterial3D::TEXTURE_ROUGHNESS)->get_data().is_valid(); | |
+ bool has_ao = material->get_feature(StandardMaterial3D::FEATURE_AMBIENT_OCCLUSION) && material->get_texture(StandardMaterial3D::TEXTURE_AMBIENT_OCCLUSION).is_valid(); | |
+ bool has_metalness = material->get_texture(StandardMaterial3D::TEXTURE_METALLIC).is_valid() && material->get_texture(StandardMaterial3D::TEXTURE_METALLIC)->get_data().is_valid(); | |
if (has_ao || has_roughness || has_metalness) { | |
Dictionary mrt; | |
- Ref<Texture> roughness_texture = material->get_texture(SpatialMaterial::TEXTURE_ROUGHNESS); | |
- SpatialMaterial::TextureChannel roughness_channel = material->get_roughness_texture_channel(); | |
- Ref<Texture> metallic_texture = material->get_texture(SpatialMaterial::TEXTURE_METALLIC); | |
- SpatialMaterial::TextureChannel metalness_channel = material->get_metallic_texture_channel(); | |
- Ref<Texture> ao_texture = material->get_texture(SpatialMaterial::TEXTURE_AMBIENT_OCCLUSION); | |
- SpatialMaterial::TextureChannel ao_channel = material->get_ao_texture_channel(); | |
+ Ref<Texture2D> roughness_texture = material->get_texture(StandardMaterial3D::TEXTURE_ROUGHNESS); | |
+ StandardMaterial3D::TextureChannel roughness_channel = material->get_roughness_texture_channel(); | |
+ Ref<Texture2D> metallic_texture = material->get_texture(StandardMaterial3D::TEXTURE_METALLIC); | |
+ StandardMaterial3D::TextureChannel metalness_channel = material->get_metallic_texture_channel(); | |
+ Ref<Texture2D> ao_texture = material->get_texture(StandardMaterial3D::TEXTURE_AMBIENT_OCCLUSION); | |
+ StandardMaterial3D::TextureChannel ao_channel = material->get_ao_texture_channel(); | |
Ref<ImageTexture> orm_texture; | |
orm_texture.instance(); | |
Ref<Image> orm_image; | |
@@ -3256,7 +3226,7 @@ | |
metallness_image->decompress(); | |
} | |
} | |
- Ref<Texture> albedo_texture = material->get_texture(SpatialMaterial::TEXTURE_ALBEDO); | |
+ Ref<Texture2D> albedo_texture = material->get_texture(StandardMaterial3D::TEXTURE_ALBEDO); | |
if (albedo_texture.is_valid() && albedo_texture->get_data().is_valid()) { | |
height = albedo_texture->get_height(); | |
width = albedo_texture->get_width(); | |
@@ -3271,71 +3241,45 @@ | |
if (metallness_image.is_valid() && metallness_image->get_size() != Vector2(width, height)) { | |
metallness_image->resize(width, height, Image::INTERPOLATE_LANCZOS); | |
} | |
- orm_image->lock(); | |
for (int32_t h = 0; h < height; h++) { | |
for (int32_t w = 0; w < width; w++) { | |
Color c = Color(1.0f, 1.0f, 1.0f); | |
if (has_ao) { | |
- if (SpatialMaterial::TextureChannel::TEXTURE_CHANNEL_RED == ao_channel) { | |
- ao_image->lock(); | |
+ if (StandardMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == ao_channel) { | |
c.r = ao_image->get_pixel(w, h).r; | |
- ao_image->unlock(); | |
- } else if (SpatialMaterial::TextureChannel::TEXTURE_CHANNEL_GREEN == ao_channel) { | |
- ao_image->lock(); | |
+ } else if (StandardMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == ao_channel) { | |
c.r = ao_image->get_pixel(w, h).g; | |
- ao_image->unlock(); | |
- } else if (SpatialMaterial::TextureChannel::TEXTURE_CHANNEL_BLUE == ao_channel) { | |
- ao_image->lock(); | |
+ } else if (StandardMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == ao_channel) { | |
c.r = ao_image->get_pixel(w, h).b; | |
- ao_image->unlock(); | |
- } else if (SpatialMaterial::TextureChannel::TEXTURE_CHANNEL_ALPHA == ao_channel) { | |
- ao_image->lock(); | |
+ } else if (StandardMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == ao_channel) { | |
c.r = ao_image->get_pixel(w, h).a; | |
- ao_image->unlock(); | |
} | |
} | |
if (has_roughness) { | |
- if (SpatialMaterial::TextureChannel::TEXTURE_CHANNEL_RED == roughness_channel) { | |
- roughness_image->lock(); | |
+ if (StandardMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == roughness_channel) { | |
c.g = roughness_image->get_pixel(w, h).r; | |
- roughness_image->unlock(); | |
- } else if (SpatialMaterial::TextureChannel::TEXTURE_CHANNEL_GREEN == roughness_channel) { | |
- roughness_image->lock(); | |
+ } else if (StandardMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == roughness_channel) { | |
c.g = roughness_image->get_pixel(w, h).g; | |
- roughness_image->unlock(); | |
- } else if (SpatialMaterial::TextureChannel::TEXTURE_CHANNEL_BLUE == roughness_channel) { | |
- roughness_image->lock(); | |
+ } else if (StandardMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == roughness_channel) { | |
c.g = roughness_image->get_pixel(w, h).b; | |
- roughness_image->unlock(); | |
- } else if (SpatialMaterial::TextureChannel::TEXTURE_CHANNEL_ALPHA == roughness_channel) { | |
- roughness_image->lock(); | |
+ } else if (StandardMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == roughness_channel) { | |
c.g = roughness_image->get_pixel(w, h).a; | |
- roughness_image->unlock(); | |
} | |
} | |
if (has_metalness) { | |
- if (SpatialMaterial::TextureChannel::TEXTURE_CHANNEL_RED == metalness_channel) { | |
- metallness_image->lock(); | |
+ if (StandardMaterial3D::TextureChannel::TEXTURE_CHANNEL_RED == metalness_channel) { | |
c.b = metallness_image->get_pixel(w, h).r; | |
- metallness_image->unlock(); | |
- } else if (SpatialMaterial::TextureChannel::TEXTURE_CHANNEL_GREEN == metalness_channel) { | |
- metallness_image->lock(); | |
+ } else if (StandardMaterial3D::TextureChannel::TEXTURE_CHANNEL_GREEN == metalness_channel) { | |
c.b = metallness_image->get_pixel(w, h).g; | |
- metallness_image->unlock(); | |
- } else if (SpatialMaterial::TextureChannel::TEXTURE_CHANNEL_BLUE == metalness_channel) { | |
- metallness_image->lock(); | |
+ } else if (StandardMaterial3D::TextureChannel::TEXTURE_CHANNEL_BLUE == metalness_channel) { | |
c.b = metallness_image->get_pixel(w, h).b; | |
- metallness_image->unlock(); | |
- } else if (SpatialMaterial::TextureChannel::TEXTURE_CHANNEL_ALPHA == metalness_channel) { | |
- metallness_image->lock(); | |
+ } else if (StandardMaterial3D::TextureChannel::TEXTURE_CHANNEL_ALPHA == metalness_channel) { | |
c.b = metallness_image->get_pixel(w, h).a; | |
- metallness_image->unlock(); | |
} | |
} | |
orm_image->set_pixel(w, h, c); | |
} | |
} | |
- orm_image->unlock(); | |
orm_image->generate_mipmaps(); | |
orm_texture->create_from_image(orm_image); | |
GLTFTextureIndex orm_texture_index = -1; | |
@@ -3357,17 +3301,16 @@ | |
d["pbrMetallicRoughness"] = mr; | |
} | |
- if (material->get_feature(SpatialMaterial::FEATURE_NORMAL_MAPPING)) { | |
+ if (material->get_feature(StandardMaterial3D::FEATURE_NORMAL_MAPPING)) { | |
Dictionary nt; | |
Ref<ImageTexture> tex; | |
tex.instance(); | |
{ | |
- Ref<Texture> normal_texture = material->get_texture(SpatialMaterial::TEXTURE_NORMAL); | |
+ Ref<Texture2D> normal_texture = material->get_texture(StandardMaterial3D::TEXTURE_NORMAL); | |
// Code for uncompressing RG normal maps | |
Ref<Image> img = normal_texture->get_data(); | |
img->decompress(); | |
img->convert(Image::FORMAT_RGBA8); | |
- img->lock(); | |
for (int32_t y = 0; y < img->get_height(); y++) { | |
for (int32_t x = 0; x < img->get_width(); x++) { | |
Color c = img->get_pixel(x, y); | |
@@ -3379,10 +3322,10 @@ | |
img->set_pixel(x, y, c); | |
} | |
} | |
- img->unlock(); | |
img = dilate(img); | |
tex->create_from_image(img); | |
} | |
+ Ref<Texture2D> normal_texture = material->get_texture(StandardMaterial3D::TEXTURE_NORMAL); | |
GLTFTextureIndex gltf_texture_index = -1; | |
if (tex.is_valid() && tex->get_data().is_valid()) { | |
tex->set_name(material->get_name() + "_normal"); | |
@@ -3395,7 +3338,7 @@ | |
} | |
} | |
- if (material->get_feature(SpatialMaterial::FEATURE_EMISSION)) { | |
+ if (material->get_feature(StandardMaterial3D::FEATURE_EMISSION)) { | |
const Color c = material->get_emission().to_srgb(); | |
Array arr; | |
arr.push_back(c.r); | |
@@ -3403,9 +3346,9 @@ | |
arr.push_back(c.b); | |
d["emissiveFactor"] = arr; | |
} | |
- if (material->get_feature(SpatialMaterial::FEATURE_EMISSION)) { | |
+ if (material->get_feature(StandardMaterial3D::FEATURE_EMISSION)) { | |
Dictionary et; | |
- Ref<Texture> emission_texture = material->get_texture(SpatialMaterial::TEXTURE_EMISSION); | |
+ Ref<Texture2D> emission_texture = material->get_texture(StandardMaterial3D::TEXTURE_EMISSION); | |
GLTFTextureIndex gltf_texture_index = -1; | |
if (emission_texture.is_valid() && emission_texture->get_data().is_valid()) { | |
emission_texture->set_name(material->get_name() + "_emission"); | |
@@ -3417,14 +3360,14 @@ | |
d["emissiveTexture"] = et; | |
} | |
} | |
- const bool ds = material->get_cull_mode() == SpatialMaterial::CULL_DISABLED; | |
+ const bool ds = material->get_cull_mode() == StandardMaterial3D::CULL_DISABLED; | |
if (ds) { | |
d["doubleSided"] = ds; | |
} | |
- if (material->get_flag(SpatialMaterial::FLAG_USE_ALPHA_SCISSOR) && !material->get_feature(SpatialMaterial::FEATURE_TRANSPARENT)) { | |
+ if (material->get_transparency() == StandardMaterial3D::TRANSPARENCY_ALPHA_SCISSOR) { | |
d["alphaMode"] = "MASK"; | |
d["alphaCutoff"] = material->get_alpha_scissor_threshold(); | |
- } else if (material->get_feature(SpatialMaterial::FEATURE_TRANSPARENT)) { | |
+ } else if (material->get_transparency() != StandardMaterial3D::TRANSPARENCY_DISABLED) { | |
d["alphaMode"] = "BLEND"; | |
} | |
materials.push_back(d); | |
@@ -3436,21 +3379,19 @@ | |
} | |
Error GLTFDocument::_parse_materials(Ref<GLTFState> state) { | |
- | |
if (!state->json.has("materials")) | |
return OK; | |
const Array &materials = state->json["materials"]; | |
for (GLTFMaterialIndex i = 0; i < materials.size(); i++) { | |
- | |
const Dictionary &d = materials[i]; | |
- Ref<SpatialMaterial> material; | |
+ Ref<StandardMaterial3D> material; | |
material.instance(); | |
if (d.has("name")) { | |
material->set_name(d["name"]); | |
} | |
- material->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); | |
+ material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); | |
Dictionary pbr_spec_gloss_extensions; | |
if (d.has("extensions")) { | |
pbr_spec_gloss_extensions = d["extensions"]; | |
@@ -3464,10 +3405,10 @@ | |
if (sgm.has("diffuseTexture")) { | |
const Dictionary &diffuse_texture_dict = sgm["diffuseTexture"]; | |
if (diffuse_texture_dict.has("index")) { | |
- Ref<Texture> diffuse_texture = _get_texture(state, diffuse_texture_dict["index"]); | |
+ Ref<Texture2D> diffuse_texture = _get_texture(state, diffuse_texture_dict["index"]); | |
if (diffuse_texture.is_valid()) { | |
spec_gloss->diffuse_img = diffuse_texture->get_data(); | |
- material->set_texture(SpatialMaterial::TEXTURE_ALBEDO, diffuse_texture); | |
+ material->set_texture(StandardMaterial3D::TEXTURE_ALBEDO, diffuse_texture); | |
} | |
} | |
} | |
@@ -3492,7 +3433,7 @@ | |
if (sgm.has("specularGlossinessTexture")) { | |
const Dictionary &spec_gloss_texture = sgm["specularGlossinessTexture"]; | |
if (spec_gloss_texture.has("index")) { | |
- const Ref<Texture> orig_texture = _get_texture(state, spec_gloss_texture["index"]); | |
+ const Ref<Texture2D> orig_texture = _get_texture(state, spec_gloss_texture["index"]); | |
if (orig_texture.is_valid()) { | |
spec_gloss->spec_gloss_img = orig_texture->get_data(); | |
} | |
@@ -3500,7 +3441,6 @@ | |
} | |
spec_gloss_to_rough_metal(spec_gloss, material); | |
} else if (d.has("pbrMetallicRoughness")) { | |
- | |
const Dictionary &mr = d["pbrMetallicRoughness"]; | |
if (mr.has("baseColorFactor")) { | |
const Array &arr = mr["baseColorFactor"]; | |
@@ -3513,7 +3453,7 @@ | |
if (mr.has("baseColorTexture")) { | |
const Dictionary &bct = mr["baseColorTexture"]; | |
if (bct.has("index")) { | |
- material->set_texture(SpatialMaterial::TEXTURE_ALBEDO, _get_texture(state, bct["index"])); | |
+ material->set_texture(StandardMaterial3D::TEXTURE_ALBEDO, _get_texture(state, bct["index"])); | |
} | |
if (bct.has("extensions")) { | |
const Dictionary &extensions = bct["extensions"]; | |
@@ -3551,10 +3491,10 @@ | |
const Dictionary &bct = mr["metallicRoughnessTexture"]; | |
if (bct.has("index")) { | |
const Ref<Texture> t = _get_texture(state, bct["index"]); | |
- material->set_texture(SpatialMaterial::TEXTURE_METALLIC, t); | |
- material->set_metallic_texture_channel(SpatialMaterial::TEXTURE_CHANNEL_BLUE); | |
- material->set_texture(SpatialMaterial::TEXTURE_ROUGHNESS, t); | |
- material->set_roughness_texture_channel(SpatialMaterial::TEXTURE_CHANNEL_GREEN); | |
+ material->set_texture(StandardMaterial3D::TEXTURE_METALLIC, t); | |
+ material->set_metallic_texture_channel(StandardMaterial3D::TEXTURE_CHANNEL_BLUE); | |
+ material->set_texture(StandardMaterial3D::TEXTURE_ROUGHNESS, t); | |
+ material->set_roughness_texture_channel(StandardMaterial3D::TEXTURE_CHANNEL_GREEN); | |
if (!mr.has("metallicFactor")) { | |
material->set_metallic(1); | |
} | |
@@ -3568,8 +3508,8 @@ | |
if (d.has("normalTexture")) { | |
const Dictionary &bct = d["normalTexture"]; | |
if (bct.has("index")) { | |
- material->set_texture(SpatialMaterial::TEXTURE_NORMAL, _get_texture(state, bct["index"])); | |
- material->set_feature(SpatialMaterial::FEATURE_NORMAL_MAPPING, true); | |
+ material->set_texture(StandardMaterial3D::TEXTURE_NORMAL, _get_texture(state, bct["index"])); | |
+ material->set_feature(StandardMaterial3D::FEATURE_NORMAL_MAPPING, true); | |
} | |
if (bct.has("scale")) { | |
material->set_normal_scale(bct["scale"]); | |
@@ -3578,9 +3518,9 @@ | |
if (d.has("occlusionTexture")) { | |
const Dictionary &bct = d["occlusionTexture"]; | |
if (bct.has("index")) { | |
- material->set_texture(SpatialMaterial::TEXTURE_AMBIENT_OCCLUSION, _get_texture(state, bct["index"])); | |
- material->set_ao_texture_channel(SpatialMaterial::TEXTURE_CHANNEL_RED); | |
- material->set_feature(SpatialMaterial::FEATURE_AMBIENT_OCCLUSION, true); | |
+ material->set_texture(StandardMaterial3D::TEXTURE_AMBIENT_OCCLUSION, _get_texture(state, bct["index"])); | |
+ material->set_ao_texture_channel(StandardMaterial3D::TEXTURE_CHANNEL_RED); | |
+ material->set_feature(StandardMaterial3D::FEATURE_AMBIENT_OCCLUSION, true); | |
} | |
} | |
@@ -3588,7 +3528,7 @@ | |
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(); | |
- material->set_feature(SpatialMaterial::FEATURE_EMISSION, true); | |
+ material->set_feature(StandardMaterial3D::FEATURE_EMISSION, true); | |
material->set_emission(c); | |
} | |
@@ -3596,8 +3536,8 @@ | |
if (d.has("emissiveTexture")) { | |
const Dictionary &bct = d["emissiveTexture"]; | |
if (bct.has("index")) { | |
- material->set_texture(SpatialMaterial::TEXTURE_EMISSION, _get_texture(state, bct["index"])); | |
- material->set_feature(SpatialMaterial::FEATURE_EMISSION, true); | |
+ material->set_texture(StandardMaterial3D::TEXTURE_EMISSION, _get_texture(state, bct["index"])); | |
+ material->set_feature(StandardMaterial3D::FEATURE_EMISSION, true); | |
material->set_emission(Color(0, 0, 0)); | |
} | |
} | |
@@ -3605,17 +3545,16 @@ | |
if (d.has("doubleSided")) { | |
const bool ds = d["doubleSided"]; | |
if (ds) { | |
- material->set_cull_mode(SpatialMaterial::CULL_DISABLED); | |
+ material->set_cull_mode(StandardMaterial3D::CULL_DISABLED); | |
} | |
} | |
if (d.has("alphaMode")) { | |
const String &am = d["alphaMode"]; | |
if (am == "BLEND") { | |
- material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); | |
- material->set_depth_draw_mode(SpatialMaterial::DEPTH_DRAW_ALPHA_OPAQUE_PREPASS); | |
+ material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA_DEPTH_PRE_PASS); | |
} else if (am == "MASK") { | |
- material->set_flag(SpatialMaterial::FLAG_USE_ALPHA_SCISSOR, true); | |
+ material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA_SCISSOR); | |
if (d.has("alphaCutoff")) { | |
material->set_alpha_scissor_threshold(d["alphaCutoff"]); | |
} else { | |
@@ -3632,7 +3571,7 @@ | |
return OK; | |
} | |
-void GLTFDocument::spec_gloss_to_rough_metal(Ref<GLTFSpecGloss> r_spec_gloss, Ref<SpatialMaterial> p_material) { | |
+void GLTFDocument::spec_gloss_to_rough_metal(Ref<GLTFSpecGloss> r_spec_gloss, Ref<StandardMaterial3D> p_material) { | |
if (r_spec_gloss->spec_gloss_img.is_null()) { | |
return; | |
} | |
@@ -3652,20 +3591,13 @@ | |
r_spec_gloss->diffuse_img->resize(r_spec_gloss->spec_gloss_img->get_width(), r_spec_gloss->spec_gloss_img->get_height(), Image::INTERPOLATE_LANCZOS); | |
r_spec_gloss->spec_gloss_img->resize(r_spec_gloss->diffuse_img->get_width(), r_spec_gloss->diffuse_img->get_height(), Image::INTERPOLATE_LANCZOS); | |
} | |
- rm_img->lock(); | |
- if (r_spec_gloss->diffuse_img.is_valid()) { | |
- r_spec_gloss->diffuse_img->lock(); | |
- r_spec_gloss->spec_gloss_img->lock(); | |
- } | |
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(); | |
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); | |
- if (r_spec_gloss->diffuse_img.is_valid()) { | |
- diffuse *= r_spec_gloss->diffuse_img->get_pixel(x, y).to_linear(); | |
- } | |
+ diffuse *= r_spec_gloss->diffuse_img->get_pixel(x, y).to_linear(); | |
float metallic = 0.0f; | |
Color base_color; | |
spec_gloss_to_metal_base_color(specular, diffuse, base_color, metallic); | |
@@ -3686,28 +3618,23 @@ | |
} | |
} | |
} | |
- if (r_spec_gloss->diffuse_img.is_valid()) { | |
- r_spec_gloss->diffuse_img->unlock(); | |
- r_spec_gloss->spec_gloss_img->unlock(); | |
- } | |
- rm_img->unlock(); | |
rm_img->generate_mipmaps(); | |
r_spec_gloss->diffuse_img->generate_mipmaps(); | |
Ref<ImageTexture> diffuse_image_texture; | |
diffuse_image_texture.instance(); | |
diffuse_image_texture->create_from_image(r_spec_gloss->diffuse_img); | |
- p_material->set_texture(SpatialMaterial::TEXTURE_ALBEDO, diffuse_image_texture); | |
+ p_material->set_texture(StandardMaterial3D::TEXTURE_ALBEDO, diffuse_image_texture); | |
Ref<ImageTexture> rm_image_texture; | |
rm_image_texture.instance(); | |
rm_image_texture->create_from_image(rm_img); | |
if (has_roughness) { | |
- p_material->set_texture(SpatialMaterial::TEXTURE_ROUGHNESS, rm_image_texture); | |
- p_material->set_roughness_texture_channel(SpatialMaterial::TEXTURE_CHANNEL_GREEN); | |
+ p_material->set_texture(StandardMaterial3D::TEXTURE_ROUGHNESS, rm_image_texture); | |
+ p_material->set_roughness_texture_channel(StandardMaterial3D::TEXTURE_CHANNEL_GREEN); | |
} | |
if (has_metal) { | |
- p_material->set_texture(SpatialMaterial::TEXTURE_METALLIC, rm_image_texture); | |
- p_material->set_metallic_texture_channel(SpatialMaterial::TEXTURE_CHANNEL_BLUE); | |
+ p_material->set_texture(StandardMaterial3D::TEXTURE_METALLIC, rm_image_texture); | |
+ p_material->set_metallic_texture_channel(StandardMaterial3D::TEXTURE_CHANNEL_BLUE); | |
} | |
} | |
@@ -3750,7 +3677,6 @@ | |
} | |
bool GLTFDocument::_capture_nodes_in_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin, const GLTFNodeIndex node_index) { | |
- | |
bool found_joint = false; | |
for (int i = 0; i < state->nodes[node_index]->children.size(); ++i) { | |
@@ -3774,7 +3700,6 @@ | |
} | |
void GLTFDocument::_capture_nodes_for_multirooted_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin) { | |
- | |
DisjointSet<GLTFNodeIndex> disjoint_set; | |
for (int i = 0; i < skin->joints.size(); ++i) { | |
@@ -3808,7 +3733,6 @@ | |
// Go up the tree till all of the multiple roots of the skin are at the same hierarchy level. | |
// This sucks, but 99% of all game engines (not just Godot) would have this same issue. | |
for (int i = 0; i < roots.size(); ++i) { | |
- | |
GLTFNodeIndex current_node = roots[i]; | |
while (state->nodes[current_node]->height > maxHeight) { | |
GLTFNodeIndex parent = state->nodes[current_node]->parent; | |
@@ -3856,7 +3780,6 @@ | |
} | |
Error GLTFDocument::_expand_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin) { | |
- | |
_capture_nodes_for_multirooted_skin(state, skin); | |
// Grab all nodes that lay in between skin joints/nodes | |
@@ -3902,7 +3825,6 @@ | |
} | |
Error GLTFDocument::_verify_skin(Ref<GLTFState> state, Ref<GLTFSkin> skin) { | |
- | |
// This may seem duplicated from expand_skins, but this is really a sanity check! (so it kinda is) | |
// In case additional interpolating logic is added to the skins, this will help ensure that you | |
// do not cause it to self implode into a fiery blaze | |
@@ -3968,7 +3890,6 @@ | |
} | |
Error GLTFDocument::_parse_skins(Ref<GLTFState> state) { | |
- | |
if (!state->json.has("skins")) | |
return OK; | |
@@ -3976,7 +3897,6 @@ | |
// Create the base skins, and mark nodes that are joints | |
for (int i = 0; i < skins.size(); i++) { | |
- | |
const Dictionary &d = skins[i]; | |
Ref<GLTFSkin> skin; | |
@@ -4027,7 +3947,6 @@ | |
} | |
Error GLTFDocument::_determine_skeletons(Ref<GLTFState> state) { | |
- | |
// Using a disjoint set, we are going to potentially combine all skins that are actually branches | |
// of a main skeleton, or treat skins defining the same set of nodes as ONE skeleton. | |
// This is another unclear issue caused by the current glTF specification. | |
@@ -4063,7 +3982,7 @@ | |
skeleton_sets.get_representatives(groups_representatives); | |
Vector<GLTFNodeIndex> highest_group_members; | |
- Vector<Vector<GLTFNodeIndex> > groups; | |
+ Vector<Vector<GLTFNodeIndex>> groups; | |
for (int i = 0; i < groups_representatives.size(); ++i) { | |
Vector<GLTFNodeIndex> group; | |
skeleton_sets.get_members(group, groups_representatives[i]); | |
@@ -4105,7 +4024,6 @@ | |
// Mark all the skins actual skeletons, after we have merged them | |
for (GLTFSkeletonIndex skel_i = 0; skel_i < skeleton_owners.size(); ++skel_i) { | |
- | |
const GLTFNodeIndex skeleton_owner = skeleton_owners[skel_i]; | |
Ref<GLTFSkeleton> skeleton; | |
skeleton.instance(); | |
@@ -4161,7 +4079,6 @@ | |
} | |
Error GLTFDocument::_reparent_non_joint_skeleton_subtrees(Ref<GLTFState> state, Ref<GLTFSkeleton> skeleton, const Vector<GLTFNodeIndex> &non_joints) { | |
- | |
DisjointSet<GLTFNodeIndex> subtree_set; | |
// Populate the disjoint set with ONLY non joints that are in the skeleton hierarchy (non_joints vector) | |
@@ -4276,7 +4193,6 @@ | |
} | |
Error GLTFDocument::_determine_skeleton_roots(Ref<GLTFState> state, const GLTFSkeletonIndex skel_i) { | |
- | |
DisjointSet<GLTFNodeIndex> disjoint_set; | |
for (GLTFNodeIndex i = 0; i < state->nodes.size(); ++i) { | |
@@ -4331,14 +4247,13 @@ | |
Error GLTFDocument::_create_skeletons(Ref<GLTFState> state) { | |
for (GLTFSkeletonIndex skel_i = 0; skel_i < state->skeletons.size(); ++skel_i) { | |
- | |
Ref<GLTFSkeleton> gltf_skeleton = state->skeletons.write[skel_i]; | |
- Skeleton *skeleton = memnew(Skeleton); | |
+ Skeleton3D *skeleton = memnew(Skeleton3D); | |
gltf_skeleton->godot_skeleton = skeleton; | |
// Make a unique name, no gltf node represents this skeleton | |
- skeleton->set_name(_gen_unique_name(state, "Skeleton")); | |
+ skeleton->set_name(_gen_unique_name(state, "Skeleton3D")); | |
List<GLTFNodeIndex> bones; | |
@@ -4420,7 +4335,6 @@ | |
} | |
Error GLTFDocument::_serialize_skins(Ref<GLTFState> state) { | |
- | |
Array json_skins; | |
for (GLTFNodeIndex node_i = 0; node_i < state->nodes.size(); node_i++) { | |
Dictionary json_skin; | |
@@ -4432,11 +4346,11 @@ | |
if (!node) { | |
continue; | |
} | |
- MeshInstance *mi = Object::cast_to<MeshInstance>(node); | |
+ MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(node); | |
if (!mi) { | |
continue; | |
} | |
- Skeleton *skeleton = Object::cast_to<Skeleton>(mi->get_node(mi->get_skeleton_path())); | |
+ Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(mi->get_node(mi->get_skeleton_path())); | |
if (!skeleton) { | |
continue; | |
} | |
@@ -4488,8 +4402,6 @@ | |
state->nodes.write[node_index]->joint = true; | |
gltf_skin->inverse_binds.push_back(skin->get_bind_pose(bind_i)); | |
json_joints.push_back(node_index); | |
- // print_verbose("glTF: bind pose " + itos(bind_i) + " " + skin->get_bind_pose(bind_i)); | |
- // print_verbose("glTF: bone rest " + itos(bone_index) + " " + skeleton->get_bone_rest(bone_index)); | |
} | |
for (int32_t joint_i = 0; joint_i < gltf_skin->joints.size(); joint_i++) { | |
@@ -4577,7 +4489,6 @@ | |
} | |
for (int i = 0; i < skin_a->get_bind_count(); ++i) { | |
- | |
if (skin_a->get_bind_bone(i) != skin_b->get_bind_bone(i)) { | |
return false; | |
} | |
@@ -4608,7 +4519,6 @@ | |
} | |
Error GLTFDocument::_serialize_lights(Ref<GLTFState> state) { | |
- | |
Array lights; | |
for (GLTFLightIndex i = 0; i < state->lights.size(); i++) { | |
Dictionary d; | |
@@ -4655,11 +4565,9 @@ | |
} | |
Error GLTFDocument::_serialize_cameras(Ref<GLTFState> state) { | |
- | |
Array cameras; | |
cameras.resize(state->cameras.size()); | |
for (GLTFCameraIndex i = 0; i < state->cameras.size(); i++) { | |
- | |
Dictionary d; | |
Ref<GLTFCamera> camera = state->cameras[i]; | |
@@ -4749,14 +4657,12 @@ | |
} | |
Error GLTFDocument::_parse_cameras(Ref<GLTFState> state) { | |
- | |
if (!state->json.has("cameras")) | |
return OK; | |
const Array cameras = state->json["cameras"]; | |
for (GLTFCameraIndex i = 0; i < cameras.size(); i++) { | |
- | |
const Dictionary &d = cameras[i]; | |
Ref<GLTFCamera> camera; | |
@@ -4764,7 +4670,6 @@ | |
ERR_FAIL_COND_V(!d.has("type"), ERR_PARSE_ERROR); | |
const String &type = d["type"]; | |
if (type == "orthographic") { | |
- | |
camera->set_perspective(false); | |
if (d.has("orthographic")) { | |
const Dictionary &og = d["orthographic"]; | |
@@ -4776,7 +4681,6 @@ | |
camera->set_fov_size(10); | |
} | |
} else if (type == "perspective") { | |
- | |
camera->set_perspective(true); | |
if (d.has("perspective")) { | |
const Dictionary &ppt = d["perspective"]; | |
@@ -4788,7 +4692,7 @@ | |
camera->set_fov_size(10); | |
} | |
} else { | |
- ERR_FAIL_V_MSG(ERR_PARSE_ERROR, "Camera should be in 'orthographic' or 'perspective'"); | |
+ ERR_FAIL_V_MSG(ERR_PARSE_ERROR, "Camera3D should be in 'orthographic' or 'perspective'"); | |
} | |
state->cameras.push_back(camera); | |
@@ -4843,7 +4747,6 @@ | |
Array samplers; | |
for (Map<int, GLTFAnimation::Track>::Element *track_i = gltf_animation->get_tracks().front(); track_i; track_i = track_i->next()) { | |
- | |
GLTFAnimation::Track track = track_i->get(); | |
if (track.translation_track.times.size()) { | |
Dictionary t; | |
@@ -4956,14 +4859,12 @@ | |
} | |
Error GLTFDocument::_parse_animations(Ref<GLTFState> state) { | |
- | |
if (!state->json.has("animations")) | |
return OK; | |
const Array &animations = state->json["animations"]; | |
for (GLTFAnimationIndex i = 0; i < animations.size(); i++) { | |
- | |
const Dictionary &d = animations[i]; | |
Ref<GLTFAnimation> animation; | |
@@ -4984,7 +4885,6 @@ | |
} | |
for (int j = 0; j < channels.size(); j++) { | |
- | |
const Dictionary &c = channels[j]; | |
if (!c.has("target")) | |
continue; | |
@@ -5093,7 +4993,6 @@ | |
} | |
void GLTFDocument::_assign_scene_names(Ref<GLTFState> state) { | |
- | |
for (int i = 0; i < state->nodes.size(); i++) { | |
Ref<GLTFNode> n = state->nodes[i]; | |
@@ -5103,11 +5002,11 @@ | |
if (n->get_name().empty()) { | |
if (n->mesh >= 0) { | |
- n->set_name("Mesh"); | |
+ n->set_name(_gen_unique_name(state, "Mesh")); | |
} else if (n->camera >= 0) { | |
- n->set_name("Camera"); | |
+ n->set_name(_gen_unique_name(state, "Camera3D")); | |
} else { | |
- n->set_name("Node"); | |
+ n->set_name(_gen_unique_name(state, "Node")); | |
} | |
} | |
@@ -5115,12 +5014,11 @@ | |
} | |
} | |
-BoneAttachment *GLTFDocument::_generate_bone_attachment(Ref<GLTFState> state, Skeleton *skeleton, const GLTFNodeIndex node_index) { | |
- | |
+BoneAttachment3D *GLTFDocument::_generate_bone_attachment(Ref<GLTFState> state, Skeleton3D *skeleton, const GLTFNodeIndex node_index) { | |
Ref<GLTFNode> gltf_node = state->nodes[node_index]; | |
Ref<GLTFNode> bone_node = state->nodes[gltf_node->parent]; | |
- BoneAttachment *bone_attachment = memnew(BoneAttachment); | |
+ BoneAttachment3D *bone_attachment = memnew(BoneAttachment3D); | |
print_verbose("glTF: Creating bone attachment for: " + gltf_node->get_name()); | |
ERR_FAIL_COND_V(!bone_node->joint, nullptr); | |
@@ -5130,7 +5028,7 @@ | |
return bone_attachment; | |
} | |
-GLTFMeshIndex GLTFDocument::_convert_mesh_instance(Ref<GLTFState> state, MeshInstance *p_mesh_instance) { | |
+GLTFMeshIndex GLTFDocument::_convert_mesh_instance(Ref<GLTFState> state, MeshInstance3D *p_mesh_instance) { | |
Ref<GLTFMesh> mesh; | |
mesh.instance(); | |
if (p_mesh_instance->get_mesh().is_null()) { | |
@@ -5167,19 +5065,19 @@ | |
return state->meshes.size() - 1; | |
} | |
-MeshInstance *GLTFDocument::_generate_mesh_instance(Ref<GLTFState> state, Node *scene_parent, const GLTFNodeIndex node_index) { | |
+MeshInstance3D *GLTFDocument::_generate_mesh_instance(Ref<GLTFState> state, Node *scene_parent, const GLTFNodeIndex node_index) { | |
Ref<GLTFNode> gltf_node = state->nodes[node_index]; | |
ERR_FAIL_INDEX_V(gltf_node->mesh, state->meshes.size(), nullptr); | |
- MeshInstance *mi = memnew(MeshInstance); | |
+ MeshInstance3D *mi = memnew(MeshInstance3D); | |
print_verbose("glTF: Creating mesh for: " + gltf_node->get_name()); | |
Ref<GLTFMesh> mesh = state->meshes.write[gltf_node->mesh]; | |
mi->set_mesh(mesh->mesh); | |
if (mesh->mesh->get_name().empty()) { | |
- mesh->mesh->set_name(gltf_node->get_name()); | |
+ mesh->mesh->set_name(_gen_unique_name(state, gltf_node->get_name())); | |
} | |
for (int i = 0; i < mesh->blend_weights.size(); i++) { | |
@@ -5189,7 +5087,7 @@ | |
return mi; | |
} | |
-Light *GLTFDocument::_generate_light(Ref<GLTFState> state, Node *scene_parent, const GLTFNodeIndex node_index) { | |
+Light3D *GLTFDocument::_generate_light(Ref<GLTFState> state, Node *scene_parent, const GLTFNodeIndex node_index) { | |
Ref<GLTFNode> gltf_node = state->nodes[node_index]; | |
ERR_FAIL_INDEX_V(gltf_node->light, state->lights.size(), nullptr); | |
@@ -5207,8 +5105,8 @@ | |
} | |
if (l->type == "directional") { | |
- DirectionalLight *light = memnew(DirectionalLight); | |
- light->set_param(Light::PARAM_ENERGY, intensity); | |
+ DirectionalLight3D *light = memnew(DirectionalLight3D); | |
+ light->set_param(Light3D::PARAM_ENERGY, intensity); | |
light->set_color(l->color); | |
return light; | |
} | |
@@ -5218,35 +5116,35 @@ | |
// We want to have double intensity give double brightness, so we need half the attenuation. | |
const float attenuation = range / intensity; | |
if (l->type == "point") { | |
- OmniLight *light = memnew(OmniLight); | |
- light->set_param(OmniLight::PARAM_ATTENUATION, attenuation); | |
- light->set_param(OmniLight::PARAM_RANGE, range); | |
+ OmniLight3D *light = memnew(OmniLight3D); | |
+ light->set_param(OmniLight3D::PARAM_ATTENUATION, attenuation); | |
+ light->set_param(OmniLight3D::PARAM_RANGE, range); | |
light->set_color(l->color); | |
return light; | |
} | |
if (l->type == "spot") { | |
- SpotLight *light = memnew(SpotLight); | |
- light->set_param(SpotLight::PARAM_ATTENUATION, attenuation); | |
- light->set_param(SpotLight::PARAM_RANGE, range); | |
- light->set_param(SpotLight::PARAM_SPOT_ANGLE, Math::rad2deg(l->outer_cone_angle)); | |
+ SpotLight3D *light = memnew(SpotLight3D); | |
+ light->set_param(SpotLight3D::PARAM_ATTENUATION, attenuation); | |
+ light->set_param(SpotLight3D::PARAM_RANGE, range); | |
+ light->set_param(SpotLight3D::PARAM_SPOT_ANGLE, Math::rad2deg(l->outer_cone_angle)); | |
light->set_color(l->color); | |
// Line of best fit derived from guessing, see https://www.desmos.com/calculator/biiflubp8b | |
// The points in desmos are not exact, except for (1, infinity). | |
float angle_ratio = l->inner_cone_angle / l->outer_cone_angle; | |
float angle_attenuation = 0.2 / (1 - angle_ratio) - 0.1; | |
- light->set_param(SpotLight::PARAM_SPOT_ATTENUATION, angle_attenuation); | |
+ light->set_param(SpotLight3D::PARAM_SPOT_ATTENUATION, angle_attenuation); | |
return light; | |
} | |
return nullptr; | |
} | |
-Camera *GLTFDocument::_generate_camera(Ref<GLTFState> state, Node *scene_parent, const GLTFNodeIndex node_index) { | |
+Camera3D *GLTFDocument::_generate_camera(Ref<GLTFState> state, Node *scene_parent, const GLTFNodeIndex node_index) { | |
Ref<GLTFNode> gltf_node = state->nodes[node_index]; | |
ERR_FAIL_INDEX_V(gltf_node->camera, state->cameras.size(), nullptr); | |
- Camera *camera = memnew(Camera); | |
+ Camera3D *camera = memnew(Camera3D); | |
print_verbose("glTF: Creating camera for: " + gltf_node->get_name()); | |
Ref<GLTFCamera> c = state->cameras[gltf_node->camera]; | |
@@ -5259,13 +5157,13 @@ | |
return camera; | |
} | |
-GLTFCameraIndex GLTFDocument::_convert_camera(Ref<GLTFState> state, Camera *p_camera) { | |
+GLTFCameraIndex GLTFDocument::_convert_camera(Ref<GLTFState> state, Camera3D *p_camera) { | |
print_verbose("glTF: Converting camera: " + p_camera->get_name()); | |
Ref<GLTFCamera> c; | |
c.instance(); | |
- if (p_camera->get_projection() == Camera::Projection::PROJECTION_PERSPECTIVE) { | |
+ if (p_camera->get_projection() == Camera3D::Projection::PROJECTION_PERSPECTIVE) { | |
c->set_perspective(true); | |
c->set_fov_size(p_camera->get_fov()); | |
c->set_zfar(p_camera->get_zfar()); | |
@@ -5280,33 +5178,33 @@ | |
return camera_index; | |
} | |
-GLTFLightIndex GLTFDocument::_convert_light(Ref<GLTFState> state, Light *p_light) { | |
+GLTFLightIndex GLTFDocument::_convert_light(Ref<GLTFState> state, Light3D *p_light) { | |
print_verbose("glTF: Converting light: " + p_light->get_name()); | |
Ref<GLTFLight> l; | |
l.instance(); | |
l->color = p_light->get_color(); | |
- if (cast_to<DirectionalLight>(p_light)) { | |
+ if (cast_to<DirectionalLight3D>(p_light)) { | |
l->type = "directional"; | |
- DirectionalLight *light = cast_to<DirectionalLight>(p_light); | |
- l->intensity = light->get_param(DirectionalLight::PARAM_ENERGY); | |
+ DirectionalLight3D *light = cast_to<DirectionalLight3D>(p_light); | |
+ l->intensity = light->get_param(DirectionalLight3D::PARAM_ENERGY); | |
l->range = FLT_MAX; // Range for directional lights is infinite in Godot. | |
- } else if (cast_to<OmniLight>(p_light)) { | |
+ } else if (cast_to<OmniLight3D>(p_light)) { | |
l->type = "point"; | |
- OmniLight *light = cast_to<OmniLight>(p_light); | |
- l->range = light->get_param(OmniLight::PARAM_RANGE); | |
- float attenuation = p_light->get_param(OmniLight::PARAM_ATTENUATION); | |
+ OmniLight3D *light = cast_to<OmniLight3D>(p_light); | |
+ l->range = light->get_param(OmniLight3D::PARAM_RANGE); | |
+ float attenuation = p_light->get_param(OmniLight3D::PARAM_ATTENUATION); | |
l->intensity = l->range / attenuation; | |
- } else if (cast_to<SpotLight>(p_light)) { | |
+ } else if (cast_to<SpotLight3D>(p_light)) { | |
l->type = "spot"; | |
- SpotLight *light = cast_to<SpotLight>(p_light); | |
- l->range = light->get_param(SpotLight::PARAM_RANGE); | |
- float attenuation = light->get_param(SpotLight::PARAM_ATTENUATION); | |
+ SpotLight3D *light = cast_to<SpotLight3D>(p_light); | |
+ l->range = light->get_param(SpotLight3D::PARAM_RANGE); | |
+ float attenuation = light->get_param(SpotLight3D::PARAM_ATTENUATION); | |
l->intensity = l->range / attenuation; | |
- l->outer_cone_angle = Math::deg2rad(light->get_param(SpotLight::PARAM_SPOT_ANGLE)); | |
+ l->outer_cone_angle = Math::deg2rad(light->get_param(SpotLight3D::PARAM_SPOT_ANGLE)); | |
// This equation is the inverse of the import equation (which has a desmos link). | |
- float angle_ratio = 1 - (0.2 / (0.1 + light->get_param(SpotLight::PARAM_SPOT_ATTENUATION))); | |
+ float angle_ratio = 1 - (0.2 / (0.1 + light->get_param(SpotLight3D::PARAM_SPOT_ATTENUATION))); | |
angle_ratio = MAX(0, angle_ratio); | |
l->inner_cone_angle = l->outer_cone_angle * angle_ratio; | |
} | |
@@ -5316,37 +5214,36 @@ | |
return light_index; | |
} | |
-GLTFSkeletonIndex GLTFDocument::_convert_skeleton(Ref<GLTFState> state, Skeleton *p_skeleton, GLTFNodeIndex p_node_index) { | |
+GLTFSkeletonIndex GLTFDocument::_convert_skeleton(Ref<GLTFState> state, Skeleton3D *p_skeleton, GLTFNodeIndex p_node_index) { | |
print_verbose("glTF: Converting skeleton: " + p_skeleton->get_name()); | |
Ref<GLTFSkeleton> gltf_skeleton; | |
gltf_skeleton.instance(); | |
+ gltf_skeleton->set_name(_gen_unique_name(state, p_skeleton->get_name())); | |
gltf_skeleton->godot_skeleton = p_skeleton; | |
state->skeleton_to_node.insert(state->skeletons.size(), p_node_index); | |
state->skeletons.push_back(gltf_skeleton); | |
return state->skeletons.size() - 1; | |
} | |
-void GLTFDocument::_convert_spatial(Ref<GLTFState> state, Spatial *p_spatial, Ref<GLTFNode> p_node) { | |
+void GLTFDocument::_convert_spatial(Ref<GLTFState> state, Node3D *p_spatial, Ref<GLTFNode> p_node) { | |
Transform xform = p_spatial->get_transform(); | |
p_node->scale = xform.basis.get_scale(); | |
p_node->rotation = xform.basis.get_rotation_quat(); | |
p_node->translation = xform.origin; | |
} | |
-Spatial *GLTFDocument::_generate_spatial(Ref<GLTFState> state, Node *scene_parent, const GLTFNodeIndex node_index) { | |
+Node3D *GLTFDocument::_generate_spatial(Ref<GLTFState> state, Node *scene_parent, const GLTFNodeIndex node_index) { | |
Ref<GLTFNode> gltf_node = state->nodes[node_index]; | |
- Spatial *spatial = memnew(Spatial); | |
+ Node3D *spatial = memnew(Node3D); | |
print_verbose("glTF: Converting spatial: " + gltf_node->get_name()); | |
return spatial; | |
} | |
void GLTFDocument::_convert_scene_node(Ref<GLTFState> state, Node *p_current, Node *p_root, const GLTFNodeIndex p_gltf_parent, const GLTFNodeIndex p_gltf_root) { | |
- | |
- bool retflag; | |
- Spatial *spatial = Object::cast_to<Spatial>(p_current); | |
- Node2D *node_2d = Object::cast_to<Node2D>(p_current); | |
- _check_visibility(node_2d, spatial, retflag); | |
+ bool retflag = true; | |
+ Node3D *spatial = cast_to<Node3D>(p_current); | |
+ _check_visibility(p_current, retflag); | |
if (retflag) { | |
return; | |
} | |
@@ -5354,39 +5251,41 @@ | |
Ref<GLTFNode> gltf_node; | |
gltf_node.instance(); | |
gltf_node->set_name(_gen_unique_name(state, p_current->get_name())); | |
- if (cast_to<MeshInstance>(p_current)) { | |
+ | |
+ if (cast_to<Node3D>(p_current)) { | |
+ _convert_spatial(state, spatial, gltf_node); | |
+ } | |
+ | |
+ if (cast_to<MeshInstance3D>(p_current)) { | |
_convert_mesh_to_gltf(p_current, state, spatial, gltf_node); | |
- } else if (cast_to<BoneAttachment>(p_current)) { | |
+ } else if (cast_to<BoneAttachment3D>(p_current)) { | |
_convert_bone_attachment_to_gltf(p_current, state, gltf_node, retflag); | |
return; | |
- } else if (cast_to<Skeleton>(p_current)) { | |
+ } else if (cast_to<Skeleton3D>(p_current)) { | |
_convert_skeleton_to_gltf(p_current, state, p_gltf_parent, p_gltf_root, gltf_node, p_root); | |
return; | |
- } else if (cast_to<MultiMeshInstance>(p_current)) { | |
+ } else if (cast_to<MultiMeshInstance3D>(p_current)) { | |
_convert_mult_mesh_instance_to_gltf(p_current, p_gltf_parent, p_gltf_root, gltf_node, state, p_root); | |
- } else if (cast_to<CSGShape>(p_current)) { | |
- if (p_current->get_parent() && !cast_to<CSGShape>(p_current->get_parent())) { | |
+ } else if (cast_to<CSGShape3D>(p_current)) { | |
+ if (p_current->get_parent() && !cast_to<CSGShape3D>(p_current->get_parent())) { | |
_convert_csg_shape_to_gltf(p_current, p_gltf_parent, gltf_node, state); | |
- _convert_spatial(state, spatial, gltf_node); | |
} | |
} else if (cast_to<GridMap>(p_current)) { | |
_convert_grid_map_to_gltf(p_current, p_gltf_parent, p_gltf_root, gltf_node, state, p_root); | |
- } else if (cast_to<Camera>(p_current)) { | |
- Camera *camera = Object::cast_to<Camera>(p_current); | |
+ } else if (cast_to<Camera3D>(p_current)) { | |
+ Camera3D *camera = Object::cast_to<Camera3D>(p_current); | |
_convert_camera_to_gltf(camera, state, spatial, gltf_node); | |
- } else if (cast_to<Light>(p_current)) { | |
- Light *light = Object::cast_to<Light>(p_current); | |
+ } else if (cast_to<Light3D>(p_current)) { | |
+ Light3D *light = Object::cast_to<Light3D>(p_current); | |
_convert_light_to_gltf(light, state, spatial, gltf_node); | |
} else if (cast_to<AnimationPlayer>(p_current)) { | |
AnimationPlayer *animation_player = Object::cast_to<AnimationPlayer>(p_current); | |
_convert_animation_player_to_gltf(animation_player, state, p_gltf_parent, p_gltf_root, gltf_node, p_current, p_root); | |
return; | |
- } else { | |
- _convert_spatial_to_gltf(spatial, state, gltf_node); | |
} | |
GLTFNodeIndex current_node_i = state->nodes.size(); | |
- _create_gltf_node(state, current_node_i, p_current, p_gltf_parent, gltf_node); | |
+ _create_gltf_node(state, current_node_i, p_current, p_gltf_parent, p_gltf_root, gltf_node); | |
for (int node_i = 0; node_i < p_current->get_child_count(); node_i++) { | |
_convert_scene_node(state, p_current->get_child(node_i), p_root, current_node_i, p_gltf_root); | |
@@ -5394,9 +5293,9 @@ | |
} | |
void GLTFDocument::_convert_csg_shape_to_gltf(Node *p_current, GLTFNodeIndex p_gltf_parent, Ref<GLTFNode> gltf_node, Ref<GLTFState> state) { | |
- CSGShape *csg = Object::cast_to<CSGShape>(p_current); | |
+ CSGShape3D *csg = Object::cast_to<CSGShape3D>(p_current); | |
// HACK to call _make_dirty function | |
- CSGShape::Operation operation = csg->get_operation(); | |
+ CSGShape3D::Operation operation = csg->get_operation(); | |
csg->set_operation(operation); | |
// END HACK | |
csg->call("_update_shape"); | |
@@ -5420,41 +5319,35 @@ | |
gltf_node->mesh = state->meshes.size(); | |
state->meshes.push_back(gltf_mesh); | |
gltf_node->xform = csg->get_meshes()[0]; | |
- gltf_node->set_name(csg->get_name()); | |
+ gltf_node->set_name(_gen_unique_name(state, csg->get_name())); | |
} | |
void GLTFDocument::_create_gltf_node(Ref<GLTFState> state, GLTFNodeIndex current_node_i, Node *p_scene_parent, | |
- GLTFNodeIndex p_parent_node_index, Ref<GLTFNode> gltf_node) { | |
- gltf_node->parent = p_parent_node_index; | |
+ GLTFNodeIndex p_parent_node_index, GLTFNodeIndex p_root_gltf_node, Ref<GLTFNode> gltf_node) { | |
state->scene_nodes.insert(current_node_i, p_scene_parent); | |
state->nodes.push_back(gltf_node); | |
- if (p_parent_node_index != current_node_i) { | |
+ if (p_parent_node_index != p_root_gltf_node) { | |
+ gltf_node->parent = p_parent_node_index; | |
state->nodes.write[p_parent_node_index]->children.push_back(current_node_i); | |
} | |
} | |
void GLTFDocument::_convert_animation_player_to_gltf(AnimationPlayer *animation_player, Ref<GLTFState> state, const GLTFNodeIndex &p_gltf_current, const GLTFNodeIndex &p_gltf_root_index, Ref<GLTFNode> p_gltf_node, Node *p_scene_parent, Node *p_root) { | |
- if (animation_player) { | |
- state->animation_players.push_back(animation_player); | |
- print_verbose(String("glTF: Converting animation player: ") + animation_player->get_name()); | |
- if (p_gltf_current != p_gltf_root_index) { | |
- p_gltf_node.unref(); | |
- } | |
- for (int node_i = 0; node_i < p_scene_parent->get_child_count(); node_i++) { | |
- _convert_scene_node(state, p_scene_parent->get_child(node_i), p_root, p_gltf_current, p_gltf_root_index); | |
- } | |
+ ERR_FAIL_COND(!animation_player); | |
+ state->animation_players.push_back(animation_player); | |
+ print_verbose(String("glTF: Converting animation player: ") + animation_player->get_name()); | |
+ if (p_gltf_current != p_gltf_root_index) { | |
+ p_gltf_node.unref(); | |
} | |
-} | |
- | |
-void GLTFDocument::_convert_spatial_to_gltf(Spatial *spatial, Ref<GLTFState> state, Ref<GLTFNode> gltf_node) { | |
- if (spatial) { | |
- _convert_spatial(state, spatial, gltf_node); | |
- print_verbose(String("glTF: Converting spatial: ") + spatial->get_name()); | |
+ for (int node_i = 0; node_i < p_scene_parent->get_child_count(); node_i++) { | |
+ _convert_scene_node(state, p_scene_parent->get_child(node_i), p_root, p_gltf_current, p_gltf_root_index); | |
} | |
} | |
-void GLTFDocument::_check_visibility(Node2D *node_2d, Spatial *spatial, bool &retflag) { | |
+void GLTFDocument::_check_visibility(Node *p_node, bool &retflag) { | |
retflag = true; | |
+ Node3D *spatial = Object::cast_to<Node3D>(p_node); | |
+ Node2D *node_2d = Object::cast_to<Node2D>(p_node); | |
if (node_2d && !node_2d->is_visible()) { | |
return; | |
} | |
@@ -5464,116 +5357,105 @@ | |
retflag = false; | |
} | |
-void GLTFDocument::_convert_camera_to_gltf(Camera *camera, Ref<GLTFState> state, Spatial *spatial, Ref<GLTFNode> gltf_node) { | |
- if (camera) { | |
- GLTFCameraIndex camera_index = _convert_camera(state, camera); | |
- if (camera_index != -1) { | |
- _convert_spatial(state, spatial, gltf_node); | |
- gltf_node->camera = camera_index; | |
- } | |
+void GLTFDocument::_convert_camera_to_gltf(Camera3D *camera, Ref<GLTFState> state, Node3D *spatial, Ref<GLTFNode> gltf_node) { | |
+ ERR_FAIL_COND(!camera); | |
+ GLTFCameraIndex camera_index = _convert_camera(state, camera); | |
+ if (camera_index != -1) { | |
+ gltf_node->camera = camera_index; | |
} | |
} | |
-void GLTFDocument::_convert_light_to_gltf(Light *light, Ref<GLTFState> state, Spatial *spatial, Ref<GLTFNode> gltf_node) { | |
- if (light) { | |
- GLTFLightIndex light_index = _convert_light(state, light); | |
- if (light_index != -1) { | |
- _convert_spatial(state, spatial, gltf_node); | |
- gltf_node->light = light_index; | |
- } | |
+void GLTFDocument::_convert_light_to_gltf(Light3D *light, Ref<GLTFState> state, Node3D *spatial, Ref<GLTFNode> gltf_node) { | |
+ ERR_FAIL_COND(!light); | |
+ GLTFLightIndex light_index = _convert_light(state, light); | |
+ if (light_index != -1) { | |
+ gltf_node->light = light_index; | |
} | |
} | |
void GLTFDocument::_convert_grid_map_to_gltf(Node *p_scene_parent, const GLTFNodeIndex &p_parent_node_index, const GLTFNodeIndex &p_root_node_index, Ref<GLTFNode> gltf_node, Ref<GLTFState> state, Node *p_root_node) { | |
GridMap *grid_map = Object::cast_to<GridMap>(p_scene_parent); | |
- if (grid_map) { | |
- Array cells = grid_map->get_used_cells(); | |
- for (int32_t k = 0; k < cells.size(); k++) { | |
- GLTFNode *new_gltf_node = memnew(GLTFNode); | |
- new_gltf_node->parent = p_parent_node_index; | |
- gltf_node->children.push_back(state->nodes.size()); | |
- state->nodes.push_back(new_gltf_node); | |
- Vector3 cell_location = cells[k]; | |
- int32_t cell = grid_map->get_cell_item( | |
- cell_location.x, cell_location.y, cell_location.z); | |
- Ref<Mesh> mesh = | |
- grid_map->get_mesh_library()->get_item_mesh(cell); | |
- Transform cell_xform; | |
- cell_xform.basis.set_orthogonal_index( | |
- grid_map->get_cell_item_orientation( | |
- cell_location.x, cell_location.y, cell_location.z)); | |
- cell_xform.basis.scale(Vector3(grid_map->get_cell_scale(), | |
- grid_map->get_cell_scale(), | |
- grid_map->get_cell_scale())); | |
- cell_xform.set_origin(grid_map->map_to_world( | |
- cell_location.x, cell_location.y, cell_location.z)); | |
- Ref<GLTFMesh> gltf_mesh; | |
- gltf_mesh->mesh = mesh; | |
- new_gltf_node->mesh = state->meshes.size(); | |
- state->meshes.push_back(gltf_mesh); | |
- new_gltf_node->xform = cell_xform * grid_map->get_transform(); | |
- new_gltf_node->set_name(grid_map->get_mesh_library()->get_item_name(cell)); | |
- } | |
+ ERR_FAIL_COND(!grid_map); | |
+ Array cells = grid_map->get_used_cells(); | |
+ for (int32_t k = 0; k < cells.size(); k++) { | |
+ GLTFNode *new_gltf_node = memnew(GLTFNode); | |
+ new_gltf_node->parent = p_parent_node_index; | |
+ gltf_node->children.push_back(state->nodes.size()); | |
+ state->nodes.push_back(new_gltf_node); | |
+ Vector3 cell_location = cells[k]; | |
+ int32_t cell = grid_map->get_cell_item( | |
+ Vector3(cell_location.x, cell_location.y, cell_location.z)); | |
+ Ref<Mesh> mesh = | |
+ grid_map->get_mesh_library()->get_item_mesh(cell); | |
+ Transform cell_xform; | |
+ cell_xform.basis.set_orthogonal_index( | |
+ grid_map->get_cell_item_orientation( | |
+ Vector3(cell_location.x, cell_location.y, cell_location.z))); | |
+ cell_xform.basis.scale(Vector3(grid_map->get_cell_scale(), | |
+ grid_map->get_cell_scale(), | |
+ grid_map->get_cell_scale())); | |
+ cell_xform.set_origin(grid_map->map_to_world( | |
+ Vector3(cell_location.x, cell_location.y, cell_location.z))); | |
+ Ref<GLTFMesh> gltf_mesh; | |
+ gltf_mesh->mesh = mesh; | |
+ new_gltf_node->mesh = state->meshes.size(); | |
+ state->meshes.push_back(gltf_mesh); | |
+ new_gltf_node->xform = cell_xform * grid_map->get_transform(); | |
+ new_gltf_node->set_name(_gen_unique_name(state, grid_map->get_mesh_library()->get_item_name(cell))); | |
} | |
} | |
void GLTFDocument::_convert_mult_mesh_instance_to_gltf(Node *p_scene_parent, const GLTFNodeIndex &p_parent_node_index, const GLTFNodeIndex &p_root_node_index, Ref<GLTFNode> gltf_node, Ref<GLTFState> state, Node *p_root_node) { | |
- MultiMeshInstance *multi_mesh_instance = Object::cast_to<MultiMeshInstance>(p_scene_parent); | |
- if (multi_mesh_instance) { | |
- Ref<MultiMesh> multi_mesh = multi_mesh_instance->get_multimesh(); | |
- if (multi_mesh.is_valid()) { | |
- for (int32_t instance_i = 0; instance_i < multi_mesh->get_instance_count(); | |
- instance_i++) { | |
- GLTFNode *new_gltf_node = memnew(GLTFNode); | |
- Transform transform; | |
- if (multi_mesh->get_transform_format() == MultiMesh::TRANSFORM_2D) { | |
- Transform2D xform_2d = multi_mesh->get_instance_transform_2d(instance_i); | |
- transform.origin = | |
- Vector3(xform_2d.get_origin().x, 0, xform_2d.get_origin().y); | |
- real_t rotation = xform_2d.get_rotation(); | |
- Quat quat; | |
- quat.set_axis_angle(Vector3(0, 1, 0), rotation); | |
- Size2 scale = xform_2d.get_scale(); | |
- transform.basis.set_quat_scale(quat, | |
- Vector3(scale.x, 0, scale.y)); | |
- transform = | |
- multi_mesh_instance->get_transform() * transform; | |
- } else if (multi_mesh->get_transform_format() == MultiMesh::TRANSFORM_3D) { | |
- transform = multi_mesh_instance->get_transform() * | |
- multi_mesh->get_instance_transform(instance_i); | |
- } | |
- Ref<ArrayMesh> mesh = multi_mesh->get_mesh(); | |
- Ref<GLTFMesh> gltf_mesh; | |
- if (multi_mesh_instance->get_material_override().is_valid()) { | |
- for (int32_t material_i = 0; material_i < mesh->get_surface_count(); | |
- material_i++) { | |
- mesh->surface_set_material(material_i, multi_mesh_instance->get_material_override()); | |
- } | |
- } | |
- gltf_mesh->mesh = mesh; | |
- new_gltf_node->mesh = state->meshes.size(); | |
- state->meshes.push_back(gltf_mesh); | |
- new_gltf_node->xform = transform; | |
- new_gltf_node->set_name(multi_mesh_instance->get_name()); | |
- new_gltf_node->parent = p_parent_node_index; | |
- gltf_node->children.push_back(state->nodes.size()); | |
- state->nodes.push_back(new_gltf_node); | |
+ MultiMeshInstance3D *multi_mesh_instance = Object::cast_to<MultiMeshInstance3D>(p_scene_parent); | |
+ ERR_FAIL_COND(!multi_mesh_instance); | |
+ Ref<MultiMesh> multi_mesh = multi_mesh_instance->get_multimesh(); | |
+ if (multi_mesh.is_valid()) { | |
+ for (int32_t instance_i = 0; instance_i < multi_mesh->get_instance_count(); | |
+ instance_i++) { | |
+ GLTFNode *new_gltf_node = memnew(GLTFNode); | |
+ Transform transform; | |
+ if (multi_mesh->get_transform_format() == MultiMesh::TRANSFORM_2D) { | |
+ Transform2D xform_2d = multi_mesh->get_instance_transform_2d(instance_i); | |
+ transform.origin = | |
+ Vector3(xform_2d.get_origin().x, 0, xform_2d.get_origin().y); | |
+ real_t rotation = xform_2d.get_rotation(); | |
+ Quat quat; | |
+ quat.set_axis_angle(Vector3(0, 1, 0), rotation); | |
+ Size2 scale = xform_2d.get_scale(); | |
+ transform.basis.set_quat_scale(quat, | |
+ Vector3(scale.x, 0, scale.y)); | |
+ transform = | |
+ multi_mesh_instance->get_transform() * transform; | |
+ } else if (multi_mesh->get_transform_format() == MultiMesh::TRANSFORM_3D) { | |
+ transform = multi_mesh_instance->get_transform() * | |
+ multi_mesh->get_instance_transform(instance_i); | |
+ } | |
+ Ref<ArrayMesh> mesh = multi_mesh->get_mesh(); | |
+ Ref<GLTFMesh> gltf_mesh; | |
+ if (multi_mesh_instance->get_material_override().is_valid()) { | |
+ for (int32_t material_i = 0; material_i < mesh->get_surface_count(); | |
+ material_i++) { | |
+ mesh->surface_set_material(material_i, multi_mesh_instance->get_material_override()); | |
+ } | |
} | |
+ gltf_mesh->mesh = mesh; | |
+ new_gltf_node->mesh = state->meshes.size(); | |
+ state->meshes.push_back(gltf_mesh); | |
+ new_gltf_node->xform = transform; | |
+ new_gltf_node->set_name(_gen_unique_name(state, multi_mesh_instance->get_name())); | |
+ new_gltf_node->parent = p_parent_node_index; | |
+ gltf_node->children.push_back(state->nodes.size()); | |
+ state->nodes.push_back(new_gltf_node); | |
} | |
} | |
} | |
void GLTFDocument::_convert_skeleton_to_gltf(Node *p_scene_parent, Ref<GLTFState> state, const GLTFNodeIndex &p_parent_node_index, const GLTFNodeIndex &p_root_node_index, Ref<GLTFNode> gltf_node, Node *p_root_node) { | |
- Skeleton *skeleton = Object::cast_to<Skeleton>(p_scene_parent); | |
+ Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(p_scene_parent); | |
if (skeleton) { | |
GLTFSkeletonIndex gltf_skeleton_index = -1; | |
gltf_skeleton_index = _convert_skeleton(state, skeleton, p_parent_node_index); | |
- if (gltf_skeleton_index != -1) { | |
- gltf_node->skeleton = gltf_skeleton_index; | |
- } | |
- if (p_parent_node_index != p_root_node_index) { | |
- gltf_node.unref(); | |
- } | |
+ gltf_node->skeleton = gltf_skeleton_index; | |
for (int node_i = 0; node_i < p_scene_parent->get_child_count(); node_i++) { | |
_convert_scene_node(state, p_scene_parent->get_child(node_i), p_root_node, p_parent_node_index, p_root_node_index); | |
} | |
@@ -5582,12 +5464,11 @@ | |
void GLTFDocument::_convert_bone_attachment_to_gltf(Node *p_scene_parent, Ref<GLTFState> state, Ref<GLTFNode> gltf_node, bool &retflag) { | |
retflag = true; | |
- BoneAttachment *bone_attachment = Object::cast_to<BoneAttachment>(p_scene_parent); | |
+ BoneAttachment3D *bone_attachment = Object::cast_to<BoneAttachment3D>(p_scene_parent); | |
if (bone_attachment) { | |
Node *node = bone_attachment->get_parent(); | |
while (node) { | |
- | |
- Skeleton *bone_attachment_skeleton = Object::cast_to<Skeleton>(node); | |
+ Skeleton3D *bone_attachment_skeleton = Object::cast_to<Skeleton3D>(node); | |
if (bone_attachment_skeleton) { | |
for (GLTFSkeletonIndex skeleton_i = 0; skeleton_i < state->skeletons.size(); skeleton_i++) { | |
if (state->skeletons[skeleton_i]->godot_skeleton != bone_attachment_skeleton) { | |
@@ -5606,28 +5487,26 @@ | |
retflag = false; | |
} | |
-void GLTFDocument::_convert_mesh_to_gltf(Node *p_scene_parent, Ref<GLTFState> state, Spatial *spatial, Ref<GLTFNode> gltf_node) { | |
- MeshInstance *mi = Object::cast_to<MeshInstance>(p_scene_parent); | |
+void GLTFDocument::_convert_mesh_to_gltf(Node *p_scene_parent, Ref<GLTFState> state, Node3D *spatial, Ref<GLTFNode> gltf_node) { | |
+ MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_scene_parent); | |
if (mi) { | |
GLTFMeshIndex gltf_mesh_index = _convert_mesh_instance(state, mi); | |
if (gltf_mesh_index != -1) { | |
- _convert_spatial(state, spatial, gltf_node); | |
gltf_node->mesh = gltf_mesh_index; | |
} | |
} | |
} | |
-void GLTFDocument::_generate_scene_node(Ref<GLTFState> state, Node *scene_parent, Spatial *scene_root, const GLTFNodeIndex node_index) { | |
- | |
+void GLTFDocument::_generate_scene_node(Ref<GLTFState> state, Node *scene_parent, Node3D *scene_root, const GLTFNodeIndex node_index) { | |
Ref<GLTFNode> gltf_node = state->nodes[node_index]; | |
- Spatial *current_node = nullptr; | |
+ Node3D *current_node = nullptr; | |
// Is our parent a skeleton | |
- Skeleton *active_skeleton = Object::cast_to<Skeleton>(scene_parent); | |
+ Skeleton3D *active_skeleton = Object::cast_to<Skeleton3D>(scene_parent); | |
if (gltf_node->skeleton >= 0) { | |
- Skeleton *skeleton = state->skeletons[gltf_node->skeleton]->godot_skeleton; | |
+ Skeleton3D *skeleton = state->skeletons[gltf_node->skeleton]->godot_skeleton; | |
if (active_skeleton != skeleton) { | |
ERR_FAIL_COND_MSG(active_skeleton != nullptr, "glTF: Generating scene detected direct parented Skeletons"); | |
@@ -5645,13 +5524,13 @@ | |
// If we have an active skeleton, and the node is node skinned, we need to create a bone attachment | |
if (current_node == nullptr && active_skeleton != nullptr && gltf_node->skin < 0) { | |
- BoneAttachment *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index); | |
+ BoneAttachment3D *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index); | |
scene_parent->add_child(bone_attachment); | |
bone_attachment->set_owner(scene_root); | |
// There is no gltf_node that represent this, so just directly create a unique name | |
- bone_attachment->set_name(_gen_unique_name(state, "BoneAttachment")); | |
+ bone_attachment->set_name(_gen_unique_name(state, "BoneAttachment3D")); | |
// We change the scene_parent to our bone attachment now. We do not set current_node because we want to make the node | |
// and attach it to the bone_attachment | |
@@ -5689,18 +5568,15 @@ | |
template <class T> | |
struct EditorSceneImporterGLTFInterpolate { | |
- | |
T lerp(const T &a, const T &b, float c) const { | |
- | |
return a + (b - a) * c; | |
} | |
T catmull_rom(const T &p0, const T &p1, const T &p2, const T &p3, float t) { | |
- | |
const float t2 = t * t; | |
const float t3 = t2 * t; | |
- return 0.5f * ((2.0f * p1) + (-p0 + p2) * t + (2.0f * p0 - 5.0f * p1 + 4 * p2 - p3) * t2 + (-p0 + 3.0f * p1 - 3.0f * p2 + p3) * t3); | |
+ return 0.5f * ((2.0f * p1) + (-p0 + p2) * t + (2.0f * p0 - 5.0f * p1 + 4.0f * p2 - p3) * t2 + (-p0 + 3.0f * p1 - 3.0f * p2 + p3) * t3); | |
} | |
T bezier(T start, T control_1, T control_2, T end, float t) { | |
@@ -5718,7 +5594,6 @@ | |
// thank you for existing, partial specialization | |
template <> | |
struct EditorSceneImporterGLTFInterpolate<Quat> { | |
- | |
Quat lerp(const Quat &a, const Quat &b, const float c) const { | |
ERR_FAIL_COND_V_MSG(!a.is_normalized(), Quat(), "The quaternion \"a\" must be normalized."); | |
ERR_FAIL_COND_V_MSG(!b.is_normalized(), Quat(), "The quaternion \"b\" must be normalized."); | |
@@ -5743,7 +5618,6 @@ | |
template <class T> | |
T GLTFDocument::_interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values, const float p_time, const GLTFAnimation::Interpolation p_interp) { | |
- | |
//could use binary search, worth it? | |
int idx = -1; | |
for (int i = 0; i < p_times.size(); i++) { | |
@@ -5756,7 +5630,6 @@ | |
switch (p_interp) { | |
case GLTFAnimation::INTERP_LINEAR: { | |
- | |
if (idx == -1) { | |
return p_values[0]; | |
} else if (idx >= p_times.size() - 1) { | |
@@ -5768,7 +5641,6 @@ | |
return interp.lerp(p_values[idx], p_values[idx + 1], c); | |
} break; | |
case GLTFAnimation::INTERP_STEP: { | |
- | |
if (idx == -1) { | |
return p_values[0]; | |
} else if (idx >= p_times.size() - 1) { | |
@@ -5778,7 +5650,6 @@ | |
return p_values[idx]; | |
} break; | |
case GLTFAnimation::INTERP_CATMULLROMSPLINE: { | |
- | |
if (idx == -1) { | |
return p_values[1]; | |
} else if (idx >= p_times.size() - 1) { | |
@@ -5790,7 +5661,6 @@ | |
return interp.catmull_rom(p_values[idx - 1], p_values[idx], p_values[idx + 1], p_values[idx + 3], c); | |
} break; | |
case GLTFAnimation::INTERP_CUBIC_SPLINE: { | |
- | |
if (idx == -1) { | |
return p_values[1]; | |
} else if (idx >= p_times.size() - 1) { | |
@@ -5812,7 +5682,6 @@ | |
} | |
void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap, const GLTFAnimationIndex index, const int bake_fps) { | |
- | |
Ref<GLTFAnimation> anim = state->animations[index]; | |
String name = anim->get_name(); | |
@@ -5832,7 +5701,6 @@ | |
float length = 0; | |
for (Map<int, GLTFAnimation::Track>::Element *track_i = anim->get_tracks().front(); track_i; track_i = track_i->next()) { | |
- | |
const GLTFAnimation::Track &track = track_i->get(); | |
//need to find the path | |
NodePath node_path; | |
@@ -5846,7 +5714,7 @@ | |
const Ref<GLTFNode> gltf_node = state->nodes[track_i->key()]; | |
if (gltf_node->skeleton >= 0) { | |
- const Skeleton *sk = Object::cast_to<Skeleton>(state->scene_nodes.find(node_index)->get()); | |
+ const Skeleton3D *sk = Object::cast_to<Skeleton3D>(state->scene_nodes.find(node_index)->get()); | |
ERR_FAIL_COND(sk == nullptr); | |
const String path = ap->get_parent()->get_path_to(sk); | |
@@ -5902,7 +5770,6 @@ | |
bool last = false; | |
while (true) { | |
- | |
Vector3 pos = base_pos; | |
Quat rot = base_rot; | |
Vector3 scale = base_scale; | |
@@ -5920,12 +5787,11 @@ | |
} | |
if (gltf_node->skeleton >= 0) { | |
- | |
Transform xform; | |
xform.basis.set_quat_scale(rot, scale); | |
xform.origin = pos; | |
- const Skeleton *skeleton = state->skeletons[gltf_node->skeleton]->godot_skeleton; | |
+ const Skeleton3D *skeleton = state->skeletons[gltf_node->skeleton]->godot_skeleton; | |
const int bone_idx = skeleton->find_bone(gltf_node->get_name()); | |
xform = skeleton->get_bone_rest(bone_idx).affine_inverse() * xform; | |
@@ -6001,8 +5867,7 @@ | |
Ref<GLTFNode> node; | |
node.instance(); | |
String bone_name = state->skeletons[skeleton_i]->godot_skeleton->get_bone_name(bone_i); | |
- bone_name = _sanitize_bone_name(bone_name); | |
- node->set_name(_gen_unique_name(state, bone_name)); | |
+ node->set_name(_gen_unique_bone_name(state, skeleton_i, bone_name)); | |
Transform xform = state->skeletons[skeleton_i]->godot_skeleton->get_bone_rest(bone_i); | |
node->scale = xform.basis.get_scale(); | |
@@ -6044,7 +5909,7 @@ | |
if (!mi_element) { | |
continue; | |
} | |
- MeshInstance *mi = Object::cast_to<MeshInstance>(mi_element->get()); | |
+ MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(mi_element->get()); | |
ERR_CONTINUE(!mi); | |
Transform xform = mi->get_transform(); | |
@@ -6094,12 +5959,12 @@ | |
const GLTFSkinIndex skin_i = node->skin; | |
Map<GLTFNodeIndex, Node *>::Element *mi_element = state->scene_nodes.find(node_i); | |
- MeshInstance *mi = Object::cast_to<MeshInstance>(mi_element->get()); | |
+ MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(mi_element->get()); | |
ERR_FAIL_COND(mi == nullptr); | |
const GLTFSkeletonIndex skel_i = state->skins.write[node->skin]->skeleton; | |
Ref<GLTFSkeleton> gltf_skeleton = state->skeletons.write[skel_i]; | |
- Skeleton *skeleton = gltf_skeleton->godot_skeleton; | |
+ Skeleton3D *skeleton = gltf_skeleton->godot_skeleton; | |
ERR_FAIL_COND(skeleton == nullptr); | |
mi->get_parent()->remove_child(mi); | |
@@ -6303,7 +6168,6 @@ | |
} | |
void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap, String p_animation_track_name) { | |
- | |
Ref<Animation> animation = ap->get_animation(p_animation_track_name); | |
Ref<GLTFAnimation> gltf_animation; | |
gltf_animation.instance(); | |
@@ -6379,7 +6243,7 @@ | |
const String suffix = node_suffix[1]; | |
const NodePath path = node; | |
Node *godot_node = ap->get_parent()->get_node_or_null(node); | |
- MeshInstance *mi = Object::cast_to<MeshInstance>(godot_node); | |
+ MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(godot_node); | |
if (!mi) { | |
continue; | |
} | |
@@ -6551,7 +6415,6 @@ | |
} | |
Error GLTFDocument::parse(Ref<GLTFState> state, String p_path, bool p_read_binary) { | |
- | |
Error err; | |
FileAccessRef f = FileAccess::open(p_path, FileAccess::READ, &err); | |
if (!f) { | |
@@ -6672,9 +6535,8 @@ | |
Dictionary GLTFDocument::_serialize_texture_transform_uv2(Ref<Material> p_material) { | |
Dictionary extension; | |
- Ref<SpatialMaterial> mat = p_material; | |
+ Ref<StandardMaterial3D> mat = p_material; | |
if (mat.is_valid()) { | |
- | |
Dictionary texture_transform; | |
Array offset; | |
offset.resize(2); | |
@@ -6694,9 +6556,8 @@ | |
Dictionary GLTFDocument::_serialize_texture_transform_uv1(Ref<Material> p_material) { | |
Dictionary extension; | |
- Ref<SpatialMaterial> mat = p_material; | |
+ Ref<StandardMaterial3D> mat = p_material; | |
if (mat.is_valid()) { | |
- | |
Dictionary texture_transform; | |
Array offset; | |
offset.resize(2); | |
@@ -6772,7 +6633,6 @@ | |
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); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment