summaryrefslogtreecommitdiff
path: root/modules/fbx/data/fbx_mesh_data.h
blob: eec7f38cd627b3eee9af5ee8a20a40293bf6697a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/*************************************************************************/
/*  fbx_mesh_data.h                                                      */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#ifndef FBX_MESH_DATA_H
#define FBX_MESH_DATA_H

#include "core/templates/hash_map.h"
#include "core/templates/local_vector.h"
#include "core/templates/ordered_hash_map.h"
#include "editor/import/resource_importer_scene.h"
#include "scene/3d/importer_mesh_instance_3d.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/resources/surface_tool.h"

#include "fbx_bone.h"
#include "fbx_parser/FBXMeshGeometry.h"
#include "import_state.h"
#include "tools/import_utils.h"

struct FBXNode;
struct FBXMeshData;
struct FBXBone;
struct ImportState;

typedef int Vertex;
typedef int SurfaceId;
typedef int PolygonId;
typedef int DataIndex;

struct SurfaceData {
	Ref<SurfaceTool> surface_tool;
	OrderedHashMap<Vertex, int> lookup_table; // proposed fix is to replace lookup_table[vertex_id] to give the position of the vertices_map[int] index.
	LocalVector<Vertex> vertices_map; // this must be ordered the same as insertion <-- slow to do find() operation.
	Ref<Material> material;
	HashMap<PolygonId, Vector<DataIndex>> surface_polygon_vertex;
	Array morphs;
};

struct VertexWeightMapping {
	Vector<float> weights;
	Vector<int> bones;
	// This extra vector is used because the bone id is computed in a second step.
	// TODO Get rid of this extra step is a good idea.
	Vector<Ref<FBXBone>> bones_ref;
};

template <class T>
struct VertexData {
	int polygon_index;
	T data;
};

// Caches mesh information and instantiates meshes for you using helper functions.
struct FBXMeshData : RefCounted {
	struct MorphVertexData {
		// TODO we have only these??
		/// Each element is a vertex. Not supposed to be void.
		Vector<Vector3> vertices;
		/// Each element is a vertex. Not supposed to be void.
		Vector<Vector3> normals;
	};

	// FIXME: remove this is a hack for testing only
	mutable const FBXDocParser::MeshGeometry *mesh_geometry = nullptr;

	Ref<FBXNode> mesh_node = nullptr;
	/// vertex id, Weight Info
	/// later: perf we can use array here
	HashMap<int, VertexWeightMapping> vertex_weights;

	// translate fbx mesh data from document context to FBX Mesh Geometry Context
	bool valid_weight_indexes = false;

	ImporterMeshInstance3D *create_fbx_mesh(const ImportState &state, const FBXDocParser::MeshGeometry *p_mesh_geometry, const FBXDocParser::Model *model, bool use_compression);

	void gen_weight_info(Ref<SurfaceTool> st, int vertex_id) const;

	/* mesh maximum weight count */
	bool valid_weight_count = false;
	int max_weight_count = 0;
	uint64_t armature_id = 0;
	bool valid_armature_id = false;
	ImporterMeshInstance3D *godot_mesh_instance = nullptr;

private:
	void sanitize_vertex_weights(const ImportState &state);

	/// Make sure to reorganize the vertices so that the correct UV is taken.
	/// This step is needed because differently from the normal, that can be
	/// combined, the UV may need its own triangle because sometimes they have
	/// really different UV for the same vertex but different polygon.
	/// This function make sure to add another vertex for those UVS.
	void reorganize_vertices(
			std::vector<int> &r_polygon_indices,
			std::vector<Vector3> &r_vertices,
			HashMap<int, Vector3> &r_normals,
			HashMap<int, Vector2> &r_uv_1,
			HashMap<int, Vector2> &r_uv_2,
			HashMap<int, Color> &r_color,
			HashMap<String, MorphVertexData> &r_morphs,
			HashMap<int, HashMap<int, Vector3>> &r_normals_raw,
			HashMap<int, HashMap<int, Color>> &r_colors_raw,
			HashMap<int, HashMap<int, Vector2>> &r_uv_1_raw,
			HashMap<int, HashMap<int, Vector2>> &r_uv_2_raw);

	void add_vertex(
			const ImportState &state,
			Ref<SurfaceTool> p_surface_tool,
			real_t p_scale,
			int p_vertex,
			const std::vector<Vector3> &p_vertices_position,
			const HashMap<int, Vector3> &p_normals,
			const HashMap<int, Vector2> &p_uvs_0,
			const HashMap<int, Vector2> &p_uvs_1,
			const HashMap<int, Color> &p_colors,
			const Vector3 &p_morph_value = Vector3(),
			const Vector3 &p_morph_normal = Vector3());

	void triangulate_polygon(SurfaceData *surface, const Vector<int> &p_polygon_vertex, const std::vector<Vector3> &p_vertices) const;

	/// This function is responsible to convert the FBX polygon vertex to
	/// vertex index.
	/// The polygon vertices are stored in an array with some negative
	/// values. The negative values define the last face index.
	/// For example the following `face_array` contains two faces, the former
	/// with 3 vertices and the latter with a line:
	/// [0,2,-2,3,-5]
	/// Parsed as:
	/// [0, 2, 1, 3, 4]
	/// The negative values are computed using this formula: `(-value) - 1`
	///
	/// Returns the vertex index from the polygon vertex.
	/// Returns -1 if `p_index` is invalid.
	int get_vertex_from_polygon_vertex(const std::vector<int> &p_face_indices, int p_index) const;

	/// Returns true if this polygon_vertex_index is the end of a new polygon.
	bool is_end_of_polygon(const std::vector<int> &p_face_indices, int p_index) const;

	/// Returns true if this polygon_vertex_index is the begin of a new polygon.
	bool is_start_of_polygon(const std::vector<int> &p_face_indices, int p_index) const;

	/// Returns the number of polygons.
	int count_polygons(const std::vector<int> &p_face_indices) const;

	/// Used to extract data from the `MappingData` aligned with vertex.
	/// Useful to extract normal/uvs/colors/tangents/etc...
	/// If the function fails somehow, it returns an hollow vector and print an error.
	template <class R, class T>
	HashMap<int, R> extract_per_vertex_data(
			int p_vertex_count,
			const std::vector<FBXDocParser::MeshGeometry::Edge> &p_edges,
			const std::vector<int> &p_mesh_indices,
			const FBXDocParser::MeshGeometry::MappingData<T> &p_mapping_data,
			R (*collector_function)(const Vector<VertexData<T>> *p_vertex_data, R p_fall_back),
			R p_fall_back) const;

	/// Used to extract data from the `MappingData` organized per polygon.
	/// Useful to extract the material
	/// If the function fails somehow, it returns an hollow vector and print an error.
	template <class T>
	HashMap<int, T> extract_per_polygon(
			int p_vertex_count,
			const std::vector<int> &p_face_indices,
			const FBXDocParser::MeshGeometry::MappingData<T> &p_fbx_data,
			T p_fallback_value) const;

	/// Extracts the morph data and organizes it per vertices.
	/// The returned `MorphVertexData` arrays are never something different
	/// then the `vertex_count`.
	void extract_morphs(const FBXDocParser::MeshGeometry *mesh_geometry, HashMap<String, MorphVertexData> &r_data);
};

#endif // FBX_MESH_DATA_H