Merge pull request #44305 from RevoluPowered/fbx-update-plugin
[fbx] Implement ColorIndex for Vertex Colors to ensure they are correct and duplicate vertexes correctly for multiple color attributes.
This commit is contained in:
commit
65c1db3131
4 changed files with 122 additions and 16 deletions
|
@ -172,13 +172,14 @@ MeshInstance *FBXMeshData::create_fbx_mesh(const ImportState &state, const FBXDo
|
|||
&collect_all,
|
||||
HashMap<int, Vector2>());
|
||||
|
||||
HashMap<int, Color> colors = extract_per_vertex_data(
|
||||
HashMap<int, Color> colors;
|
||||
HashMap<int, HashMap<int, Color> > colors_raw = extract_per_vertex_data(
|
||||
vertices.size(),
|
||||
mesh_geometry->get_edge_map(),
|
||||
polygon_indices,
|
||||
mesh_geometry->get_colors(),
|
||||
&collect_first,
|
||||
Color());
|
||||
&collect_all,
|
||||
HashMap<int, Color>());
|
||||
|
||||
// TODO what about tangents?
|
||||
// TODO what about bi-nomials?
|
||||
|
@ -209,15 +210,21 @@ MeshInstance *FBXMeshData::create_fbx_mesh(const ImportState &state, const FBXDo
|
|||
colors,
|
||||
morphs,
|
||||
normals_raw,
|
||||
colors_raw,
|
||||
uvs_0_raw,
|
||||
uvs_1_raw);
|
||||
|
||||
const int color_count = colors.size();
|
||||
print_verbose("Vertex color count: " + itos(color_count));
|
||||
|
||||
// Make sure that from this moment on the mesh_geometry is no used anymore.
|
||||
// This is a safety step, because the mesh_geometry data are no more valid
|
||||
// at this point.
|
||||
|
||||
const int vertex_count = vertices.size();
|
||||
|
||||
print_verbose("Vertex count: " + itos(vertex_count));
|
||||
|
||||
// The map key is the material allocator id that is also used as surface id.
|
||||
HashMap<SurfaceId, SurfaceData> surfaces;
|
||||
|
||||
|
@ -267,7 +274,7 @@ MeshInstance *FBXMeshData::create_fbx_mesh(const ImportState &state, const FBXDo
|
|||
for (size_t polygon_vertex = 0; polygon_vertex < polygon_indices.size(); polygon_vertex += 1) {
|
||||
if (is_start_of_polygon(polygon_indices, polygon_vertex)) {
|
||||
polygon_index += 1;
|
||||
ERR_FAIL_COND_V_MSG(polygon_surfaces.has(polygon_index) == false, nullptr, "The FBX file is currupted, This surface_index is not expected.");
|
||||
ERR_FAIL_COND_V_MSG(polygon_surfaces.has(polygon_index) == false, nullptr, "The FBX file is corrupted, This surface_index is not expected.");
|
||||
surface_id = polygon_surfaces[polygon_index];
|
||||
surface_data = surfaces.getptr(surface_id);
|
||||
CRASH_COND(surface_data == nullptr); // Can't be null.
|
||||
|
@ -385,7 +392,10 @@ MeshInstance *FBXMeshData::create_fbx_mesh(const ImportState &state, const FBXDo
|
|||
for (const SurfaceId *surface_id = surfaces.next(nullptr); surface_id != nullptr; surface_id = surfaces.next(surface_id)) {
|
||||
SurfaceData *surface = surfaces.getptr(*surface_id);
|
||||
|
||||
// you can't generate them without a valid uv map.
|
||||
if (uvs_0_raw.size() > 0) {
|
||||
surface->surface_tool->generate_tangents();
|
||||
}
|
||||
|
||||
mesh->add_surface_from_arrays(
|
||||
Mesh::PRIMITIVE_TRIANGLES,
|
||||
|
@ -496,6 +506,7 @@ void FBXMeshData::reorganize_vertices(
|
|||
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) {
|
||||
|
||||
|
@ -513,6 +524,7 @@ void FBXMeshData::reorganize_vertices(
|
|||
Vector2 this_vert_poly_uv1 = Vector2();
|
||||
Vector2 this_vert_poly_uv2 = Vector2();
|
||||
Vector3 this_vert_poly_normal = Vector3();
|
||||
Color this_vert_poly_color = Color();
|
||||
|
||||
// Take the normal and see if we need to duplicate this polygon.
|
||||
if (r_normals_raw.has(index)) {
|
||||
|
@ -548,6 +560,41 @@ void FBXMeshData::reorganize_vertices(
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: make me vertex color
|
||||
// Take the normal and see if we need to duplicate this polygon.
|
||||
if (r_colors_raw.has(index)) {
|
||||
const HashMap<PolygonId, Color> *color_arr = r_colors_raw.getptr(index);
|
||||
|
||||
if (color_arr->has(polygon_index)) {
|
||||
this_vert_poly_color = color_arr->get(polygon_index);
|
||||
} else if (color_arr->has(-1)) {
|
||||
this_vert_poly_color = color_arr->get(-1);
|
||||
} else {
|
||||
print_error("invalid color detected: " + itos(index) + " polygon index: " + itos(polygon_index));
|
||||
for (const PolygonId *pid = color_arr->next(nullptr); pid != nullptr; pid = color_arr->next(pid)) {
|
||||
print_verbose("debug contents key: " + itos(*pid));
|
||||
|
||||
if (color_arr->has(*pid)) {
|
||||
print_verbose("contents valid: " + color_arr->get(*pid));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now, check if we need to duplicate it.
|
||||
for (const PolygonId *pid = color_arr->next(nullptr); pid != nullptr; pid = color_arr->next(pid)) {
|
||||
if (*pid == polygon_index) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const Color vert_poly_color = *color_arr->getptr(*pid);
|
||||
if (!this_vert_poly_color.is_equal_approx(vert_poly_color)) {
|
||||
// Yes this polygon need duplication.
|
||||
need_duplication = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Take the UV1 and UV2 and see if we need to duplicate this polygon.
|
||||
{
|
||||
HashMap<int, HashMap<int, Vector2> > *uv_raw = &r_uv_1_raw;
|
||||
|
@ -599,6 +646,7 @@ void FBXMeshData::reorganize_vertices(
|
|||
bool same_uv1 = false;
|
||||
bool same_uv2 = false;
|
||||
bool same_normal = false;
|
||||
bool same_color = false;
|
||||
|
||||
if (r_uv_1.has(new_vertex)) {
|
||||
if ((this_vert_poly_uv1 - (*r_uv_1.getptr(new_vertex))).length_squared() <= CMP_EPSILON) {
|
||||
|
@ -612,13 +660,19 @@ void FBXMeshData::reorganize_vertices(
|
|||
}
|
||||
}
|
||||
|
||||
if (r_color.has(new_vertex)) {
|
||||
if (this_vert_poly_color.is_equal_approx((*r_color.getptr(new_vertex)))) {
|
||||
same_color = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (r_normals.has(new_vertex)) {
|
||||
if ((this_vert_poly_normal - (*r_normals.getptr(new_vertex))).length_squared() <= CMP_EPSILON) {
|
||||
same_uv2 = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (same_uv1 && same_uv2 && same_normal) {
|
||||
if (same_uv1 && same_uv2 && same_normal && same_color) {
|
||||
similar_vertex = new_vertex;
|
||||
break;
|
||||
}
|
||||
|
@ -636,6 +690,8 @@ void FBXMeshData::reorganize_vertices(
|
|||
}
|
||||
}
|
||||
|
||||
need_duplication = false;
|
||||
|
||||
if (need_duplication) {
|
||||
const Vertex old_index = index;
|
||||
const Vertex new_index = r_vertices.size();
|
||||
|
@ -657,6 +713,13 @@ void FBXMeshData::reorganize_vertices(
|
|||
r_normals_raw[new_index][polygon_index] = this_vert_poly_normal;
|
||||
}
|
||||
|
||||
// Vertex Color
|
||||
if (r_colors_raw.has(old_index)) {
|
||||
r_color.set(new_index, this_vert_poly_color);
|
||||
r_colors_raw.getptr(old_index)->erase(polygon_index);
|
||||
r_colors_raw[new_index][polygon_index] = this_vert_poly_color;
|
||||
}
|
||||
|
||||
// UV 0
|
||||
if (r_uv_1_raw.has(old_index)) {
|
||||
r_uv_1.set(new_index, this_vert_poly_uv1);
|
||||
|
@ -671,11 +734,6 @@ void FBXMeshData::reorganize_vertices(
|
|||
r_uv_2_raw[new_index][polygon_index] = this_vert_poly_uv2;
|
||||
}
|
||||
|
||||
// Vertex color.
|
||||
if (r_color.has(old_index)) {
|
||||
r_color[new_index] = r_color[old_index];
|
||||
}
|
||||
|
||||
// Morphs
|
||||
for (const String *mname = r_morphs.next(nullptr); mname != nullptr; mname = r_morphs.next(mname)) {
|
||||
MorphVertexData *d = r_morphs.getptr(*mname);
|
||||
|
@ -700,6 +758,10 @@ void FBXMeshData::reorganize_vertices(
|
|||
r_normals.set(index, this_vert_poly_normal);
|
||||
}
|
||||
|
||||
if (r_colors_raw.has(index) && r_color.has(index) == false) {
|
||||
r_color.set(index, this_vert_poly_color);
|
||||
}
|
||||
|
||||
if (r_uv_1_raw.has(index) &&
|
||||
r_uv_1.has(index) == false) {
|
||||
r_uv_1.set(index, this_vert_poly_uv1);
|
||||
|
@ -1010,8 +1072,14 @@ HashMap<int, R> FBXMeshData::extract_per_vertex_data(
|
|||
* data size is 96 (contains uv coordinates)
|
||||
* this means index is simple data reduction basically
|
||||
*/
|
||||
////
|
||||
if (p_mapping_data.ref_type == FBXDocParser::MeshGeometry::ReferenceType::index_to_direct && p_mapping_data.index.size() == 0) {
|
||||
print_verbose("debug count: index size: " + itos(p_mapping_data.index.size()) + ", data size: " + itos(p_mapping_data.data.size()));
|
||||
print_verbose("vertex indices count: " + itos(p_mesh_indices.size()));
|
||||
print_verbose("Edge map size: " + itos(p_edge_map.size()));
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V_MSG(p_mapping_data.ref_type == FBXDocParser::MeshGeometry::ReferenceType::index_to_direct && p_mapping_data.index.size() == 0, (HashMap<int, R>()), "FBX file is missing indexing array");
|
||||
ERR_FAIL_COND_V_MSG(p_mapping_data.ref_type == FBXDocParser::MeshGeometry::ReferenceType::index_to_direct && p_mapping_data.index.size() == 0, (HashMap<int, R>()), "FBX importer needs to map correctly to this field, please specify the override index name to fix this problem!");
|
||||
ERR_FAIL_COND_V_MSG(p_mapping_data.ref_type == FBXDocParser::MeshGeometry::ReferenceType::index && p_mapping_data.index.size() == 0, (HashMap<int, R>()), "The FBX seems corrupted");
|
||||
|
||||
// Aggregate vertex data.
|
||||
|
|
|
@ -108,6 +108,7 @@ private:
|
|||
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);
|
||||
|
||||
|
|
|
@ -211,7 +211,33 @@ MeshGeometry::MeshGeometry(uint64_t id, const ElementPtr element, const std::str
|
|||
} else if (layer_type_name == "LayerElementNormal") {
|
||||
m_normals = resolve_vertex_data_array<Vector3>(layer_scope, MappingInformationType, ReferenceInformationType, "Normals");
|
||||
} else if (layer_type_name == "LayerElementColor") {
|
||||
m_colors = resolve_vertex_data_array<Color>(layer_scope, MappingInformationType, ReferenceInformationType, "Colors");
|
||||
m_colors = resolve_vertex_data_array<Color>(layer_scope, MappingInformationType, ReferenceInformationType, "Colors", "ColorIndex");
|
||||
// NOTE: this is a useful sanity check to ensure you're getting any color data which is not default.
|
||||
// const Color first_color_check = m_colors.data[0];
|
||||
// bool colors_are_all_the_same = true;
|
||||
// size_t i = 1;
|
||||
// for(i = 1; i < m_colors.data.size(); i++)
|
||||
// {
|
||||
// const Color current_color = m_colors.data[i];
|
||||
// if(current_color.is_equal_approx(first_color_check))
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// colors_are_all_the_same = false;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if(colors_are_all_the_same)
|
||||
// {
|
||||
// print_error("Color serialisation is not working for vertex colors some should be different in the test asset.");
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// print_verbose("Color array has unique colors at index: " + itos(i));
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -335,12 +361,22 @@ MeshGeometry::MappingData<T> MeshGeometry::resolve_vertex_data_array(
|
|||
const ScopePtr source,
|
||||
const std::string &MappingInformationType,
|
||||
const std::string &ReferenceInformationType,
|
||||
const std::string &dataElementName) {
|
||||
const std::string &dataElementName,
|
||||
const std::string &indexOverride) {
|
||||
|
||||
ERR_FAIL_COND_V_MSG(source == nullptr, MappingData<T>(), "Invalid scope operator preventing memory corruption");
|
||||
|
||||
// UVIndex, MaterialIndex, NormalIndex, etc..
|
||||
std::string indexDataElementName = dataElementName + "Index";
|
||||
std::string indexDataElementName;
|
||||
|
||||
if (indexOverride != "") {
|
||||
// Colors should become ColorIndex
|
||||
indexDataElementName = indexOverride;
|
||||
} else {
|
||||
// Some indexes will exist.
|
||||
indexDataElementName = dataElementName + "Index";
|
||||
}
|
||||
|
||||
// goal: expand everything to be per vertex
|
||||
|
||||
ReferenceType l_ref_type = ReferenceType::direct;
|
||||
|
|
|
@ -207,7 +207,8 @@ private:
|
|||
const ScopePtr source,
|
||||
const std::string &MappingInformationType,
|
||||
const std::string &ReferenceInformationType,
|
||||
const std::string &dataElementName);
|
||||
const std::string &dataElementName,
|
||||
const std::string &indexOverride = "");
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue