diff --git a/.vscode/settings.json b/.vscode/settings.json index 805bf82..be8ca90 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -70,6 +70,7 @@ "ratio": "cpp", "iomanip": "cpp", "numbers": "cpp", - "cinttypes": "cpp" + "cinttypes": "cpp", + "fstream": "cpp" } } \ No newline at end of file diff --git a/Makefile b/Makefile index 9aca9ef..0763ec4 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,8 @@ ALL_SRCS := RT.cpp gl.cpp \ class/Window.cpp \ class/Shader.cpp \ class/Camera.cpp \ - class/Scene.cpp + class/Scene.cpp \ + class/SceneParser.cpp SRCS := $(ALL_SRCS:%=$(SRCS_DIR)/%) OBJS := $(addprefix $(OBJS_DIR)/, $(SRCS:%.cpp=%.o)) diff --git a/includes/RT.hpp b/includes/RT.hpp index 19b56fe..14501c8 100644 --- a/includes/RT.hpp +++ b/includes/RT.hpp @@ -24,7 +24,11 @@ # include "GLFW/glfw3.h" # include +# include +# include +# include # include +# include struct Vertex { glm::vec2 position; @@ -38,6 +42,7 @@ struct Vertex { # include "Window.hpp" # include "Shader.hpp" # include "Scene.hpp" +# include "SceneParser.hpp" diff --git a/includes/RT/Object.hpp b/includes/RT/Object.hpp index 9e94d89..4a734f9 100644 --- a/includes/RT/Object.hpp +++ b/includes/RT/Object.hpp @@ -39,7 +39,7 @@ class Object SPHERE, }; - virtual Type getType() const = 0; + virtual Type getType() const = 0; }; #endif \ No newline at end of file diff --git a/includes/RT/Scene.hpp b/includes/RT/Scene.hpp index ca134af..a88f77a 100644 --- a/includes/RT/Scene.hpp +++ b/includes/RT/Scene.hpp @@ -36,17 +36,20 @@ class Scene Scene(); ~Scene(); - Camera *getCamera(void) const; + bool parseScene(char *name); + void addObject(Object *object); void updateGPUData(); - const std::vector& getGPUData() const; + + const std::vector &getGPUData() const; + Camera *getCamera(void) const; private: - std::vector _objects; - std::vector _gpuObjects; + std::vector _objects; + std::vector _gpu_objects; - Camera *_camera; + Camera *_camera; }; #endif \ No newline at end of file diff --git a/includes/RT/SceneParser.hpp b/includes/RT/SceneParser.hpp new file mode 100644 index 0000000..2e3eded --- /dev/null +++ b/includes/RT/SceneParser.hpp @@ -0,0 +1,31 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* SceneParser.hpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: TheRed +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/12/26 21:37:37 by TheRed #+# #+# */ +/* Updated: 2024/12/26 21:37:37 by TheRed ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef RT_SceneParser__HPP +# define RT_SceneParser__HPP + +# include "RT.hpp" + +class SceneParser +{ + public: + SceneParser(Scene *scene); + + bool parseLine(const std::string &line); + + private: + Scene *_scene; + + std::map> object_parsers; +}; + +#endif \ No newline at end of file diff --git a/includes/RT/Window.hpp b/includes/RT/Window.hpp index 210f15e..6178a5b 100644 --- a/includes/RT/Window.hpp +++ b/includes/RT/Window.hpp @@ -20,11 +20,10 @@ class Scene; class Window { public: - Window(int width, int height, const char *title, int sleep); + Window(Scene *scene, int width, int height, const char *title, int sleep); ~Window(void); GLFWwindow *getWindow(void) const; - Scene *getScene(void) const; float getFps(void) const; void display(); diff --git a/includes/RT/objects/Sphere.hpp b/includes/RT/objects/Sphere.hpp index 28d5d4e..b4f2fcb 100644 --- a/includes/RT/objects/Sphere.hpp +++ b/includes/RT/objects/Sphere.hpp @@ -17,15 +17,59 @@ class Sphere : public Object { + public: + struct ParseError : public std::runtime_error + { + ParseError(const std::string& msg) : std::runtime_error("Sphere parse error: " + msg) {} + }; + + Sphere(std::stringstream &line) : Object(glm::vec3(0.0f), nullptr) + { + _mat = new Material; + + try { + float x, y, z, radius; + float r, g, b, rough, spec; + + if (!(line >> x >> y >> z >> radius)) + throw std::invalid_argument("Missing position or radius values"); + + if (radius <= 0.0f) + throw std::invalid_argument("Radius must be positive"); + + if (!(line >> r >> g >> b >> rough >> spec)) + throw std::invalid_argument("Missing material properties"); + + if (r < 0.0f || r > 255.0f || g < 0.0f || g > 255.0f || b < 0.0f || b > 255.0f) + throw std::invalid_argument("Color values must be between 0 and 255"); + + if (rough < 0.0f || rough > 1.0f) + throw std::invalid_argument("Roughness must be between 0 and 1"); + + if (spec < 0.0f || spec > 1.0f) + throw std::invalid_argument("Specular must be between 0 and 1"); + + _position = glm::vec3(x, y, z); + _radius = radius; + + _mat->color = glm::vec3(r / 255.0f, g / 255.0f, b / 255.0f); + _mat->roughness = rough; + _mat->specular = spec; + + _material = _mat; + } + catch (const std::exception& e) { throw; } + } Sphere(const glm::vec3& position, float radius, const Material *material) : Object(position, material), _radius(radius) {} - float getRadius() const { return (_radius); } - Type getType() const override { return Type::SPHERE; } + float getRadius() const { return (_radius); } + Type getType() const override { return Type::SPHERE; } private: - float _radius; + Material *_mat; + float _radius; }; #endif \ No newline at end of file diff --git a/scenes/test.rt b/scenes/test.rt new file mode 100644 index 0000000..cfd25b8 --- /dev/null +++ b/scenes/test.rt @@ -0,0 +1,4 @@ + +sp 0 -1 -6 2.0 255 255 255 0.0 0.0 + +R 1.0 -2.0 10 diff --git a/srcs/RT.cpp b/srcs/RT.cpp index 49d85dc..51eba2a 100644 --- a/srcs/RT.cpp +++ b/srcs/RT.cpp @@ -12,26 +12,29 @@ #include "RT.hpp" -int main(void) +int main(int argc, char **argv) { - Window window(WIDTH, HEIGHT, "RT_GPU", 1); + Scene scene; + + if (argc > 1 && !scene.parseScene(argv[1])) + return (1); + + Window window(&scene, WIDTH, HEIGHT, "RT_GPU", 1); Shader shader("shaders/vertex.vert", "shaders/frag.frag", "shaders/compute.glsl"); - Material redMaterial = {glm::vec3(1.0f, 0.2f, 0.2f), 1.0, 1.0}; - float radius = 30.0f; - for (int i = 0; i < 150; i++) { - float angle = (2.0f * M_PI * i) / 150.0f; - float x = radius * cos(angle); - float z = radius * sin(angle); - - float y = 2.0f * sin(angle * 3.0f); - - glm::vec3 position(x, y, z); - float sphereSize = 0.8f + 0.4f * sin(angle * 2.0f); - - window.getScene()->addObject(new Sphere(position, sphereSize, &redMaterial)); - } + // Material redMaterial = {glm::vec3(1.0f, 0.2f, 0.2f), 1.0, 1.0}; + + // for (int i = 0; i < 150; i++) + // { + // float angle = (2.0f * M_PI * i) / 150.0f; + // float x = 30.0f * cos(angle); + // float z = 30.0f * sin(angle); + // float y = 2.0f * sin(angle * 3.0f); + // glm::vec3 position(x, y, z); + // float sphereSize = 0.8f + 0.4f * sin(angle * 2.0f); + // scene.addObject(new Sphere(position, sphereSize, &redMaterial)); + // } GLuint objectSSBO; glGenBuffers(1, &objectSSBO); @@ -40,16 +43,13 @@ int main(void) Vertex vertices[3] = {{{-1.0f, -1.0f}, {0.0f, 0.0f}},{{3.0f, -1.0f}, {2.0f, 0.0f}},{{-1.0f, 3.0f}, {0.0f, 2.0f}}}; size_t size = sizeof(vertices) / sizeof(Vertex) / 3; - shader.setupVertexBuffer(vertices, size); while (!window.shouldClose()) { glUseProgram(shader.getProgramCompute()); - const std::vector &gpu_data = window.getScene()->getGPUData(); - - window.getScene()->updateGPUData(); + const std::vector &gpu_data = scene.getGPUData(); // Update SSBO with latest object data glBindBuffer(GL_SHADER_STORAGE_BUFFER, objectSSBO); @@ -58,8 +58,8 @@ int main(void) shader.set_int("u_objectsNum", gpu_data.size()); shader.set_vec2("u_resolution", glm::vec2(WIDTH, HEIGHT)); - shader.set_vec3("u_cameraPosition", window.getScene()->getCamera()->get_position()); - shader.set_mat4("u_viewMatrix", window.getScene()->getCamera()->get_view_matrix()); + shader.set_vec3("u_cameraPosition", scene.getCamera()->get_position()); + shader.set_mat4("u_viewMatrix", scene.getCamera()->get_view_matrix()); glDispatchCompute((WIDTH + 15) / 16, (HEIGHT + 15) / 16, 1); glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); @@ -67,7 +67,6 @@ int main(void) glClear(GL_COLOR_BUFFER_BIT); glUseProgram(shader.getProgram()); - shader.drawTriangles(size); std::cout << "\rFPS: " << int(window.getFps()) << " " << std::flush; diff --git a/srcs/class/Scene.cpp b/srcs/class/Scene.cpp index d692a59..b4a7610 100644 --- a/srcs/class/Scene.cpp +++ b/srcs/class/Scene.cpp @@ -22,40 +22,71 @@ Scene::~Scene() delete (_camera); } -Camera *Scene::getCamera(void) const +bool Scene::parseScene(char *name) { - return (_camera); + std::ifstream file(name); + std::string line; + + if (!file.is_open()) + { + std::cout << "Error opening the file" << std::endl; + file.close(); + return (false); + } + + SceneParser scene_parser(this); + + while (std::getline(file, line)) + { + if (!scene_parser.parseLine(line)) + { + std::cerr << line << std::endl; + file.close(); + return (false); + } + } + file.close(); + return (true); } + void Scene::addObject(Object *object) { _objects.push_back(object); - this->updateGPUData(); } void Scene::updateGPUData() { - _gpuObjects.clear(); + + _gpu_objects.clear(); for (const auto& obj : _objects) { - GPUObject gpuObj; - gpuObj.position = obj->getPosition(); - gpuObj.color = obj->getMaterial()->color; - gpuObj.roughness = obj->getMaterial()->roughness; - gpuObj.specular = obj->getMaterial()->specular; - gpuObj.type = static_cast(obj->getType()); + GPUObject gpu_obj; + gpu_obj.position = obj->getPosition(); + gpu_obj.color = obj->getMaterial()->color; + gpu_obj.roughness = obj->getMaterial()->roughness; + gpu_obj.specular = obj->getMaterial()->specular; + gpu_obj.type = static_cast(obj->getType()); - if (obj->getType() == Object::Type::SPHERE) { + if (obj->getType() == Object::Type::SPHERE) + { auto sphere = static_cast(obj); - gpuObj.radius = sphere->getRadius(); + gpu_obj.radius = sphere->getRadius(); } - _gpuObjects.push_back(gpuObj); + std::cout << gpu_obj.position.x << " " << gpu_obj.position.y << " " << gpu_obj.position.z << " " << gpu_obj.radius << " " << gpu_obj.roughness << " " << gpu_obj.specular << std::endl; + + _gpu_objects.push_back(gpu_obj); } } const std::vector& Scene::getGPUData() const { - return (_gpuObjects); + return (_gpu_objects); +} + +Camera *Scene::getCamera(void) const +{ + return (_camera); } \ No newline at end of file diff --git a/srcs/class/SceneParser.cpp b/srcs/class/SceneParser.cpp new file mode 100644 index 0000000..fe047a0 --- /dev/null +++ b/srcs/class/SceneParser.cpp @@ -0,0 +1,47 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* SceneParser.cpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: TheRed +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/12/26 21:43:51 by TheRed #+# #+# */ +/* Updated: 2024/12/26 21:43:51 by TheRed ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "SceneParser.hpp" + +SceneParser::SceneParser(Scene *scene) : _scene(scene) +{ + object_parsers["sp"] = [](std::stringstream& ss) -> Object* + { + try { return (new Sphere(ss)); } + catch (const std::exception& e) { throw; } + }; +} + +bool SceneParser::parseLine(const std::string &line) +{ + if (line.empty() || line[0] == '#') + return (true); + + std::stringstream ss(line); + std::string identifier; + + ss >> identifier; + + auto it = object_parsers.find(identifier); + if (it != object_parsers.end()) + { + try { + Object *obj = it->second(ss); + _scene->addObject(obj); + } catch (const std::exception& e) { + std::cerr << "Error parsing sphere: " << e.what() << std::endl; + return false; + } + } + + return (true); +} \ No newline at end of file diff --git a/srcs/class/Window.cpp b/srcs/class/Window.cpp index 31d4113..7cf179c 100644 --- a/srcs/class/Window.cpp +++ b/srcs/class/Window.cpp @@ -12,10 +12,10 @@ #include "Window.hpp" -Window::Window(int width, int height, const char *title, int sleep) +Window::Window(Scene *scene, int width, int height, const char *title, int sleep) { - _scene = new Scene(); - + _scene = scene; + if (!glfwInit()) { fprintf( stderr, "Failed to initialize GLFW\n" ); @@ -130,11 +130,6 @@ GLFWwindow *Window::getWindow(void) const return (_window); } -Scene *Window::getScene(void) const -{ - return (_scene); -} - float Window::getFps(void) const { return (_fps);