diff --git a/libs/Prism/include/Prism.hpp b/libs/Prism/include/Prism.hpp index 18ee04d..d17f727 100644 --- a/libs/Prism/include/Prism.hpp +++ b/libs/Prism/include/Prism.hpp @@ -1,16 +1,16 @@ +#include "Prism/Colormap.hpp" +#include "Prism/ObjReader.hpp" #include "Prism/camera.hpp" #include "Prism/color.hpp" #include "Prism/material.hpp" #include "Prism/matrix.hpp" +#include "Prism/mesh.hpp" #include "Prism/objects.hpp" #include "Prism/plane.hpp" #include "Prism/point.hpp" #include "Prism/ray.hpp" #include "Prism/scene.hpp" #include "Prism/sphere.hpp" +#include "Prism/triangle.hpp" #include "Prism/utils.hpp" #include "Prism/vector.hpp" -#include "Prism/triangle.hpp" -#include "Prism/ObjReader.hpp" -#include "Prism/Colormap.hpp" -#include "Prism/mesh.hpp" \ No newline at end of file diff --git a/libs/Prism/include/Prism/Colormap.hpp b/libs/Prism/include/Prism/Colormap.hpp index 671986a..62dbcd7 100644 --- a/libs/Prism/include/Prism/Colormap.hpp +++ b/libs/Prism/include/Prism/Colormap.hpp @@ -8,7 +8,7 @@ Classe de leitura de arquivos .mtl, que guarda cores e propriedades de materiais A saber que: - kd = Difuso (Cor do objeto) - ks = Specular (Reflexivo) - - ke = Emissivo + - ke = Emissivo - ka = Ambiente - ns = Brilho - ni = Índice de refração @@ -17,26 +17,26 @@ A saber que: A classe precisa ser instânciada passando o caminho do arquivo .mtl correspondente */ -#include -#include -#include -#include -#include -#include -#include "Prism/vector.hpp" #include "Prism/material.hpp" +#include "Prism/vector.hpp" #include "prism_export.h" +#include +#include +#include +#include +#include +#include using namespace std; -namespace Prism{ +namespace Prism { class colormap { -public: + public: map mp; - //Construtor + // Construtor colormap(){}; - colormap(string input){ + colormap(string input) { // construtor: lê arquivo cores.mtl e guarda valores RGB associados a cada nome @@ -94,16 +94,16 @@ class colormap { mtlFile.close(); } - Vector3 getColor(string& s){ + Vector3 getColor(string& s) { if (mp.find(s) != mp.end()) { return Vector3(mp[s].color.r, mp[s].color.g, mp[s].color.b); } else { cerr << "Error: cor " << s << " indefinida no arquivo .mtl\n"; - return Vector3(0,0,0); + return Vector3(0, 0, 0); } } - Material getMaterial(string& s){ + Material getMaterial(string& s) { if (mp.find(s) != mp.end()) { return mp[s]; } else { @@ -111,7 +111,6 @@ class colormap { return Material(); } } - }; -} +} // namespace Prism #endif diff --git a/libs/Prism/include/Prism/ObjReader.hpp b/libs/Prism/include/Prism/ObjReader.hpp index 62ce364..949dccb 100644 --- a/libs/Prism/include/Prism/ObjReader.hpp +++ b/libs/Prism/include/Prism/ObjReader.hpp @@ -1,19 +1,19 @@ #ifndef PRISM_OBJREADER_HPP_ #define PRISM_OBJREADER_HPP_ -#include -#include -#include -#include -#include -#include -#include -#include "Prism/vector.hpp" -#include "Prism/point.hpp" #include "Prism/Colormap.hpp" -#include "Prism/triangle.hpp" #include "Prism/material.hpp" +#include "Prism/point.hpp" +#include "Prism/triangle.hpp" +#include "Prism/vector.hpp" #include "prism_export.h" +#include +#include +#include +#include +#include +#include +#include namespace Prism { @@ -22,15 +22,13 @@ class ObjReader { std::shared_ptr curMaterial; std::vector> vertices; std::vector> triangles; - ObjReader(const std::string& filename) { file.open(filename); if (!file.is_open()) { std::cerr << "Erro ao abrir o arquivo: " << filename << std::endl; return; - } - + } std::string line, mtlfile, colorname, filename_mtl; while (std::getline(file, line)) { @@ -47,14 +45,12 @@ class ObjReader { iss >> colorname; auto mtlProps = cmap.getMaterial(colorname); curMaterial = std::make_shared( - Color(mtlProps.color.r, mtlProps.color.g, mtlProps.color.b), - mtlProps.ka, mtlProps.ks, mtlProps.ke, - mtlProps.ns, mtlProps.ni, mtlProps.d - ); + Color(mtlProps.color.r, mtlProps.color.g, mtlProps.color.b), mtlProps.ka, + mtlProps.ks, mtlProps.ke, mtlProps.ns, mtlProps.ni, mtlProps.d); } else if (prefix == "v") { double x, y, z; iss >> x >> y >> z; - vertices.push_back({x,y,z}); + vertices.push_back({x, y, z}); } else if (prefix == "f") { unsigned int vi[3], ni[3]; char slash; @@ -71,9 +67,9 @@ class ObjReader { file.close(); } - private: - std::ifstream file; - colormap cmap; + private: + std::ifstream file; + colormap cmap; // /** // * @brief Prints each triangle’s vertices to the console @@ -82,9 +78,10 @@ class ObjReader { // int i = 0; // for (const auto& tri : triangles) { // std::clog << "Face " << (++i) << ": "; - // std::cout << "(" << tri.getPoint1().x << ", " << tri.getPoint1().y << ", " << tri.getPoint1().z << ") "; - // std::cout << "(" << tri.getPoint2().x << ", " << tri.getPoint2().y << ", " << tri.getPoint2().z << ") "; - // std::cout << "(" << tri.getPoint3().x << ", " << tri.getPoint3().y << ", " << tri.getPoint3().z << ") "; + // std::cout << "(" << tri.getPoint1().x << ", " << tri.getPoint1().y << ", " << + // tri.getPoint1().z << ") "; std::cout << "(" << tri.getPoint2().x << ", " << + // tri.getPoint2().y << ", " << tri.getPoint2().z << ") "; std::cout << "(" << + // tri.getPoint3().x << ", " << tri.getPoint3().y << ", " << tri.getPoint3().z << ") "; // std::cout << std::flush; // std::clog << std::endl; // } diff --git a/libs/Prism/include/Prism/camera.hpp b/libs/Prism/include/Prism/camera.hpp index 215673b..1119b3b 100644 --- a/libs/Prism/include/Prism/camera.hpp +++ b/libs/Prism/include/Prism/camera.hpp @@ -1,10 +1,10 @@ #ifndef PRISM_CAMERA_HPP_ #define PRISM_CAMERA_HPP_ +#include "Prism/matrix.hpp" #include "Prism/point.hpp" #include "Prism/ray.hpp" #include "Prism/vector.hpp" -#include "Prism/matrix.hpp" #include "prism_export.h" #include #include @@ -29,10 +29,25 @@ class PRISM_EXPORT Camera { * @param image_height The height of the image in pixels. * @param image_width The width of the image in pixels. */ - Camera(const Point3& position, const Point3& target, const Vector3& upvec, - double distance, double viewport_height, double viewport_width, - int image_height, int image_width); + Camera(const Point3& position, const Point3& target, const Vector3& upvec, double distance, + double viewport_height, double viewport_width, int image_height, int image_width); + /** + * @brief Constructs a Camera with default parameters. + * This constructor initializes the camera at the origin, looking down the negative z-axis, + * with the up vector pointing in the positive y direction. + */ + Camera() + : Camera(Point3(0, 0, 0), Point3(0, 0, -1), Vector3(0, 1, 0), 1.0, 1.0, 1.0, 480, 640) { + } + + /** + * @class CameraIterator + * @brief An iterator for traversing the pixels of the camera's view. + * + * This iterator allows iteration over the rays that correspond to each pixel in the camera's + * view. It provides a way to access each pixel's ray in a forward manner. + */ class CameraIterator { public: using iterator_category = std::forward_iterator_tag; @@ -41,9 +56,19 @@ class PRISM_EXPORT Camera { using pointer = Ray*; using reference = Ray&; + /** + * @brief Constructs a CameraIterator for the given camera, starting at pixel (y, x). + * @param cam Pointer to the Camera object. + * @param y The starting row (y-coordinate) of the pixel. + * @param x The starting column (x-coordinate) of the pixel. + */ CameraIterator(const Camera* cam, int y, int x) : camera(cam), current_y(y), current_x(x) { } + /** + * @brief Dereferences the iterator to get the Ray corresponding to the current pixel. + * @return A Ray object representing the ray for the current pixel. + */ Ray operator*() const { Point3 pixel_center = camera->pixel_00_loc + (camera->pixel_delta_u * current_x) - (camera->pixel_delta_v * current_y); @@ -51,6 +76,10 @@ class PRISM_EXPORT Camera { return Ray(camera->pos, pixel_center); } + /** + * @brief Post-increment operator to move the iterator to the next pixel. + * @return A reference to the updated CameraIterator. + */ CameraIterator& operator++() { current_x++; if (current_x >= camera->pixel_width) { @@ -60,47 +89,60 @@ class PRISM_EXPORT Camera { return *this; } + /** + * @brief Difference operator to compare two CameraIterator objects. + * @param other The other CameraIterator to compare with. + * @return True if the current iterator is not equal to the other, false otherwise. + */ bool operator!=(const CameraIterator& other) const { return current_y != other.current_y || current_x != other.current_x; } private: - const Camera* camera; - int current_y; - int current_x; + const Camera* camera; ///< Pointer to the Camera object being iterated over + int current_y; ///< Current row (y-coordinate) of the pixel + int current_x; ///< Current column (x-coordinate) of the pixel }; - CameraIterator begin() { - return CameraIterator(this, 0, 0); - } - CameraIterator end() { - return CameraIterator(this, pixel_height, 0); - } - + /** + * @brief Returns a const iterator to the beginning of the camera's pixel rays. + * @return A CameraIterator pointing to the first pixel ray. + * + * This function allows iteration over the rays corresponding to each pixel + * in the camera's view. It works for both const and non-const Camera objects. + */ CameraIterator begin() const { return CameraIterator(this, 0, 0); } + + /** + * @brief Returns a const iterator to the end of the camera's pixel rays. + * @return A CameraIterator pointing to one past the last pixel ray. + */ CameraIterator end() const { return CameraIterator(this, pixel_height, 0); } - Point3 pos; - Point3 aim; - Vector3 up; + Point3 pos; ///< Camera position in 3D space + Point3 aim; ///< Point the camera is looking at (the target point) + Vector3 up; ///< Up vector indicating the upward direction from the camera - Matrix coordinate_basis; + Matrix coordinate_basis; ///< Coordinate basis matrix for the camera, defining its orientation + ///< in space - double screen_distance; - double screen_height; - double screen_width; + double screen_distance; ///< Distance from the camera to the projection screen (view plane) + double screen_height; ///< Height of the projection screen (view plane) + double screen_width; ///< Width of the projection screen (view plane) - int pixel_height; - int pixel_width; + int pixel_height; ///< Height of the image in pixels + int pixel_width; ///< Width of the image in pixels private: - Point3 pixel_00_loc; - Vector3 pixel_delta_u; - Vector3 pixel_delta_v; + Point3 pixel_00_loc; ///< Location of the pixel at (0, 0) in the camera's view + Vector3 pixel_delta_u; ///< Vector representing the change in position along the u direction + ///< (horizontal) + Vector3 pixel_delta_v; ///< Vector representing the change in position along the v direction + ///< (vertical) }; } // namespace Prism diff --git a/libs/Prism/include/Prism/color.hpp b/libs/Prism/include/Prism/color.hpp index 0360b8a..72d7e21 100644 --- a/libs/Prism/include/Prism/color.hpp +++ b/libs/Prism/include/Prism/color.hpp @@ -4,14 +4,48 @@ #include "prism_export.h" namespace Prism { - class PRISM_EXPORT Color { - public: - Color(); - Color(double red, double green, double blue); - Color(int red, int green, int blue); - Color(const Color& other); - double r, g, b; - }; +/** + * @class Color + * @brief Represents a color in RGB format. + * The Color class encapsulates a color defined by its red, green, and blue components. + * Each component is a double value ranging from 0.0 to 1.0, representing the intensity of the + * color. The class provides constructors for initializing colors with double or integer values. + */ +class PRISM_EXPORT Color { + public: + /** + * @brief Default constructor that initializes the color to black (0, 0, 0). + */ + Color(); + + /** + * @brief Constructor that initializes the color with specified red, green, and blue values. + * @param red The red component of the color (0.0 to 1.0). + * @param green The green component of the color (0.0 to 1.0). + * @param blue The blue component of the color (0.0 to 1.0). + */ + Color(double red, double green, double blue); + + /** + * @brief Constructor that initializes the color with specified red, green, and blue values as + * integers. + * @param red The red component of the color (0 to 255). + * @param green The green component of the color (0 to 255). + * @param blue The blue component of the color (0 to 255). + * This constructor converts the integer values to double in the range of 0.0 to 1.0. + */ + Color(int red, int green, int blue); + + /** + * @brief Copy constructor that initializes the color from another Color object. + * @param other The Color object to copy from. + */ + Color(const Color& other); + + double r; ///< Red component of the color (0.0 to 1.0) + double g; ///< Green component of the color (0.0 to 1.0) + double b; ///< Blue component of the color (0.0 to 1.0) +}; } // namespace Prism #endif // PRISM_COLOR_HPP_ \ No newline at end of file diff --git a/libs/Prism/include/Prism/material.hpp b/libs/Prism/include/Prism/material.hpp index bce3270..726f964 100644 --- a/libs/Prism/include/Prism/material.hpp +++ b/libs/Prism/include/Prism/material.hpp @@ -1,28 +1,52 @@ #ifndef PRISM_MATERIAL_HPP_ #define PRISM_MATERIAL_HPP_ -#include "prism_export.h" #include "Prism/color.hpp" +#include "Prism/vector.hpp" +#include "prism_export.h" namespace Prism { - class PRISM_EXPORT Material { - public: - - Material(Color color = Color(), Vector3 ka = Vector3(), Vector3 ks = Vector3(), Vector3 ke = Vector3(), double ns = 0, double ni = 0 , double d = 0) : - color(color), ka(ka), ks(ks), ke(ke), ns(ns), ni(ni), d(d) {} - - Color color; - Vector3 ka; - Vector3 ks; - Vector3 ke; - double ns; - double ni; - double d; - - - }; - -} // namespace Prism - -#endif // PRISM_MATERIAL_HPP_ \ No newline at end of file +/** + * @class Material + * @brief Represents a material with various properties used in rendering. + * The Material class encapsulates the properties of a material, including its color, ambient + * reflectivity (ka), specular reflectivity (ks), emissive color (ke), shininess (ns), index of + * refraction (ni), and transparency (d). These properties are commonly used in computer graphics to + * define how a material interacts with light and how it appears in a rendered scene. + */ +class PRISM_EXPORT Material { + public: + /** + * @brief + * Default constructor that initializes the material with default values. + * The default values are: + * - Color: Black (0, 0, 0) + * - Ambient reflectivity (ka): (0, 0, 0) + * - Specular reflectivity (ks): (0, 0, 0) + * - Emissive color (ke): (0, 0, 0) + * - Shininess (ns): 0 + * - Index of refraction (ni): 0 + * - Transparency (d): 0 + */ + Material(Color color = Color(), Vector3 ka = Vector3(), Vector3 ks = Vector3(), + Vector3 ke = Vector3(), double ns = 0, double ni = 0, double d = 0) + : color(color), ka(ka), ks(ks), ke(ke), ns(ns), ni(ni), d(d) { + } + + Color color; ///< The color of the material, typically used for diffuse reflection. + Vector3 ka; ///< Ambient reflectivity of the material, representing how much ambient light it + ///< reflects. + Vector3 ks; ///< Specular reflectivity of the material, representing how much specular light it + ///< reflects. + Vector3 + ke; ///< Emissive color of the material, representing light emitted by the material itself. + double ns; ///< Shininess factor of the material, affecting the size and intensity of specular + ///< highlights. + double ni; ///< Index of refraction of the material, used for simulating refraction effects. + double d; ///< Transparency of the material, where 0 is fully opaque and 1 is fully transparent. +}; + +} // namespace Prism + +#endif // PRISM_MATERIAL_HPP_ \ No newline at end of file diff --git a/libs/Prism/include/Prism/matrix.hpp b/libs/Prism/include/Prism/matrix.hpp index 2ed9650..d5440a7 100644 --- a/libs/Prism/include/Prism/matrix.hpp +++ b/libs/Prism/include/Prism/matrix.hpp @@ -3,74 +3,308 @@ #include "prism_export.h" +#include #include #include #include #include -#include -#include "Prism/vector.hpp" + #include "Prism/point.hpp" +#include "Prism/vector.hpp" namespace Prism { +class Matrix; // Forward declaration for proxy classes + +/** + * @class MatrixRow + * @brief Proxy class for accessing a specific row of a Matrix. + * This class allows access to a row of the matrix using the syntax `matrix[row][col]`. + * + * A MatrixRow object is created by the Matrix class when using the `operator[]` to access a row. + * It provides a way to access and modify elements in that row without exposing the entire matrix. + */ +class PRISM_EXPORT MatrixRow { + public: + /** + * @brief Constructs a MatrixRow for a specific row of a Matrix. + * @param matrix The Matrix to access. + * @param row The index of the row to access. + * This constructor initializes the MatrixRow with a reference to the specified matrix and the + * row index. + * @throws std::out_of_range if the row index is out of bounds. + */ + MatrixRow(Matrix& matrix, size_t row); + + /** + * @brief Accesses an element in the specified row of the matrix. + * @param col The index of the column to access. + * @return A reference to the element at the specified row and column. + * @throws std::out_of_range if the column index is out of bounds. + * This operator allows you to access elements in the specified row of the matrix using the + * syntax `matrix[row][col]`. + */ + double& operator[](size_t col); + + private: + Matrix& matrix_; ///< Reference to the matrix being accessed + size_t row_; ///< Index of the row being accessed +}; + +/** + * @class ConstMatrixRow + * @brief Proxy class for accessing a specific row of a Matrix in a const context. + * This class allows read-only access to a row of the matrix using the syntax `matrix[row][col]`. + * + * A ConstMatrixRow object is created by the Matrix class when using the `operator[]` to access a + * row in a const context. It provides a way to access elements in that row without allowing + * modifications, ensuring the integrity of the matrix data. + */ +class PRISM_EXPORT ConstMatrixRow { + public: + /** + * @brief Constructs a ConstMatrixRow for a specific row of a Matrix. + * @param matrix The Matrix to access. + * @param row The index of the row to access. + * This constructor initializes the ConstMatrixRow with a reference to the specified matrix and + * the row index. + * @throws std::out_of_range if the row index is out of bounds. + */ + ConstMatrixRow(const Matrix& matrix, size_t row); + + /** + * @brief Accesses an element in the specified row of the matrix. + * @param col The index of the column to access. + * @return A const reference to the element at the specified row and column. + * @throws std::out_of_range if the column index is out of bounds. + * This operator allows you to access elements in the specified row of the matrix using the + * syntax `const_matrix[row][col]`. + */ + const double& operator[](size_t col) const; + + private: + const Matrix& matrix_; ///< Reference to the matrix being accessed + size_t row_; ///< Index of the row being accessed +}; + +/** + * @class Matrix + * @brief Represents a mathematical matrix with various operations. + * The Matrix class provides a flexible way to create, manipulate, and perform mathematical + * operations on matrices. It supports basic operations like addition, subtraction, multiplication, + * and more advanced operations like determinant calculation and matrix inversion. + */ class PRISM_EXPORT Matrix { -public: - // --- Construtores e Destrutor --- + friend class MatrixRow; // Allows MatrixRow to access private members of Matrix + friend class ConstMatrixRow; // Allows ConstMatrixRow to access private members of Matrix + + public: + /** + * @brief Default constructor that initializes a 3x3 identity matrix. + * This constructor creates a 3x3 matrix with ones on the diagonal and zeros elsewhere. + * It is useful for initializing matrices in transformations where an identity matrix is needed. + */ Matrix(); + + /** + * @brief Constructs a Matrix with specified dimensions. + * @param rows The number of rows in the matrix. + * @param cols The number of columns in the matrix. + */ Matrix(size_t rows, size_t cols); + + /** + * @brief Constructs a Matrix from an initializer list of initializer lists. + * @param data An initializer list containing rows of the matrix, where each row is itself an + * initializer list of doubles. + * @throws std::invalid_argument if the rows have different sizes. + */ Matrix(std::initializer_list> data); - Matrix(const Matrix& m); - - // --- Classes aninhadas para acesso --- - class PRISM_EXPORT MatrixRow { - private: - std::vector& m_row_vector; - public: - MatrixRow(std::vector& row_vec); - double& operator[](int col); - }; - - class PRISM_EXPORT ConstMatrixRow { - private: - const std::vector& m_row_vector; - public: - ConstMatrixRow(const std::vector& row_vec); - const double& operator[](int col) const; - }; - - // --- Getters --- - size_t getRows() const; - size_t getCols() const; - - // --- Operadores --- + + /** + * @brief Gets the number of rows in the matrix. + * @return The number of rows in the matrix. + */ + size_t getRows() const { + return rows_; + } + + /** + * @brief Gets the number of columns in the matrix. + * @return The number of columns in the matrix. + */ + size_t getCols() const { + return cols_; + } + + /** + * @brief Accesses a specific row of the matrix. + * @param row The index of the row to access. + * @return A MatrixRow object that allows access to the specified row. + * @throws std::out_of_range if the row index is out of bounds. + * + * This operator allows you to access a row of the matrix using the syntax `matrix[row]`. + * It returns a MatrixRow object that can be used to access or modify elements in that row. + */ + MatrixRow operator[](size_t row); + + /** + * @brief Accesses a specific row of the matrix in a const context. + * @param row The index of the row to access. + * @return A ConstMatrixRow object that allows read-only access to the specified row. + * @throws std::out_of_range if the row index is out of bounds. + * + * This operator allows you to access a row of the matrix in a const context using the syntax + * `matrix[row]`. It returns a ConstMatrixRow object that can be used to read elements in that + * row without allowing modifications. + */ + ConstMatrixRow operator[](size_t row) const; + + /** + * @brief Checks if two matrices are equal. + * @param m The matrix to compare with. + * @return True if the matrices have the same dimensions and all corresponding elements are + * equal, false otherwise. + */ bool operator==(const Matrix& m) const; + + /** + * @brief Checks if two matrices are not equal. + * @param m The matrix to compare with. + * @return True if the matrices differ in dimensions or any corresponding elements are not + * equal, false otherwise. + */ bool operator!=(const Matrix& m) const; - Matrix& operator=(const Matrix& m); + + /** + * @brief Multiplies this matrix by another matrix. + * @param m The matrix to multiply with. + * @return A new Matrix that is the result of the multiplication. + * @throws std::invalid_argument if the number of columns in this matrix does not match the + * number of rows in the other matrix. + */ Matrix operator*(const Matrix& m) const; - Matrix operator*(const double& scalar) const; + + /** + * @brief Multiplies this matrix by a scalar. + * @param scalar The scalar value to multiply with. + * @return A new Matrix that is the result of the multiplication. + */ + Matrix operator*(double scalar) const; + + /** + * @brief Multiplies this matrix by a Point3. + * @param p The Point3 to multiply with. + * @return A Point3 that is the result of the multiplication. + * @throws std::domain_error if the matrix is not 3x3 or 4x4. + * + * This operator allows you to multiply a matrix by a Point3, which is useful for applying + * transformations such as translation, rotation, or scaling to a point in 3D space. + */ Point3 operator*(const Point3& p) const; + + /** + * @brief Multiplies this matrix by a Vector3. + * @param v The Vector3 to multiply with. + * @return A Vector3 that is the result of the multiplication. + * @throws std::domain_error if the matrix is not 3x3 or 4x4. + * + * This operator allows you to multiply a matrix by a Vector3, which is useful for transforming + * vectors in 3D space. + */ Vector3 operator*(const Vector3& v) const; + + /** + * @brief Multiplies this matrix by another matrix in place. + * @param m The matrix to multiply with. + * @return Reference to this matrix after multiplication. + * + * This operator allows you to perform matrix multiplication and update the current matrix with + * the result. + */ Matrix& operator*=(const Matrix& m); - Matrix& operator*=(const double& scalar); - MatrixRow operator[](size_t i); - ConstMatrixRow operator[](size_t i) const; - // --- Operações Matemáticas --- + /** + * @brief Multiplies this matrix by a scalar in place. + * @param scalar The scalar value to multiply with. + * @return Reference to this matrix after multiplication. + * + * This operator allows you to scale all elements of the matrix by a scalar value, modifying the + * current matrix. + */ + Matrix& operator*=(double scalar); + + /** + * @brief Computes the determinant of the matrix. + * @return The determinant of the matrix. + * @throws std::domain_error if the matrix is not square. + */ double determinant() const; + + /** + * @brief Computes the inverse of the matrix. + * @return A new Matrix that is the inverse of this matrix. + * @throws std::domain_error if the matrix is singular (determinant is zero). + * + * This method uses the Gauss-Jordan elimination method to compute the inverse of the matrix. + * It is applicable only for square matrices (3x3 or 4x4). + */ Matrix inverse() const; + + /** + * @brief Computes the transpose of the matrix. + * @return A new Matrix that is the transpose of this matrix. + * This method swaps the rows and columns of the matrix, effectively flipping it over its + * diagonal. + * @return A new Matrix that is the transpose of this matrix. + */ Matrix transpose() const; - // --- Funções Estáticas (Factories) --- + /** + * @brief Creates an identity matrix of size n x n. + * @param n The size of the identity matrix (number of rows and columns). + * @return A new Matrix that is the identity matrix of size n x n. + * An identity matrix has ones on the diagonal and zeros elsewhere, serving as the + * multiplicative identity in matrix operations. + */ static Matrix identity(size_t n); - static Matrix translation(int dimension, std::initializer_list values); - static Matrix scaling(int dimension, std::initializer_list values); - static Matrix rotation2d(double angle); - static Matrix rotation3d(double angle, const Vector3& axis); - -private: - size_t rows_; - size_t cols_; - std::vector> data_; + + /** + * @brief Creates a translation matrix. + * @param tx The translation distance along the x-axis. + * @param ty The translation distance along the y-axis. + * @param tz The translation distance along the z-axis. + * @return A new Matrix that represents a translation transformation. + * This matrix can be used to translate points or vectors in 3D space by adding the translation + * distances to the respective coordinates. + */ + static Matrix translation(double tx, double ty, double tz); + + /** + * @brief Creates a scaling matrix. + * @param sx The scaling factor along the x-axis. + * @param sy The scaling factor along the y-axis. + * @param sz The scaling factor along the z-axis. + * @return A new Matrix that represents a scaling transformation. + * This matrix can be used to scale points or vectors in 3D space by multiplying the respective + * coordinates by the scaling factors. + */ + static Matrix scaling(double sx, double sy, double sz); + + /** + * @brief Creates a rotation matrix. + * @param angle The angle of rotation in radians. + * @param axis The axis of rotation as a Vector3. + * @return A new Matrix that represents a rotation transformation. + * This matrix can be used to rotate points or vectors in 3D space around the specified axis by + * the given angle. + */ + static Matrix rotation(double angle, const Vector3& axis); + + private: + size_t rows_; // Number of rows in the matrix + size_t cols_; // Number of columns in the matrix + std::vector data_; // Data storage for the matrix elements }; } // namespace Prism diff --git a/libs/Prism/include/Prism/mesh.hpp b/libs/Prism/include/Prism/mesh.hpp index ba54775..3571a59 100644 --- a/libs/Prism/include/Prism/mesh.hpp +++ b/libs/Prism/include/Prism/mesh.hpp @@ -1,28 +1,63 @@ #ifndef PRISM_MESH_HPP_ #define PRISM_MESH_HPP_ -#include "prism_export.h" +#include "Prism/ObjReader.hpp" +#include "Prism/material.hpp" #include "Prism/objects.hpp" #include "Prism/point.hpp" #include "Prism/triangle.hpp" -#include "Prism/ObjReader.hpp" -#include "Prism/material.hpp" -#include +#include "prism_export.h" #include #include +#include namespace Prism { +/** + * @class Mesh + * @brief Represents a 3D mesh object composed of triangles. + * The Mesh class is designed to hold a collection of triangles, each defined by three points in 3D + * space. It provides functionality to read mesh data from an OBJ file and check for ray + * intersections with the mesh. It inherits from the Object class, allowing it to be used in a scene + * with other objects. + */ class PRISM_EXPORT Mesh : public Object { public: - Mesh(ObjReader& reader); + /** + * @brief Constructs a Mesh object from a file path. + * @param path The file path to the OBJ file containing the mesh data. + * This constructor initializes the Mesh by reading points and triangles from the specified OBJ + * file. + */ + explicit Mesh(std::string path); + + /** + * @brief Constructs a Mesh object from an ObjReader. + * @param reader An ObjReader object that contains the mesh data to be loaded. + * This constructor initializes the Mesh by reading points and triangles from the provided + * ObjReader. + */ + explicit Mesh(ObjReader& reader); + /** + * @brief Checks if a ray intersects with the mesh. + * @param ray The ray to test for intersection with the mesh. + * @param t_min The minimum distance for a valid hit. + * @param t_max The maximum distance for a valid hit. + * @param rec The hit record to be filled with intersection details if a hit occurs. + * @return True if the ray intersects with the mesh within the specified distance range, false + * otherwise. This method transforms the ray using the inverse transformation matrix of the mesh + * and checks each triangle for intersection. If a hit is found, it updates the hit record with + * the intersection point, normal, and material properties. + */ virtual bool hit(const Ray& ray, double t_min, double t_max, HitRecord& rec) const override; private: - std::vector> points; - std::vector mesh; - std::shared_ptr material; + std::vector> points; ///< Points that define the vertices of the mesh + std::vector + mesh; ///< Triangles that make up the mesh, each defined by three points + std::shared_ptr + material; ///< Material properties of the mesh, defining how it interacts with light }; } // namespace Prism diff --git a/libs/Prism/include/Prism/objects.hpp b/libs/Prism/include/Prism/objects.hpp index 9d82949..e008491 100644 --- a/libs/Prism/include/Prism/objects.hpp +++ b/libs/Prism/include/Prism/objects.hpp @@ -6,12 +6,19 @@ #include "Prism/ray.hpp" #include "Prism/vector.hpp" #include "prism_export.h" +#include namespace Prism { class Ray; // Forward declaration of Ray class class Material; // Forward declaration of Material class +/** + * @class HitRecord + * @brief Represents the details of a ray-object intersection. + * This class stores the intersection point, normal at the intersection, distance along the ray, + * material properties, and whether the hit is on the front face of the object. + */ struct PRISM_EXPORT HitRecord { Point3 p; Vector3 normal; @@ -25,6 +32,13 @@ struct PRISM_EXPORT HitRecord { } }; +/** + * @class Object + * @brief Abstract base class for all objects in the scene. + * This class defines the interface for objects that can be hit by rays, providing a method to check + * for intersections. It also manages the transformation of the object in 3D space using a + * transformation matrix. + */ class PRISM_EXPORT Object { public: virtual ~Object() = default; @@ -39,16 +53,32 @@ class PRISM_EXPORT Object { */ virtual bool hit(const Ray& ray, double t_min, double t_max, HitRecord& rec) const = 0; + /** + * @brief Gets the transformation matrix of the object. + * @param The transformation matrix. + * This matrix represents the object's position, orientation, and scale in the scene. + */ void setTransform(const Matrix& new_transform) { transform = new_transform; inverseTransform = transform.inverse(); inverseTransposeTransform = inverseTransform.transpose(); } + /** + * @brief Gets the transformation matrix of the object. + * @return The transformation matrix. + * This matrix can be used to transform points or vectors in the object's local space to world + * space. + */ + Matrix getTransform() const { + return transform; + } + protected: - Matrix transform = Matrix::identity(4); - Matrix inverseTransform = Matrix::identity(4); - Matrix inverseTransposeTransform = Matrix::identity(4); + Matrix transform = Matrix::identity(4); ///< Transformation matrix for the object + Matrix inverseTransform = Matrix::identity(4); ///< Inverse of the transformation matrix + Matrix inverseTransposeTransform = + Matrix::identity(4); ///< Inverse transpose of the transformation matrix }; } // namespace Prism diff --git a/libs/Prism/include/Prism/plane.hpp b/libs/Prism/include/Prism/plane.hpp index 03ecbd9..ee02017 100644 --- a/libs/Prism/include/Prism/plane.hpp +++ b/libs/Prism/include/Prism/plane.hpp @@ -1,23 +1,45 @@ #ifndef PRISM_PLANE_HPP_ #define PRISM_PLANE_HPP_ -#include "prism_export.h" #include "Prism/objects.hpp" #include "Prism/point.hpp" #include "Prism/vector.hpp" +#include "prism_export.h" namespace Prism { +/** + * @class Plane + * @brief Represents a plane in 3D space defined by a point and a normal vector. + * This class inherits from Object and implements the hit method to check for ray-plane + * intersections. + */ class PRISM_EXPORT Plane : public Object { public: + /** + * @brief Constructs a Plane given a point on the plane, a normal vector, and a material. + * @param point_on_plane A Point3 representing a point on the plane. + * @param normal A Vector3 representing the normal vector of the plane. + * @param material A shared pointer to a Material object associated with the plane. + */ Plane(Point3 point_on_plane, Vector3 normal, std::shared_ptr material); + /** + * @brief Checks if a ray intersects with the plane. + * @param ray The Ray to test for intersection. + * @param t_min The minimum distance for a valid hit. + * @param t_max The maximum distance for a valid hit. + * @param rec The HitRecord to be filled upon a collision. + * @return True if the ray intersects the plane within the specified distance range, false + * otherwise. + */ virtual bool hit(const Ray& ray, double t_min, double t_max, HitRecord& rec) const override; private: - Point3 point_on_plane; - Vector3 normal; - std::shared_ptr material; + Point3 point_on_plane; ///< A point on the plane + Vector3 normal; ///< The normal vector of the plane + std::shared_ptr + material; ///< Material properties of the plane, defining how it interacts with light }; } // namespace Prism diff --git a/libs/Prism/include/Prism/point.hpp b/libs/Prism/include/Prism/point.hpp index ccdf160..d1b1556 100644 --- a/libs/Prism/include/Prism/point.hpp +++ b/libs/Prism/include/Prism/point.hpp @@ -6,7 +6,7 @@ namespace Prism { class Vector3; // Forward declaration of Vector3 class -class Matrix; // Forward declaration of Matrix class +class Matrix; // Forward declaration of Matrix class /** * @class Point3 diff --git a/libs/Prism/include/Prism/ray.hpp b/libs/Prism/include/Prism/ray.hpp index 832731a..75e945f 100644 --- a/libs/Prism/include/Prism/ray.hpp +++ b/libs/Prism/include/Prism/ray.hpp @@ -1,16 +1,16 @@ #ifndef PRISM_RAY_HPP_ #define PRISM_RAY_HPP_ -#include "prism_export.h" #include "Prism/point.hpp" #include "Prism/vector.hpp" +#include "prism_export.h" #include -#include #include +#include namespace Prism { -class Object; // Forward declaration of Object class -struct HitRecord; // Forward declaration of HitRecord struct +class Object; // Forward declaration of Object class +struct HitRecord; // Forward declaration of HitRecord struct /** * @class Ray @@ -23,7 +23,7 @@ class PRISM_EXPORT Ray { * @param origin Point in 3d space that originates the ray. * @param direction normalized vector representing the direction which the ray points towards. */ - + Ray(const Point3& origin, const Vector3& direction); /** * @brief Constucts a ray that goes from its origin torwards another given point @@ -31,21 +31,35 @@ class PRISM_EXPORT Ray { * @param target Point which the ray targets */ Ray(const Point3& origin, const Point3& target); - + /** * @brief gets the direction of ray. if not instantiated, returns null */ Vector3 direction() const; + /** + * @brief Transforms the ray using a transformation matrix + * @param m The transformation matrix to apply to the ray + * @return A new Ray object that is transformed by the given matrix + */ Ray transform(const Matrix& m) const; - + + /** + * @brief Gets the origin point of the ray + * @return The origin point of the ray + */ Point3 origin() const; + /** + * @brief Gets the point at a specific distance along the ray + * @param t The distance along the ray from its origin + * @return The Point3 at the specified distance along the ray + */ Point3 at(const double& t) const; private: - Point3 origin_; - Vector3 direction_; + Point3 origin_; ///< The origin point of the ray + Vector3 direction_; ///< The direction vector of the ray, normalized to unit length }; } // namespace Prism diff --git a/libs/Prism/include/Prism/scene.hpp b/libs/Prism/include/Prism/scene.hpp index cdbd787..68359c5 100644 --- a/libs/Prism/include/Prism/scene.hpp +++ b/libs/Prism/include/Prism/scene.hpp @@ -15,13 +15,20 @@ namespace Prism { PRISM_EXPORT std::filesystem::path generate_filename(); +/** + * @class Scene + * @brief Represents a 3D scene containing objects and a camera for rendering. + * This class manages the collection of objects in the scene and provides functionality to render + * the scene from the camera's perspective. + */ class PRISM_EXPORT Scene { public: /** - * @brief Constrói a cena, movendo uma câmera para dentro dela. - * @param camera A câmera que será usada para renderizar a cena. + * @brief Constructs a Scene with a specified camera. + * @param camera The Camera object that defines the viewpoint and projection parameters for + * rendering the scene. */ - Scene(Camera camera); + explicit Scene(Camera camera); Scene(const Scene&) = delete; Scene& operator=(const Scene&) = delete; @@ -30,20 +37,24 @@ class PRISM_EXPORT Scene { Scene& operator=(Scene&&) = default; /** - * @brief Adiciona um objeto à cena. - * A posse do objeto é transferida para a cena. - * @param object Um unique_ptr para um objeto derivado de Object (e.g., Sphere). + * @brief Adds an object to the scene. + * @param object A unique pointer to an Object that will be added to the scene. + * This method takes ownership of the object and stores it in the scene's collection. */ void addObject(std::unique_ptr object); /** - * @brief Renderiza a cena a partir da perspectiva da câmera e salva em um arquivo PPM. + * @brief Renders the scene from the camera's perspective. + * This method iterates over all objects in the scene, checks for ray-object intersections, and + * generates the final image. The rendered image is saved to a file with a timestamped filename. + * The rendering process involves casting rays from the camera through each pixel of the + * viewport and checking for hits with the objects. */ void render() const; private: - std::vector> objects_; - Camera camera_; + std::vector> objects_; ///< Collection of objects in the scene + Camera camera_; ///< The camera used to view the scene }; } // namespace Prism diff --git a/libs/Prism/include/Prism/sphere.hpp b/libs/Prism/include/Prism/sphere.hpp index 65255c0..867806d 100644 --- a/libs/Prism/include/Prism/sphere.hpp +++ b/libs/Prism/include/Prism/sphere.hpp @@ -8,16 +8,42 @@ namespace Prism { +/** + * @class Sphere + * @brief Represents a sphere in 3D space defined by its center and radius. + * This class inherits from Object and implements the hit method to check for ray-sphere + * intersections. + */ class PRISM_EXPORT Sphere : public Object { public: + /** + * @brief Constructs a Sphere given its center, radius, and material. + * @param center A Point3 representing the center of the sphere. + * @param radius The radius of the sphere. + * @param material A shared pointer to a Material object associated with the sphere. + * This constructor initializes the sphere with the specified center, radius, and material + * properties. + */ Sphere(Point3 center, double radius, std::shared_ptr material); + /** + * @brief Checks if a ray intersects with the sphere. + * @param ray The Ray to test for intersection with the sphere. + * @param t_min The minimum distance for a valid hit. + * @param t_max The maximum distance for a valid hit. + * @param rec The HitRecord to be filled upon a collision. + * @return True if the ray intersects the sphere within the specified distance range, false + * otherwise. This method transforms the ray using the inverse transformation matrix of the + * sphere and checks for intersection. If a hit is found, it updates the hit record with the + * intersection point, normal, and material properties. + */ virtual bool hit(const Ray& ray, double t_min, double t_max, HitRecord& rec) const override; private: - Point3 center; - double radius; - std::shared_ptr material; + Point3 center; ///< The center point of the sphere + double radius; ///< The radius of the sphere + std::shared_ptr + material; ///< Material properties of the sphere, defining how it interacts with light }; } // namespace Prism diff --git a/libs/Prism/include/Prism/triangle.hpp b/libs/Prism/include/Prism/triangle.hpp index 5211cd5..a7de231 100644 --- a/libs/Prism/include/Prism/triangle.hpp +++ b/libs/Prism/include/Prism/triangle.hpp @@ -1,48 +1,150 @@ #ifndef PRISM_TRIANGLE_HPP_ #define PRISM_TRIANGLE_HPP_ -#include "prism_export.h" +#include "Prism/material.hpp" #include "Prism/objects.hpp" #include "Prism/point.hpp" -#include "Prism/material.hpp" -#include +#include "prism_export.h" #include +#include -namespace Prism { - class Matrix; // Forward declaration for Matrix - class Ray; // Forward declaration for Ray - class Point3; // Forward declaration for Point3 - struct HitRecord; // Forward declaration for HitRecord +namespace Prism { +class Matrix; // Forward declaration for Matrix +class Ray; // Forward declaration for Ray +class Point3; // Forward declaration for Point3 +struct HitRecord; // Forward declaration for HitRecord +/** + * @class Triangle + * @brief Represents a triangle in 3D space defined by its three vertices. + * This class inherits from Object and implements the hit method to check for ray-triangle + * intersections. It is used to represent a triangle in a 3D scene, allowing for ray tracing and + * collision detection. + */ class PRISM_EXPORT Triangle : public Object { -public: - Triangle(Point3 p1, Point3 p2, Point3 p3, std::shared_ptr mat = std::make_shared()); + public: + /** + * @brief Constructs a Triangle given its three vertices and an optional material. + * @param p1 The first vertex of the triangle. + * @param p2 The second vertex of the triangle. + * @param p3 The third vertex of the triangle. + * @param mat An optional shared pointer to a Material object associated with the triangle. + * If no material is provided, a default Material is created. + * This constructor initializes the triangle with the specified vertices and material + * properties. + */ + Triangle(Point3 p1, Point3 p2, Point3 p3, + std::shared_ptr mat = std::make_shared()); + /** + * @brief Gets the first vertex of the triangle. + * @return The first vertex of the triangle as a Point3 object. + */ Point3 getPoint1() const; + + /** + * @brief Gets the second vertex of the triangle. + * @return The second vertex of the triangle as a Point3 object. + */ Point3 getPoint2() const; + + /** + * @brief Gets the third vertex of the triangle. + * @return The third vertex of the triangle as a Point3 object. + */ Point3 getPoint3() const; - bool hit(const Ray& ray, double t_min, double t_max, HitRecord& rec) const override; + /** + * @brief Checks if a ray intersects with the triangle. + * @param ray The Ray to test for intersection with the triangle. + * @param t_min The minimum distance for a valid hit. + * @param t_max The maximum distance for a valid hit. + * @param rec The HitRecord to be filled upon a collision. + * @return True if the ray intersects the triangle within the specified distance range, false + * otherwise. This method transforms the ray using the inverse transformation matrix of the + * triangle and checks for intersection. If a hit is found, it updates the hit record with the + * intersection point, normal, and material properties. + */ + virtual bool hit(const Ray& ray, double t_min, double t_max, HitRecord& rec) const override; -private: - Point3 point1, point2, point3; - std::shared_ptr material; + private: + Point3 point1; ///< The first vertex of the triangle + Point3 point2; ///< The second vertex of the triangle + Point3 point3; ///< The third vertex of the triangle + std::shared_ptr + material; ///< Material properties of the triangle, defining how it interacts with light }; -class PRISM_EXPORT MeshTriangle { -public: - MeshTriangle(std::shared_ptr p1, std::shared_ptr p2, std::shared_ptr p3); +/** + * @class MeshTriangle + * @brief Represents a triangle in a mesh, defined by three points. + * This class is used to represent a triangle in a 3D mesh, allowing for ray tracing and collision + * detection. It can be constructed from shared pointers to Point3 objects or directly from Point3 + * objects. + */ +class PRISM_EXPORT MeshTriangle { + public: + /** + * @brief Constructs a MeshTriangle given three points. + * @param p1 The first point of the triangle. + * @param p2 The second point of the triangle. + * @param p3 The third point of the triangle. + * This constructor initializes the MeshTriangle with the specified points. + */ + MeshTriangle(std::shared_ptr p1, std::shared_ptr p2, + std::shared_ptr p3); + + /** + * @brief Constructs a MeshTriangle given three Point3 objects. + * @param p1 The first vertex of the triangle. + * @param p2 The second vertex of the triangle. + * @param p3 The third vertex of the triangle. + * This constructor initializes the MeshTriangle with the specified Point3 objects. + */ MeshTriangle(Point3 p1, Point3 p2, Point3 p3); + + /** + * @brief Constructs a MeshTriangle from an initializer list of Point3 objects. + * @param points An initializer list containing three Point3 objects representing the vertices + * of the triangle. This constructor initializes the MeshTriangle with the specified points. + */ MeshTriangle(std::initializer_list points); + /** + * @brief Gets the first point of the triangle. + * @return The first point of the triangle as a Point3 object. + */ Point3 getPoint1() const; + + /** + * @brief Gets the second point of the triangle. + * @return The second point of the triangle as a Point3 object. + */ Point3 getPoint2() const; + + /** + * @brief Gets the third point of the triangle. + * @return The third point of the triangle as a Point3 object. + */ Point3 getPoint3() const; + /** + * @brief Checks if a ray intersects with the triangle. + * @param ray The Ray to test for intersection with the triangle. + * @param t_min The minimum distance for a valid hit. + * @param t_max The maximum distance for a valid hit. + * @param rec The HitRecord to be filled upon a collision. + * @return True if the ray intersects the triangle within the specified distance range, false + * otherwise. This method checks for intersection between the ray and the triangle defined by + * the three points. If a hit is found, it updates the hit record with the intersection point, + * normal, and other relevant details. + */ bool hit(const Ray& ray, double t_min, double t_max, HitRecord& rec) const; -private: - std::shared_ptr point1, point2, point3; + private: + std::shared_ptr point1; ///< The first point of the triangle + std::shared_ptr point2; ///< The second point of the triangle + std::shared_ptr point3; ///< The third point of the triangle }; } // namespace Prism diff --git a/libs/Prism/src/camera.cpp b/libs/Prism/src/camera.cpp index d68d4f0..542a9ce 100644 --- a/libs/Prism/src/camera.cpp +++ b/libs/Prism/src/camera.cpp @@ -9,19 +9,11 @@ namespace Prism { -Camera::Camera(const Point3& position, const Point3& target, const Vector3& upvec, - double distance, double viewport_height, double viewport_width, - int image_height, int image_width) - : pos(position), - aim(target), - up(upvec), - coordinate_basis(), - screen_distance(distance), - screen_height(viewport_height), - screen_width(viewport_width), - pixel_height(image_height), - pixel_width(image_width) -{ +Camera::Camera(const Point3& position, const Point3& target, const Vector3& upvec, double distance, + double viewport_height, double viewport_width, int image_height, int image_width) + : pos(position), aim(target), up(upvec), coordinate_basis(), screen_distance(distance), + screen_height(viewport_height), screen_width(viewport_width), pixel_height(image_height), + pixel_width(image_width) { coordinate_basis = orthonormalBasisContaining(pos - aim); const auto& basis = coordinate_basis; diff --git a/libs/Prism/src/color.cpp b/libs/Prism/src/color.cpp index cb36f3b..5ab9e8c 100644 --- a/libs/Prism/src/color.cpp +++ b/libs/Prism/src/color.cpp @@ -2,9 +2,15 @@ namespace Prism { -Color::Color() : r(0), g(0), b(0) {} -Color::Color(double red, double green, double blue) : r(red), g(green), b(blue) {} -Color::Color(int red, int green, int blue): r(static_cast(red) / 255.0), g(static_cast(green) / 255.0), b(static_cast(blue) / 255.0) {} -Color::Color(const Color& other) : r(other.r), g(other.g), b(other.b) {} +Color::Color() : r(0), g(0), b(0) { +} +Color::Color(double red, double green, double blue) : r(red), g(green), b(blue) { +} +Color::Color(int red, int green, int blue) + : r(static_cast(red) / 255.0), g(static_cast(green) / 255.0), + b(static_cast(blue) / 255.0) { +} +Color::Color(const Color& other) : r(other.r), g(other.g), b(other.b) { +} } // namespace Prism \ No newline at end of file diff --git a/libs/Prism/src/material.cpp b/libs/Prism/src/material.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/libs/Prism/src/matrix.cpp b/libs/Prism/src/matrix.cpp index 26d1af7..a1f6546 100644 --- a/libs/Prism/src/matrix.cpp +++ b/libs/Prism/src/matrix.cpp @@ -1,71 +1,80 @@ #include "Prism/matrix.hpp" -#include #include +#include +#include namespace Prism { -// --- Implementações dos Construtores --- -Matrix::Matrix() : rows_(3), cols_(3), data_(3, std::vector(3, 0.0)) {}; +// --- Implementação do Proxy (não-const) --- +MatrixRow::MatrixRow(Matrix& matrix, size_t row) : matrix_(matrix), row_(row) { +} -Matrix::Matrix(size_t rows, size_t cols) { - if (rows == 0 || cols == 0) { - throw std::invalid_argument("Matrix dimensions must be greater than zero."); - } - rows_ = rows; - cols_ = cols; - data_.resize(rows_, std::vector(cols_, 0.0)); -}; - -Matrix::Matrix(std::initializer_list> data) { - rows_ = data.size(); - if (rows_ == 0) { - cols_ = 0; - data_ = {}; - return; - } +double& MatrixRow::operator[](size_t col) { + // Adicionar checagem de limites (bounds checking) se desejar + return matrix_.data_[row_ * matrix_.cols_ + col]; +} - cols_ = data.begin()->size(); - data_.reserve(rows_); - for (const auto& row : data) { - if (row.size() != cols_) { - throw std::invalid_argument("All rows in initializer list must have the same size."); - } - data_.emplace_back(row); - } +// --- Implementação do Proxy (const) --- +ConstMatrixRow::ConstMatrixRow(const Matrix& matrix, size_t row) : matrix_(matrix), row_(row) { } -Matrix::Matrix(const Matrix& m) : rows_(m.rows_), cols_(m.cols_), data_(m.data_) {}; +const double& ConstMatrixRow::operator[](size_t col) const { + // Adicionar checagem de limites (bounds checking) se desejar + return matrix_.data_[row_ * matrix_.cols_ + col]; +} -// --- Implementações das Classes Aninhadas --- +// --- Implementação dos Construtores da Matrix --- -Matrix::MatrixRow::MatrixRow(std::vector& row_vec) : m_row_vector(row_vec) {} +Matrix::Matrix() : rows_(3), cols_(3), data_(3 * 3, 0.0) { + // Construtor padrão agora cria uma matriz identidade 3x3 + (*this)[0][0] = 1.0; + (*this)[1][1] = 1.0; + (*this)[2][2] = 1.0; +} -double& Matrix::MatrixRow::operator[](int col) { - return m_row_vector.at(col); +Matrix::Matrix(size_t rows, size_t cols) : rows_(rows), cols_(cols) { + if (rows == 0 || cols == 0) { + // Permite matrizes 0x0 para consistência, mas não lança erro. + // Opcional: throw std::invalid_argument("Matrix dimensions cannot be zero."); + rows_ = 0; + cols_ = 0; + } + data_.assign(rows_ * cols_, 0.0); // Usa 'assign' para preencher com zeros } -Matrix::ConstMatrixRow::ConstMatrixRow(const std::vector& row_vec) : m_row_vector(row_vec) {} +Matrix::Matrix(std::initializer_list> list) { + rows_ = list.size(); + if (rows_ > 0) { + cols_ = list.begin()->size(); + } else { + cols_ = 0; + } -const double& Matrix::ConstMatrixRow::operator[](int col) const { - return m_row_vector.at(col); + data_.reserve(rows_ * cols_); + for (const auto& row_list : list) { + if (row_list.size() != cols_) { + throw std::invalid_argument("All rows in initializer list must have the same size."); + } + // Insere os elementos da linha no final do vetor linear + data_.insert(data_.end(), row_list.begin(), row_list.end()); + } } -// --- Implementações dos Getters --- +// --- Implementação dos Operadores --- -size_t Matrix::getRows() const { - return rows_; +MatrixRow Matrix::operator[](size_t row) { + return MatrixRow(*this, row); } -size_t Matrix::getCols() const { - return cols_; +ConstMatrixRow Matrix::operator[](size_t row) const { + return ConstMatrixRow(*this, row); } -// --- Implementações dos Operadores --- - bool Matrix::operator==(const Matrix& m) const { if (rows_ != m.rows_ || cols_ != m.cols_) { return false; } + // std::vector já tem um operador== eficiente para dados contíguos. return data_ == m.data_; } @@ -73,15 +82,6 @@ bool Matrix::operator!=(const Matrix& m) const { return !(*this == m); } -Matrix& Matrix::operator=(const Matrix& m) { - if (this != &m) { - rows_ = m.rows_; - cols_ = m.cols_; - data_ = m.data_; - } - return *this; -} - Matrix Matrix::operator*(const Matrix& m) const { if (cols_ != m.rows_) { throw std::invalid_argument("Matrix dimensions are not compatible for multiplication."); @@ -89,58 +89,54 @@ Matrix Matrix::operator*(const Matrix& m) const { Matrix result(rows_, m.cols_); for (size_t i = 0; i < rows_; ++i) { for (size_t j = 0; j < m.cols_; ++j) { + double sum = 0.0; for (size_t k = 0; k < cols_; ++k) { - result.data_[i][j] += data_[i][k] * m.data_[k][j]; + sum += (*this)[i][k] * m[k][j]; } + result[i][j] = sum; } } return result; } -Matrix Matrix::operator*(const double& scalar) const { - Matrix result(*this); - result *= scalar; - return result; -} - Point3 Matrix::operator*(const Point3& p) const { - if (rows_ == 3 && cols_ == 3) { - // Lógica para Matriz 3x3: aplica rotação/escala - double x = data_[0][0] * p.x + data_[0][1] * p.y + data_[0][2] * p.z; - double y = data_[1][0] * p.x + data_[1][1] * p.y + data_[1][2] * p.z; - double z = data_[2][0] * p.x + data_[2][1] * p.y + data_[2][2] * p.z; - return Point3(x, y, z); - - } else if (rows_ == 4 && cols_ == 4) { - // Lógica para Matriz 4x4: aplica rotação/escala E translação - // Coordenada homogênea w=1 para pontos - double x = data_[0][0] * p.x + data_[0][1] * p.y + data_[0][2] * p.z + data_[0][3]; - double y = data_[1][0] * p.x + data_[1][1] * p.y + data_[1][2] * p.z + data_[1][3]; - double z = data_[2][0] * p.x + data_[2][1] * p.y + data_[2][2] * p.z + data_[2][3]; - double w = data_[3][0] * p.x + data_[3][1] * p.y + data_[3][2] * p.z + data_[3][3]; - - if (w != 1.0 && w != 0.0) { - return Point3(x / w, y / w, z / w); - } - return Point3(x, y, z); - - } else { + if (!((rows_ == 3 && cols_ == 3) || (rows_ == 4 && cols_ == 4))) { throw std::domain_error("Matrix must be 3x3 or 4x4 to multiply by a Point3."); } + + double x = (*this)[0][0] * p.x + (*this)[0][1] * p.y + (*this)[0][2] * p.z; + double y = (*this)[1][0] * p.x + (*this)[1][1] * p.y + (*this)[1][2] * p.z; + double z = (*this)[2][0] * p.x + (*this)[2][1] * p.y + (*this)[2][2] * p.z; + double w = 1.0; + + if (rows_ == 4) { // Adiciona a parte da translação e perspectiva + x += (*this)[0][3]; + y += (*this)[1][3]; + z += (*this)[2][3]; + w = (*this)[3][0] * p.x + (*this)[3][1] * p.y + (*this)[3][2] * p.z + (*this)[3][3]; + } + + if (w != 1.0 && w != 0.0) { + return Point3(x / w, y / w, z / w); + } + return Point3(x, y, z); } Vector3 Matrix::operator*(const Vector3& v) const { - if ((rows_ == 3 && cols_ == 3) || (rows_ == 4 && cols_ == 4)) { - // Lógica para Matriz 3x3: aplica rotação/escala - // Lógica para Matriz 4x4: aplica rotação/escala (ignora translação) - // Coordenada homogênea w=0 para vetores - double x = data_[0][0] * v.x + data_[0][1] * v.y + data_[0][2] * v.z; - double y = data_[1][0] * v.x + data_[1][1] * v.y + data_[1][2] * v.z; - double z = data_[2][0] * v.x + data_[2][1] * v.y + data_[2][2] * v.z; - return Vector3(x, y, z); - } else { + if (!((rows_ == 3 && cols_ == 3) || (rows_ == 4 && cols_ == 4))) { throw std::domain_error("Matrix must be 3x3 or 4x4 to multiply by a Vector3."); } + // A multiplicação de vetores ignora a translação (quarta coluna/linha) + double x = (*this)[0][0] * v.x + (*this)[0][1] * v.y + (*this)[0][2] * v.z; + double y = (*this)[1][0] * v.x + (*this)[1][1] * v.y + (*this)[1][2] * v.z; + double z = (*this)[2][0] * v.x + (*this)[2][1] * v.y + (*this)[2][2] * v.z; + return Vector3(x, y, z); +} + +Matrix Matrix::operator*(double scalar) const { + Matrix result(*this); + result *= scalar; + return result; } Matrix& Matrix::operator*=(const Matrix& m) { @@ -148,94 +144,98 @@ Matrix& Matrix::operator*=(const Matrix& m) { return *this; } -Matrix& Matrix::operator*=(const double& scalar) { - for (auto& row : data_) { - for (auto& val : row) { - val *= scalar; - } +Matrix& Matrix::operator*=(double scalar) { + for (double& val : data_) { + val *= scalar; } return *this; } -Matrix::MatrixRow Matrix::operator[](size_t i) { - return MatrixRow(data_.at(i)); -} - -Matrix::ConstMatrixRow Matrix::operator[](size_t i) const { - return ConstMatrixRow(data_.at(i)); -} - - -// --- Implementações das Operações Matemáticas --- +// --- Operações Matemáticas --- double Matrix::determinant() const { if (rows_ != cols_) { throw std::domain_error("Matrix must be square to compute determinant."); } - if (rows_ == 0) return 1; // Determinant of 0x0 matrix is 1 - if (rows_ == 1) return data_[0][0]; - if (rows_ == 2) return data_[0][0] * data_[1][1] - data_[0][1] * data_[1][0]; - - double det = 0; - for (size_t j = 0; j < cols_; ++j) { - Matrix submatrix(rows_ - 1, cols_ - 1); - for (size_t r = 1; r < rows_; ++r) { + size_t n = rows_; + if (n == 0) + return 1.0; + if (n == 1) + return (*this)[0][0]; + if (n == 2) + return (*this)[0][0] * (*this)[1][1] - (*this)[0][1] * (*this)[1][0]; + + // Para matrizes maiores, é mais eficiente usar a decomposição LU, + // mas a expansão por cofatores é mantida aqui para consistência com o original. + double det = 0.0; + for (size_t j = 0; j < n; ++j) { + Matrix submatrix(n - 1, n - 1); + for (size_t r = 1; r < n; ++r) { size_t sub_col = 0; - for (size_t c = 0; c < cols_; ++c) { - if (c != j) { - submatrix.data_[r - 1][sub_col++] = data_[r][c]; - } + for (size_t c = 0; c < n; ++c) { + if (c == j) + continue; + submatrix[r - 1][sub_col++] = (*this)[r][c]; } } double sign = (j % 2 == 0) ? 1.0 : -1.0; - det += sign * data_[0][j] * submatrix.determinant(); + det += sign * (*this)[0][j] * submatrix.determinant(); } return det; } Matrix Matrix::inverse() const { double det = determinant(); - if (det == 0) { + if (std::abs(det) < 1e-9) { // Comparação segura para ponto flutuante throw std::domain_error("Matrix is singular and cannot be inverted."); } size_t n = rows_; + // Cria uma matriz aumentada [A|I] Matrix augmented(n, 2 * n); for (size_t i = 0; i < n; ++i) { for (size_t j = 0; j < n; ++j) { - augmented.data_[i][j] = data_[i][j]; + augmented[i][j] = (*this)[i][j]; } - augmented.data_[i][i + n] = 1; + augmented[i][i + n] = 1.0; } + // Processo de eliminação de Gauss-Jordan for (size_t i = 0; i < n; i++) { + // Encontra o pivô size_t pivot = i; for (size_t j = i + 1; j < n; j++) { - if (std::abs(augmented.data_[j][i]) > std::abs(augmented.data_[pivot][i])) { + if (std::abs(augmented[j][i]) > std::abs(augmented[pivot][i])) { pivot = j; } } - std::swap(augmented.data_[i], augmented.data_[pivot]); + // Troca as linhas + for (size_t k = 0; k < 2 * n; ++k) { + std::swap(augmented[i][k], augmented[pivot][k]); + } - double div = augmented.data_[i][i]; + // Normaliza a linha do pivô + double div = augmented[i][i]; for (size_t j = i; j < 2 * n; j++) { - augmented.data_[i][j] /= div; + augmented[i][j] /= div; } + // Elimina outras entradas na coluna for (size_t j = 0; j < n; j++) { if (i != j) { - double mult = augmented.data_[j][i]; + double mult = augmented[j][i]; for (size_t k = i; k < 2 * n; k++) { - augmented.data_[j][k] -= mult * augmented.data_[i][k]; + augmented[j][k] -= mult * augmented[i][k]; } } } } + // Extrai a matriz inversa da parte direita da matriz aumentada Matrix result(n, n); for (size_t i = 0; i < n; ++i) { for (size_t j = 0; j < n; ++j) { - result.data_[i][j] = augmented.data_[i][j + n]; + result[i][j] = augmented[i][j + n]; } } return result; @@ -245,74 +245,56 @@ Matrix Matrix::transpose() const { Matrix transposed(cols_, rows_); for (size_t i = 0; i < rows_; ++i) { for (size_t j = 0; j < cols_; ++j) { - transposed.data_[j][i] = data_[i][j]; + transposed[j][i] = (*this)[i][j]; } } return transposed; } -// --- Implementações das Funções Estáticas (Factories) --- +// --- Funções Estáticas (Factories) --- Matrix Matrix::identity(size_t n) { - Matrix id(n, n); + Matrix id(n, n); // Já inicializa com zeros for (size_t i = 0; i < n; ++i) { - id.data_[i][i] = 1; + id[i][i] = 1.0; } return id; } -Matrix Matrix::translation(int dimension, std::initializer_list values) { - if (dimension <= 0 || values.size() != static_cast(dimension)) { - throw std::invalid_argument("Invalid dimension or values for translation matrix."); - } - - Matrix t = identity(dimension + 1); - auto val_it = values.begin(); - for (size_t i = 0; i < static_cast(dimension); ++i) { - t.data_[i][dimension] = *val_it++; - } +Matrix Matrix::translation(double tx, double ty, double tz) { + Matrix t = identity(4); + t[0][3] = tx; + t[1][3] = ty; + t[2][3] = tz; return t; } -Matrix Matrix::scaling(int dimension, std::initializer_list values) { - if (dimension <= 0 || values.size() != static_cast(dimension)) { - throw std::invalid_argument("Invalid dimension or values for scaling matrix."); - } - Matrix s = identity(dimension + 1); - auto val_it = values.begin(); - for (size_t i = 0; i < static_cast(dimension); ++i) { - s.data_[i][i] = *val_it++; - } +Matrix Matrix::scaling(double sx, double sy, double sz) { + Matrix s = identity(4); + s[0][0] = sx; + s[1][1] = sy; + s[2][2] = sz; return s; } -Matrix Matrix::rotation2d(double angle) { - Matrix r = identity(3); - double c = std::cos(angle); - double s = std::sin(angle); - r.data_[0][0] = c; r.data_[0][1] = -s; - r.data_[1][0] = s; r.data_[1][1] = c; - return r; -} - -Matrix Matrix::rotation3d(double angle, const Vector3& axis) { +Matrix Matrix::rotation(double angle, const Vector3& axis) { Vector3 a = axis.normalize(); Matrix r = identity(4); double c = cos(angle); double s = sin(angle); double omc = 1.0 - c; - r.data_[0][0] = c + a.x * a.x * omc; - r.data_[0][1] = a.x * a.y * omc - a.z * s; - r.data_[0][2] = a.x * a.z * omc + a.y * s; + r[0][0] = c + a.x * a.x * omc; + r[0][1] = a.x * a.y * omc - a.z * s; + r[0][2] = a.x * a.z * omc + a.y * s; - r.data_[1][0] = a.y * a.x * omc + a.z * s; - r.data_[1][1] = c + a.y * a.y * omc; - r.data_[1][2] = a.y * a.z * omc - a.x * s; + r[1][0] = a.y * a.x * omc + a.z * s; + r[1][1] = c + a.y * a.y * omc; + r[1][2] = a.y * a.z * omc - a.x * s; - r.data_[2][0] = a.z * a.x * omc - a.y * s; - r.data_[2][1] = a.z * a.y * omc + a.x * s; - r.data_[2][2] = c + a.z * a.z * omc; + r[2][0] = a.z * a.x * omc - a.y * s; + r[2][1] = a.z * a.y * omc + a.x * s; + r[2][2] = c + a.z * a.z * omc; return r; } diff --git a/libs/Prism/src/mesh.cpp b/libs/Prism/src/mesh.cpp index b995242..cb6bcc4 100644 --- a/libs/Prism/src/mesh.cpp +++ b/libs/Prism/src/mesh.cpp @@ -5,17 +5,25 @@ namespace Prism { // TODO: Implementar BVH aqui -Mesh::Mesh(ObjReader& reader):material(std::move(reader.curMaterial)){ +Mesh::Mesh(std::string path) { + ObjReader reader(path); + material = std::move(reader.curMaterial); - for(auto& point: reader.vertices){ - points.emplace_back(std::make_shared(point[0],point[1],point[2])); + for (auto& point : reader.vertices) { + points.emplace_back(std::make_shared(point[0], point[1], point[2])); } - for(auto& triangle: reader.triangles){ - mesh.push_back({ - points[triangle[0]], - points[triangle[1]], - points[triangle[2]]} - ); + for (auto& triangle : reader.triangles) { + mesh.push_back({points[triangle[0]], points[triangle[1]], points[triangle[2]]}); + } +}; + +Mesh::Mesh(ObjReader& reader) : material(std::move(reader.curMaterial)) { + + for (auto& point : reader.vertices) { + points.emplace_back(std::make_shared(point[0], point[1], point[2])); + } + for (auto& triangle : reader.triangles) { + mesh.push_back({points[triangle[0]], points[triangle[1]], points[triangle[2]]}); } }; @@ -38,4 +46,4 @@ bool Mesh::hit(const Ray& ray, double t_min, double t_max, HitRecord& rec) const return false; }; -}; +}; // namespace Prism diff --git a/libs/Prism/src/point.cpp b/libs/Prism/src/point.cpp index ce073c9..428d19c 100644 --- a/libs/Prism/src/point.cpp +++ b/libs/Prism/src/point.cpp @@ -1,6 +1,6 @@ #include "Prism/point.hpp" -#include "Prism/vector.hpp" #include "Prism/matrix.hpp" +#include "Prism/vector.hpp" #include namespace Prism { diff --git a/libs/Prism/src/ray.cpp b/libs/Prism/src/ray.cpp index acf30a8..8769fae 100644 --- a/libs/Prism/src/ray.cpp +++ b/libs/Prism/src/ray.cpp @@ -10,13 +10,15 @@ namespace Prism { -Ray::Ray(const Point3& origin_pt, const Vector3& direction_vec) : origin_(origin_pt), direction_(direction_vec.normalize()) { +Ray::Ray(const Point3& origin_pt, const Vector3& direction_vec) + : origin_(origin_pt), direction_(direction_vec.normalize()) { if (direction().magnitude() == 0) { throw std::invalid_argument("Direction vector cannot be zero length."); } } -Ray::Ray(const Point3& origin_pt, const Point3& target_point) : origin_(origin_pt), direction_((target_point - origin_pt).normalize()) { +Ray::Ray(const Point3& origin_pt, const Point3& target_point) + : origin_(origin_pt), direction_((target_point - origin_pt).normalize()) { if (direction().magnitude() == 0) { throw std::invalid_argument("Direction vector cannot be zero length."); } diff --git a/libs/Prism/src/scene.cpp b/libs/Prism/src/scene.cpp index 13ca386..0363792 100644 --- a/libs/Prism/src/scene.cpp +++ b/libs/Prism/src/scene.cpp @@ -1,13 +1,13 @@ #include "Prism/scene.hpp" #include "Prism/color.hpp" #include "Prism/material.hpp" -#include -#include -#include -#include #include +#include +#include +#include #include -#include +#include +#include namespace Prism { @@ -22,27 +22,28 @@ PRISM_EXPORT std::ostream& operator<<(std::ostream& os, const Color& color) { return os; } -Scene::Scene(Camera camera) : camera_(std::move(camera)) {} +Scene::Scene(Camera camera) : camera_(std::move(camera)) { +} void Scene::addObject(std::unique_ptr object) { objects_.push_back(std::move(object)); } bool get_local_time(std::tm* tm_out, const std::time_t* time_in) { - #if defined(_WIN32) || defined(_MSC_VER) - // Usa a versão segura do Windows (MSVC) - return localtime_s(tm_out, time_in) == 0; - #else - // Usa a versão reentrante/segura do Linux e macOS (GCC/Clang) - return localtime_r(time_in, tm_out) != nullptr; - #endif +#if defined(_WIN32) || defined(_MSC_VER) + // Usa a versão segura do Windows (MSVC) + return localtime_s(tm_out, time_in) == 0; +#else + // Usa a versão reentrante/segura do Linux e macOS (GCC/Clang) + return localtime_r(time_in, tm_out) != nullptr; +#endif } std::filesystem::path generate_filename() { auto now = std::chrono::system_clock::now(); auto in_time_t = std::chrono::system_clock::to_time_t(now); - - std::tm time_info; + + std::tm time_info; if (get_local_time(&time_info, &in_time_t)) { std::stringstream ss; @@ -52,7 +53,7 @@ std::filesystem::path generate_filename() { std::cerr << "Error: Could not get local time for filename generation.\n"; std::cerr << "Using fallback filename.\n"; - return "render_fallback.ppm"; + return "render_fallback.ppm"; } void Scene::render() const { @@ -60,21 +61,20 @@ void Scene::render() const { std::filesystem::create_directories(output_dir); auto filename = generate_filename(); auto full_path = output_dir / filename; - + std::ofstream image_file(full_path, std::ios::trunc); if (!image_file.is_open()) { std::cerr << "Error: Could not open the file for writing.\n"; return; } - image_file << "P3\n" - << camera_.pixel_width << " " << camera_.pixel_height << "\n255\n"; + image_file << "P3\n" << camera_.pixel_width << " " << camera_.pixel_height << "\n255\n"; std::clog << "Starting render...\n"; int pixels_done = 0; - for (Ray const &ray : camera_) { + for (Ray const& ray : camera_) { HitRecord closest_hit_rec; bool hit_anything = false; double closest_t = INFINITY; @@ -93,13 +93,15 @@ void Scene::render() const { pixel_color = closest_hit_rec.material->color; } else { Vector3 unit_direction = ray.direction().normalize(); - pixel_color = Color(0,0,0); + pixel_color = Color(0, 0, 0); } - + image_file << pixel_color << '\n'; if (++pixels_done % camera_.pixel_width == 0) { - double percent = (static_cast(pixels_done) / (camera_.pixel_height * camera_.pixel_width)) * 100.0; + double percent = + (static_cast(pixels_done) / (camera_.pixel_height * camera_.pixel_width)) * + 100.0; std::clog << "\rProgress: " << static_cast(percent) << "%" << std::flush; } } diff --git a/libs/Prism/src/sphere.cpp b/libs/Prism/src/sphere.cpp index 494b250..749dfc5 100644 --- a/libs/Prism/src/sphere.cpp +++ b/libs/Prism/src/sphere.cpp @@ -20,7 +20,7 @@ bool Sphere::hit(const Ray& ray, double t_min, double t_max, HitRecord& rec) con Ray transformed_ray = ray.transform(inverseTransform); Vector3 oc = transformed_ray.origin() - center; - + auto a = sqr(transformed_ray.direction().magnitude()); auto halfb = oc * transformed_ray.direction(); auto c = oc.dot(oc) - sqr(radius); diff --git a/libs/Prism/src/vector.cpp b/libs/Prism/src/vector.cpp index b7e4d1f..543b725 100644 --- a/libs/Prism/src/vector.cpp +++ b/libs/Prism/src/vector.cpp @@ -1,6 +1,6 @@ #include "Prism/vector.hpp" -#include "Prism/point.hpp" #include "Prism/matrix.hpp" +#include "Prism/point.hpp" #include #include diff --git a/src/main.cpp b/src/main.cpp index ed8e8a6..b69e8a2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,44 +12,53 @@ int main() { int image_width = 480; int image_height = static_cast(image_width / aspect_ratio); - Prism::Camera cam(lookfrom, lookat, vup, 2.0, 2.0, 2.0 * aspect_ratio, image_height, image_width); + Prism::Camera cam(lookfrom, lookat, vup, 2.0, 2.0, 2.0 * aspect_ratio, image_height, + image_width); // Criação da Cena Prism::Scene scene(std::move(cam)); - //Objreader - Prism :: ObjReader reader("./data/input/cubo.obj"); + // Objreader + Prism ::ObjReader reader("./data/input/cubo.obj"); // Criação dos Materiais auto material_chao = std::make_shared(Prism::Color(0.8, 0.8, 0.8)); - auto material_esfera_1 = std::make_shared(Prism::Color(1.0, 0.3, 0.3)); // Vermelho/Rosa - auto material_esfera_2 = std::make_shared(Prism::Color(0.3, 0.3, 1.0)); // Azul + auto material_esfera_1 = + std::make_shared(Prism::Color(1.0, 0.3, 0.3)); // Vermelho/Rosa + auto material_esfera_2 = std::make_shared(Prism::Color(0.3, 0.3, 1.0)); // Azul // Adição dos Objetos à Cena - + auto cube = std::make_unique(reader); - Prism::Matrix teste = Prism::Matrix(4,4); - teste[0][0] = 1; teste[0][1] = 0; teste[0][2] = 0; teste[0][3] = 2; - teste[1][0] = 0; teste[1][1] = 1; teste[1][2] = 0; teste[1][3] = 2; - teste[2][0] = 0; teste[2][1] = 0; teste[2][2] = 1; teste[2][3] = 0; - teste[3][0] = 0; teste[3][1] = 0; teste[3][2] = 0; teste[3][3] = 1; + Prism::Matrix teste = Prism::Matrix(4, 4); + teste[0][0] = 1; + teste[0][1] = 0; + teste[0][2] = 0; + teste[0][3] = 2; + teste[1][0] = 0; + teste[1][1] = 1; + teste[1][2] = 0; + teste[1][3] = 2; + teste[2][0] = 0; + teste[2][1] = 0; + teste[2][2] = 1; + teste[2][3] = 0; + teste[3][0] = 0; + teste[3][1] = 0; + teste[3][2] = 0; + teste[3][3] = 1; cube->setTransform( - // Prism::Matrix::translation(3, {2, 2, 0}) * - teste * - Prism::Matrix::rotation3d(45, {1, 0, 0}) * - Prism::Matrix::scaling(3, {0.5, 0.5, 0.5}) - ); + // Prism::Matrix::translation(3, {2, 2, 0}) * + teste * Prism::Matrix::rotation(45, {1, 0, 0}) * Prism::Matrix::scaling(0.5, 0.5, 0.5)); scene.addObject(std::move(cube)); - auto plane = std::make_unique( - Prism::Point3(0, -0.5, 0), Prism::Vector3(0, 1, 0), material_chao - ); + auto plane = std::make_unique(Prism::Point3(0, -0.5, 0), Prism::Vector3(0, 1, 0), + material_chao); - // plane->setTransform(Prism::Matrix::rotation3d(45, {1,0,0})); - + // plane->setTransform(Prism::Matrix::rotation(45, {1,0,0})); scene.addObject(std::move(plane)); diff --git a/tests/src/MatrixTest.cpp b/tests/src/MatrixTest.cpp index a848d74..8f38d55 100644 --- a/tests/src/MatrixTest.cpp +++ b/tests/src/MatrixTest.cpp @@ -1,4 +1,5 @@ #include "Prism/matrix.hpp" +#include "Prism/point.hpp" #include "Prism/vector.hpp" #include "TestHelpers.hpp" #include @@ -9,6 +10,7 @@ #endif using Prism::Matrix; +using Prism::Point3; using Prism::Vector3; TEST(MatrixTest, Construction) { @@ -16,6 +18,7 @@ TEST(MatrixTest, Construction) { ASSERT_EQ(m1.getRows(), 2); ASSERT_EQ(m1.getCols(), 3); + // Verifica se a matriz é inicializada com zeros for (size_t i = 0; i < 2; ++i) { for (size_t j = 0; j < 3; ++j) { ASSERT_DOUBLE_EQ(m1[i][j], 0.0); @@ -30,7 +33,8 @@ TEST(MatrixTest, Construction) { Matrix m3(m2); ASSERT_TRUE(m3 == m2); - ASSERT_THROW(Matrix m_err(0, 5), std::invalid_argument); + // Verifica se o construtor de lista de inicialização lança exceção para linhas de tamanhos + // diferentes ASSERT_THROW(([]() { Matrix m_err_list = {{1, 2}, {3}}; })(), std::invalid_argument); } @@ -47,7 +51,8 @@ TEST(MatrixTest, AccessAndAssignment) { ASSERT_DOUBLE_EQ(m2[0][1], 42.0); ASSERT_TRUE(m1 == m2); - ASSERT_THROW(m1[5][5], std::out_of_range); + // NOTA: A checagem de acesso fora dos limites não é mais feita para performance. + // ASSERT_THROW(m1[5][5], std::out_of_range); // Este teste foi removido. } TEST(MatrixTest, Equality) { @@ -73,7 +78,6 @@ TEST(MatrixTest, Multiplication) { Matrix m_err(5, 5); ASSERT_THROW(m1 * m_err, std::invalid_argument); - ASSERT_THROW(m1 * m_err, std::invalid_argument); Matrix m_scalar = {{1, 2}, {3, 4}}; Matrix result_scalar = m_scalar * 2.0; @@ -84,17 +88,14 @@ TEST(MatrixTest, Multiplication) { ASSERT_TRUE(m_scalar == expected_scalar); } -TEST(MatrixTest, DefaultConstructorCreates3x3ZeroMatrix) { +TEST(MatrixTest, DefaultConstructorCreates3x3IdentityMatrix) { Matrix m; ASSERT_EQ(m.getRows(), 3); ASSERT_EQ(m.getCols(), 3); - for (size_t i = 0; i < 3; ++i) { - for (size_t j = 0; j < 3; ++j) { - ASSERT_DOUBLE_EQ(m[i][j], 0); - } - } + Matrix expected = Matrix::identity(3); + ASSERT_TRUE(m == expected); } TEST(MatrixTest, Inverse) { @@ -104,7 +105,7 @@ TEST(MatrixTest, Inverse) { AssertMatrixAlmostEqual(inv, expected_inv); - // Test with a non-invertible matrix + // Teste com matriz não inversível Matrix singular = {{1, 2}, {2, 4}}; ASSERT_THROW(singular.inverse(), std::domain_error); } @@ -115,11 +116,6 @@ TEST(MatrixTest, Determinant) { Matrix m2 = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; ASSERT_DOUBLE_EQ(m2.determinant(), 1.0); - - Matrix m3 = {{1, 2}, {3, 5}}; - ASSERT_DOUBLE_EQ(m3.determinant(), -1.0); - - Matrix singular = {{1, 2}, {2, 4}}; } TEST(MatrixTest, Transpose) { @@ -128,13 +124,6 @@ TEST(MatrixTest, Transpose) { Matrix expected = {{1, 4}, {2, 5}, {3, 6}}; AssertMatrixAlmostEqual(transposed, expected); - Matrix m_square = {{1, 2}, {3, 4}}; - Matrix expected_square = {{1, 3}, {2, 4}}; - AssertMatrixAlmostEqual(m_square.transpose(), expected_square); - - Matrix m_symmetric = {{1, 8, 7}, {8, 2, 4}, {7, 4, 3}}; - AssertMatrixAlmostEqual(m_symmetric.transpose(), m_symmetric); - Matrix m_identity = Matrix::identity(3); AssertMatrixAlmostEqual(m_identity.transpose(), m_identity); } @@ -156,48 +145,29 @@ TEST(MatrixTest, IdentityMatrix) { } TEST(MatrixTest, TranslationMatrix) { - Matrix translation = Matrix::translation(2, {3.0, 4.0}); - ASSERT_EQ(translation.getRows(), 3); - ASSERT_EQ(translation.getCols(), 3); - ASSERT_DOUBLE_EQ(translation[0][2], 3.0); - ASSERT_DOUBLE_EQ(translation[1][2], 4.0); - ASSERT_DOUBLE_EQ(translation[2][2], 1.0); - - // Test with invalid dimension - ASSERT_THROW(Matrix::translation(-1, {1.0}), std::invalid_argument); - ASSERT_THROW(Matrix::translation(2, {1.0}), std::invalid_argument); + Matrix translation = Matrix::translation(3.0, 4.0, 5.0); + ASSERT_EQ(translation.getRows(), 4); + ASSERT_EQ(translation.getCols(), 4); + ASSERT_DOUBLE_EQ(translation[0][3], 3.0); + ASSERT_DOUBLE_EQ(translation[1][3], 4.0); + ASSERT_DOUBLE_EQ(translation[2][3], 5.0); + ASSERT_DOUBLE_EQ(translation[3][3], 1.0); } TEST(MatrixTest, ScalingMatrix) { - Matrix scaling = Matrix::scaling(2, {2.0, 3.0}); - ASSERT_EQ(scaling.getRows(), 3); - ASSERT_EQ(scaling.getCols(), 3); + Matrix scaling = Matrix::scaling(2.0, 3.0, 4.0); + ASSERT_EQ(scaling.getRows(), 4); + ASSERT_EQ(scaling.getCols(), 4); ASSERT_DOUBLE_EQ(scaling[0][0], 2.0); ASSERT_DOUBLE_EQ(scaling[1][1], 3.0); - ASSERT_DOUBLE_EQ(scaling[2][2], 1.0); - - // Test with invalid dimension - ASSERT_THROW(Matrix::scaling(-1, {1.0}), std::invalid_argument); - ASSERT_THROW(Matrix::scaling(2, {1.0}), std::invalid_argument); -} - -TEST(MatrixTest, Rotation2D) { - double angle = M_PI / 4; // 45 degrees - Matrix rotation = Matrix::rotation2d(angle); - ASSERT_EQ(rotation.getRows(), 3); - ASSERT_EQ(rotation.getCols(), 3); - - ASSERT_NEAR(rotation[0][0], std::cos(angle), 1e-9); - ASSERT_NEAR(rotation[0][1], -std::sin(angle), 1e-9); - ASSERT_NEAR(rotation[1][0], std::sin(angle), 1e-9); - ASSERT_NEAR(rotation[1][1], std::cos(angle), 1e-9); - ASSERT_DOUBLE_EQ(rotation[2][2], 1.0); + ASSERT_DOUBLE_EQ(scaling[2][2], 4.0); + ASSERT_DOUBLE_EQ(scaling[3][3], 1.0); } -TEST(MatrixTest, Rotation3D) { - Vector3 axis(1, 0, 0); // Rotation around x-axis - double angle = M_PI / 4; // 45 degrees - Matrix rotation = Matrix::rotation3d(angle, axis); +TEST(MatrixTest, Rotation) { + Vector3 axis(1, 0, 0); // Rotação em torno do eixo x + double angle = M_PI / 4; // 45 graus + Matrix rotation = Matrix::rotation(angle, axis); ASSERT_EQ(rotation.getRows(), 4); ASSERT_EQ(rotation.getCols(), 4); @@ -210,77 +180,53 @@ TEST(MatrixTest, Rotation3D) { } TEST(MatrixTest, MultiplyByPoint) { - Prism::Point3 p(1.0, 2.0, 3.0); - - // Teste com identidade 3x3 - Prism::Matrix id3 = Prism::Matrix::identity(3); - AssertPointAlmostEqual(id3 * p, p); - - // Teste com escala 3x3 - Prism::Matrix scale3 = Prism::Matrix::scaling( - 3, {2.0, 3.0, 4.0}); // Isso criará uma matriz 4x4, vamos criar uma 3x3 manualmente - Prism::Matrix manual_scale3 = {{2.0, 0.0, 0.0}, {0.0, 3.0, 0.0}, {0.0, 0.0, 4.0}}; - Prism::Point3 expected_scaled_p(2.0, 6.0, 12.0); - AssertPointAlmostEqual(manual_scale3 * p, expected_scaled_p); - AssertPointAlmostEqual(scale3 * p, expected_scaled_p); + Point3 p(1.0, 2.0, 3.0); // Teste com identidade 4x4 - Prism::Matrix id4 = Prism::Matrix::identity(4); + Matrix id4 = Matrix::identity(4); AssertPointAlmostEqual(id4 * p, p); // Teste com translação 4x4 - Prism::Matrix translation_matrix = Prism::Matrix::translation(3, {5.0, -2.0, 1.0}); - Prism::Point3 expected_translated_p(6.0, 0.0, 4.0); + Matrix translation_matrix = Matrix::translation(5.0, -2.0, 1.0); + Point3 expected_translated_p(6.0, 0.0, 4.0); AssertPointAlmostEqual(translation_matrix * p, expected_translated_p); // Teste com transformação combinada (escala e depois translação) - Prism::Matrix s = Prism::Matrix::scaling(3, {2.0, 2.0, 2.0}); - Prism::Matrix t = Prism::Matrix::translation(3, {1.0, 1.0, 1.0}); - Prism::Matrix combined = t * s; // Aplica escala, depois translação - Prism::Point3 expected_combined_p(3.0, 5.0, 7.0); // p*2 -> (2,4,6), +1 -> (3,5,7) + Matrix s = Matrix::scaling(2.0, 2.0, 2.0); + Matrix t = Matrix::translation(1.0, 1.0, 1.0); + Matrix combined = t * s; // Aplica escala, depois translação + Point3 expected_combined_p(3.0, 5.0, 7.0); // p*2 -> (2,4,6), +1 -> (3,5,7) AssertPointAlmostEqual(combined * p, expected_combined_p); } -// Testa a multiplicação de Matriz por Vetor TEST(MatrixTest, MultiplyByVector) { - Prism::Vector3 v(1.0, 2.0, 3.0); - - // Teste com identidade 3x3 - Prism::Matrix id3 = Prism::Matrix::identity(3); - AssertVectorAlmostEqual(id3 * v, v); - - // Teste com escala 3x3 - Prism::Matrix manual_scale3 = {{2.0, 0.0, 0.0}, {0.0, 3.0, 0.0}, {0.0, 0.0, 4.0}}; - Prism::Vector3 expected_scaled_v(2.0, 6.0, 12.0); - AssertVectorAlmostEqual(manual_scale3 * v, expected_scaled_v); + Vector3 v(1.0, 2.0, 3.0); // Teste com identidade 4x4 - Prism::Matrix id4 = Prism::Matrix::identity(4); + Matrix id4 = Matrix::identity(4); AssertVectorAlmostEqual(id4 * v, v); // Teste com translação 4x4 - O VETOR NÃO DEVE MUDAR! - Prism::Matrix translation_matrix = Prism::Matrix::translation(3, {5.0, -2.0, 1.0}); + Matrix translation_matrix = Matrix::translation(5.0, -2.0, 1.0); AssertVectorAlmostEqual(translation_matrix * v, v); // Essencial: translação não afeta vetores // Teste com transformação combinada (escala e depois translação) - Prism::Matrix s = Prism::Matrix::scaling(3, {2.0, 2.0, 2.0}); - Prism::Matrix t = Prism::Matrix::translation(3, {1.0, 1.0, 1.0}); - Prism::Matrix combined = t * s; - Prism::Vector3 expected_combined_v(2.0, 4.0, 6.0); // Vetor é escalado, mas não transladado + Matrix s = Matrix::scaling(2.0, 2.0, 2.0); + Matrix t = Matrix::translation(1.0, 1.0, 1.0); + Matrix combined = t * s; + Vector3 expected_combined_v(2.0, 4.0, 6.0); // Vetor é escalado, mas não transladado AssertVectorAlmostEqual(combined * v, expected_combined_v); // Teste com rotação - Prism::Matrix rot = - Prism::Matrix::rotation3d(M_PI / 2.0, {0, 1, 0}); // Rotação de 90 graus em torno do eixo Y - Prism::Vector3 rotated_v = rot * Prism::Vector3(1, 0, 0); - AssertVectorAlmostEqual(rotated_v, Prism::Vector3(0, 0, -1), 1e-9); + Matrix rot = Matrix::rotation(M_PI / 2.0, {0, 1, 0}); // Rotação de 90 graus em torno do eixo Y + Vector3 rotated_v = rot * Vector3(1, 0, 0); + AssertVectorAlmostEqual(rotated_v, Vector3(0, 0, -1), 1e-9); } -// Testa o lançamento de exceções para dimensões inválidas TEST(MatrixTest, MultiplyThrowsOnInvalidDimensions) { - Prism::Matrix m5x5 = Prism::Matrix::identity(5); - Prism::Vector3 v(1, 2, 3); - Prism::Point3 p(1, 2, 3); + Matrix m5x5 = Matrix::identity(5); + Vector3 v(1, 2, 3); + Point3 p(1, 2, 3); ASSERT_THROW(m5x5 * v, std::domain_error); ASSERT_THROW(m5x5 * p, std::domain_error); diff --git a/tests/src/Point3Test.cpp b/tests/src/Point3Test.cpp index 6d2314d..2e067ec 100644 --- a/tests/src/Point3Test.cpp +++ b/tests/src/Point3Test.cpp @@ -1,13 +1,13 @@ +#include "Prism/matrix.hpp" #include "Prism/point.hpp" #include "Prism/utils.hpp" #include "Prism/vector.hpp" -#include "Prism/matrix.hpp" #include "TestHelpers.hpp" #include +using Prism::Matrix; using Prism::Point3; using Prism::Vector3; -using Prism::Matrix; TEST(Point3Test, ConstructorsAndAssignment) { Point3 p1(1.0, 2.0, 3.0); diff --git a/tests/src/SphereTest.cpp b/tests/src/SphereTest.cpp index 489f127..a2971b9 100644 --- a/tests/src/SphereTest.cpp +++ b/tests/src/SphereTest.cpp @@ -1,7 +1,7 @@ #include "Prism.hpp" #include "TestHelpers.hpp" -#include #include +#include #include using namespace Prism; @@ -37,7 +37,7 @@ TEST(SphereTest, Miss) { TEST(SphereTest, Tangent) { Point3 center(0.0L, 0.0L, 0.0L); auto material = std::make_shared(Color(1.0f, 0.0f, 0.0f)); - Sphere sphere( center, 1.0L, material); + Sphere sphere(center, 1.0L, material); Ray ray(Point3(0.0L, 1.0L, -5.0L), Vector3(0.0L, 0.0L, 1.0L)); HitRecord rec; diff --git a/tests/src/TransformationsTest.cpp b/tests/src/TransformationsTest.cpp index 02f9c28..0e608d5 100644 --- a/tests/src/TransformationsTest.cpp +++ b/tests/src/TransformationsTest.cpp @@ -1,6 +1,6 @@ +#include #include #include -#include #ifndef M_PI #define M_PI 3.14159265358979323846 @@ -16,7 +16,7 @@ TEST(TransformationsTest, RayTransform) { // Arrange Ray r(Point3(0, 0, 0), Vector3(0, 0, 1)); // CORREÇÃO: Passando a dimensão (3D) e a lista de valores - Matrix translation = Matrix::translation(3, {10, 5, -3}); + Matrix translation = Matrix::translation(10, 5, -3); // Act Ray transformed_r = r.transform(translation); @@ -31,7 +31,7 @@ TEST(TransformationsTest, SphereHitWithTranslation) { // Arrange auto s = std::make_shared(Point3(0, 0, 0), 1.0, nullptr); // CORREÇÃO: Passando a dimensão (3D) e a lista de valores - Matrix translation = Matrix::translation(3, {10, 0, 0}); + Matrix translation = Matrix::translation(10, 0, 0); s->setTransform(translation); Ray ray_that_hits(Point3(10, 0, -5), Vector3(0, 0, 1)); @@ -52,7 +52,7 @@ TEST(TransformationsTest, SphereHitWithNonUniformScale) { // Arrange auto s = std::make_shared(Point3(0, 0, 0), 1.0, nullptr); // Estica a esfera 2x no eixo Y - Matrix scale = Matrix::scaling(3, {1, 2, 1}); + Matrix scale = Matrix::scaling(1, 2, 1); s->setTransform(scale); // Atira um raio de cima para baixo, em direção ao topo da esfera esticada @@ -61,19 +61,18 @@ TEST(TransformationsTest, SphereHitWithNonUniformScale) { // Act & Assert EXPECT_TRUE(s->hit(ray_that_hits, 0, 100, rec)); - EXPECT_NEAR(rec.t, 1.5, 1e-6); - + EXPECT_NEAR(rec.t, 1.5, 1e-6); + // As asserções mais importantes (ponto e normal em espaço global) continuam as mesmas. AssertPointAlmostEqual(rec.p, Point3(0, 2, 0)); AssertVectorAlmostEqual(rec.normal, Vector3(0, 1, 0)); } - // Testa a colisão com um plano rotacionado TEST(TransformationsTest, PlaneHitWithRotation) { // Arrange auto p = std::make_shared(Point3(0, 0, 0), Vector3(0, 1, 0), nullptr); - Matrix rotation = Matrix::rotation3d(M_PI / 2.0, Vector3(0, 0, 1)); + Matrix rotation = Matrix::rotation(M_PI / 2.0, Vector3(0, 0, 1)); p->setTransform(rotation); Ray ray_that_hits(Point3(-5, 0, 0), Vector3(1, 0, 0)); @@ -92,13 +91,9 @@ TEST(TransformationsTest, PlaneHitWithRotation) { // Testa a colisão com um triângulo transladado TEST(TransformationsTest, TriangleHitWithTranslation) { // Arrange - auto tri = std::make_shared( - Point3(0, 0, 0), - Point3(1, 0, 0), - Point3(0, 1, 0), - nullptr - ); - Matrix translation = Matrix::translation(3, {0, 0, 5}); + auto tri = + std::make_shared(Point3(0, 0, 0), Point3(1, 0, 0), Point3(0, 1, 0), nullptr); + Matrix translation = Matrix::translation(0, 0, 5); tri->setTransform(translation); Ray ray_that_hits(Point3(0.25, 0.25, 0), Vector3(0, 0, 1)); @@ -117,18 +112,26 @@ TEST(TransformationsTest, TriangleHitWithTranslation) { class TestableObject : public Object { public: // Implementação mínima para a função virtual pura - bool hit(const Ray&, double, double, HitRecord&) const override { return false; } + bool hit(const Ray&, double, double, HitRecord&) const override { + return false; + } // Funções para acessar as matrizes protegidas da classe base - const Matrix& getTransform() const { return transform; } - const Matrix& getInverseTransform() const { return inverseTransform; } - const Matrix& getInverseTransposeTransform() const { return inverseTransposeTransform; } + const Matrix& getTransform() const { + return transform; + } + const Matrix& getInverseTransform() const { + return inverseTransform; + } + const Matrix& getInverseTransposeTransform() const { + return inverseTransposeTransform; + } }; TEST(TransformationsTest, ObjectSetTransform) { // Arrange TestableObject test_obj; - Matrix t = Matrix::translation(3, {10, 20, 30}); + Matrix t = Matrix::translation(10, 20, 30); Matrix inv_t = t.inverse(); Matrix inv_t_transpose = inv_t.transpose(); diff --git a/tests/src/Vector3Test.cpp b/tests/src/Vector3Test.cpp index cd73671..e578d78 100644 --- a/tests/src/Vector3Test.cpp +++ b/tests/src/Vector3Test.cpp @@ -1,10 +1,10 @@ -#include "Prism/vector.hpp" #include "Prism/matrix.hpp" +#include "Prism/vector.hpp" #include "TestHelpers.hpp" #include -using Prism::Vector3; using Prism::Matrix; +using Prism::Vector3; TEST(Vector3Test, ConstructorsAndAssignment) { Vector3 v1(1.0, 2.0, 3.0); diff --git a/vendor/CMakeLists.txt b/vendor/CMakeLists.txt index de3085a..03e7ab8 100644 --- a/vendor/CMakeLists.txt +++ b/vendor/CMakeLists.txt @@ -1,4 +1 @@ -add_subdirectory(ObjReader) - add_library(vendor INTERFACE) -target_link_libraries(vendor INTERFACE ObjReader) diff --git a/vendor/ObjReader/CMakeLists.txt b/vendor/ObjReader/CMakeLists.txt deleted file mode 100644 index 7888792..0000000 --- a/vendor/ObjReader/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -add_library(ObjReader INTERFACE) - - -target_include_directories(ObjReader INTERFACE "include") \ No newline at end of file diff --git a/vendor/ObjReader/include/ObjReader/Colormap.hpp b/vendor/ObjReader/include/ObjReader/Colormap.hpp deleted file mode 100644 index 2823a61..0000000 --- a/vendor/ObjReader/include/ObjReader/Colormap.hpp +++ /dev/null @@ -1,127 +0,0 @@ - -#ifndef COLORMAPHEADER -#define COLORMAPHEADER - -/* -Classe de leitura de arquivos .mtl, que guarda cores e propriedades de materiais. - -A saber que: - - kd = Difuso (Cor do objeto) - - ks = Specular (Reflexivo) - - ke = Emissivo - - ka = Ambiente - - ns = Brilho - - ni = Índice de refração - - d = Opacidade - -A classe precisa ser instânciada passando o caminho do arquivo .mtl correspondente -*/ - -#include -#include -#include -#include -#include -#include -#include "Vector.hpp" - -using namespace std; - -struct MaterialProperties { - vetor kd; // Difuso - vetor ks; // Specular - vetor ke; // Emissivo - vetor ka; // Ambiente - double ns; // Brilho - double ni; // Índice de refração - double d; // Opacidade - - MaterialProperties() : kd(0, 0, 0), ks(0, 0, 0), ke(0, 0, 0), ka(0, 0, 0), ns(0), ni(0), d(0) {} -}; - -class colormap { - -public: - map mp; - - //Construtor - colormap(){}; - colormap(string input){ - - // construtor: lê arquivo cores.mtl e guarda valores RGB associados a cada nome - - std::ifstream mtlFile(input); - - if (!mtlFile.is_open()) { - std::cerr << "erro abrindo arquivo cores.mtl\n"; - } - - string line, currentMaterial; - - while (std::getline(mtlFile, line)) { - std::istringstream iss(line); - std::string keyword; - iss >> keyword; - - if (keyword == "newmtl") { - iss >> currentMaterial; - if (!currentMaterial.empty()) { - mp[currentMaterial] = MaterialProperties(); - } - } else if (keyword == "Kd") { - double kdR, kdG, kdB; - iss >> kdR >> kdG >> kdB; - if (!currentMaterial.empty()) { - mp[currentMaterial].kd = vetor(kdR, kdG, kdB); - } - } else if (keyword == "Ks") { - double ksR, ksG, ksB; - iss >> ksR >> ksG >> ksB; - if (!currentMaterial.empty()) { - mp[currentMaterial].ks = vetor(ksR, ksG, ksB); - } - } else if (keyword == "Ke") { - double keR, keG, keB; - iss >> keR >> keG >> keB; - if (!currentMaterial.empty()) { - mp[currentMaterial].ke = vetor(keR, keG, keB); - } - } else if (keyword == "Ka") { - double kaR, kaG, kaB; - iss >> kaR >> kaG >> kaB; - if (!currentMaterial.empty()) { - mp[currentMaterial].ka = vetor(kaR, kaG, kaB); - } - } else if (keyword == "Ns") { - iss >> mp[currentMaterial].ns; - } else if (keyword == "Ni") { - iss >> mp[currentMaterial].ni; - } else if (keyword == "d") { - iss >> mp[currentMaterial].d; - } - } - - mtlFile.close(); - } - - vetor getColor(string& s){ - if (mp.find(s) != mp.end()) { - return mp[s].kd; - } else { - cerr << "Error: cor " << s << " indefinida no arquivo .mtl\n"; - return vetor(0,0,0); - } - } - - MaterialProperties getMaterialProperties(string& s){ - if (mp.find(s) != mp.end()) { - return mp[s]; - } else { - cerr << "Error: Cor " << s << " indefinida no arquivo .mtl\n"; - return MaterialProperties(); - } - } - -}; - -#endif diff --git a/vendor/ObjReader/include/ObjReader/ObjReader.hpp b/vendor/ObjReader/include/ObjReader/ObjReader.hpp deleted file mode 100644 index 66fb019..0000000 --- a/vendor/ObjReader/include/ObjReader/ObjReader.hpp +++ /dev/null @@ -1,213 +0,0 @@ -#ifndef OBJREADERHEADER -#define OBJREADERHEADER - -/* -Classe leitora de arquivos .obj. Onde o arquivo contém os vários pontos, normais e faces do objeto. No projeto -trabalhamos com faces triangulares, ou seja, uma face consiste em 3 pontos. - -No arquivo .obj, temos: - - v = pontos - - vn = normais - - vt = texturas - - f = faces - -Nessa classe podem ser obtidas as seguintes informações (por meio dos Getters): - - Pontos - - Normais - - Lista de faces com seus respectivos pontos - - Informações de cor, brilho, opacidade, etc. - -Obs: - Para fins de abstração, as normais de cada ponto são ignoradas e assumimos apenas uma normal para cada face. - - As texturas também são ignoradas. - -Caso sintam necessidade, podem editar a classe para obter mais informações. -*/ - - -#include -#include -#include -#include -#include -#include "Vector.hpp" -#include "Point.hpp" -#include "Colormap.hpp" - -struct Face { - int verticeIndice[3]; - int normalIndice[3]; - vetor ka; - vetor kd; - vetor ks; - vetor ke; - double ns; - double ni; - double d; - - Face() { - for (int i = 0; i < 3; ++i) { - verticeIndice[i] = 0; - normalIndice[i] = 0; - } - ka = vetor(); - kd = vetor(); - ks = vetor(); - ke = vetor(); - ns = 0.0; - ni = 0.0; - d = 0.0; - } -}; - -class objReader { - -private: - std::ifstream file; // Arquivo .obj - std::vector vertices; // Lista de pontos - std::vector normals; // Lista de normais - std::vector faces; // Lista de indices de faces - std::vector> facePoints; // Lista de pontos das faces - MaterialProperties curMaterial; // Material atual - colormap cmap; // Objeto de leitura de arquivos .mtl - -public: - objReader(std::string filename) : cmap(cmap) { - - // Abre o arquivo - file.open(filename); - if (!file.is_open()) { - std::cerr << "Erro ao abrir o arquivo: " << filename << std::endl; - return; - } - - // Leitura do arquivo - std::string line, mtlfile, colorname, filename_mtl; - while (std::getline(file, line)) { - std::istringstream iss(line); - std::string prefix; - iss >> prefix; - - if (prefix == "mtllib") { - iss >> filename_mtl; - std::string filename_mtl_path = filename.replace(filename.length() - 3, 3, "mtl"); - cmap = colormap(filename_mtl_path); - } else if (prefix == "usemtl") { - iss >> colorname; - curMaterial = cmap.getMaterialProperties(colorname); - } else if (prefix == "v") { - double x, y, z; - iss >> x >> y >> z; - vertices.emplace_back(x, y, z); - } else if (prefix == "vn") { - double x, y, z; - iss >> x >> y >> z; - normals.emplace_back(x, y, z); - } else if (prefix == "f") { - Face face; - char slash; - for (int i = 0; i < 3; ++i) { - int _; - iss >> face.verticeIndice[i] >> slash >> _ >> slash >> face.normalIndice[i]; - face.ka = curMaterial.ka; - face.kd = curMaterial.kd; - face.ks = curMaterial.ks; - face.ke = curMaterial.ke; - face.ns = curMaterial.ns; - face.ni = curMaterial.ni; - face.d = curMaterial.d; - face.verticeIndice[i]--; - face.normalIndice[i]--; - } - faces.push_back(face); - } - - } - for (const auto& face : faces) { - std::vector points = { - vertices[face.verticeIndice[0]], - vertices[face.verticeIndice[1]], - vertices[face.verticeIndice[2]] - }; - facePoints.push_back(points); - } - - file.close(); - } - - // Getters - - // Método para retornar as coordenadas dos pontos das faces - std::vector> getFacePoints() { - return facePoints; - } - - /* - Retorna uma lista com um struct faces do objeto. Cada face contém: - - Índices dos pontos - - Índices das normais - - Cores (ka, kd, ks, ke) - - Brilho (ns) - - Índice de refração (ni) - - Opacidade (d) - */ - std::vector getFaces() { - return faces; - } - - // Método para retornar a cor do material (Coeficiente de difusão) - vetor getKd() { - return curMaterial.kd; - } - - // Método para retornar a cor do ambiente - vetor getKa() { - return curMaterial.ka; - } - - // Método para retornar o coeficiente especular (Refletência) - vetor getKe() { - return curMaterial.ke; - } - - // Método para retornar o coeficiente de brilho - double getNs() { - return curMaterial.ns; - } - - // Método para retornar o índice de refração - double getNi() { - return curMaterial.ni; - } - - // Método para retornar o coeficiente de especularidade - vetor getKs() { - return curMaterial.ks; - } - - // Método para retornar o indice de opacidade - double getD() { - return curMaterial.d; - } - - // Método para retornar as coordenadas dos pontos - std::vector getVertices() { - return vertices; - } - - - // Emite um output no terminal para cada face, com seus respectivos pontos (x, y, z) - void print_faces() { - int i = 0; - for (const auto& face : facePoints) { - i++; - std::clog << "Face " << i << ": "; - for (const auto& point : face) { - std::cout << "(" << point.getX() << ", " << point.getY() << ", " << point.getZ() << ")"; - } - std::cout << flush; - std::clog << std::endl; - } - } -}; - -#endif \ No newline at end of file diff --git a/vendor/ObjReader/include/ObjReader/Point.hpp b/vendor/ObjReader/include/ObjReader/Point.hpp deleted file mode 100644 index 1342398..0000000 --- a/vendor/ObjReader/include/ObjReader/Point.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef POINTHEADER -#define POINTHEADER - -#include - -/* -Classe de pontos. - -A saber que: - - x = componente x - - y = componente y - - z = componente z - -A classe precisa ser instanciada passando as componentes x, y e z -*/ - -class point{ - private: - double x; - double y; - double z; -public: - - //Construtores - point() {} - point(double x, double y, double z) - { - this->x = x; - this->y = y; - this->z = z; - } - - //Implemente os métodos de pontos aqui - - //Print do vetor no formato (x, y, z) - void print(){ - std::cout << "(" << x << ", " << y << ", " << z << ")" << std::endl; - } - - //Getters - double getX() const { return x; } - double getY() const { return y; } - double getZ() const { return z; } -}; - -#endif \ No newline at end of file diff --git a/vendor/ObjReader/include/ObjReader/Vector.hpp b/vendor/ObjReader/include/ObjReader/Vector.hpp deleted file mode 100644 index 38c6bc9..0000000 --- a/vendor/ObjReader/include/ObjReader/Vector.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef VECTORHEADER -#define VECTORHEADER -#include -#include - -/* -Classe de vetores. - -A saber que: - - x = componente x - - y = componente y - - z = componente z - -A classe precisa ser instanciada passando as componentes x, y e z -*/ - -class vetor{ - private: - double x; - double y; - double z; - - public: - - //Construtores - vetor() {} - vetor(double x, double y, double z){ - this->x = x; - this->y = y; - this->z = z; - } - - //Implemente os métodos de vetores aqui - - //Print do vetor no formato - void print(){ - std::cout << "<" << x << ", " << y << ", " << z << ">" << std::endl; - } - - //Getters - double getX() const { return x; } - double getY() const { return y; } - double getZ() const { return z; } -}; - -#endif \ No newline at end of file