Skip to content

Commit

Permalink
#5326: Export a .mtl material library file next to the .obj file
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed Oct 7, 2020
1 parent cbba460 commit 23373e8
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 8 deletions.
100 changes: 93 additions & 7 deletions radiantcore/model/export/WavefrontExporter.cpp
Expand Up @@ -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<WavefrontExporter>();
Expand All @@ -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
Expand Down Expand Up @@ -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;
}
}

}
3 changes: 2 additions & 1 deletion radiantcore/model/export/WavefrontExporter.h
Expand Up @@ -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);
};

}

0 comments on commit 23373e8

Please sign in to comment.