Browse Source

Clean up ASSIMP import code.

Juan Linietsky 6 years ago
parent
commit
ad1368a625

File diff suppressed because it is too large
+ 608 - 1134
modules/assimp/editor_scene_importer_assimp.cpp


+ 52 - 24
modules/assimp/editor_scene_importer_assimp.h

@@ -146,37 +146,65 @@ private:
 			COORD_LEFT = 1
 		};
 	};
-	Spatial *_generate_scene(const String &p_path, const aiScene *scene, const uint32_t p_flags, int p_bake_fps, const int32_t p_max_bone_weights);
-	void _fill_kept_node(Set<Node *> &keep_nodes);
-	String _find_skeleton_bone_root(Map<Skeleton *, MeshInstance *> &skeletons, Map<MeshInstance *, String> &meshes, Spatial *root);
-	void _set_bone_parent(Skeleton *s, Node *p_owner, aiNode *p_node);
-	Transform _get_global_ai_node_transform(const aiScene *p_scene, const aiNode *p_current_node);
-	void _generate_node_bone(const aiScene *p_scene, const aiNode *p_node, Map<String, bool> &p_mesh_bones, Skeleton *p_skeleton, const String p_path, const int32_t p_max_bone_weights);
-	void _generate_node_bone_parents(const aiScene *p_scene, const aiNode *p_node, Map<String, bool> &p_mesh_bones, Skeleton *p_skeleton, const MeshInstance *p_mi);
-	void _calculate_skeleton_root(Skeleton *s, const aiScene *p_scene, aiNode *&p_ai_skeleton_root, Map<String, bool> &mesh_bones, const aiNode *p_node);
-	void _fill_skeleton(const aiScene *p_scene, const aiNode *p_node, Spatial *p_current, Node *p_owner, Skeleton *p_skeleton, const Map<String, bool> p_mesh_bones, const Map<String, Transform> &p_bone_rests, Set<String> p_tracks, const String p_path, Set<String> &r_removed_bones);
-	void _keep_node(const String &p_path, Node *p_current, Node *p_owner, Set<Node *> &r_keep_nodes);
-	void _filter_node(const String &p_path, Node *p_current, Node *p_owner, const Set<Node *> p_keep_nodes, Set<String> &r_removed_nodes);
-	void _generate_node(const String &p_path, const aiScene *p_scene, const aiNode *p_node, Node *p_parent, Node *p_owner, Set<String> &r_bone_name, Set<String> p_light_names, Set<String> p_camera_names, Map<Skeleton *, MeshInstance *> &r_skeletons, const Map<String, Transform> &p_bone_rests, Vector<MeshInstance *> &r_mesh_instances, int32_t &r_mesh_count, Skeleton *p_skeleton, const int32_t p_max_bone_weights, Set<String> &r_removed_bones, Map<String, Map<uint32_t, String> > &r_name_morph_mesh_names);
-	aiNode *_ai_find_node(aiNode *ai_child_node, const String bone_name);
-	Transform _format_rot_xform(const String p_path, const aiScene *p_scene);
-	void _get_track_set(const aiScene *p_scene, Set<String> &tracks);
-	void _insert_animation_track(const aiScene *p_scene, const String p_path, int p_bake_fps, Ref<Animation> animation, float ticks_per_second, float length, const Skeleton *sk, const aiNodeAnim *track, String node_name, NodePath node_path);
-	void _add_mesh_to_mesh_instance(const aiNode *p_node, const aiScene *p_scene, Skeleton *s, const String &p_path, MeshInstance *p_mesh_instance, Node *p_owner, Set<String> &r_bone_name, int32_t &r_mesh_count, int32_t p_max_bone_weights, Map<String, Map<uint32_t, String> > &r_name_morph_mesh_names);
-	Ref<Texture> _load_texture(const aiScene *p_scene, String p_path);
+
+	struct ImportState {
+
+		String path;
+		const aiScene *assimp_scene;
+		uint32_t max_bone_weights;
+		Spatial *root;
+		Map<String, Ref<Mesh> > mesh_cache;
+		Map<int, Ref<Material> > material_cache;
+		Map<String, int> light_cache;
+		Map<String, int> camera_cache;
+		Vector<Skeleton *> skeletons;
+		Map<String, int> bone_owners; //maps bones to skeleton index owned by
+		Map<String, Node *> node_map;
+		Map<MeshInstance *, Skeleton *> mesh_skeletons;
+		bool fbx; //for some reason assimp does some things different for FBX
+		AnimationPlayer *animation_player;
+	};
+
+	struct BoneInfo {
+		uint32_t bone;
+		float weight;
+	};
+
+	struct SkeletonHole { //nodes may be part of the skeleton by used by vertex
+		String name;
+		String parent;
+		Transform pose;
+		const aiNode *node;
+	};
+
+	const Transform _assimp_matrix_transform(const aiMatrix4x4 p_matrix);
+	String _assimp_get_string(const aiString p_string) const;
+	Transform _get_global_assimp_node_transform(const aiNode *p_current_node);
+
 	void _calc_tangent_from_mesh(const aiMesh *ai_mesh, int i, int tri_index, int index, PoolColorArray::Write &w);
 	void _set_texture_mapping_mode(aiTextureMapMode *map_mode, Ref<Texture> texture);
 	void _find_texture_path(const String &p_path, String &path, bool &r_found);
 	void _find_texture_path(const String &p_path, _Directory &dir, String &path, bool &found, String extension);
