From 23373e85da6f2543c93ac3b79ec90c842e0537c7 Mon Sep 17 00:00:00 2001 From: codereader Date: Wed, 7 Oct 2020 20:25:15 +0200 Subject: [PATCH] #5326: Export a .mtl material library file next to the .obj file --- .../model/export/WavefrontExporter.cpp | 100 ++++++++++++++++-- radiantcore/model/export/WavefrontExporter.h | 3 +- 2 files changed, 95 insertions(+), 8 deletions(-) diff --git a/radiantcore/model/export/WavefrontExporter.cpp b/radiantcore/model/export/WavefrontExporter.cpp index 4444c74de1..b30c85a894 100644 --- a/radiantcore/model/export/WavefrontExporter.cpp +++ b/radiantcore/model/export/WavefrontExporter.cpp @@ -7,6 +7,11 @@ namespace model { +namespace +{ + const char* const EXPORT_COMMENT_HEADER = "# Generated by DarkRadiant's OBJ file exporter"; +} + IModelExporterPtr WavefrontExporter::clone() { return std::make_shared(); @@ -26,29 +31,45 @@ const std::string& WavefrontExporter::getExtension() const void WavefrontExporter::exportToPath(const std::string& outputPath, const std::string& filename) { - // Open the stream to the output file - stream::ExportStream output(outputPath, filename, stream::ExportStream::Mode::Text); + // Open the stream to the .obj file (and the .mtl file) + stream::ExportStream objFile(outputPath, filename, stream::ExportStream::Mode::Text); - exportToStream(output.getStream()); + fs::path mtlFilename(filename); + mtlFilename.replace_extension(".mtl"); + stream::ExportStream mtlFile(outputPath, mtlFilename.string(), stream::ExportStream::Mode::Text); - output.close(); + writeObjFile(objFile.getStream(), mtlFilename.string()); + writeMaterialLib(mtlFile.getStream()); + + objFile.close(); + mtlFile.close(); } -void WavefrontExporter::exportToStream(std::ostream& stream) +void WavefrontExporter::writeObjFile(std::ostream& stream, const std::string& mtlFilename) { + // Write export comment + stream << EXPORT_COMMENT_HEADER << std::endl; + + // Write mtllib file + stream << "mtllib " << mtlFilename << std::endl; + stream << std::endl; + // Count exported vertices. Exported indices are 1-based though. std::size_t vertexCount = 0; // Each surface is exported as group. - for (const Surfaces::value_type& pair : _surfaces) + for (const auto& pair : _surfaces) { const Surface& surface = pair.second; // Base index for vertices, added to the surface indices std::size_t vertBaseIndex = vertexCount; - // Since we don't write .mtl files store at least the material into the group name + // Store the material into the group name stream << "g " << surface.materialName << std::endl; + + // Reference the material we're going to export to the .mtl file + stream << "usemtl " << surface.materialName << std::endl; stream << std::endl; // Temporary buffers for vertices, texcoords and polys @@ -89,4 +110,69 @@ void WavefrontExporter::exportToStream(std::ostream& stream) } } +void WavefrontExporter::writeMaterialLib(std::ostream& stream) +{ + // Write export comment + stream << EXPORT_COMMENT_HEADER << std::endl; + + for (const auto& pair : _surfaces) + { + const Surface& surface = pair.second; + + auto material = GlobalMaterialManager().getMaterialForName(surface.materialName); + + const auto& layers = material->getAllLayers(); + + stream << "newmtl " << surface.materialName << std::endl; + stream << "Ns 0.0" << std::endl; // shininess + stream << "Ka 1.000000 1.000000 1.000000" << std::endl; // ambient colour + stream << "Kd 1.000000 1.000000 1.000000" << std::endl; // diffuse colour + stream << "Ks 1.000000 1.000000 1.000000" << std::endl; // specular colour + stream << "d 1.000000" << std::endl; // (not transparent at all) + + std::string diffuseFilename; + std::string specularFilename; + std::string bumpFilename; + + for (const auto& layer : layers) + { + if (layer->getType() == ShaderLayer::DIFFUSE) + { + diffuseFilename = layer->getMapImageFilename(); + } + else if (layer->getType() == ShaderLayer::BUMP) + { + bumpFilename = layer->getMapImageFilename(); + } + else if (layer->getType() == ShaderLayer::SPECULAR) + { + specularFilename = layer->getMapImageFilename(); + } + } + + if (!diffuseFilename.empty()) + { + stream << "map_Kd " << diffuseFilename << std::endl; // diffusemap + } + + if (!bumpFilename.empty()) + { + stream << "map_Kn " << bumpFilename << std::endl; // normalmap + } + + if (!specularFilename.empty()) + { + stream << "map_Ks " << specularFilename << std::endl; // specularmap + stream << "illum 2" << std::endl; // specular colour + } + else + { + stream << "illum 1" << std::endl; // specular colour + } + + stream << std::endl; + stream << std::endl; + } +} + } diff --git a/radiantcore/model/export/WavefrontExporter.h b/radiantcore/model/export/WavefrontExporter.h index 5e2bbadd9b..c02049c35b 100644 --- a/radiantcore/model/export/WavefrontExporter.h +++ b/radiantcore/model/export/WavefrontExporter.h @@ -21,7 +21,8 @@ class WavefrontExporter : private: // Export the model file to the given stream - void exportToStream(std::ostream& stream); + void writeObjFile(std::ostream& stream, const std::string& mtlFilename); + void writeMaterialLib(std::ostream& stream); }; }