OBJ class for representing .obj files.
This commit is contained in:
@@ -0,0 +1,217 @@
|
||||
#include "OBJ.h"
|
||||
|
||||
OBJ::OBJ()
|
||||
{
|
||||
m_CurrentMaterial = nullptr;
|
||||
}
|
||||
|
||||
void OBJ::LoadFromFile(std::string filename)
|
||||
{
|
||||
m_Path = boost::filesystem::path(filename);
|
||||
LOG_INFO("Parsing .obj \"%s\"", m_Path.c_str());
|
||||
|
||||
// http://paulbourke.net/dataformats/obj/
|
||||
std::ifstream file(m_Path.string());
|
||||
|
||||
std::string line;
|
||||
while (std::getline(file, line)) {
|
||||
if (line.length() == 0)
|
||||
continue;
|
||||
|
||||
std::stringstream ss(line);
|
||||
|
||||
std::string prefix;
|
||||
ss >> prefix;
|
||||
|
||||
// Ignore comments
|
||||
if (prefix == "#")
|
||||
continue;
|
||||
|
||||
// Material files
|
||||
if (prefix == "mtllib") {
|
||||
std::string materialFilename;
|
||||
ss >> materialFilename;
|
||||
m_MaterialPath = m_Path.branch_path() / materialFilename;
|
||||
ParseMaterial();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Material statement
|
||||
if (prefix == "usemtl") {
|
||||
std::string material;
|
||||
ss >> material;
|
||||
m_CurrentMaterial = &Materials[material];
|
||||
continue;
|
||||
}
|
||||
|
||||
// Vertices
|
||||
if (prefix == "v") {
|
||||
float x, y, z;
|
||||
ss >> x >> y >> z;
|
||||
Vertices.push_back(std::make_tuple(x, y, z));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Normals
|
||||
if (prefix == "vn") {
|
||||
float x, y, z;
|
||||
ss >> x >> y >> z;
|
||||
Normals.push_back(std::make_tuple(x, y, z));
|
||||
}
|
||||
|
||||
// Texture coordinates
|
||||
if (prefix == "vt") {
|
||||
float u, v, w;
|
||||
ss >> u >> v >> w;
|
||||
TextureCoords.push_back(std::make_tuple(u, v, w));
|
||||
}
|
||||
|
||||
// Face definitions
|
||||
if (prefix == "f") {
|
||||
Face face;
|
||||
face.Material = m_CurrentMaterial;
|
||||
|
||||
std::string faceDefString;
|
||||
while (ss >> faceDefString) {
|
||||
std::stringstream ss2(faceDefString);
|
||||
FaceDefinition faceDef = { -1, -1, -1 };
|
||||
|
||||
ss2 >> faceDef.VertexIndex;
|
||||
ss2.ignore(); // Ignore first delimiter
|
||||
if (!ss2)
|
||||
continue;
|
||||
|
||||
if (ss2.peek() == '/') {
|
||||
ss2.ignore();
|
||||
ss2 >> faceDef.NormalIndex;
|
||||
} else {
|
||||
ss2 >> faceDef.TextureCoordIndex;
|
||||
ss2.ignore();
|
||||
ss2 >> faceDef.NormalIndex;
|
||||
}
|
||||
face.Definitions.push_back(faceDef);
|
||||
}
|
||||
Faces.push_back(face);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OBJ::ParseMaterial()
|
||||
{
|
||||
// http://paulbourke.net/dataformats/mtl/
|
||||
std::ifstream file(m_MaterialPath.string());
|
||||
|
||||
std::string currentMaterialName;
|
||||
MaterialInfo* currentMaterial = nullptr;
|
||||
|
||||
std::string line;
|
||||
while (std::getline(file, line)) {
|
||||
if (line.length() == 0)
|
||||
continue;
|
||||
|
||||
std::stringstream ss(line);
|
||||
|
||||
std::string prefix;
|
||||
ss >> prefix;
|
||||
|
||||
// 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,
|
||||
};
|
||||
|
||||
ss >> currentMaterialName;
|
||||
LOG_INFO("Parsing material %s", currentMaterialName);
|
||||
Materials[currentMaterialName] = mat;
|
||||
currentMaterial = &Materials[currentMaterialName];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!currentMaterial)
|
||||
continue;
|
||||
|
||||
// Ambient color
|
||||
if (prefix == "Ka") {
|
||||
float r, g, b;
|
||||
ss >> r >> g >> b;
|
||||
currentMaterial->AmbientColor = std::make_tuple(r, g, b);
|
||||
continue;
|
||||
}
|
||||
// Diffuse color
|
||||
if (prefix == "Kd") {
|
||||
float r, g, b;
|
||||
ss >> r >> g >> b;
|
||||
currentMaterial->DiffuseColor = std::make_tuple(r, g, b);
|
||||
continue;
|
||||
}
|
||||
// Specular color
|
||||
if (prefix == "Ks") {
|
||||
float r, g, b;
|
||||
ss >> r >> g >> b;
|
||||
currentMaterial->SpecularColor = std::make_tuple(r, g, b);
|
||||
continue;
|
||||
}
|
||||
// Transmission filter
|
||||
if (prefix == "Tf") {
|
||||
std::stringstream ss2;
|
||||
ss2 << ss.str();
|
||||
|
||||
std::string command;
|
||||
ss2 >> command;
|
||||
if (command == "xyz") {
|
||||
// TODO: "The "Ks xyz" statement specifies the specular reflectivity using CIEXYZ values."
|
||||
}
|
||||
else if (command == "spectral") {
|
||||
// TODO: "The "Tf spectral" statement specifies the transmission filter using a spectral curve."
|
||||
} else {
|
||||
float r, g, b;
|
||||
ss >> r;
|
||||
// G and B are optional
|
||||
if (!(ss >> g >> b))
|
||||
{
|
||||
g = r;
|
||||
b = r;
|
||||
}
|
||||
currentMaterial->TransmissionFilter = std::make_tuple(r, g, b);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// Optical density
|
||||
if (prefix == "Ni") {
|
||||
ss >> currentMaterial->OpticalDensity;
|
||||
continue;
|
||||
}
|
||||
// Alpha
|
||||
if (prefix == "d" || prefix == "Tr") {
|
||||
ss >> currentMaterial->Alpha;
|
||||
continue;
|
||||
}
|
||||
// Shininess
|
||||
if (prefix == "Ns") {
|
||||
ss >> currentMaterial->Shininess;
|
||||
continue;
|
||||
}
|
||||
// Illumination model
|
||||
if (prefix == "illum") {
|
||||
int illum = 0;
|
||||
ss >> illum;
|
||||
currentMaterial->IlluminationModel = illum;
|
||||
continue;
|
||||
}
|
||||
// Texture file
|
||||
// TODO:
|
||||
if (prefix == "map_Ka" || prefix == "map_Kd") {
|
||||
ss >> currentMaterial->TextureFile;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user