Extended OBJ loader to parse specular and normal maps
This commit is contained in:
+1
-1
@@ -18,7 +18,7 @@ Model::Model(OBJ &obj, ResourceManager* rm)
|
|||||||
{
|
{
|
||||||
currentMaterial = face.Material;
|
currentMaterial = face.Material;
|
||||||
// Load texture
|
// Load texture
|
||||||
auto texture = std::shared_ptr<Texture>(rm->Load<Texture>("Texture", currentMaterial->TextureFile));
|
auto texture = std::shared_ptr<Texture>(rm->Load<Texture>("Texture", currentMaterial->DiffuseTexture.FileName));
|
||||||
// TODO: Load material parameters
|
// TODO: Load material parameters
|
||||||
// Create new texture group (start index of new group is upcoming index)
|
// Create new texture group (start index of new group is upcoming index)
|
||||||
TextureGroup texGroup = { texture, index, index };
|
TextureGroup texGroup = { texture, index, index };
|
||||||
|
|||||||
+172
-19
@@ -126,9 +126,11 @@ void OBJ::ParseMaterial()
|
|||||||
std::string currentMaterialName;
|
std::string currentMaterialName;
|
||||||
MaterialInfo* currentMaterial = nullptr;
|
MaterialInfo* currentMaterial = nullptr;
|
||||||
|
|
||||||
|
unsigned int currentLine = 0;
|
||||||
std::string line;
|
std::string line;
|
||||||
while (std::getline(file, line))
|
while (std::getline(file, line))
|
||||||
{
|
{
|
||||||
|
currentLine++;
|
||||||
if (line.length() == 0)
|
if (line.length() == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -140,19 +142,7 @@ void OBJ::ParseMaterial()
|
|||||||
// Create a new material definition
|
// Create a new material definition
|
||||||
if (prefix == "newmtl")
|
if (prefix == "newmtl")
|
||||||
{
|
{
|
||||||
MaterialInfo mat =
|
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,
|
|
||||||
};
|
|
||||||
|
|
||||||
ss >> currentMaterialName;
|
ss >> currentMaterialName;
|
||||||
LOG_INFO("Parsing material %s", currentMaterialName.c_str());
|
LOG_INFO("Parsing material %s", currentMaterialName.c_str());
|
||||||
Materials[currentMaterialName] = mat;
|
Materials[currentMaterialName] = mat;
|
||||||
@@ -243,14 +233,177 @@ void OBJ::ParseMaterial()
|
|||||||
currentMaterial->IlluminationModel = illum;
|
currentMaterial->IlluminationModel = illum;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Texture file
|
// Diffuse texture
|
||||||
// TODO:
|
if (prefix == "map_Kd")
|
||||||
if (prefix == "map_Ka" || prefix == "map_Kd")
|
|
||||||
{
|
{
|
||||||
std::string textureFile;
|
MaterialInfo::ColorMap colorMap;
|
||||||
ss >> textureFile;
|
|
||||||
currentMaterial->TextureFile = (m_MaterialPath.branch_path() / textureFile).string();
|
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;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,21 +10,78 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
class OBJ
|
class OBJ
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct MaterialInfo
|
struct MaterialInfo
|
||||||
{
|
{
|
||||||
std::string TextureFile;
|
struct TextureMap
|
||||||
std::tuple<float, float, float> AmbientColor;
|
{
|
||||||
std::tuple<float, float, float> DiffuseColor;
|
TextureMap()
|
||||||
std::tuple<float, float, float> SpecularColor;
|
: blendu(true)
|
||||||
std::tuple<float, float, float> TransmissionFilter;
|
, blendv(true)
|
||||||
float OpticalDensity;
|
, clamp(false)
|
||||||
float Alpha;
|
, o(std::make_tuple(0.f, 0.f, 0.f))
|
||||||
float Shininess;
|
, s(std::make_tuple(1.f, 1.f, 1.f)) { }
|
||||||
int IlluminationModel;
|
|
||||||
|
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<float, float, float> o; // = (0, 0, 0)
|
||||||
|
// Scale
|
||||||
|
std::tuple<float, float, float> 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<float, float, float> AmbientColor; // = (0.2, 0.2, 0.2)
|
||||||
|
std::tuple<float, float, float> DiffuseColor; // = (0.8, 0.8, 0.8)
|
||||||
|
std::tuple<float, float, float> SpecularColor; // = (1, 1, 1)
|
||||||
|
std::tuple<float, float, float> TransmissionFilter; // = (1, 1, 1)
|
||||||
|
float OpticalDensity; // = 1
|
||||||
|
float Alpha; // = 1
|
||||||
|
float Shininess; // = 0
|
||||||
|
int IlluminationModel; // = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FaceDefinition
|
struct FaceDefinition
|
||||||
@@ -59,6 +116,9 @@ private:
|
|||||||
MaterialInfo* m_CurrentMaterial;
|
MaterialInfo* m_CurrentMaterial;
|
||||||
|
|
||||||
void ParseMaterial();
|
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__
|
#endif // OBJ_h__
|
||||||
Reference in New Issue
Block a user