diff --git a/test/ModelExport.cpp b/test/ModelExport.cpp index 9cb59aca71..09ce7fccd1 100644 --- a/test/ModelExport.cpp +++ b/test/ModelExport.cpp @@ -3,6 +3,8 @@ #include "imodel.h" #include "imodelcache.h" #include "imap.h" +#include "ieclass.h" +#include "ientity.h" #include "algorithm/Scene.h" #include "scenelib.h" #include "os/path.h" @@ -85,4 +87,182 @@ TEST_F(ModelExportTest, ExportFolderNotExisting) EXPECT_TRUE(fs::exists(outputPath)) << "Exporter didn't create the file " << outputPath; } +inline bool surfaceHasVertex(const model::IModelSurface& surface, const std::function& functor) +{ + for (int i = 0; i < surface.getNumVertices(); ++i) + { + if (functor(surface.getVertex(i))) + { + return true; + } + } + + return false; +} + +const std::string CustomMaterialName = "custom_surface_name"; +const Vector3 VertexColour1(0.1, 0.2, 0.3); +const Vector3 VertexColour2(0.4, 0.5, 0.6); +const Vector3 VertexColour3(0.7, 0.8, 0.9); + +inline void checkVertexColoursOfExportedModel(const model::IModelExporterPtr& exporter, const std::string& outputPath_) +{ + fs::path outputPath = outputPath_; + outputPath /= "models/"; + fs::path filename = "dummy.lwo"; + + EXPECT_FALSE(fs::exists(outputPath / filename)) << filename << " already exists in " << outputPath.string(); + + exporter->exportToPath(outputPath.string(), filename.string()); + + EXPECT_TRUE(fs::exists(outputPath / filename)) << filename << " should exists in " << outputPath.string(); + + try + { + // Create a func_static using this new model + auto eclass = GlobalEntityClassManager().findClass("func_static"); + auto entity = GlobalEntityModule().createEntity(eclass); + + scene::addNodeToContainer(entity, GlobalMapModule().getRoot()); + + // This should assign the model node to the entity + Node_getEntity(entity)->setKeyValue("model", "models/" + filename.string()); + + // Locate the IModel node among the entity's children + model::ModelNodePtr model; + entity->foreachNode([&](const scene::INodePtr& node) + { + if (Node_isModel(node)) + { + model = Node_getModel(node); + } + return true; + }); + + EXPECT_TRUE(model) << "Could not locate the model node of the entity"; + + EXPECT_EQ(model->getIModel().getSurfaceCount(), 1); + + const auto& surface = model->getIModel().getSurface(0); + EXPECT_EQ(surface.getDefaultMaterial(), CustomMaterialName); + + EXPECT_EQ(surface.getNumVertices(), 3); + + // The three colours we exported need to be present in the mesh + EXPECT_TRUE(surfaceHasVertex(surface, [&](const ArbitraryMeshVertex& vertex) + { + return math::isNear(vertex.colour, VertexColour1, 0.01); + })); + EXPECT_TRUE(surfaceHasVertex(surface, [&](const ArbitraryMeshVertex& vertex) + { + return math::isNear(vertex.colour, VertexColour2, 0.01); + })); + EXPECT_TRUE(surfaceHasVertex(surface, [&](const ArbitraryMeshVertex& vertex) + { + return math::isNear(vertex.colour, VertexColour3, 0.01); + })); + + fs::remove(outputPath / filename); + } + catch (const std::exception&) + { + fs::remove(outputPath / filename); + throw; + } +} + +// #5717: LWO Model exporter didn't write any vertex colours +TEST_F(ModelExportTest, LwoVertexColoursAddedByPolygon) +{ + auto exporter = GlobalModelFormatManager().getExporter("lwo"); + EXPECT_TRUE(exporter); + + // Create a few vertices with custom colours + std::vector polys; + + polys.emplace_back(model::ModelPolygon + { + ArbitraryMeshVertex(Vertex3f(1,0,0), Normal3f(1,0,0), TexCoord2f(1,0), VertexColour1), + ArbitraryMeshVertex(Vertex3f(0,1,0), Normal3f(1,0,0), TexCoord2f(0,0), VertexColour2), + ArbitraryMeshVertex(Vertex3f(1,1,0), Normal3f(1,0,0), TexCoord2f(1,0), VertexColour3) + }); + + exporter->addPolygons(CustomMaterialName, polys, Matrix4::getIdentity()); + + checkVertexColoursOfExportedModel(exporter, _context.getTestProjectPath()); +} + +class TestModelSurface : + public model::IIndexedModelSurface +{ +public: + std::vector vertices; + std::vector indices; + + int getNumVertices() const override + { + return static_cast(vertices.size()); + } + + int getNumTriangles() const override + { + return static_cast(indices.size() / 3); + } + + const ArbitraryMeshVertex& getVertex(int vertexNum) const override + { + return vertices[vertexNum]; + } + + model::ModelPolygon getPolygon(int polygonNum) const override + { + return model::ModelPolygon + { + vertices[polygonNum * 3 + 0], + vertices[polygonNum * 3 + 1], + vertices[polygonNum * 3 + 2] + }; + } + + const std::string& getDefaultMaterial() const override + { + return CustomMaterialName; + } + + const std::string& getActiveMaterial() const override + { + return getDefaultMaterial(); + } + + const std::vector& getVertexArray() const override + { + return vertices; + } + + const std::vector& getIndexArray() const override + { + return indices; + } +}; + +TEST_F(ModelExportTest, LwoVertexColoursAddedBySurface) +{ + auto exporter = GlobalModelFormatManager().getExporter("lwo"); + EXPECT_TRUE(exporter); + + // Create a few vertices with custom colours + TestModelSurface surface; + + surface.vertices.emplace_back(Vertex3f(1, 0, 0), Normal3f(1, 0, 0), TexCoord2f(1, 0), VertexColour1); + surface.vertices.emplace_back(Vertex3f(0, 1, 0), Normal3f(1, 0, 0), TexCoord2f(0, 0), VertexColour2); + surface.vertices.emplace_back(Vertex3f(1, 1, 0), Normal3f(1, 0, 0), TexCoord2f(1, 0), VertexColour3); + surface.indices.push_back(0); + surface.indices.push_back(1); + surface.indices.push_back(2); + + exporter->addSurface(surface, Matrix4::getIdentity()); + + checkVertexColoursOfExportedModel(exporter, _context.getTestProjectPath()); +} + }