From 8ffad0d8bda78acc24e63b8a80811399a017b9b2 Mon Sep 17 00:00:00 2001 From: Gordon MacPherson Date: Mon, 14 Dec 2020 16:50:46 +0000 Subject: [PATCH] ColorIndex supported now for vertex colors. Other properties should index override where appropriate in future. --- modules/fbx/data/fbx_mesh_data.cpp | 92 +++++++++++++++++++--- modules/fbx/data/fbx_mesh_data.h | 1 + modules/fbx/fbx_parser/FBXMeshGeometry.cpp | 42 +++++++++- modules/fbx/fbx_parser/FBXMeshGeometry.h | 3 +- 4 files changed, 122 insertions(+), 16 deletions(-) diff --git a/modules/fbx/data/fbx_mesh_data.cpp b/modules/fbx/data/fbx_mesh_data.cpp index a6138bd7c38..1b59a42683c 100644 --- a/modules/fbx/data/fbx_mesh_data.cpp +++ b/modules/fbx/data/fbx_mesh_data.cpp @@ -172,13 +172,14 @@ MeshInstance *FBXMeshData::create_fbx_mesh(const ImportState &state, const FBXDo &collect_all, HashMap()); - HashMap colors = extract_per_vertex_data( + HashMap colors; + HashMap > 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()); // 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 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); - surface->surface_tool->generate_tangents(); + // 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 &r_color, HashMap &r_morphs, HashMap > &r_normals_raw, + HashMap > &r_colors_raw, HashMap > &r_uv_1_raw, HashMap > &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 *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 > *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 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()), "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()), "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()), "The FBX seems corrupted"); // Aggregate vertex data. diff --git a/modules/fbx/data/fbx_mesh_data.h b/modules/fbx/data/fbx_mesh_data.h index 76f861280bd..2d76048f002 100644 --- a/modules/fbx/data/fbx_mesh_data.h +++ b/modules/fbx/data/fbx_mesh_data.h @@ -108,6 +108,7 @@ private: HashMap &r_color, HashMap &r_morphs, HashMap > &r_normals_raw, + HashMap > &r_colors_raw, HashMap > &r_uv_1_raw, HashMap > &r_uv_2_raw); diff --git a/modules/fbx/fbx_parser/FBXMeshGeometry.cpp b/modules/fbx/fbx_parser/FBXMeshGeometry.cpp index 6c6bfbdb093..380ecc97852 100644 --- a/modules/fbx/fbx_parser/FBXMeshGeometry.cpp +++ b/modules/fbx/fbx_parser/FBXMeshGeometry.cpp @@ -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(layer_scope, MappingInformationType, ReferenceInformationType, "Normals"); } else if (layer_type_name == "LayerElementColor") { - m_colors = resolve_vertex_data_array(layer_scope, MappingInformationType, ReferenceInformationType, "Colors"); + m_colors = resolve_vertex_data_array(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 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(), "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; diff --git a/modules/fbx/fbx_parser/FBXMeshGeometry.h b/modules/fbx/fbx_parser/FBXMeshGeometry.h index bd89572c696..2f2a35d740c 100644 --- a/modules/fbx/fbx_parser/FBXMeshGeometry.h +++ b/modules/fbx/fbx_parser/FBXMeshGeometry.h @@ -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 = ""); }; /*