diff --git a/Makefile b/Makefile index fe7a16a..3344893 100644 --- a/Makefile +++ b/Makefile @@ -52,7 +52,8 @@ ALL_SRCS := $(IMGUI_SRCS) \ class/Shader.cpp \ class/Camera.cpp \ class/Scene.cpp \ - class/SceneParser.cpp + class/SceneParser.cpp \ + class/ObjParser.cpp SRCS := $(ALL_SRCS:%=$(SRCS_DIR)/%) OBJS := $(addprefix $(OBJS_DIR)/, $(SRCS:%.cpp=%.o)) diff --git a/includes/RT.hpp b/includes/RT.hpp index 15b6ee8..3c6a1a3 100644 --- a/includes/RT.hpp +++ b/includes/RT.hpp @@ -6,7 +6,7 @@ /* By: ycontre +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/09/27 14:52:10 by TheRed #+# #+# */ -/* Updated: 2025/01/08 17:44:56 by ycontre ### ########.fr */ +/* Updated: 2025/01/16 15:02:34 by tomoron ### ########.fr */ /* */ /* ************************************************************************** */ @@ -60,7 +60,8 @@ struct Vertex { # include "Shader.hpp" # include "Scene.hpp" # include "SceneParser.hpp" +# include "ObjParser.hpp" -#endif \ No newline at end of file +#endif diff --git a/includes/RT/ObjParser.hpp b/includes/RT/ObjParser.hpp new file mode 100644 index 0000000..b28b264 --- /dev/null +++ b/includes/RT/ObjParser.hpp @@ -0,0 +1,37 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ObjParser.hpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: tomoron +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/01/16 15:00:49 by tomoron #+# #+# */ +/* Updated: 2025/01/16 22:00:15 by tomoron ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef OBJPARSER_HPP +# define OBJPARSER_HPP + +#include "RT.hpp" + +class ObjParser +{ + public: + ObjParser(std::string &filename); + ~ObjParser(); + void parse(Scene &scene); + + private: + glm::vec3 getVertex(std::stringstream &line); + void addFace(std::stringstream &line, std::vector &vertices, int mat, Scene &scene); + long int checkVertexIndex(int index, size_t size); + void parseMtl(std::stringstream &line, std::map &materials, Scene &scene); + void addTriangleFromPolygon(std::vector &vertices, Scene &scene); + void addTriangle(glm::vec3 v1, glm::vec3 v2, glm::vec3 v3, int mat, Scene &scene); + + std::ifstream _file; + std::vector vertex; +}; + +#endif diff --git a/includes/RT/SceneParser.hpp b/includes/RT/SceneParser.hpp index 8eebb81..3fae29f 100644 --- a/includes/RT/SceneParser.hpp +++ b/includes/RT/SceneParser.hpp @@ -6,7 +6,7 @@ /* By: TheRed +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/12/26 21:37:37 by TheRed #+# #+# */ -/* Updated: 2025/01/15 12:34:11 by tomoron ### ########.fr */ +/* Updated: 2025/01/16 15:02:01 by tomoron ### ########.fr */ /* */ /* ************************************************************************** */ @@ -25,11 +25,6 @@ class SceneParser private: void parseMaterial(std::stringstream &line); void parseCamera(std::stringstream &line); - void parseObj(std::stringstream &line); - glm::vec3 getVertex(std::stringstream &line); - Triangle *getFace(std::stringstream &line, std::vector &vertices, int mat); - long int getVertexIndex(std::stringstream &line, size_t size); - void parseMtl(std::stringstream &line, std::map &materials); Scene *_scene; diff --git a/obj/Lowpoly_tree_sample.obj b/obj/Lowpoly_tree_sample.obj index 2e2928f..9c2c816 100644 --- a/obj/Lowpoly_tree_sample.obj +++ b/obj/Lowpoly_tree_sample.obj @@ -1,3 +1,7 @@ +# OBJ written from D:\Cloud\Projects\Personal\Turbosquid\Lowpoly_Trees\Publish_Sample\Lowpoly_tree_sample.obj +# Units meters + +o Tree_lp_11 v -0.524753 -0.707811 -1.37533 v -1.53072 -0.666692 -0.246043 v -0.906262 -0.661508 1.11465 @@ -989,6 +993,7 @@ vt 0.715921 0.408093 vt 0.487555 0.408093 mtllib obj/Lowpoly_tree_sample.mtl usemtl Bark +g Default f 7 8 14 13 f 9 15 14 8 f 10 16 15 9 diff --git a/srcs/class/ObjParser.cpp b/srcs/class/ObjParser.cpp new file mode 100644 index 0000000..d83055f --- /dev/null +++ b/srcs/class/ObjParser.cpp @@ -0,0 +1,218 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ObjParser.cpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: tomoron +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/01/16 15:00:33 by tomoron #+# #+# */ +/* Updated: 2025/01/16 22:00:46 by tomoron ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "RT.hpp" + +ObjParser::ObjParser(std::string &filename) +{ + _file.open(filename); + if(!_file.is_open()) + throw std::runtime_error("OBJ : could not open object file"); +} + +ObjParser::~ObjParser() +{ + _file.close(); +} + +glm::vec3 ObjParser::getVertex(std::stringstream &line) +{ + glm::vec3 res; + + if(!(line >> res.x >> res.y >> res.z)) + throw std::runtime_error("syntax error in obj file while parsing vertex"); + return(res); +} + +long int ObjParser::checkVertexIndex(int index, size_t size) +{ + if((size_t)index > size || index == 0 || (index < 0 && (size_t)(-index) > size)) + throw std::runtime_error("obj file error, invalid vertex index"); + if(index < 0) + index = size - index; + return(index - 1); +} + +//void ObjParser::isEar(glm::vec3 v1, glm::vec3 v2, glm::vec3 v3, std::vector &vertices) +//{ +// +//} + +void ObjParser::addTriangleFromPolygon(std::vector &vertices, Scene &scene) +{ + glm::vec3 normal; + glm::vec3 v1, v2 ,v3, v4; + + (void)scene; + for (size_t i = 0; i < vertices.size(); i++) + { + v1 = vertices[(i - 1) % vertices.size()]; + v2 = vertices[i]; + v3 = vertices[(i + 1) % vertices.size()]; + v4 = vertices[(i + 2) % vertices.size()]; + + normal = glm::normalize(glm::cross(v2 - v1, v3 - v1)); + std::cout << glm::to_string(normal) << std::endl; + + float dot = glm::dot(normal, v4 - v1); + std::cout << dot << std::endl; + //if(isEar(v1, v2 ,v3, vertices)) + //{ + // vertices.erase(vertices.begin() + i); + // scene.addObject(new Triangle(v1, v2 ,v3)); + //} + } + std::cout << std::endl; + std::cout << std::endl; + std::cout << std::endl; + std::cout << std::endl; +} + +void ObjParser::addFace(std::stringstream &line, std::vector &vertices, int mat, Scene &scene) +{ + int vert_index; + std::vector face_vertices; + + (void)mat; + (void)scene; + while((line >> vert_index)) + face_vertices.push_back(vertices[checkVertexIndex(vert_index, vertices.size())]); + if(face_vertices.size() < 3) + throw std::runtime_error("OBJ : face does not have enough vertices"); + + for(size_t i = 0; i < face_vertices.size(); i++) + std::cout << face_vertices[i].x << " " << face_vertices[i].y << " " << face_vertices[i].z << " | "; + std::cout << std::endl; + +// while(face_vertices.size() > 3) +// addTriangleFromPolygon(face_vertices, scene); + if(!line.eof()) + throw std::runtime_error("OBJ: an error occured while parsing face"); + addTriangle(face_vertices[0], face_vertices[1], face_vertices[2],mat, scene); +} + +void ObjParser::addTriangle(glm::vec3 v1, glm::vec3 v2, glm::vec3 v3, int mat, Scene &scene) +{ + scene.addObject(new Triangle(v1, v2, v3, mat)); +} + +void ObjParser::parseMtl(std::stringstream &input_line, std::map &materials, Scene &scene) +{ + std::string filename; + std::ifstream file; + std::string matName; + std::string identifier; + std::string line; + Material *mat; + + input_line >> filename; + file.open(filename); + mat = 0; + if(!file.is_open()) + throw std::runtime_error("OBJ : could not open material file"); + while(getline(file, line)) + { + if (line.empty() || line[0] == '#') + continue; + std::stringstream lineStream(line); + lineStream >> identifier; + if(identifier == "newmtl") + { + if(mat) + { + scene.addMaterial(mat); + materials[matName] = scene.getMaterialData().size() - 1; + } + lineStream >> matName; + if(matName.empty()) + throw std::runtime_error("OBJ: syntax error in material file, missing material name"); + mat = new Material; + memset(mat, 0, sizeof(Material)); + mat->metallic = 1.0f; + continue; + } + if(!mat) + throw std::runtime_error("OBJ: error in material file, material name not defined"); + if(identifier == "Kd") + { + if(!(lineStream >> mat->color.x >> mat->color.y >> mat->color.z)) + throw std::runtime_error("OBJ: syntax error while getting material color"); + } + else if(identifier == "Ns") + { + if(!(lineStream >> mat->roughness) || mat->roughness > 1000 || mat->roughness < 0) + throw std::runtime_error("OBJ: syntax error while getting material softness"); + mat->roughness /= 1000; + } + else if(identifier == "Ke") + { + float x, y, z; + if(!(lineStream >> x >> y >> z)) + throw std::runtime_error("OBJ: syntax error while getting material emission"); + mat->emission = (x + y + z) / 3; + } + else if(identifier == "Ni") + { + if(!(lineStream >> mat->refraction)) + throw std::runtime_error("OBJ: syntax error while getting material refraction"); + } + else + std::cerr << "unsupported material setting : " << identifier << std::endl; + } + if(mat) + { + scene.addMaterial(mat); + materials[matName] = scene.getMaterialData().size() - 1; + } + file.close(); +} + +void ObjParser::parse(Scene &scene) +{ + std::vector vertices; + std::string filename; + std::map matNames; + std::string line; + std::string identifier; + std::ifstream file; + int curMat; + + curMat = 0; + while (getline(_file, line)) + { + try{ + if(line[0] == '#' || line.empty()) + continue; + std::stringstream lineStream(line); + identifier = ""; + lineStream >> identifier; + if(identifier == "v") + vertices.push_back(getVertex(lineStream)); + else if (identifier == "f") + addFace(lineStream, vertices, curMat, scene); + else if (identifier == "mtllib") + parseMtl(lineStream, matNames, scene); + else if (identifier == "usemtl") + { + lineStream >> identifier; + if(matNames.find(identifier) == matNames.end()) + throw std::runtime_error("OBJ: invalid material name"); + curMat = matNames[identifier]; + } + }catch (std::exception &e) + { + std::cerr << line << std::endl; + throw; + } + } +} + diff --git a/srcs/class/SceneParser.cpp b/srcs/class/SceneParser.cpp index 0b0da61..83c62ed 100644 --- a/srcs/class/SceneParser.cpp +++ b/srcs/class/SceneParser.cpp @@ -6,7 +6,7 @@ /* By: ycontre +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/12/26 21:43:51 by TheRed #+# #+# */ -/* Updated: 2025/01/15 19:52:51 by ycontre ### ########.fr */ +/* Updated: 2025/01/16 15:17:10 by tomoron ### ########.fr */ /* */ /* ************************************************************************** */ @@ -95,152 +95,6 @@ void SceneParser::parseCamera(std::stringstream &line) } -glm::vec3 SceneParser::getVertex(std::stringstream &line) -{ - glm::vec3 res; - - if(!(line >> res.x >> res.y >> res.z)) - throw std::runtime_error("syntax error in obj file while parsing vertex"); - return(res); -} - -long int SceneParser::getVertexIndex(std::stringstream &line, size_t size) -{ - long int index; - - if(!(line >> index)) - throw std::runtime_error("syntax error in obj file while parsing face"); - if((size_t)index > size || index == 0 || (index < 0 && (size_t)(-index) > size)) - throw std::runtime_error("obj file error, invalid vertex index"); - if(index < 0) - index = size - index; - return(index - 1); -} - -Triangle *SceneParser::getFace(std::stringstream &line, std::vector &vertices, int mat) -{ - glm::vec3 triangle[3]; - - triangle[0] = vertices[getVertexIndex(line, vertices.size())]; - triangle[1] = vertices[getVertexIndex(line, vertices.size())]; - triangle[2] = vertices[getVertexIndex(line, vertices.size())]; - return (new Triangle(triangle[0], triangle[1], triangle[2], mat)); -} - -void SceneParser::parseMtl(std::stringstream &input_line, std::map &materials) -{ - std::string filename; - std::ifstream file; - std::string matName; - std::string identifier; - std::string line; - Material *mat; - - input_line >> filename; - file.open(filename); - mat = 0; - if(!file.is_open()) - throw std::runtime_error("OBJ : could not open material file"); - while(getline(file, line)) - { - if (line.empty() || line[0] == '#') - continue; - std::stringstream lineStream(line); - lineStream >> identifier; - if(identifier == "newmtl") - { - if(mat) - { - _scene->addMaterial(mat); - materials[matName] = _scene->getMaterialData().size() - 1; - } - lineStream >> matName; - if(matName.empty()) - throw std::runtime_error("OBJ: syntax error in material file, missing material name"); - mat = new Material; - memset(mat, 0, sizeof(Material)); - mat->metallic = 1.0f; - continue; - } - if(!mat) - throw std::runtime_error("OBJ: error in material file, material name not defined"); - if(identifier == "Kd") - { - if(!(lineStream >> mat->color.x >> mat->color.y >> mat->color.z)) - throw std::runtime_error("OBJ: syntax error while getting material color"); - } - else if(identifier == "Ns") - { - if(!(lineStream >> mat->roughness) || mat->roughness > 1000 || mat->roughness < 0) - throw std::runtime_error("OBJ: syntax error while getting material softness"); - mat->roughness /= 1000; - } - else if(identifier == "Ke") - { - float x, y, z; - if(!(lineStream >> x >> y >> z)) - throw std::runtime_error("OBJ: syntax error while getting material emission"); - mat->emission = (x + y + z) / 3; - } - else if(identifier == "Ni") - { - if(!(lineStream >> mat->refraction)) - throw std::runtime_error("OBJ: syntax error while getting material refraction"); - } - else - std::cerr << "unsupported material setting : " << identifier << std::endl; - } - if(mat) - { - _scene->addMaterial(mat); - materials[matName] = _scene->getMaterialData().size() - 1; - } -} - -void SceneParser::parseObj(std::stringstream &objInfo) -{ - std::vector vertices; - std::string filename; - std::map matNames; - std::string line; - std::string identifier; - std::ifstream file; - int curMat; - - objInfo >> filename; - file.open(filename); - curMat = 0; - if (!file.is_open()) - throw std::runtime_error("OBJ : could not open object file"); - while (getline(file, line)) - { - try{ - if(line[0] == '#' || line.empty()) - continue; - std::stringstream lineStream(line); - identifier = ""; - lineStream >> identifier; - if(identifier == "v") - vertices.push_back(getVertex(lineStream)); - else if (identifier == "f") - _scene->addObject(getFace(lineStream, vertices, curMat)); - else if (identifier == "mtllib") - parseMtl(lineStream, matNames); - else if (identifier == "usemtl") - { - lineStream >> identifier; - if(matNames.find(identifier) == matNames.end()) - throw std::runtime_error("OBJ: invalid material name"); - curMat = matNames[identifier]; - } - }catch (std::exception &e) - { - std::cerr << line << std::endl; - throw; - } - } -} - bool SceneParser::parseLine(const std::string &line) { if (line.empty() || line[0] == '#') @@ -274,7 +128,11 @@ bool SceneParser::parseLine(const std::string &line) else if (identifier == "CAM") this->parseCamera(ss); else if (identifier == "OBJ") - parseObj(ss); + { + ss >> identifier; + ObjParser obj(identifier); + obj.parse(*_scene); + } } catch (const std::exception& e) {