1 /*************************************************************************/
2 /*  editor_scene_importer_assimp.cpp                                     */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
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 "editor_scene_importer_assimp.h"
32 #include "core/io/image_loader.h"
33 #include "editor/import/resource_importer_scene.h"
34 #include "import_utils.h"
35 #include "scene/3d/camera.h"
36 #include "scene/3d/light.h"
37 #include "scene/3d/mesh_instance.h"
38 #include "scene/main/node.h"
39 #include "scene/resources/material.h"
40 #include "scene/resources/surface_tool.h"
41 
42 #include <assimp/matrix4x4.h>
43 #include <assimp/postprocess.h>
44 #include <assimp/scene.h>
45 #include <assimp/Importer.hpp>
46 #include <assimp/LogStream.hpp>
47 
48 // move into assimp
get_bone_by_name(const aiScene * scene,aiString bone_name)49 aiBone *get_bone_by_name(const aiScene *scene, aiString bone_name) {
50 	for (unsigned int mesh_id = 0; mesh_id < scene->mNumMeshes; ++mesh_id) {
51 		aiMesh *mesh = scene->mMeshes[mesh_id];
52 
53 		// iterate over all the bones on the mesh for this node only!
54 		for (unsigned int boneIndex = 0; boneIndex < mesh->mNumBones; boneIndex++) {
55 
56 			aiBone *bone = mesh->mBones[boneIndex];
57 			if (bone->mName == bone_name) {
58 				printf("matched bone by name: %s\n", bone->mName.C_Str());
59 				return bone;
60 			}
61 		}
62 	}
63 
64 	return NULL;
65 }
66 
get_extensions(List<String> * r_extensions) const67 void EditorSceneImporterAssimp::get_extensions(List<String> *r_extensions) const {
68 
69 	const String import_setting_string = "filesystem/import/open_asset_import/";
70 
71 	Map<String, ImportFormat> import_format;
72 	{
73 		Vector<String> exts;
74 		exts.push_back("fbx");
75 		ImportFormat import = { exts, true };
76 		import_format.insert("fbx", import);
77 	}
78 	for (Map<String, ImportFormat>::Element *E = import_format.front(); E; E = E->next()) {
79 		_register_project_setting_import(E->key(), import_setting_string, E->get().extensions, r_extensions,
80 				E->get().is_default);
81 	}
82 }
83 
_register_project_setting_import(const String generic,const String import_setting_string,const Vector<String> & exts,List<String> * r_extensions,const bool p_enabled) const84 void EditorSceneImporterAssimp::_register_project_setting_import(const String generic, const String import_setting_string,
85 		const Vector<String> &exts, List<String> *r_extensions,
86 		const bool p_enabled) const {
87 	const String use_generic = "use_" + generic;
88 	_GLOBAL_DEF(import_setting_string + use_generic, p_enabled, true);
89 	if (ProjectSettings::get_singleton()->get(import_setting_string + use_generic)) {
90 		for (int32_t i = 0; i < exts.size(); i++) {
91 			r_extensions->push_back(exts[i]);
92 		}
93 	}
94 }
95 
get_import_flags() const96 uint32_t EditorSceneImporterAssimp::get_import_flags() const {
97 	return IMPORT_SCENE;
98 }
99 
_bind_methods()100 void EditorSceneImporterAssimp::_bind_methods() {
101 }
102 
import_scene(const String & p_path,uint32_t p_flags,int p_bake_fps,List<String> * r_missing_deps,Error * r_err)103 Node *EditorSceneImporterAssimp::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps,
104 		List<String> *r_missing_deps, Error *r_err) {
105 	Assimp::Importer importer;
106 	importer.SetPropertyBool(AI_CONFIG_PP_FD_REMOVE, true);
107 	// Cannot remove pivot points because the static mesh will be in the wrong place
108 	importer.SetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, false);
109 	int32_t max_bone_weights = 4;
110 	//if (p_flags & IMPORT_ANIMATION_EIGHT_WEIGHTS) {
111 	//	const int eight_bones = 8;
112 	//	importer.SetPropertyBool(AI_CONFIG_PP_LBW_MAX_WEIGHTS, eight_bones);
113 	//	max_bone_weights = eight_bones;
114 	//}
115 
116 	importer.SetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_LINE | aiPrimitiveType_POINT);
117 
118 	//importer.SetPropertyFloat(AI_CONFIG_PP_DB_THRESHOLD, 1.0f);
119 	int32_t post_process_Steps = aiProcess_CalcTangentSpace |
120 								 aiProcess_GlobalScale |
121 								 // imports models and listens to their file scale for CM to M conversions
122 								 //aiProcess_FlipUVs |
123 								 aiProcess_FlipWindingOrder |
124 								 // very important for culling so that it is done in the correct order.
125 								 //aiProcess_DropNormals |
126 								 //aiProcess_GenSmoothNormals |
127 								 //aiProcess_JoinIdenticalVertices |
128 								 aiProcess_ImproveCacheLocality |
129 								 //aiProcess_RemoveRedundantMaterials | // Causes a crash
130 								 //aiProcess_SplitLargeMeshes |
131 								 aiProcess_Triangulate |
132 								 aiProcess_GenUVCoords |
133 								 //aiProcess_FindDegenerates |
134 								 //aiProcess_SortByPType |
135 								 // aiProcess_FindInvalidData |
136 								 aiProcess_TransformUVCoords |
137 								 aiProcess_FindInstances |
138 								 //aiProcess_FixInfacingNormals |
139 								 //aiProcess_ValidateDataStructure |
140 								 aiProcess_OptimizeMeshes |
141 								 aiProcess_PopulateArmatureData |
142 								 //aiProcess_OptimizeGraph |
143 								 //aiProcess_Debone |
144 								 // aiProcess_EmbedTextures |
145 								 //aiProcess_SplitByBoneCount |
146 								 0;
147 	String g_path = ProjectSettings::get_singleton()->globalize_path(p_path);
148 	aiScene *scene = (aiScene *)importer.ReadFile(g_path.utf8().ptr(), post_process_Steps);
149 
150 	ERR_FAIL_COND_V_MSG(scene == NULL, NULL, String("Open Asset Import failed to open: ") + String(importer.GetErrorString()));
151 
152 	return _generate_scene(p_path, scene, p_flags, p_bake_fps, max_bone_weights);
153 }
154 
155 template <class T>
156 struct EditorSceneImporterAssetImportInterpolate {
157 
lerpEditorSceneImporterAssetImportInterpolate158 	T lerp(const T &a, const T &b, float c) const {
159 
160 		return a + (b - a) * c;
161 	}
162 
catmull_romEditorSceneImporterAssetImportInterpolate163 	T catmull_rom(const T &p0, const T &p1, const T &p2, const T &p3, float t) {
164 
165 		float t2 = t * t;
166 		float t3 = t2 * t;
167 
168 		return 0.5f * ((2.0f * p1) + (-p0 + p2) * t + (2.0f * p0 - 5.0f * p1 + 4 * p2 - p3) * t2 +
169 							  (-p0 + 3.0f * p1 - 3.0f * p2 + p3) * t3);
170 	}
171 
bezierEditorSceneImporterAssetImportInterpolate172 	T bezier(T start, T control_1, T control_2, T end, float t) {
173 		/* Formula from Wikipedia article on Bezier curves. */
174 		real_t omt = (1.0 - t);
175 		real_t omt2 = omt * omt;
176 		real_t omt3 = omt2 * omt;
177 		real_t t2 = t * t;
178 		real_t t3 = t2 * t;
179 
180 		return start * omt3 + control_1 * omt2 * t * 3.0 + control_2 * omt * t2 * 3.0 + end * t3;
181 	}
182 };
183 
184 //thank you for existing, partial specialization
185 template <>
186 struct EditorSceneImporterAssetImportInterpolate<Quat> {
187 
lerpEditorSceneImporterAssetImportInterpolate188 	Quat lerp(const Quat &a, const Quat &b, float c) const {
189 		ERR_FAIL_COND_V_MSG(!a.is_normalized(), Quat(), "The quaternion \"a\" must be normalized.");
190 		ERR_FAIL_COND_V_MSG(!b.is_normalized(), Quat(), "The quaternion \"b\" must be normalized.");
191 
192 		return a.slerp(b, c).normalized();
193 	}
194 
catmull_romEditorSceneImporterAssetImportInterpolate195 	Quat catmull_rom(const Quat &p0, const Quat &p1, const Quat &p2, const Quat &p3, float c) {
196 		ERR_FAIL_COND_V_MSG(!p1.is_normalized(), Quat(), "The quaternion \"p1\" must be normalized.");
197 		ERR_FAIL_COND_V_MSG(!p2.is_normalized(), Quat(), "The quaternion \"p2\" must be normalized.");
198 
199 		return p1.slerp(p2, c).normalized();
200 	}
201 
bezierEditorSceneImporterAssetImportInterpolate202 	Quat bezier(Quat start, Quat control_1, Quat control_2, Quat end, float t) {
203 		ERR_FAIL_COND_V_MSG(!start.is_normalized(), Quat(), "The start quaternion must be normalized.");
204 		ERR_FAIL_COND_V_MSG(!end.is_normalized(), Quat(), "The end quaternion must be normalized.");
205 
206 		return start.slerp(end, t).normalized();
207 	}
208 };
209 
210 template <class T>
_interpolate_track(const Vector<float> & p_times,const Vector<T> & p_values,float p_time,AssetImportAnimation::Interpolation p_interp)211 T EditorSceneImporterAssimp::_interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values, float p_time,
212 		AssetImportAnimation::Interpolation p_interp) {
213 	//could use binary search, worth it?
214 	int idx = -1;
215 	for (int i = 0; i < p_times.size(); i++) {
216 		if (p_times[i] > p_time)
217 			break;
218 		idx++;
219 	}
220 
221 	EditorSceneImporterAssetImportInterpolate<T> interp;
222 
223 	switch (p_interp) {
224 		case AssetImportAnimation::INTERP_LINEAR: {
225 
226 			if (idx == -1) {
227 				return p_values[0];
228 			} else if (idx >= p_times.size() - 1) {
229 				return p_values[p_times.size() - 1];
230 			}
231 
232 			float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]);
233 
234 			return interp.lerp(p_values[idx], p_values[idx + 1], c);
235 
236 		} break;
237 		case AssetImportAnimation::INTERP_STEP: {
238 
239 			if (idx == -1) {
240 				return p_values[0];
241 			} else if (idx >= p_times.size() - 1) {
242 				return p_values[p_times.size() - 1];
243 			}
244 
245 			return p_values[idx];
246 
247 		} break;
248 		case AssetImportAnimation::INTERP_CATMULLROMSPLINE: {
249 
250 			if (idx == -1) {
251 				return p_values[1];
252 			} else if (idx >= p_times.size() - 1) {
253 				return p_values[1 + p_times.size() - 1];
254 			}
255 
256 			float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]);
257 
258 			return interp.catmull_rom(p_values[idx - 1], p_values[idx], p_values[idx + 1], p_values[idx + 3], c);
259 
260 		} break;
261 		case AssetImportAnimation::INTERP_CUBIC_SPLINE: {
262 
263 			if (idx == -1) {
264 				return p_values[1];
265 			} else if (idx >= p_times.size() - 1) {
266 				return p_values[(p_times.size() - 1) * 3 + 1];
267 			}
268 
269 			float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]);
270 
271 			T from = p_values[idx * 3 + 1];
272 			T c1 = from + p_values[idx * 3 + 2];
273 			T to = p_values[idx * 3 + 4];
274 			T c2 = to + p_values[idx * 3 + 3];
275 
276 			return interp.bezier(from, c1, c2, to, c);
277 
278 		} break;
279 	}
280 
281 	ERR_FAIL_V(p_values[0]);
282 }
283 
get_bone_from_stack(ImportState & state,aiString name)284 aiBone *EditorSceneImporterAssimp::get_bone_from_stack(ImportState &state, aiString name) {
285 	List<aiBone *>::Element *iter;
286 	aiBone *bone = NULL;
287 	for (iter = state.bone_stack.front(); iter; iter = iter->next()) {
288 		bone = (aiBone *)iter->get();
289 
290 		if (bone && bone->mName == name) {
291 			state.bone_stack.erase(bone);
292 			return bone;
293 		}
294 	}
295 
296 	return NULL;
297 }
298 
299 Spatial *
_generate_scene(const String & p_path,aiScene * scene,const uint32_t p_flags,int p_bake_fps,const int32_t p_max_bone_weights)300 EditorSceneImporterAssimp::_generate_scene(const String &p_path, aiScene *scene, const uint32_t p_flags, int p_bake_fps,
301 		const int32_t p_max_bone_weights) {
302 	ERR_FAIL_COND_V(scene == NULL, NULL);
303 
304 	ImportState state;
305 	state.path = p_path;
306 	state.assimp_scene = scene;
307 	state.max_bone_weights = p_max_bone_weights;
308 	state.animation_player = NULL;
309 	state.import_flags = p_flags;
310 
311 	// populate light map
312 	for (unsigned int l = 0; l < scene->mNumLights; l++) {
313 
314 		aiLight *ai_light = scene->mLights[l];
315 		ERR_CONTINUE(ai_light == NULL);
316 		state.light_cache[AssimpUtils::get_assimp_string(ai_light->mName)] = l;
317 	}
318 
319 	// fill camera cache
320 	for (unsigned int c = 0; c < scene->mNumCameras; c++) {
321 		aiCamera *ai_camera = scene->mCameras[c];
322 		ERR_CONTINUE(ai_camera == NULL);
323 		state.camera_cache[AssimpUtils::get_assimp_string(ai_camera->mName)] = c;
324 	}
325 
326 	if (scene->mRootNode) {
327 		state.nodes.push_back(scene->mRootNode);
328 
329 		// make flat node tree - in order to make processing deterministic
330 		for (unsigned int i = 0; i < scene->mRootNode->mNumChildren; i++) {
331 			_generate_node(state, scene->mRootNode->mChildren[i]);
332 		}
333 
334 		RegenerateBoneStack(state);
335 
336 		Node *last_valid_parent = NULL;
337 
338 		List<const aiNode *>::Element *iter;
339 		for (iter = state.nodes.front(); iter; iter = iter->next()) {
340 			const aiNode *element_assimp_node = iter->get();
341 			const aiNode *parent_assimp_node = element_assimp_node->mParent;
342 
343 			String node_name = AssimpUtils::get_assimp_string(element_assimp_node->mName);
344 			//print_verbose("node: " + node_name);
345 
346 			Spatial *spatial = NULL;
347 			Transform transform = AssimpUtils::assimp_matrix_transform(element_assimp_node->mTransformation);
348 
349 			// retrieve this node bone
350 			aiBone *bone = get_bone_from_stack(state, element_assimp_node->mName);
351 
352 			if (state.light_cache.has(node_name)) {
353 				spatial = create_light(state, node_name, transform);
354 			} else if (state.camera_cache.has(node_name)) {
355 				spatial = create_camera(state, node_name, transform);
356 			} else if (state.armature_nodes.find(element_assimp_node)) {
357 				// create skeleton
358 				print_verbose("Making skeleton: " + node_name);
359 				Skeleton *skeleton = memnew(Skeleton);
360 				spatial = skeleton;
361 				if (!state.armature_skeletons.has(element_assimp_node)) {
362 					state.armature_skeletons.insert(element_assimp_node, skeleton);
363 				}
364 			} else if (bone != NULL) {
365 				continue;
366 			} else {
367 				spatial = memnew(Spatial);
368 			}
369 
370 			ERR_CONTINUE_MSG(spatial == NULL, "FBX Import - are we out of ram?");
371 			// we on purpose set the transform and name after creating the node.
372 
373 			spatial->set_name(node_name);
374 			spatial->set_global_transform(transform);
375 
376 			// first element is root
377 			if (iter == state.nodes.front()) {
378 				state.root = spatial;
379 			}
380 
381 			// flat node map parent lookup tool
382 			state.flat_node_map.insert(element_assimp_node, spatial);
383 
384 			Map<const aiNode *, Spatial *>::Element *parent_lookup = state.flat_node_map.find(parent_assimp_node);
385 
386 			// note: this always fails on the root node :) keep that in mind this is by design
387 			if (parent_lookup) {
388 				Spatial *parent_node = parent_lookup->value();
389 
390 				ERR_FAIL_COND_V_MSG(parent_node == NULL, state.root,
391 						"Parent node invalid even though lookup successful, out of ram?")
392 
393 				if (spatial != state.root) {
394 					parent_node->add_child(spatial);
395 					spatial->set_owner(state.root);
396 				} else {
397 					// required - think about it root never has a parent yet is valid, anything else without a parent is not valid.
398 				}
399 			} else if (spatial != state.root) {
400 				// if the ainode is not in the tree
401 				// parent it to the last good parent found
402 				if (last_valid_parent) {
403 					last_valid_parent->add_child(spatial);
404 					spatial->set_owner(state.root);
405 				} else {
406 					// this is a serious error?
407 					memdelete(spatial);
408 				}
409 			}
410 
411 			// update last valid parent
412 			last_valid_parent = spatial;
413 		}
414 		print_verbose("node counts: " + itos(state.nodes.size()));
415 
416 		// make clean bone stack
417 		RegenerateBoneStack(state);
418 
419 		print_verbose("generating godot bone data");
420 
421 		print_verbose("Godot bone stack count: " + itos(state.bone_stack.size()));
422 
423 		// This is a list of bones, duplicates are from other meshes and must be dealt with properly
424 		for (List<aiBone *>::Element *element = state.bone_stack.front(); element; element = element->next()) {
425 			aiBone *bone = element->get();
426 
427 			ERR_CONTINUE_MSG(!bone, "invalid bone read from assimp?");
428 
429 			// Utilities for armature lookup - for now only FBX makes these
430 			aiNode *armature_for_bone = bone->mArmature;
431 
432 			// Utilities for bone node lookup - for now only FBX makes these
433 			aiNode *bone_node = bone->mNode;
434 			aiNode *parent_node = bone_node->mParent;
435 
436 			String bone_name = AssimpUtils::get_anim_string_from_assimp(bone->mName);
437 			ERR_CONTINUE_MSG(armature_for_bone == NULL, "Armature for bone invalid: " + bone_name);
438 			Skeleton *skeleton = state.armature_skeletons[armature_for_bone];
439 
440 			state.skeleton_bone_map[bone] = skeleton;
441 
442 			if (bone_name.empty()) {
443 				bone_name = "untitled_bone_name";
444 				WARN_PRINT("Untitled bone name detected... report with file please");
445 			}
446 
447 			// todo: this is where skin support goes
448 			if (skeleton && skeleton->find_bone(bone_name) == -1) {
449 				print_verbose("[Godot Glue] Imported bone" + bone_name);
450 				int boneIdx = skeleton->get_bone_count();
451 
452 				Transform pform = AssimpUtils::assimp_matrix_transform(bone->mNode->mTransformation);
453 				skeleton->add_bone(bone_name);
454 				skeleton->set_bone_rest(boneIdx, pform);
455 				skeleton->set_bone_pose(boneIdx, pform);
456 
457 				if (parent_node != NULL) {
458 					int parent_bone_id = skeleton->find_bone(AssimpUtils::get_anim_string_from_assimp(parent_node->mName));
459 					int current_bone_id = boneIdx;
460 					skeleton->set_bone_parent(current_bone_id, parent_bone_id);
461 				}
462 			}
463 		}
464 
465 		print_verbose("generating mesh phase from skeletal mesh");
466 
467 		List<Spatial *> cleanup_template_nodes;
468 
469 		for (Map<const aiNode *, Spatial *>::Element *key_value_pair = state.flat_node_map.front(); key_value_pair; key_value_pair = key_value_pair->next()) {
470 			const aiNode *assimp_node = key_value_pair->key();
471 			Spatial *mesh_template = key_value_pair->value();
472 
473 			ERR_CONTINUE(assimp_node == NULL);
474 			ERR_CONTINUE(mesh_template == NULL);
475 
476 			Node *parent_node = mesh_template->get_parent();
477 
478 			if (mesh_template == state.root) {
479 				continue;
480 			}
481 
482 			if (parent_node == NULL) {
483 				print_error("Found invalid parent node!");
484 				continue; // root node
485 			}
486 
487 			String node_name = AssimpUtils::get_assimp_string(assimp_node->mName);
488 			Transform node_transform = AssimpUtils::assimp_matrix_transform(assimp_node->mTransformation);
489 
490 			if (assimp_node->mNumMeshes > 0) {
491 				MeshInstance *mesh = create_mesh(state, assimp_node, node_name, parent_node, node_transform);
492 				if (mesh) {
493 
494 					parent_node->remove_child(mesh_template);
495 
496 					// re-parent children
497 					List<Node *> children;
498 					// re-parent all children to new node
499 					// note: since get_child_count will change during execution we must build a list first to be safe.
500 					for (int childId = 0; childId < mesh_template->get_child_count(); childId++) {
501 						// get child
502 						Node *child = mesh_template->get_child(childId);
503 						children.push_back(child);
504 					}
505 
506 					for (List<Node *>::Element *element = children.front(); element; element = element->next()) {
507 						// reparent the children to the real mesh node.
508 						mesh_template->remove_child(element->get());
509 						mesh->add_child(element->get());
510 						element->get()->set_owner(state.root);
511 					}
512 
513 					// update mesh in list so that each mesh node is available
514 					// this makes the template unavailable which is the desired behaviour
515 					state.flat_node_map[assimp_node] = mesh;
516 
517 					cleanup_template_nodes.push_back(mesh_template);
518 
519 					// clean up this list we don't need it
520 					children.clear();
521 				}
522 			}
523 		}
524 
525 		for (List<Spatial *>::Element *element = cleanup_template_nodes.front(); element; element = element->next()) {
526 			if (element->get()) {
527 				memdelete(element->get());
528 			}
529 		}
530 	}
531 
532 	if (p_flags & IMPORT_ANIMATION && scene->mNumAnimations) {
533 
534 		state.animation_player = memnew(AnimationPlayer);
535 		state.root->add_child(state.animation_player);
536 		state.animation_player->set_owner(state.root);
537 
538 		for (uint32_t i = 0; i < scene->mNumAnimations; i++) {
539 			_import_animation(state, i, p_bake_fps);
540 		}
541 	}
542 
543 	//
544 	// Cleanup operations
545 	//
546 
547 	state.mesh_cache.clear();
548 	state.material_cache.clear();
549 	state.light_cache.clear();
550 	state.camera_cache.clear();
551 	state.assimp_node_map.clear();
552 	state.path_to_image_cache.clear();
553 	state.nodes.clear();
554 	state.flat_node_map.clear();
555 	state.armature_skeletons.clear();
556 	state.bone_stack.clear();
557 	return state.root;
558 }
559 
_insert_animation_track(ImportState & scene,const aiAnimation * assimp_anim,int track_id,int anim_fps,Ref<Animation> animation,float ticks_per_second,Skeleton * skeleton,const NodePath & node_path,const String & node_name,aiBone * track_bone)560 void EditorSceneImporterAssimp::_insert_animation_track(ImportState &scene, const aiAnimation *assimp_anim, int track_id,
561 		int anim_fps, Ref<Animation> animation, float ticks_per_second,
562 		Skeleton *skeleton, const NodePath &node_path,
563 		const String &node_name, aiBone *track_bone) {
564 	const aiNodeAnim *assimp_track = assimp_anim->mChannels[track_id];
565 	//make transform track
566 	int track_idx = animation->get_track_count();
567 	animation->add_track(Animation::TYPE_TRANSFORM);
568 	animation->track_set_path(track_idx, node_path);
569 	//first determine animation length
570 
571 	float increment = 1.0 / float(anim_fps);
572 	float time = 0.0;
573 
574 	bool last = false;
575 
576 	Vector<Vector3> pos_values;
577 	Vector<float> pos_times;
578 	Vector<Vector3> scale_values;
579 	Vector<float> scale_times;
580 	Vector<Quat> rot_values;
581 	Vector<float> rot_times;
582 
583 	for (size_t p = 0; p < assimp_track->mNumPositionKeys; p++) {
584 		aiVector3D pos = assimp_track->mPositionKeys[p].mValue;
585 		pos_values.push_back(Vector3(pos.x, pos.y, pos.z));
586 		pos_times.push_back(assimp_track->mPositionKeys[p].mTime / ticks_per_second);
587 	}
588 
589 	for (size_t r = 0; r < assimp_track->mNumRotationKeys; r++) {
590 		aiQuaternion quat = assimp_track->mRotationKeys[r].mValue;
591 		rot_values.push_back(Quat(quat.x, quat.y, quat.z, quat.w).normalized());
592 		rot_times.push_back(assimp_track->mRotationKeys[r].mTime / ticks_per_second);
593 	}
594 
595 	for (size_t sc = 0; sc < assimp_track->mNumScalingKeys; sc++) {
596 		aiVector3D scale = assimp_track->mScalingKeys[sc].mValue;
597 		scale_values.push_back(Vector3(scale.x, scale.y, scale.z));
598 		scale_times.push_back(assimp_track->mScalingKeys[sc].mTime / ticks_per_second);
599 	}
600 
601 	while (true) {
602 		Vector3 pos;
603 		Quat rot;
604 		Vector3 scale(1, 1, 1);
605 
606 		if (pos_values.size()) {
607 			pos = _interpolate_track<Vector3>(pos_times, pos_values, time, AssetImportAnimation::INTERP_LINEAR);
608 		}
609 
610 		if (rot_values.size()) {
611 			rot = _interpolate_track<Quat>(rot_times, rot_values, time,
612 					AssetImportAnimation::INTERP_LINEAR)
613 						  .normalized();
614 		}
615 
616 		if (scale_values.size()) {
617 			scale = _interpolate_track<Vector3>(scale_times, scale_values, time, AssetImportAnimation::INTERP_LINEAR);
618 		}
619 
620 		if (skeleton) {
621 			int skeleton_bone = skeleton->find_bone(node_name);
622 
623 			if (skeleton_bone >= 0 && track_bone) {
624 
625 				Transform xform;
626 				xform.basis.set_quat_scale(rot, scale);
627 				xform.origin = pos;
628 
629 				xform = skeleton->get_bone_pose(skeleton_bone).inverse() * xform;
630 
631 				rot = xform.basis.get_rotation_quat();
632 				rot.normalize();
633 				scale = xform.basis.get_scale();
634 				pos = xform.origin;
635 			} else {
636 				ERR_FAIL_MSG("Skeleton bone lookup failed for skeleton: " + skeleton->get_name());
637 			}
638 		}
639 
640 		animation->track_set_interpolation_type(track_idx, Animation::INTERPOLATION_LINEAR);
641 		animation->transform_track_insert_key(track_idx, time, pos, rot, scale);
642 
643 		if (last) { //done this way so a key is always inserted past the end (for proper interpolation)
644 			break;
645 		}
646 		time += increment;
647 		if (time >= animation->get_length()) {
648 			last = true;
649 		}
650 	}
651 }
652 
653 // I really do not like this but need to figure out a better way of removing it later.
get_node_by_name(ImportState & state,String name)654 Node *EditorSceneImporterAssimp::get_node_by_name(ImportState &state, String name) {
655 	for (Map<const aiNode *, Spatial *>::Element *key_value_pair = state.flat_node_map.front(); key_value_pair; key_value_pair = key_value_pair->next()) {
656 		const aiNode *assimp_node = key_value_pair->key();
657 		Spatial *node = key_value_pair->value();
658 
659 		String node_name = AssimpUtils::get_assimp_string(assimp_node->mName);
660 		if (name == node_name && node) {
661 			return node;
662 		}
663 	}
664 	return NULL;
665 }
666 
667 /* Bone stack is a fifo handler for multiple armatures since armatures aren't a thing in assimp (yet) */
RegenerateBoneStack(ImportState & state)668 void EditorSceneImporterAssimp::RegenerateBoneStack(ImportState &state) {
669 
670 	state.bone_stack.clear();
671 	// build bone stack list
672 	for (unsigned int mesh_id = 0; mesh_id < state.assimp_scene->mNumMeshes; ++mesh_id) {
673 		aiMesh *mesh = state.assimp_scene->mMeshes[mesh_id];
674 
675 		// iterate over all the bones on the mesh for this node only!
676 		for (unsigned int boneIndex = 0; boneIndex < mesh->mNumBones; boneIndex++) {
677 			aiBone *bone = mesh->mBones[boneIndex];
678 
679 			// doubtful this is required right now but best to check
680 			if (!state.bone_stack.find(bone)) {
681 				//print_verbose("[assimp] bone stack added: " + String(bone->mName.C_Str()) );
682 				state.bone_stack.push_back(bone);
683 			}
684 		}
685 	}
686 }
687 
688 /* Bone stack is a fifo handler for multiple armatures since armatures aren't a thing in assimp (yet) */
RegenerateBoneStack(ImportState & state,aiMesh * mesh)689 void EditorSceneImporterAssimp::RegenerateBoneStack(ImportState &state, aiMesh *mesh) {
690 	state.bone_stack.clear();
691 	// iterate over all the bones on the mesh for this node only!
692 	for (unsigned int boneIndex = 0; boneIndex < mesh->mNumBones; boneIndex++) {
693 		aiBone *bone = mesh->mBones[boneIndex];
694 		if (state.bone_stack.find(bone) == NULL) {
695 			state.bone_stack.push_back(bone);
696 		}
697 	}
698 }
699 
700 // animation tracks are per bone
701 
_import_animation(ImportState & state,int p_animation_index,int p_bake_fps)702 void EditorSceneImporterAssimp::_import_animation(ImportState &state, int p_animation_index, int p_bake_fps) {
703 
704 	ERR_FAIL_INDEX(p_animation_index, (int)state.assimp_scene->mNumAnimations);
705 
706 	const aiAnimation *anim = state.assimp_scene->mAnimations[p_animation_index];
707 	String name = AssimpUtils::get_anim_string_from_assimp(anim->mName);
708 	if (name == String()) {
709 		name = "Animation " + itos(p_animation_index + 1);
710 	}
711 	print_verbose("import animation: " + name);
712 	float ticks_per_second = anim->mTicksPerSecond;
713 
714 	if (state.assimp_scene->mMetaData != NULL && Math::is_equal_approx(ticks_per_second, 0.0f)) {
715 		int32_t time_mode = 0;
716 		state.assimp_scene->mMetaData->Get("TimeMode", time_mode);
717 		ticks_per_second = AssimpUtils::get_fbx_fps(time_mode, state.assimp_scene);
718 	}
719 
720 	//?
721 	//if ((p_path.get_file().get_extension().to_lower() == "glb" || p_path.get_file().get_extension().to_lower() == "gltf") && Math::is_equal_approx(ticks_per_second, 0.0f)) {
722 	//	ticks_per_second = 1000.0f;
723 	//}
724 
725 	if (Math::is_equal_approx(ticks_per_second, 0.0f)) {
726 		ticks_per_second = 25.0f;
727 	}
728 
729 	Ref<Animation> animation;
730 	animation.instance();
731 	animation->set_name(name);
732 	animation->set_length(anim->mDuration / ticks_per_second);
733 
734 	if (name.begins_with("loop") || name.ends_with("loop") || name.begins_with("cycle") || name.ends_with("cycle")) {
735 		animation->set_loop(true);
736 	}
737 
738 	// generate bone stack for animation import
739 	RegenerateBoneStack(state);
740 
741 	//regular tracks
742 	for (size_t i = 0; i < anim->mNumChannels; i++) {
743 		const aiNodeAnim *track = anim->mChannels[i];
744 		String node_name = AssimpUtils::get_assimp_string(track->mNodeName);
745 		print_verbose("track name import: " + node_name);
746 		if (track->mNumRotationKeys == 0 && track->mNumPositionKeys == 0 && track->mNumScalingKeys == 0) {
747 			continue; //do not bother
748 		}
749 
750 		Skeleton *skeleton = NULL;
751 		NodePath node_path;
752 		aiBone *bone = NULL;
753 
754 		// Import skeleton bone animation for this track
755 		// Any bone will do, no point in processing more than just what is in the skeleton
756 		{
757 			bone = get_bone_from_stack(state, track->mNodeName);
758 
759 			if (bone) {
760 				// get skeleton by bone
761 				skeleton = state.armature_skeletons[bone->mArmature];
762 
763 				if (skeleton) {
764 					String path = state.root->get_path_to(skeleton);
765 					path += ":" + node_name;
766 					node_path = path;
767 
768 					if (node_path != NodePath()) {
769 						_insert_animation_track(state, anim, i, p_bake_fps, animation, ticks_per_second, skeleton,
770 								node_path, node_name, bone);
771 					} else {
772 						print_error("Failed to find valid node path for animation");
773 					}
774 				}
775 			}
776 		}
777 
778 		// not a bone
779 		// note this is flaky it uses node names which is unreliable
780 		Node *allocated_node = get_node_by_name(state, node_name);
781 		// todo: implement skeleton grabbing for node based animations too :)
782 		// check if node exists, if it does then also apply animation track for node and bones above are all handled.
783 		// this is now inclusive animation handling so that
784 		// we import all the data and do not miss anything.
785 		if (allocated_node) {
786 			node_path = state.root->get_path_to(allocated_node);
787 
788 			if (node_path != NodePath()) {
789 				_insert_animation_track(state, anim, i, p_bake_fps, animation, ticks_per_second, skeleton,
790 						node_path, node_name, nullptr);
791 			}
792 		}
793 	}
794 
795 	//blend shape tracks
796 
797 	for (size_t i = 0; i < anim->mNumMorphMeshChannels; i++) {
798 
799 		const aiMeshMorphAnim *anim_mesh = anim->mMorphMeshChannels[i];
800 
801 		const String prop_name = AssimpUtils::get_assimp_string(anim_mesh->mName);
802 		const String mesh_name = prop_name.split("*")[0];
803 
804 		ERR_CONTINUE(prop_name.split("*").size() != 2);
805 
806 		Node *item = get_node_by_name(state, mesh_name);
807 		ERR_CONTINUE_MSG(!item, "failed to look up node by name");
808 		const MeshInstance *mesh_instance = Object::cast_to<MeshInstance>(item);
809 		ERR_CONTINUE(mesh_instance == NULL);
810 
811 		String base_path = state.root->get_path_to(mesh_instance);
812 
813 		Ref<Mesh> mesh = mesh_instance->get_mesh();
814 		ERR_CONTINUE(mesh.is_null());
815 
816 		//add the tracks for this mesh
817 		int base_track = animation->get_track_count();
818 		for (int j = 0; j < mesh->get_blend_shape_count(); j++) {
819 
820 			animation->add_track(Animation::TYPE_VALUE);
821 			animation->track_set_path(base_track + j, base_path + ":blend_shapes/" + mesh->get_blend_shape_name(j));
822 		}
823 
824 		for (size_t k = 0; k < anim_mesh->mNumKeys; k++) {
825 			for (size_t j = 0; j < anim_mesh->mKeys[k].mNumValuesAndWeights; j++) {
826 
827 				float t = anim_mesh->mKeys[k].mTime / ticks_per_second;
828 				float w = anim_mesh->mKeys[k].mWeights[j];
829 
830 				animation->track_insert_key(base_track + j, t, w);
831 			}
832 		}
833 	}
834 
835 	if (animation->get_track_count()) {
836 		state.animation_player->add_animation(name, animation);
837 	}
838 }
839 //
840 // Mesh Generation from indices ? why do we need so much mesh code
841 // [debt needs looked into]
842 Ref<Mesh>
_generate_mesh_from_surface_indices(ImportState & state,const Vector<int> & p_surface_indices,const aiNode * assimp_node,Ref<Skin> & skin,Skeleton * & skeleton_assigned)843 EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &state, const Vector<int> &p_surface_indices,
844 		const aiNode *assimp_node, Ref<Skin> &skin,
845 		Skeleton *&skeleton_assigned) {
846 
847 	Ref<ArrayMesh> mesh;
848 	mesh.instance();
849 	bool has_uvs = false;
850 	bool compress_vert_data = state.import_flags & IMPORT_USE_COMPRESSION;
851 	uint32_t mesh_flags = compress_vert_data ? Mesh::ARRAY_COMPRESS_DEFAULT : 0;
852 
853 	Map<String, uint32_t> morph_mesh_string_lookup;
854 
855 	for (int i = 0; i < p_surface_indices.size(); i++) {
856 		const unsigned int mesh_idx = p_surface_indices[0];
857 		const aiMesh *ai_mesh = state.assimp_scene->mMeshes[mesh_idx];
858 		for (size_t j = 0; j < ai_mesh->mNumAnimMeshes; j++) {
859 			String ai_anim_mesh_name = AssimpUtils::get_assimp_string(ai_mesh->mAnimMeshes[j]->mName);
860 			if (!morph_mesh_string_lookup.has(ai_anim_mesh_name)) {
861 				morph_mesh_string_lookup.insert(ai_anim_mesh_name, j);
862 				mesh->set_blend_shape_mode(Mesh::BLEND_SHAPE_MODE_NORMALIZED);
863 				if (ai_anim_mesh_name.empty()) {
864 					ai_anim_mesh_name = String("morph_") + itos(j);
865 				}
866 				mesh->add_blend_shape(ai_anim_mesh_name);
867 			}
868 		}
869 	}
870 	//
871 	// Process Vertex Weights
872 	//
873 	for (int i = 0; i < p_surface_indices.size(); i++) {
874 		const unsigned int mesh_idx = p_surface_indices[i];
875 		const aiMesh *ai_mesh = state.assimp_scene->mMeshes[mesh_idx];
876 
877 		Map<uint32_t, Vector<BoneInfo> > vertex_weights;
878 
879 		if (ai_mesh->mNumBones > 0) {
880 			for (size_t b = 0; b < ai_mesh->mNumBones; b++) {
881 				aiBone *bone = ai_mesh->mBones[b];
882 
883 				if (!skeleton_assigned) {
884 					print_verbose("Assigned mesh skeleton during mesh creation");
885 					skeleton_assigned = state.skeleton_bone_map[bone];
886 
887 					if (!skin.is_valid()) {
888 						print_verbose("Configured new skin");
889 						skin.instance();
890 					} else {
891 						print_verbose("Reusing existing skin!");
892 					}
893 				}
894 				//                skeleton_assigned =
895 				String bone_name = AssimpUtils::get_assimp_string(bone->mName);
896 				int bone_index = skeleton_assigned->find_bone(bone_name);
897 				ERR_CONTINUE(bone_index == -1);
898 				for (size_t w = 0; w < bone->mNumWeights; w++) {
899 
900 					aiVertexWeight ai_weights = bone->mWeights[w];
901 
902 					BoneInfo bi;
903 					uint32_t vertex_index = ai_weights.mVertexId;
904 					bi.bone = bone_index;
905 					bi.weight = ai_weights.mWeight;
906 
907 					if (!vertex_weights.has(vertex_index)) {
908 						vertex_weights[vertex_index] = Vector<BoneInfo>();
909 					}
910 
911 					vertex_weights[vertex_index].push_back(bi);
912 				}
913 			}
914 		}
915 
916 		//
917 		// Create mesh from data from assimp
918 		//
919 
920 		Ref<SurfaceTool> st;
921 		st.instance();
922 		st->begin(Mesh::PRIMITIVE_TRIANGLES);
923 
924 		for (size_t j = 0; j < ai_mesh->mNumVertices; j++) {
925 
926 			// Get the texture coordinates if they exist
927 			if (ai_mesh->HasTextureCoords(0)) {
928 				has_uvs = true;
929 				st->add_uv(Vector2(ai_mesh->mTextureCoords[0][j].x, 1.0f - ai_mesh->mTextureCoords[0][j].y));
930 			}
931 
932 			if (ai_mesh->HasTextureCoords(1)) {
933 				has_uvs = true;
934 				st->add_uv2(Vector2(ai_mesh->mTextureCoords[1][j].x, 1.0f - ai_mesh->mTextureCoords[1][j].y));
935 			}
936 
937 			// Assign vertex colors
938 			if (ai_mesh->HasVertexColors(0)) {
939 				Color color = Color(ai_mesh->mColors[0]->r, ai_mesh->mColors[0]->g, ai_mesh->mColors[0]->b,
940 						ai_mesh->mColors[0]->a);
941 				st->add_color(color);
942 			}
943 
944 			// Work out normal calculations? - this needs work it doesn't work properly on huestos
945 			if (ai_mesh->mNormals != NULL) {
946 				const aiVector3D normals = ai_mesh->mNormals[j];
947 				const Vector3 godot_normal = Vector3(normals.x, normals.y, normals.z);
948 				st->add_normal(godot_normal);
949 				if (ai_mesh->HasTangentsAndBitangents()) {
950 					const aiVector3D tangents = ai_mesh->mTangents[j];
951 					const Vector3 godot_tangent = Vector3(tangents.x, tangents.y, tangents.z);
952 					const aiVector3D bitangent = ai_mesh->mBitangents[j];
953 					const Vector3 godot_bitangent = Vector3(bitangent.x, bitangent.y, bitangent.z);
954 					float d = godot_normal.cross(godot_tangent).dot(godot_bitangent) > 0.0f ? 1.0f : -1.0f;
955 					st->add_tangent(Plane(tangents.x, tangents.y, tangents.z, d));
956 				}
957 			}
958 
959 			// We have vertex weights right?
960 			if (vertex_weights.has(j)) {
961 
962 				Vector<BoneInfo> bone_info = vertex_weights[j];
963 				Vector<int> bones;
964 				bones.resize(bone_info.size());
965 				Vector<float> weights;
966 				weights.resize(bone_info.size());
967 
968 				// todo? do we really need to loop over all bones? - assimp may have helper to find all influences on this vertex.
969 				for (int k = 0; k < bone_info.size(); k++) {
970 					bones.write[k] = bone_info[k].bone;
971 					weights.write[k] = bone_info[k].weight;
972 				}
973 
974 				st->add_bones(bones);
975 				st->add_weights(weights);
976 			}
977 
978 			// Assign vertex
979 			const aiVector3D pos = ai_mesh->mVertices[j];
980 
981 			// note we must include node offset transform as this is relative to world space not local space.
982 			Vector3 godot_pos = Vector3(pos.x, pos.y, pos.z);
983 			st->add_vertex(godot_pos);
984 		}
985 
986 		// fire replacement for face handling
987 		for (size_t j = 0; j < ai_mesh->mNumFaces; j++) {
988 			const aiFace face = ai_mesh->mFaces[j];
989 			for (unsigned int k = 0; k < face.mNumIndices; k++) {
990 				st->add_index(face.mIndices[k]);
991 			}
992 		}
993 
994 		if (ai_mesh->HasTangentsAndBitangents() == false && has_uvs) {
995 			st->generate_tangents();
996 		}
997 
998 		aiMaterial *ai_material = state.assimp_scene->mMaterials[ai_mesh->mMaterialIndex];
999 		Ref<SpatialMaterial> mat;
1000 		mat.instance();
1001 
1002 		int32_t mat_two_sided = 0;
1003 		if (AI_SUCCESS == ai_material->Get(AI_MATKEY_TWOSIDED, mat_two_sided)) {
1004 			if (mat_two_sided > 0) {
1005 				mat->set_cull_mode(SpatialMaterial::CULL_DISABLED);
1006 			} else {
1007 				mat->set_cull_mode(SpatialMaterial::CULL_BACK);
1008 			}
1009 		}
1010 
1011 		aiString mat_name;
1012 		if (AI_SUCCESS == ai_material->Get(AI_MATKEY_NAME, mat_name)) {
1013 			mat->set_name(AssimpUtils::get_assimp_string(mat_name));
1014 		}
1015 
1016 		// Culling handling for meshes
1017 
1018 		// cull all back faces
1019 		mat->set_cull_mode(SpatialMaterial::CULL_DISABLED);
1020 
1021 		// Now process materials
1022 		aiTextureType base_color = aiTextureType_BASE_COLOR;
1023 		{
1024 			String filename, path;
1025 			AssimpImageData image_data;
1026 
1027 			if (AssimpUtils::GetAssimpTexture(state, ai_material, base_color, filename, path, image_data)) {
1028 				AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture);
1029 
1030 				// anything transparent must be culled
1031 				if (image_data.raw_image->detect_alpha() != Image::ALPHA_NONE) {
1032 					mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true);
1033 					mat->set_depth_draw_mode(SpatialMaterial::DepthDrawMode::DEPTH_DRAW_ALPHA_OPAQUE_PREPASS);
1034 					mat->set_cull_mode(
1035 							SpatialMaterial::CULL_DISABLED); // since you can see both sides in transparent mode
1036 				}
1037 
1038 				mat->set_texture(SpatialMaterial::TEXTURE_ALBEDO, image_data.texture);
1039 			}
1040 		}
1041 
1042 		aiTextureType tex_diffuse = aiTextureType_DIFFUSE;
1043 		{
1044 			String filename, path;
1045 			AssimpImageData image_data;
1046 
1047 			if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_diffuse, filename, path, image_data)) {
1048 				AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture);
1049 
1050 				// anything transparent must be culled
1051 				if (image_data.raw_image->detect_alpha() != Image::ALPHA_NONE) {
1052 					mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true);
1053 					mat->set_depth_draw_mode(SpatialMaterial::DepthDrawMode::DEPTH_DRAW_ALPHA_OPAQUE_PREPASS);
1054 					mat->set_cull_mode(
1055 							SpatialMaterial::CULL_DISABLED); // since you can see both sides in transparent mode
1056 				}
1057 
1058 				mat->set_texture(SpatialMaterial::TEXTURE_ALBEDO, image_data.texture);
1059 			}
1060 
1061 			aiColor4D clr_diffuse;
1062 			if (AI_SUCCESS == ai_material->Get(AI_MATKEY_COLOR_DIFFUSE, clr_diffuse)) {
1063 				if (Math::is_equal_approx(clr_diffuse.a, 1.0f) == false) {
1064 					mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true);
1065 					mat->set_depth_draw_mode(SpatialMaterial::DepthDrawMode::DEPTH_DRAW_ALPHA_OPAQUE_PREPASS);
1066 					mat->set_cull_mode(
1067 							SpatialMaterial::CULL_DISABLED); // since you can see both sides in transparent mode
1068 				}
1069 				mat->set_albedo(Color(clr_diffuse.r, clr_diffuse.g, clr_diffuse.b, clr_diffuse.a));
1070 			}
1071 		}
1072 
1073 		aiTextureType tex_normal = aiTextureType_NORMALS;
1074 		{
1075 			String filename, path;
1076 			Ref<ImageTexture> texture;
1077 			AssimpImageData image_data;
1078 
1079 			// Process texture normal map
1080 			if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_normal, filename, path, image_data)) {
1081 				AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture);
1082 				mat->set_feature(SpatialMaterial::Feature::FEATURE_NORMAL_MAPPING, true);
1083 				mat->set_texture(SpatialMaterial::TEXTURE_NORMAL, image_data.texture);
1084 			} else {
1085 				aiString texture_path;
1086 				if (AI_SUCCESS == ai_material->Get(AI_MATKEY_FBX_NORMAL_TEXTURE, AI_PROPERTIES, texture_path)) {
1087 					if (AssimpUtils::CreateAssimpTexture(state, texture_path, filename, path, image_data)) {
1088 						mat->set_feature(SpatialMaterial::Feature::FEATURE_NORMAL_MAPPING, true);
1089 						mat->set_texture(SpatialMaterial::TEXTURE_NORMAL, image_data.texture);
1090 					}
1091 				}
1092 			}
1093 		}
1094 
1095 		aiTextureType tex_normal_camera = aiTextureType_NORMAL_CAMERA;
1096 		{
1097 			String filename, path;
1098 			Ref<ImageTexture> texture;
1099 			AssimpImageData image_data;
1100 
1101 			// Process texture normal map
1102 			if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_normal_camera, filename, path, image_data)) {
1103 				AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture);
1104 				mat->set_feature(SpatialMaterial::Feature::FEATURE_NORMAL_MAPPING, true);
1105 				mat->set_texture(SpatialMaterial::TEXTURE_NORMAL, image_data.texture);
1106 			}
1107 		}
1108 
1109 		aiTextureType tex_emission_color = aiTextureType_EMISSION_COLOR;
1110 		{
1111 			String filename, path;
1112 			Ref<ImageTexture> texture;
1113 			AssimpImageData image_data;
1114 
1115 			// Process texture normal map
1116 			if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_emission_color, filename, path, image_data)) {
1117 				AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture);
1118 				mat->set_feature(SpatialMaterial::Feature::FEATURE_NORMAL_MAPPING, true);
1119 				mat->set_texture(SpatialMaterial::TEXTURE_NORMAL, image_data.texture);
1120 			}
1121 		}
1122 
1123 		aiTextureType tex_metalness = aiTextureType_METALNESS;
1124 		{
1125 			String filename, path;
1126 			Ref<ImageTexture> texture;
1127 			AssimpImageData image_data;
1128 
1129 			// Process texture normal map
1130 			if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_metalness, filename, path, image_data)) {
1131 				AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture);
1132 				mat->set_texture(SpatialMaterial::TEXTURE_METALLIC, image_data.texture);
1133 			}
1134 		}
1135 
1136 		aiTextureType tex_roughness = aiTextureType_DIFFUSE_ROUGHNESS;
1137 		{
1138 			String filename, path;
1139 			Ref<ImageTexture> texture;
1140 			AssimpImageData image_data;
1141 
1142 			// Process texture normal map
1143 			if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_roughness, filename, path, image_data)) {
1144 				AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture);
1145 				mat->set_texture(SpatialMaterial::TEXTURE_ROUGHNESS, image_data.texture);
1146 			}
1147 		}
1148 
1149 		aiTextureType tex_emissive = aiTextureType_EMISSIVE;
1150 		{
1151 			String filename = "";
1152 			String path = "";
1153 			Ref<Image> texture;
1154 			AssimpImageData image_data;
1155 
1156 			if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_emissive, filename, path, image_data)) {
1157 				AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture);
1158 				mat->set_feature(SpatialMaterial::FEATURE_EMISSION, true);
1159 				mat->set_texture(SpatialMaterial::TEXTURE_EMISSION, image_data.texture);
1160 			} else {
1161 				// Process emission textures
1162 				aiString texture_emissive_path;
1163 				if (AI_SUCCESS ==
1164 						ai_material->Get(AI_MATKEY_FBX_MAYA_EMISSION_TEXTURE, AI_PROPERTIES, texture_emissive_path)) {
1165 					if (AssimpUtils::CreateAssimpTexture(state, texture_emissive_path, filename, path, image_data)) {
1166 						mat->set_feature(SpatialMaterial::FEATURE_EMISSION, true);
1167 						mat->set_texture(SpatialMaterial::TEXTURE_EMISSION, image_data.texture);
1168 					}
1169 				} else {
1170 					float pbr_emission = 0.0f;
1171 					if (AI_SUCCESS == ai_material->Get(AI_MATKEY_FBX_MAYA_EMISSIVE_FACTOR, AI_NULL, pbr_emission)) {
1172 						mat->set_emission(Color(pbr_emission, pbr_emission, pbr_emission, 1.0f));
1173 					}
1174 				}
1175 			}
1176 		}
1177 
1178 		aiTextureType tex_specular = aiTextureType_SPECULAR;
1179 		{
1180 			String filename, path;
1181 			Ref<ImageTexture> texture;
1182 			AssimpImageData image_data;
1183 
1184 			// Process texture normal map
1185 			if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_specular, filename, path, image_data)) {
1186 				AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture);
1187 				mat->set_texture(SpatialMaterial::TEXTURE_METALLIC, image_data.texture);
1188 			}
1189 		}
1190 
1191 		aiTextureType tex_ao_map = aiTextureType_AMBIENT_OCCLUSION;
1192 		{
1193 			String filename, path;
1194 			Ref<ImageTexture> texture;
1195 			AssimpImageData image_data;
1196 
1197 			// Process texture normal map
1198 			if (AssimpUtils::GetAssimpTexture(state, ai_material, tex_ao_map, filename, path, image_data)) {
1199 				AssimpUtils::set_texture_mapping_mode(image_data.map_mode, image_data.texture);
1200 				mat->set_feature(SpatialMaterial::FEATURE_AMBIENT_OCCLUSION, true);
1201 				mat->set_texture(SpatialMaterial::TEXTURE_AMBIENT_OCCLUSION, image_data.texture);
1202 			}
1203 		}
1204 
1205 		Array array_mesh = st->commit_to_arrays();
1206 		Array morphs;
1207 		morphs.resize(ai_mesh->mNumAnimMeshes);
1208 		Mesh::PrimitiveType primitive = Mesh::PRIMITIVE_TRIANGLES;
1209 
1210 		for (size_t j = 0; j < ai_mesh->mNumAnimMeshes; j++) {
1211 
1212 			String ai_anim_mesh_name = AssimpUtils::get_assimp_string(ai_mesh->mAnimMeshes[j]->mName);
1213 
1214 			if (ai_anim_mesh_name.empty()) {
1215 				ai_anim_mesh_name = String("morph_") + itos(j);
1216 			}
1217 
1218 			Array array_copy;
1219 			array_copy.resize(VisualServer::ARRAY_MAX);
1220 
1221 			for (int l = 0; l < VisualServer::ARRAY_MAX; l++) {
1222 				array_copy[l] = array_mesh[l].duplicate(true);
1223 			}
1224 
1225 			const size_t num_vertices = ai_mesh->mAnimMeshes[j]->mNumVertices;
1226 			array_copy[Mesh::ARRAY_INDEX] = Variant();
1227 			if (ai_mesh->mAnimMeshes[j]->HasPositions()) {
1228 				PoolVector3Array vertices;
1229 				vertices.resize(num_vertices);
1230 				for (size_t l = 0; l < num_vertices; l++) {
1231 					const aiVector3D ai_pos = ai_mesh->mAnimMeshes[j]->mVertices[l];
1232 					Vector3 position = Vector3(ai_pos.x, ai_pos.y, ai_pos.z);
1233 					vertices.write()[l] = position;
1234 				}
1235 				PoolVector3Array new_vertices = array_copy[VisualServer::ARRAY_VERTEX].duplicate(true);
1236 				ERR_CONTINUE(vertices.size() != new_vertices.size());
1237 				for (int32_t l = 0; l < new_vertices.size(); l++) {
1238 					PoolVector3Array::Write w = new_vertices.write();
1239 					w[l] = vertices[l];
1240 				}
1241 				array_copy[VisualServer::ARRAY_VERTEX] = new_vertices;
1242 			}
1243 
1244 			int32_t color_set = 0;
1245 			if (ai_mesh->mAnimMeshes[j]->HasVertexColors(color_set)) {
1246 				PoolColorArray colors;
1247 				colors.resize(num_vertices);
1248 				for (size_t l = 0; l < num_vertices; l++) {
1249 					const aiColor4D ai_color = ai_mesh->mAnimMeshes[j]->mColors[color_set][l];
1250 					Color color = Color(ai_color.r, ai_color.g, ai_color.b, ai_color.a);
1251 					colors.write()[l] = color;
1252 				}
1253 				PoolColorArray new_colors = array_copy[VisualServer::ARRAY_COLOR].duplicate(true);
1254 				ERR_CONTINUE(colors.size() != new_colors.size());
1255 				for (int32_t l = 0; l < colors.size(); l++) {
1256 					PoolColorArray::Write w = new_colors.write();
1257 					w[l] = colors[l];
1258 				}
1259 				array_copy[VisualServer::ARRAY_COLOR] = new_colors;
1260 			}
1261 
1262 			if (ai_mesh->mAnimMeshes[j]->HasNormals()) {
1263 				PoolVector3Array normals;
1264 				normals.resize(num_vertices);
1265 				for (size_t l = 0; l < num_vertices; l++) {
1266 					const aiVector3D ai_normal = ai_mesh->mAnimMeshes[j]->mNormals[l];
1267 					Vector3 normal = Vector3(ai_normal.x, ai_normal.y, ai_normal.z);
1268 					normals.write()[l] = normal;
1269 				}
1270 				PoolVector3Array new_normals = array_copy[VisualServer::ARRAY_NORMAL].duplicate(true);
1271 				ERR_CONTINUE(normals.size() != new_normals.size());
1272 				for (int l = 0; l < normals.size(); l++) {
1273 					PoolVector3Array::Write w = new_normals.write();
1274 					w[l] = normals[l];
1275 				}
1276 				array_copy[VisualServer::ARRAY_NORMAL] = new_normals;
1277 			}
1278 
1279 			if (ai_mesh->mAnimMeshes[j]->HasTangentsAndBitangents()) {
1280 				PoolColorArray tangents;
1281 				tangents.resize(num_vertices);
1282 				PoolColorArray::Write w = tangents.write();
1283 				for (size_t l = 0; l < num_vertices; l++) {
1284 					AssimpUtils::calc_tangent_from_mesh(ai_mesh, j, l, l, w);
1285 				}
1286 				PoolRealArray new_tangents = array_copy[VisualServer::ARRAY_TANGENT].duplicate(true);
1287 				ERR_CONTINUE(new_tangents.size() != tangents.size() * 4);
1288 				for (int32_t l = 0; l < tangents.size(); l++) {
1289 					new_tangents.write()[l + 0] = tangents[l].r;
1290 					new_tangents.write()[l + 1] = tangents[l].g;
1291 					new_tangents.write()[l + 2] = tangents[l].b;
1292 					new_tangents.write()[l + 3] = tangents[l].a;
1293 				}
1294 				array_copy[VisualServer::ARRAY_TANGENT] = new_tangents;
1295 			}
1296 
1297 			morphs[j] = array_copy;
1298 		}
1299 		mesh->add_surface_from_arrays(primitive, array_mesh, morphs, mesh_flags);
1300 		mesh->surface_set_material(i, mat);
1301 		mesh->surface_set_name(i, AssimpUtils::get_assimp_string(ai_mesh->mName));
1302 	}
1303 
1304 	return mesh;
1305 }
1306 
1307 /**
1308  * Create a new mesh for the node supplied
1309  */
1310 MeshInstance *
create_mesh(ImportState & state,const aiNode * assimp_node,const String & node_name,Node * active_node,Transform node_transform)1311 EditorSceneImporterAssimp::create_mesh(ImportState &state, const aiNode *assimp_node, const String &node_name, Node *active_node, Transform node_transform) {
1312 	/* MESH NODE */
1313 	Ref<Mesh> mesh;
1314 	Ref<Skin> skin;
1315 	// see if we have mesh cache for this.
1316 	Vector<int> surface_indices;
1317 
1318 	RegenerateBoneStack(state);
1319 
1320 	// Configure indices
1321 	for (uint32_t i = 0; i < assimp_node->mNumMeshes; i++) {
1322 		int mesh_index = assimp_node->mMeshes[i];
1323 		// create list of mesh indexes
1324 		surface_indices.push_back(mesh_index);
1325 	}
1326 
1327 	//surface_indices.sort();
1328 	String mesh_key;
1329 	for (int i = 0; i < surface_indices.size(); i++) {
1330 		if (i > 0) {
1331 			mesh_key += ":";
1332 		}
1333 		mesh_key += itos(surface_indices[i]);
1334 	}
1335 
1336 	Skeleton *skeleton = NULL;
1337 	aiNode *armature = NULL;
1338 
1339 	if (!state.mesh_cache.has(mesh_key)) {
1340 		mesh = _generate_mesh_from_surface_indices(state, surface_indices, assimp_node, skin, skeleton);
1341 		state.mesh_cache[mesh_key] = mesh;
1342 	}
1343 
1344 	MeshInstance *mesh_node = memnew(MeshInstance);
1345 	mesh = state.mesh_cache[mesh_key];
1346 	mesh_node->set_mesh(mesh);
1347 
1348 	// if we have a valid skeleton set it up
1349 	if (skin.is_valid()) {
1350 		for (uint32_t i = 0; i < assimp_node->mNumMeshes; i++) {
1351 			unsigned int mesh_index = assimp_node->mMeshes[i];
1352 			const aiMesh *ai_mesh = state.assimp_scene->mMeshes[mesh_index];
1353 
1354 			// please remember bone id relative to the skin is NOT the mesh relative index.
1355 			// it is the index relative to the skeleton that is why
1356 			// we have state.bone_id_map, it allows for duplicate bone id's too :)
1357 			// hope this makes sense
1358 
1359 			int bind_count = 0;
1360 			for (unsigned int boneId = 0; boneId < ai_mesh->mNumBones; ++boneId) {
1361 				aiBone *iterBone = ai_mesh->mBones[boneId];
1362 
1363 				// used to reparent mesh to the correct armature later on if assigned.
1364 				if (!armature) {
1365 					print_verbose("Configured mesh armature, will reparent later to armature");
1366 					armature = iterBone->mArmature;
1367 				}
1368 
1369 				if (skeleton) {
1370 					int id = skeleton->find_bone(AssimpUtils::get_assimp_string(iterBone->mName));
1371 					if (id != -1) {
1372 						print_verbose("Set bind bone: mesh: " + itos(mesh_index) + " bone index: " + itos(id));
1373 						Transform t = AssimpUtils::assimp_matrix_transform(iterBone->mOffsetMatrix);
1374 
1375 						skin->add_bind(bind_count, t);
1376 						skin->set_bind_bone(bind_count, id);
1377 						bind_count++;
1378 					}
1379 				}
1380 			}
1381 		}
1382 
1383 		print_verbose("Finished configuring bind pose for skin mesh");
1384 	}
1385 
1386 	// this code parents all meshes with bones to the armature they are for
1387 	// GLTF2 specification relies on this and we are enforcing it for FBX.
1388 	if (armature && state.flat_node_map[armature]) {
1389 		Node *armature_parent = state.flat_node_map[armature];
1390 		print_verbose("Parented mesh " + node_name + " to armature " + armature_parent->get_name());
1391 		// static mesh handling
1392 		armature_parent->add_child(mesh_node);
1393 		// transform must be identity
1394 		mesh_node->set_global_transform(Transform());
1395 		mesh_node->set_name(node_name);
1396 		mesh_node->set_owner(state.root);
1397 	} else {
1398 		// static mesh handling
1399 		active_node->add_child(mesh_node);
1400 		mesh_node->set_global_transform(node_transform);
1401 		mesh_node->set_name(node_name);
1402 		mesh_node->set_owner(state.root);
1403 	}
1404 
1405 	if (skeleton) {
1406 		print_verbose("Attempted to set skeleton path!");
1407 		mesh_node->set_skeleton_path(mesh_node->get_path_to(skeleton));
1408 		mesh_node->set_skin(skin);
1409 	}
1410 
1411 	return mesh_node;
1412 }
1413 
1414 /**
1415  * Create a light for the scene
1416  * Automatically caches lights for lookup later
1417  */
create_light(ImportState & state,const String & node_name,Transform & look_at_transform)1418 Spatial *EditorSceneImporterAssimp::create_light(
1419 		ImportState &state,
1420 		const String &node_name,
1421 		Transform &look_at_transform) {
1422 	Light *light = NULL;
1423 	aiLight *assimp_light = state.assimp_scene->mLights[state.light_cache[node_name]];
1424 	ERR_FAIL_COND_V(!assimp_light, NULL);
1425 
1426 	if (assimp_light->mType == aiLightSource_DIRECTIONAL) {
1427 		light = memnew(DirectionalLight);
1428 	} else if (assimp_light->mType == aiLightSource_POINT) {
1429 		light = memnew(OmniLight);
1430 	} else if (assimp_light->mType == aiLightSource_SPOT) {
1431 		light = memnew(SpotLight);
1432 	}
1433 	ERR_FAIL_COND_V(light == NULL, NULL);
1434 
1435 	if (assimp_light->mType != aiLightSource_POINT) {
1436 		Vector3 pos = Vector3(
1437 				assimp_light->mPosition.x,
1438 				assimp_light->mPosition.y,
1439 				assimp_light->mPosition.z);
1440 		Vector3 look_at = Vector3(
1441 				assimp_light->mDirection.y,
1442 				assimp_light->mDirection.x,
1443 				assimp_light->mDirection.z)
1444 								  .normalized();
1445 		Vector3 up = Vector3(
1446 				assimp_light->mUp.x,
1447 				assimp_light->mUp.y,
1448 				assimp_light->mUp.z);
1449 
1450 		look_at_transform.set_look_at(pos, look_at, up);
1451 	}
1452 	// properties for light variables should be put here.
1453 	// not really hugely important yet but we will need them in the future
1454 
1455 	light->set_color(
1456 			Color(assimp_light->mColorDiffuse.r, assimp_light->mColorDiffuse.g, assimp_light->mColorDiffuse.b));
1457 
1458 	return light;
1459 }
1460 
1461 /**
1462  * Create camera for the scene
1463  */
create_camera(ImportState & state,const String & node_name,Transform & look_at_transform)1464 Spatial *EditorSceneImporterAssimp::create_camera(
1465 		ImportState &state,
1466 		const String &node_name,
1467 		Transform &look_at_transform) {
1468 	aiCamera *camera = state.assimp_scene->mCameras[state.camera_cache[node_name]];
1469 	ERR_FAIL_COND_V(!camera, NULL);
1470 
1471 	Camera *camera_node = memnew(Camera);
1472 	ERR_FAIL_COND_V(!camera_node, NULL);
1473 	float near = camera->mClipPlaneNear;
1474 	if (Math::is_equal_approx(near, 0.0f)) {
1475 		near = 0.1f;
1476 	}
1477 	camera_node->set_perspective(Math::rad2deg(camera->mHorizontalFOV) * 2.0f, near, camera->mClipPlaneFar);
1478 	Vector3 pos = Vector3(camera->mPosition.x, camera->mPosition.y, camera->mPosition.z);
1479 	Vector3 look_at = Vector3(camera->mLookAt.y, camera->mLookAt.x, camera->mLookAt.z).normalized();
1480 	Vector3 up = Vector3(camera->mUp.x, camera->mUp.y, camera->mUp.z);
1481 
1482 	look_at_transform.set_look_at(pos + look_at_transform.origin, look_at, up);
1483 	return camera_node;
1484 }
1485 
1486 /**
1487  * Generate node
1488  * Recursive call to iterate over all nodes
1489  */
_generate_node(ImportState & state,const aiNode * assimp_node)1490 void EditorSceneImporterAssimp::_generate_node(
1491 		ImportState &state,
1492 		const aiNode *assimp_node) {
1493 
1494 	ERR_FAIL_COND(assimp_node == NULL);
1495 	state.nodes.push_back(assimp_node);
1496 	String parent_name = AssimpUtils::get_assimp_string(assimp_node->mParent->mName);
1497 
1498 	// please note
1499 	// duplicate bone names exist
1500 	// this is why we only check if the bone exists
1501 	// so everything else is useless but the name
1502 	// please do not copy any other values from get_bone_by_name.
1503 	aiBone *parent_bone = get_bone_by_name(state.assimp_scene, assimp_node->mParent->mName);
1504 	aiBone *current_bone = get_bone_by_name(state.assimp_scene, assimp_node->mName);
1505 
1506 	// is this an armature
1507 	// parent null
1508 	// and this is the first bone :)
1509 	if (parent_bone == NULL && current_bone) {
1510 		state.armature_nodes.push_back(assimp_node->mParent);
1511 		print_verbose("found valid armature: " + parent_name);
1512 	}
1513 
1514 	for (size_t i = 0; i < assimp_node->mNumChildren; i++) {
1515 		_generate_node(state, assimp_node->mChildren[i]);
1516 	}
1517 }
1518