-	String _ai_string_to_string(const aiString p_string) const;
-	String _ai_anim_string_to_string(const aiString p_string) const;
-	String _ai_raw_string_to_string(const aiString p_string) const;
-	void _import_animation(const String p_path, const Vector<MeshInstance *> p_meshes, const aiScene *p_scene, AnimationPlayer *ap, int32_t p_index, int p_bake_fps, Map<Skeleton *, MeshInstance *> p_skeletons, const Set<String> p_removed_nodes, const Set<String> removed_bones, const Map<String, Map<uint32_t, String> > p_path_morph_mesh_names);
-	void _insert_pivot_anim_track(const Vector<MeshInstance *> p_meshes, const String p_node_name, Vector<const aiNodeAnim *> F, AnimationPlayer *ap, Skeleton *sk, float &length, float ticks_per_second, Ref<Animation> animation, int p_bake_fps, const String &p_path, const aiScene *p_scene);
+
+	Ref<Texture> _load_texture(ImportState &state, String p_path);
+	Ref<Material> _generate_material_from_index(ImportState &state, int p_index, bool p_double_sided);
+	Ref<Mesh> _generate_mesh_from_surface_indices(ImportState &state, const Vector<int> &p_surface_indices, Skeleton *p_skeleton = NULL, bool p_double_sided_material = false);
+	void _generate_node(ImportState &state, const aiNode *p_assimp_node, Node *p_parent);
+	void _generate_bone_groups(ImportState &state, const aiNode *p_assimp_node, Map<String, int> &ownership, Map<String, Transform> &bind_xforms);
+	void _fill_node_relationships(ImportState &state, const aiNode *p_assimp_node, Map<String, int> &ownership, Map<int, int> &skeleton_map, int p_skeleton_id, Skeleton *p_skeleton, const String &p_parent_name, int &holecount, const Vector<SkeletonHole> &p_holes, const Map<String, Transform> &bind_xforms);
+	void _generate_skeletons(ImportState &state, const aiNode *p_assimp_node, Map<String, int> &ownership, Map<int, int> &skeleton_map, const Map<String, Transform> &bind_xforms);
+
+	void _insert_animation_track(ImportState &scene, const aiAnimation *assimp_anim, int p_track, int p_bake_fps, Ref<Animation> animation, float ticks_per_second, Skeleton *p_skeleton, const NodePath &p_path, const String &p_name);
+
+	void _import_animation(ImportState &state, int p_animation_index, int p_bake_fps);
+
+	Spatial *_generate_scene(const String &p_path, const aiScene *scene, const uint32_t p_flags, int p_bake_fps, const int32_t p_max_bone_weights);
+
+	String _assimp_anim_string_to_string(const aiString p_string) const;
+	String _assimp_raw_string_to_string(const aiString p_string) const;
 	float _get_fbx_fps(int32_t time_mode, const aiScene *p_scene);
 	template <class T>
 	T _interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values, float p_time, AssetImportAnimation::Interpolation p_interp);
