diff --git a/src/Model.cpp b/src/Model.cpp index 5f10f29..a2f42e9 100755 --- a/src/Model.cpp +++ b/src/Model.cpp @@ -18,7 +18,7 @@ Model::Model(OBJ &obj, ResourceManager* rm) { currentMaterial = face.Material; // Load texture - auto texture = std::shared_ptr(rm->Load("Texture", currentMaterial->TextureFile)); + auto texture = std::shared_ptr(rm->Load("Texture", currentMaterial->DiffuseTexture.FileName)); // TODO: Load material parameters // Create new texture group (start index of new group is upcoming index) TextureGroup texGroup = { texture, index, index }; diff --git a/src/OBJ.cpp b/src/OBJ.cpp index 683f9e2..a8b9f03 100755 --- a/src/OBJ.cpp +++ b/src/OBJ.cpp @@ -126,9 +126,11 @@ void OBJ::ParseMaterial() std::string currentMaterialName; MaterialInfo* currentMaterial = nullptr; + unsigned int currentLine = 0; std::string line; while (std::getline(file, line)) { + currentLine++; if (line.length() == 0) continue; @@ -140,19 +142,7 @@ void OBJ::ParseMaterial() // Create a new material definition if (prefix == "newmtl") { - MaterialInfo mat = - { - "", - std::make_tuple(0.2f, 0.2f, 0.2f), - std::make_tuple(0.8f, 0.8f, 0.8f), - std::make_tuple(1.0f, 1.0f, 1.0f), - std::make_tuple(1.0f, 1.0f, 1.0f), - 1.0f, - 1.0f, - 0.0f, - 0, - }; - + MaterialInfo mat; ss >> currentMaterialName; LOG_INFO("Parsing material %s", currentMaterialName.c_str()); Materials[currentMaterialName] = mat; @@ -243,14 +233,177 @@ void OBJ::ParseMaterial() currentMaterial->IlluminationModel = illum; continue; } - // Texture file - // TODO: - if (prefix == "map_Ka" || prefix == "map_Kd") + // Diffuse texture + if (prefix == "map_Kd") { - std::string textureFile; - ss >> textureFile; - currentMaterial->TextureFile = (m_MaterialPath.branch_path() / textureFile).string(); + MaterialInfo::ColorMap colorMap; + + std::string fileName; + std::string arg; + while (ss >> arg) + { + ParseColorMap(currentLine, ss, prefix, arg, colorMap); + } + + // HACK: Should we really have to specify the full path here? + colorMap.FileName = (m_MaterialPath.branch_path() / colorMap.FileName).string(); + currentMaterial->DiffuseTexture = colorMap; + continue; + } + // Specular map + if (prefix == "map_Ks") + { + MaterialInfo::ColorMap colorMap; + + std::string fileName; + std::string arg; + while (ss >> arg) + { + ParseColorMap(currentLine, ss, prefix, arg, colorMap); + } + + // HACK: Should we really have to specify the full path here? + colorMap.FileName = (m_MaterialPath.branch_path() / colorMap.FileName).string(); + currentMaterial->SpecularMap = colorMap; + continue; + } + // Normal map (bump map) + if (prefix == "bump") + { + MaterialInfo::BumpMap bumpMap; + + std::string fileName; + std::string arg; + while (ss >> arg) + { + ParseBumpMap(currentLine, ss, prefix, arg, bumpMap); + } + + // HACK: Should we really have to specify the full path here? + bumpMap.FileName = (m_MaterialPath.branch_path() / bumpMap.FileName).string(); + currentMaterial->NormalMap = bumpMap; continue; } } } + +void OBJ::ParseTextureMap(unsigned int line, std::stringstream &ss, std::string prefix, std::string arg, MaterialInfo::TextureMap &textureMap) +{ + if (arg == "-blendu") + { + std::string val; + ss >> val; + if (val == "off") + textureMap.blendu = false; + else if (val == "on") + textureMap.blendu = true; + else + LOG_ERROR("Unrecognized MTL value \"%s\" to argument \"%s %s\" on line %i", val.c_str(), prefix.c_str(), arg.c_str(), line); + } + else if (arg == "-blendv") + { + std::string val; + ss >> val; + if (val == "off") + textureMap.blendv = false; + else if (val == "on") + textureMap.blendv = true; + else + LOG_ERROR("Unrecognized MTL value \"%s\" to argument \"%s %s\" on line %i", val.c_str(), prefix.c_str(), arg.c_str(), line); + } + else if (arg == "-clamp") + { + std::string val; + ss >> val; + if (val == "off") + textureMap.clamp = false; + else if (val == "on") + textureMap.clamp = true; + else + LOG_ERROR("Unrecognized MTL value \"%s\" to argument \"%s %s\" on line %i", val.c_str(), prefix.c_str(), arg.c_str(), line); + } + else if (arg == "-o") + { + float u, v, w; + if (ss >> u >> v >> w) + { + textureMap.o = std::make_tuple(u, v, w); + } + else + { + LOG_ERROR("Unrecognized MTL value to argument \"%s %s\" on line %i", prefix.c_str(), arg.c_str(), line); + } + } + else if (arg == "-s") + { + float u, v, w; + if (ss >> u >> v >> w) + { + textureMap.s = std::make_tuple(u, v, w); + } + else + { + LOG_ERROR("Unrecognized MTL value to argument \"%s %s\" on line %i", prefix.c_str(), arg.c_str(), line); + } + } + // Assume unrecognized options is part of the file name + else + { + if (!textureMap.FileName.empty()) + textureMap.FileName += " "; + textureMap.FileName += arg; + } +} + +void OBJ::ParseColorMap(unsigned int line, std::stringstream &ss, std::string prefix, std::string arg, MaterialInfo::ColorMap &colorMap) +{ + if (arg == "-cc") + { + if (prefix != "map_Kd" || prefix != "map_Ks") + { + LOG_ERROR("Invalid MTL argument \"%s\" to option \"%s\" on line %i", arg.c_str(), prefix.c_str(), line); + return; + } + + std::string val; + if (ss >> val) + { + if (val == "off") + colorMap.cc = false; + else if (val == "on") + colorMap.cc = true; + else + LOG_ERROR("Unrecognized MTL value \"%s\" to argument \"%s %s\" on line %i", val.c_str(), prefix.c_str(), arg.c_str(), line); + } + else + { + LOG_ERROR("Unrecognized MTL value to argument \"%s %s\" on line %i", prefix.c_str(), arg.c_str(), line); + } + } + else + { + ParseTextureMap(line, ss, prefix, arg, colorMap); + } +} + +void OBJ::ParseBumpMap(unsigned int line, std::stringstream &ss, std::string prefix, std::string arg, MaterialInfo::BumpMap &bumpMap) +{ + if (arg == "-bm") + { + if (prefix != "bump") + { + LOG_ERROR("Invalid MTL argument \"%s\" to option \"%s\" on line %i", arg.c_str(), prefix.c_str(), line); + return; + } + + float val; + if (ss >> val) + bumpMap.bm = val; + else + LOG_ERROR("Unrecognized MTL value to argument \"%s %s\" on line %i", prefix.c_str(), arg.c_str(), line); + } + else + { + ParseTextureMap(line, ss, prefix, arg, bumpMap); + } +} \ No newline at end of file diff --git a/src/OBJ.h b/src/OBJ.h index 62bce8d..2ef10e0 100755 --- a/src/OBJ.h +++ b/src/OBJ.h @@ -10,21 +10,78 @@ #include #include +#include class OBJ { public: struct MaterialInfo { - std::string TextureFile; - std::tuple AmbientColor; - std::tuple DiffuseColor; - std::tuple SpecularColor; - std::tuple TransmissionFilter; - float OpticalDensity; - float Alpha; - float Shininess; - int IlluminationModel; + struct TextureMap + { + TextureMap() + : blendu(true) + , blendv(true) + , clamp(false) + , o(std::make_tuple(0.f, 0.f, 0.f)) + , s(std::make_tuple(1.f, 1.f, 1.f)) { } + + std::string FileName; + + // http://paulbourke.net/dataformats/mtl/ + // "These options are described in detail in 'Options for texture map statements' on page 5-18." + + // Horizontal texture blending + bool blendu; // = true + // Vertical texture blending + bool blendv; // = true + // Clamping + bool clamp; // = false + // Offset + std::tuple o; // = (0, 0, 0) + // Scale + std::tuple s; // = (1, 1, 1) + }; + + struct ColorMap : public TextureMap + { + ColorMap() + : cc(false) { } + + // Color correction + bool cc; // = false + }; + + struct BumpMap : public TextureMap + { + BumpMap() + : bm(1.f) { } + + // Bump multiplier + float bm; // = 1? + }; + + MaterialInfo() + : AmbientColor(std::make_tuple(0.2f, 0.2f, 0.2f)) + , DiffuseColor(std::make_tuple(0.8f, 0.8f, 0.8f)) + , SpecularColor(std::make_tuple(1.0f, 1.0f, 1.0f)) + , TransmissionFilter(std::make_tuple(1.0f, 1.0f, 1.0f)) + , OpticalDensity(1.0f) + , Alpha(1.0f) + , Shininess(0.0f) + , IlluminationModel(0) { } + + ColorMap DiffuseTexture; + ColorMap SpecularMap; + BumpMap NormalMap; + std::tuple AmbientColor; // = (0.2, 0.2, 0.2) + std::tuple DiffuseColor; // = (0.8, 0.8, 0.8) + std::tuple SpecularColor; // = (1, 1, 1) + std::tuple TransmissionFilter; // = (1, 1, 1) + float OpticalDensity; // = 1 + float Alpha; // = 1 + float Shininess; // = 0 + int IlluminationModel; // = 0 }; struct FaceDefinition @@ -59,6 +116,9 @@ private: MaterialInfo* m_CurrentMaterial; void ParseMaterial(); + void ParseTextureMap(unsigned int line, std::stringstream &ss, std::string prefix, std::string arg, MaterialInfo::TextureMap &textureMap); + void ParseColorMap(unsigned int line, std::stringstream &ss, std::string prefix, std::string arg, MaterialInfo::ColorMap &textureMap); + void ParseBumpMap(unsigned int line, std::stringstream &ss, std::string prefix, std::string arg, MaterialInfo::BumpMap &textureMap); }; #endif // OBJ_h__ \ No newline at end of file