From 22c8d97b54ac79a7e1d1532f6dff06269cca2c57 Mon Sep 17 00:00:00 2001 From: emaame Date: Wed, 14 Jun 2023 21:02:40 +0900 Subject: [PATCH] Support OBJ specified only a part of vertex colors The omitted vertex colors are treated as (0, 0, 0, 1). e.g v 0.0 0.0 0.0 v 0.0 0.0 1.0 0.0 0.0 0.0 v 0.0 1.0 0.0 v 1.0 0.0 0.0 1.0 0.6 0.3 v 1.0 1.0 0.0 --- code/AssetLib/Obj/ObjFileData.h | 2 - code/AssetLib/Obj/ObjFileParser.cpp | 8 ++++ .../OBJ/only_a_part_of_vertexcolors.obj | 11 +++++ test/unit/utObjImportExport.cpp | 48 +++++++++++++++++++ 4 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 test/models/OBJ/only_a_part_of_vertexcolors.obj diff --git a/code/AssetLib/Obj/ObjFileData.h b/code/AssetLib/Obj/ObjFileData.h index 82296413b..22090e63e 100644 --- a/code/AssetLib/Obj/ObjFileData.h +++ b/code/AssetLib/Obj/ObjFileData.h @@ -239,8 +239,6 @@ struct Mesh { unsigned int m_uiMaterialIndex; /// True, if normals are stored. bool m_hasNormals; - /// True, if vertex colors are stored. - bool m_hasVertexColors; /// Constructor explicit Mesh(const std::string &name) : diff --git a/code/AssetLib/Obj/ObjFileParser.cpp b/code/AssetLib/Obj/ObjFileParser.cpp index ed416dc93..1fa716d05 100644 --- a/code/AssetLib/Obj/ObjFileParser.cpp +++ b/code/AssetLib/Obj/ObjFileParser.cpp @@ -156,9 +156,17 @@ void ObjFileParser::parseFile(IOStreamBuffer &streamBuffer) { // read in vertex definition (homogeneous coords) getHomogeneousVector3(m_pModel->mVertices); } else if (numComponents == 6) { + // fill previous omitted vertex-colors by default + if (m_pModel->mVertexColors.size() < m_pModel->mVertices.size()) { + m_pModel->mVertexColors.resize(m_pModel->mVertices.size(), aiVector3D(0, 0, 0)); + } // read vertex and vertex-color getTwoVectors3(m_pModel->mVertices, m_pModel->mVertexColors); } + // append omitted vertex-colors as default for the end if any vertex-color exists + if (!m_pModel->mVertexColors.empty() && m_pModel->mVertexColors.size() < m_pModel->mVertices.size()) { + m_pModel->mVertexColors.resize(m_pModel->mVertices.size(), aiVector3D(0, 0, 0)); + } } else if (*m_DataIt == 't') { // read in texture coordinate ( 2D or 3D ) ++m_DataIt; diff --git a/test/models/OBJ/only_a_part_of_vertexcolors.obj b/test/models/OBJ/only_a_part_of_vertexcolors.obj new file mode 100644 index 000000000..a9f6e1188 --- /dev/null +++ b/test/models/OBJ/only_a_part_of_vertexcolors.obj @@ -0,0 +1,11 @@ +g cube + +v 0.0 0.0 0.0 +v 0.0 0.0 1.0 0.0 0.0 1.0 +v 0.0 1.0 0.0 +v 1.0 0.0 0.0 1.0 0.6 0.3 +v 1.0 1.0 0.0 + +f 1 2 3 +f 1 4 3 +f 2 5 4 diff --git a/test/unit/utObjImportExport.cpp b/test/unit/utObjImportExport.cpp index 58eace075..ce778a950 100644 --- a/test/unit/utObjImportExport.cpp +++ b/test/unit/utObjImportExport.cpp @@ -286,6 +286,54 @@ TEST_F(utObjImportExport, issue1923_vertex_color_Test) { delete scene; } +TEST_F(utObjImportExport, only_a_part_of_vertex_colors_Test) { + ::Assimp::Importer importer; + const aiScene *const scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/OBJ/only_a_part_of_vertexcolors.obj", aiProcess_ValidateDataStructure); + EXPECT_NE(nullptr, scene); + + EXPECT_EQ(scene->mNumMeshes, 1U); + const aiMesh *const mesh = scene->mMeshes[0]; + EXPECT_EQ(mesh->mNumVertices, 9U); + EXPECT_EQ(mesh->mNumFaces, 3U); + EXPECT_TRUE(mesh->HasVertexColors(0)); + + const aiVector3D *const vertices = mesh->mVertices; + const aiColor4D *const colors = mesh->mColors[0]; + EXPECT_EQ(aiVector3D(0.0f, 0.0f, 0.0f), vertices[0]); + EXPECT_EQ(aiColor4D(0.0f, 0.0f, 0.0f, 1.0f), colors[0]); + EXPECT_EQ(aiVector3D(0.0f, 0.0f, 1.0f), vertices[1]); + EXPECT_EQ(aiColor4D(0.0f, 0.0f, 1.0f, 1.0f), colors[1]); + EXPECT_EQ(aiVector3D(0.0f, 1.0f, 0.0f), vertices[2]); + EXPECT_EQ(aiColor4D(0.0f, 0.0f, 0.0f, 1.0f), colors[2]); + EXPECT_EQ(aiVector3D(0.0f, 0.0f, 0.0f), vertices[3]); + EXPECT_EQ(aiColor4D(0.0f, 0.0f, 0.0f, 1.0f), colors[3]); + EXPECT_EQ(aiVector3D(1.0f, 0.0f, 0.0f), vertices[4]); + EXPECT_EQ(aiColor4D(1.0f, 0.6f, 0.3f, 1.0f), colors[4]); + EXPECT_EQ(aiVector3D(0.0f, 1.0f, 0.0f), vertices[5]); + EXPECT_EQ(aiColor4D(0.0f, 0.0f, 0.0f, 1.0f), colors[5]); + EXPECT_EQ(aiVector3D(0.0f, 0.0f, 1.0f), vertices[6]); + EXPECT_EQ(aiColor4D(0.0f, 0.0f, 1.0f, 1.0f), colors[6]); + EXPECT_EQ(aiVector3D(1.0f, 1.0f, 0.0f), vertices[7]); + EXPECT_EQ(aiColor4D(0.0f, 0.0f, 0.0f, 1.0f), colors[7]); + EXPECT_EQ(aiVector3D(1.0f, 0.0f, 0.0f), vertices[8]); + EXPECT_EQ(aiColor4D(1.0f, 0.6f, 0.3f, 1.0f), colors[8]); + +#ifndef ASSIMP_BUILD_NO_EXPORT + ::Assimp::Exporter exporter; + EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "obj", ASSIMP_TEST_MODELS_DIR "/OBJ/test_out.obj")); +#endif // ASSIMP_BUILD_NO_EXPORT +} + +TEST_F(utObjImportExport, no_vertex_colors_Test) { + ::Assimp::Importer importer; + const aiScene *const scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/OBJ/box.obj", aiProcess_ValidateDataStructure); + EXPECT_NE(nullptr, scene); + + EXPECT_EQ(scene->mNumMeshes, 1U); + const aiMesh *const mesh = scene->mMeshes[0]; + EXPECT_FALSE(mesh->HasVertexColors(0)); +} + TEST_F(utObjImportExport, issue1453_segfault) { static const char *curObjModel = "v 0.0 0.0 0.0\n"