OBJ class for representing .obj files.
This commit is contained in:
@@ -104,6 +104,7 @@
|
|||||||
<ClCompile Include="GUIManager.cpp" />
|
<ClCompile Include="GUIManager.cpp" />
|
||||||
<ClCompile Include="MenuFrame.cpp" />
|
<ClCompile Include="MenuFrame.cpp" />
|
||||||
<ClCompile Include="Model.cpp" />
|
<ClCompile Include="Model.cpp" />
|
||||||
|
<ClCompile Include="OBJ.cpp" />
|
||||||
<ClCompile Include="Renderer.cpp" />
|
<ClCompile Include="Renderer.cpp" />
|
||||||
<ClCompile Include="ShaderProgram.cpp" />
|
<ClCompile Include="ShaderProgram.cpp" />
|
||||||
<ClCompile Include="Systems\CollisionSystem.cpp" />
|
<ClCompile Include="Systems\CollisionSystem.cpp" />
|
||||||
@@ -145,6 +146,7 @@
|
|||||||
<ClInclude Include="glerror.h" />
|
<ClInclude Include="glerror.h" />
|
||||||
<ClInclude Include="MenuFrame.h" />
|
<ClInclude Include="MenuFrame.h" />
|
||||||
<ClInclude Include="Model.h" />
|
<ClInclude Include="Model.h" />
|
||||||
|
<ClInclude Include="OBJ.h" />
|
||||||
<ClInclude Include="Renderer.h" />
|
<ClInclude Include="Renderer.h" />
|
||||||
<ClInclude Include="ShaderProgram.h" />
|
<ClInclude Include="ShaderProgram.h" />
|
||||||
<ClInclude Include="Systems\InputSystem.h" />
|
<ClInclude Include="Systems\InputSystem.h" />
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
<Filter>GUI</Filter>
|
<Filter>GUI</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="Camera.cpp" />
|
<ClCompile Include="Camera.cpp" />
|
||||||
|
<ClCompile Include="OBJ.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Component.h" />
|
<ClInclude Include="Component.h" />
|
||||||
@@ -142,6 +143,7 @@
|
|||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="GameWorld.h" />
|
<ClInclude Include="GameWorld.h" />
|
||||||
<ClInclude Include="Camera.h" />
|
<ClInclude Include="Camera.h" />
|
||||||
|
<ClInclude Include="OBJ.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="Shaders\Fragment.glsl">
|
<None Include="Shaders\Fragment.glsl">
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
#ifndef OBJ_h__
|
||||||
|
#define OBJ_h__
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
#include <tuple>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
|
#include "logging.h"
|
||||||
|
|
||||||
|
class OBJ
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct MaterialInfo
|
||||||
|
{
|
||||||
|
std::string TextureFile;
|
||||||
|
std::tuple<float, float, float> AmbientColor;
|
||||||
|
std::tuple<float, float, float> DiffuseColor;
|
||||||
|
std::tuple<float, float, float> SpecularColor;
|
||||||
|
std::tuple<float, float, float> TransmissionFilter;
|
||||||
|
float OpticalDensity;
|
||||||
|
float Alpha;
|
||||||
|
float Shininess;
|
||||||
|
int IlluminationModel;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FaceDefinition
|
||||||
|
{
|
||||||
|
int VertexIndex;
|
||||||
|
int TextureCoordIndex;
|
||||||
|
int NormalIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Face
|
||||||
|
{
|
||||||
|
std::vector<FaceDefinition> Definitions;
|
||||||
|
MaterialInfo* Material;
|
||||||
|
};
|
||||||
|
|
||||||
|
OBJ();
|
||||||
|
OBJ(std::string filename) { LoadFromFile(filename); }
|
||||||
|
|
||||||
|
std::vector<std::tuple<float, float, float>> Vertices;
|
||||||
|
std::vector<std::tuple<float, float, float>> Normals;
|
||||||
|
std::vector<std::tuple<float, float, float>> TextureCoords;
|
||||||
|
std::vector<Face> Faces;
|
||||||
|
std::map<std::string, MaterialInfo> Materials;
|
||||||
|
|
||||||
|
void LoadFromFile(std::string filename);
|
||||||
|
|
||||||
|
private:
|
||||||
|
boost::filesystem::path m_Path;
|
||||||
|
boost::filesystem::path m_MaterialPath;
|
||||||
|
MaterialInfo* m_CurrentMaterial;
|
||||||
|
|
||||||
|
void ParseMaterial();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // OBJ_h__
|
||||||
Reference in New Issue
Block a user