-	const Transform _ai_matrix_transform(const aiMatrix4x4 p_matrix);
 	void _register_project_setting_import(const String generic, const String import_setting_string, const Vector<String> &exts, List<String> *r_extensions, const bool p_enabled) const;
 
 	struct ImportFormat {

+ 3 - 2
scene/3d/skeleton.cpp

@@ -540,10 +540,11 @@ void Skeleton::clear_bones() {
 void Skeleton::set_bone_pose(int p_bone, const Transform &p_pose) {
 
 	ERR_FAIL_INDEX(p_bone, bones.size());
-	ERR_FAIL_COND(!is_inside_tree());
 
 	bones.write[p_bone].pose = p_pose;
-	_make_dirty();
+	if (is_inside_tree()) {
+		_make_dirty();
+	}
 }
 Transform Skeleton::get_bone_pose(int p_bone) const {
 

+ 47 - 3
scene/resources/surface_tool.cpp

@@ -108,8 +108,55 @@ void SurfaceTool::add_vertex(const Vector3 &p_vertex) {
 	vtx.bones = last_bones;
 	vtx.tangent = last_tangent.normal;
 	vtx.binormal = last_normal.cross(last_tangent.normal).normalized() * last_tangent.d;
+
+	const int expected_vertices = 4;
+
+	if ((format & Mesh::ARRAY_FORMAT_WEIGHTS || format & Mesh::ARRAY_FORMAT_BONES) && (vtx.weights.size() != expected_vertices || vtx.bones.size() != expected_vertices)) {
+		//ensure vertices are the expected amount
+		ERR_FAIL_COND(vtx.weights.size() != vtx.bones.size());
+		if (vtx.weights.size() < expected_vertices) {
+			//less than requred, fill
+			for (int i = vtx.weights.size(); i < expected_vertices; i++) {
+				vtx.weights.push_back(0);
+				vtx.bones.push_back(0);
+			}
+		} else if (vtx.weights.size() > expected_vertices) {
+			//more than required, sort, cap and normalize.
+			Vector<WeightSort> weights;
+			for (int i = 0; i < vtx.weights.size(); i++) {
+				WeightSort ws;
+				ws.index = vtx.bones[i];
+				ws.weight = vtx.weights[i];
+				weights.push_back(ws);
+			}
+
+			//sort
+			weights.sort();
+			//cap
+			weights.resize(expected_vertices);
+			//renormalize
+			float total = 0;
+			for (int i = 0; i < expected_vertices; i++) {
+				total += weights[i].weight;
+			}
+
+			vtx.weights.resize(expected_vertices);
+			vtx.bones.resize(expected_vertices);
+
+			for (int i = 0; i < expected_vertices; i++) {
+				if (total > 0) {
+					vtx.weights.write[i] = weights[i].weight / total;
+				} else {
+					vtx.weights.write[i] = 0;
+				}
+				vtx.bones.write[i] = weights[i].index;
+			}
+		}
+	}
+
 	vertex_array.push_back(vtx);
 	first = false;
+
 	format |= Mesh::ARRAY_FORMAT_VERTEX;
 }
 void SurfaceTool::add_color(Color p_color) {
@@ -161,7 +208,6 @@ void SurfaceTool::add_uv2(const Vector2 &p_uv2) {
 void SurfaceTool::add_bones(const Vector<int> &p_bones) {
 
 	ERR_FAIL_COND(!begun);
-	ERR_FAIL_COND(p_bones.size() != 4);
 	ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_BONES));
 
 	format |= Mesh::ARRAY_FORMAT_BONES;
@@ -171,8 +217,6 @@ void SurfaceTool::add_bones(const Vector<int> &p_bones) {
 void SurfaceTool::add_weights(const Vector<float> &p_weights) {
 
 	ERR_FAIL_COND(!begun);
-
-	ERR_FAIL_COND(p_weights.size() != 4);
 	ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_WEIGHTS));
 
 	format |= Mesh::ARRAY_FORMAT_WEIGHTS;

+ 8 - 0
scene/resources/surface_tool.h

@@ -62,6 +62,14 @@ private:
 		static _FORCE_INLINE_ uint32_t hash(const Vertex &p_vtx);
 	};
 
+	struct WeightSort {
+		int index;
+		float weight;
+		bool operator<(const WeightSort &p_right) const {
+			return weight < p_right.weight;
+		}
+	};
+
 	bool begun;
 	bool first;
 	Mesh::PrimitiveType primitive;

Some files were not shown because too many files changed in this diff