Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/tests/scene/test_gltf_document.cpp
45991 views
1
/**************************************************************************/
2
/* test_gltf_document.cpp */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#include "tests/test_macros.h"
32
33
TEST_FORCE_LINK(test_gltf_document)
34
35
#ifndef _3D_DISABLED
36
37
#include "modules/modules_enabled.gen.h" // For gltf.
38
39
#ifdef MODULE_GLTF_ENABLED
40
41
#include "tests/test_utils.h"
42
43
#include "modules/gltf/extensions/gltf_document_extension_convert_importer_mesh.h"
44
#include "modules/gltf/gltf_document.h"
45
46
namespace TestGLTFDocument {
47
48
struct GLTFArraySize {
49
String key;
50
int val;
51
};
52
53
struct GLTFKeyValue {
54
String key;
55
Variant val;
56
};
57
58
struct GLTFTestCase {
59
String filename;
60
String copyright;
61
String generator;
62
String version;
63
Vector<GLTFArraySize> array_sizes;
64
Vector<GLTFArraySize> json_array_sizes;
65
Vector<GLTFKeyValue> keyvalues;
66
};
67
68
const GLTFTestCase glTF_test_cases[] = {
69
{ "models/cube.gltf",
70
"",
71
"Khronos glTF Blender I/O v4.3.47",
72
"2.0",
73
// Here are the array sizes.
74
{
75
{ "nodes", 1 },
76
{ "buffers", 1 },
77
{ "buffer_views", 13 },
78
{ "accessors", 13 },
79
{ "meshes", 1 },
80
{ "materials", 2 },
81
{ "root_nodes", 1 },
82
{ "textures", 0 },
83
{ "texture_samplers", 0 },
84
{ "images", 0 },
85
{ "skins", 0 },
86
{ "cameras", 0 },
87
{ "lights", 0 },
88
{ "skeletons", 0 },
89
{ "animations", 1 },
90
},
91
// Here are the json array sizes.
92
{
93
{ "scenes", 1 },
94
{ "nodes", 1 },
95
{ "animations", 1 },
96
{ "meshes", 1 },
97
{ "accessors", 13 },
98
{ "bufferViews", 13 },
99
{ "buffers", 1 },
100
},
101
// Here are the key-value pairs.
102
{
103
{ "major_version", 2 },
104
{ "minor_version", 0 },
105
{ "scene_name", "cube" },
106
{ "filename", "cube" } } },
107
{ "models/suzanne.glb",
108
"this is example text",
109
"Khronos glTF Blender I/O v4.3.47",
110
"2.0",
111
// Here are the array sizes.
112
{
113
{ "glb_data", 68908 },
114
{ "nodes", 2 },
115
{ "buffers", 1 },
116
{ "buffer_views", 5 },
117
{ "accessors", 4 },
118
{ "meshes", 1 },
119
{ "materials", 1 },
120
{ "root_nodes", 2 },
121
{ "textures", 1 },
122
{ "texture_samplers", 1 },
123
{ "images", 1 },
124
{ "skins", 0 },
125
{ "cameras", 1 },
126
{ "lights", 0 },
127
{ "unique_names", 4 },
128
{ "skeletons", 0 },
129
{ "animations", 0 },
130
},
131
// Here are the json array sizes.
132
{
133
{ "scenes", 1 },
134
{ "nodes", 2 },
135
{ "cameras", 1 },
136
{ "materials", 1 },
137
{ "meshes", 1 },
138
{ "textures", 1 },
139
{ "images", 1 },
140
{ "accessors", 4 },
141
{ "bufferViews", 5 },
142
{ "buffers", 1 },
143
},
144
// Here are the key-value pairs.
145
{
146
{ "major_version", 2 },
147
{ "minor_version", 0 },
148
{ "scene_name", "suzanne" },
149
{ "filename", "suzanne" } } },
150
};
151
152
void register_gltf_extension() {
153
GLTFDocument::unregister_all_gltf_document_extensions();
154
155
// Ensures meshes become a MeshInstance3D and not an ImporterMeshInstance3D.
156
Ref<GLTFDocumentExtensionConvertImporterMesh> extension_GLTFDocumentExtensionConvertImporterMesh;
157
extension_GLTFDocumentExtensionConvertImporterMesh.instantiate();
158
GLTFDocument::register_gltf_document_extension(extension_GLTFDocumentExtensionConvertImporterMesh);
159
}
160
161
void test_gltf_document_values(Ref<GLTFDocument> &p_gltf_document, Ref<GLTFState> &p_gltf_state, const GLTFTestCase &p_test_case) {
162
const Error err = p_gltf_document->append_from_file(TestUtils::get_data_path(p_test_case.filename), p_gltf_state);
163
REQUIRE(err == OK);
164
165
for (GLTFArraySize array_size : p_test_case.array_sizes) {
166
CHECK_MESSAGE(((Array)(p_gltf_state->getvar(array_size.key))).size() == array_size.val, "Expected \"", array_size.key, "\" to have ", array_size.val, " elements.");
167
}
168
169
for (GLTFArraySize array_size : p_test_case.json_array_sizes) {
170
CHECK(p_gltf_state->get_json().has(array_size.key));
171
CHECK_MESSAGE(((Array)(p_gltf_state->get_json()[array_size.key])).size() == array_size.val, "Expected \"", array_size.key, "\" to have ", array_size.val, " elements.");
172
}
173
174
for (GLTFKeyValue key_value : p_test_case.keyvalues) {
175
CHECK_MESSAGE(p_gltf_state->getvar(key_value.key) == key_value.val, "Expected \"", key_value.key, "\" to be \"", key_value.val, "\".");
176
}
177
178
CHECK(p_gltf_state->get_copyright() == p_test_case.copyright);
179
CHECK(((Dictionary)p_gltf_state->get_json()["asset"])["generator"] == p_test_case.generator);
180
CHECK(((Dictionary)p_gltf_state->get_json()["asset"])["version"] == p_test_case.version);
181
}
182
183
void test_gltf_save(Node *p_node) {
184
Ref<GLTFDocument> gltf_document_save;
185
gltf_document_save.instantiate();
186
Ref<GLTFState> gltf_state_save;
187
gltf_state_save.instantiate();
188
189
gltf_document_save->append_from_scene(p_node, gltf_state_save);
190
191
// Check saving the scene to gltf and glb.
192
const Error err_save_gltf = gltf_document_save->write_to_filesystem(gltf_state_save, TestUtils::get_temp_path("cube.gltf"));
193
const Error err_save_glb = gltf_document_save->write_to_filesystem(gltf_state_save, TestUtils::get_temp_path("cube.glb"));
194
CHECK(err_save_gltf == OK);
195
CHECK(err_save_glb == OK);
196
}
197
198
TEST_CASE("[SceneTree][GLTFDocument] Load cube.gltf") {
199
register_gltf_extension();
200
201
Ref<GLTFDocument> gltf_document;
202
gltf_document.instantiate();
203
Ref<GLTFState> gltf_state;
204
gltf_state.instantiate();
205
206
test_gltf_document_values(gltf_document, gltf_state, glTF_test_cases[0]);
207
208
Node *node = gltf_document->generate_scene(gltf_state);
209
210
// Check the loaded scene.
211
CHECK(node->is_class("Node3D"));
212
CHECK(node->get_name() == "cube");
213
214
CHECK(node->get_child(0)->is_class("MeshInstance3D"));
215
CHECK(node->get_child(0)->get_name() == "Cube");
216
217
CHECK(node->get_child(1)->is_class("AnimationPlayer"));
218
CHECK(node->get_child(1)->get_name() == "AnimationPlayer");
219
220
test_gltf_save(node);
221
222
// Clean up the node.
223
memdelete(node);
224
}
225
226
TEST_CASE("[SceneTree][GLTFDocument] Load suzanne.glb") {
227
register_gltf_extension();
228
229
Ref<GLTFDocument> gltf_document;
230
gltf_document.instantiate();
231
Ref<GLTFState> gltf_state;
232
gltf_state.instantiate();
233
234
test_gltf_document_values(gltf_document, gltf_state, glTF_test_cases[1]);
235
236
Node *node = gltf_document->generate_scene(gltf_state);
237
238
// Check the loaded scene.
239
CHECK(node->is_class("Node3D"));
240
CHECK(node->get_name() == "suzanne");
241
242
CHECK(node->get_child(0)->is_class("MeshInstance3D"));
243
CHECK(node->get_child(0)->get_name() == "Suzanne");
244
245
CHECK(node->get_child(1)->is_class("Camera3D"));
246
CHECK(node->get_child(1)->get_name() == "Camera");
247
248
test_gltf_save(node);
249
250
// Clean up the node.
251
memdelete(node);
252
}
253
254
} // namespace TestGLTFDocument
255
256
#endif // MODULE_GLTF_ENABLED
257
258
#endif // _3D_DISABLED
259
260