diff --git a/CMakeLists.txt b/CMakeLists.txt index 67725f4..5b5d780 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,8 +7,6 @@ # 设置最小 cmake 版本 cmake_minimum_required(VERSION 3.27 FATAL_ERROR) -set(CMAKE_CXX_STANDARD 20) -set(CMAKE_CXX_STANDARD_REQUIRED True) # 设置项目名与版本 project(SimpleRenderer @@ -42,7 +40,7 @@ set(FONT_FILE_PATH "${wqy_font_SOURCE_DIR}/wqy-zenhei.ttc") include(ProcessorCount) ProcessorCount(NPROC) # 日志文件路径 -set(LOG_FILE_PATH "${PROJECT_SOURCE_DIR}/build/logs/SimpleRendererLog.log") +set(LOG_FILE_PATH "${EXECUTABLE_OUTPUT_PATH}/logs/SimpleRendererLog.log") # 日志文件大小 set(LOG_FILE_MAX_SIZE 1024*1024*4) # 日志文件数量 @@ -50,10 +48,10 @@ set(LOG_FILE_MAX_COUNT 8) # 生成配置头文件 configure_file( "${PROJECT_SOURCE_DIR}/cmake/config.h.in" - "${PROJECT_SOURCE_DIR}/include/config.h" + "${PROJECT_SOURCE_DIR}/src/include/config.h" ) # 添加要编译的目录 add_subdirectory(src) add_subdirectory(test) -add_subdirectory(doc) +add_subdirectory(doc) \ No newline at end of file diff --git a/CMakePresets.json b/CMakePresets.json index cdab07d..6976ac5 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -1,71 +1,84 @@ { - "version": 6, - "cmakeMinimumRequired": { - "major": 3, - "minor": 27, - "patch": 0 - }, - "configurePresets": [ - { - "name": "host", - "description": "Linux Only", - "hidden": true, - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Linux" - } - }, - { - "name": "std", - "description": "This preset makes sure the project actually builds with at least the specified standard", - "hidden": true, - "cacheVariables": { - "CMAKE_C_EXTENSIONS": "OFF", - "CMAKE_C_STANDARD": "23", - "CMAKE_C_STANDARD_REQUIRED": "ON", - "CMAKE_CXX_EXTENSIONS": "OFF", - "CMAKE_CXX_STANDARD": "23", - "CMAKE_CXX_STANDARD_REQUIRED": "ON" - } + "version": 6, + "cmakeMinimumRequired": { + "major": 3, + "minor": 23, + "patch": 0 }, - { - "name": "configurePresets_base", - "hidden": true, - "inherits": [ - "host", - "std" - ], - "displayName": "configurePresets_base", - "description": "base configurePresets", - "binaryDir": "${sourceDir}/build", - "cacheVariables": { - "CMAKE_EXPORT_COMPILE_COMMANDS": { - "type": "BOOL", - "value": "ON" - }, - "EXECUTABLE_OUTPUT_PATH": { - "type": "STRING", - "value": "${sourceDir}/build/bin" - }, - "LIBRARY_OUTPUT_PATH": { - "type": "STRING", - "value": "${sourceDir}/build/lib" - }, - "COVERAGE_OUTPUT_DIR": { - "type": "STRING", - "value": "${sourceDir}/build/coverage" + "configurePresets": [ + { + "name": "std", + "description": "This preset makes sure the project actually builds with at least the specified standard", + "hidden": true, + "cacheVariables": { + "CMAKE_C_EXTENSIONS": "OFF", + "CMAKE_C_STANDARD": "23", + "CMAKE_C_STANDARD_REQUIRED": "ON", + "CMAKE_CXX_EXTENSIONS": "OFF", + "CMAKE_CXX_STANDARD": "23", + "CMAKE_CXX_STANDARD_REQUIRED": "ON" } + }, + { + "name": "config-base", + "hidden": true, + "inherits": [ "std" ], + "displayName": "config-base", + "description": "base configurePresets", + "binaryDir": "${sourceDir}/build", + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "BOOL", + "value": "ON" + }, + "EXECUTABLE_OUTPUT_PATH": { + "type": "STRING", + "value": "${sourceDir}/build/bin" + }, + "LIBRARY_OUTPUT_PATH": { + "type": "STRING", + "value": "${sourceDir}/build/lib" + }, + "COVERAGE_OUTPUT_DIR": { + "type": "STRING", + "value": "${sourceDir}/build/coverage" + } + } + }, + { + "name": "config-macos", + "hidden": true, + "inherits": [ "config-base" ], + "displayName": "config-base", + "description": "macOS configurePresets", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Darwin" + }, + "cacheVariables": { + "CMAKE_MACOSX_RPATH": "1", + "CMAKE_INSTALL_RPATH": "/Library/Frameworks", + "CMAKE_BUILD_WITH_INSTALL_RPATH": "TRUE" + } + }, + { + "name": "build", + "hidden": false, + "inherits": [ + "config-base" + ], + "displayName": "build-base", + "description": "build base configurePresets" + }, + { + "name": "build-macos", + "hidden": false, + "inherits": [ + "config-macos" + ], + "displayName": "build-macos", + "description": "macOS build configurePresets" } - }, - { - "name": "build", - "hidden": false, - "inherits": [ - "configurePresets_base" - ], - "displayName": "build", - "description": "build" - } - ] -} \ No newline at end of file + ] + } \ No newline at end of file diff --git a/cmake/3rd.cmake b/cmake/3rd.cmake index a8937c5..7c06507 100644 --- a/cmake/3rd.cmake +++ b/cmake/3rd.cmake @@ -56,7 +56,7 @@ CPMAddPackage( "gtest_force_shared_crt ON" ) -# SDL2 +# https://github.com/libsdl-org/SDL CPMAddPackage( NAME SDL2 GITHUB_REPOSITORY libsdl-org/SDL @@ -68,8 +68,6 @@ CPMAddPackage( "SDL_STATIC_PIC ON" "SDL_WERROR OFF" ) -find_package(SDL2 REQUIRED) - CPMAddPackage( NAME assimp @@ -81,6 +79,7 @@ CPMAddPackage( "ASSIMP_BUILD_SAMPLES OFF" ) +# https://github.com/g-truc/glm CPMAddPackage( NAME glm GITHUB_REPOSITORY g-truc/glm @@ -214,24 +213,12 @@ if (NOT LCOV_EXE) "Following https://github.com/linux-test-project/lcov to install.") endif () -find_package(SDL2 REQUIRED) -if (NOT SDL2_FOUND) - message(FATAL_ERROR "sdl2 not found.\n" - "Following https://github.com/libsdl-org/SDL to install.") -endif () - find_package(spdlog REQUIRED) if (NOT spdlog_FOUND) message(FATAL_ERROR "spdlog not found.\n" "Following https://github.com/gabime/spdlog to install.") endif () -find_package(glm REQUIRED) -if (NOT glm_FOUND) - message(FATAL_ERROR "glm not found.\n" - "Following https://github.com/g-truc/glm tp install") -endif () - find_package(assimp REQUIRED) if (NOT assimp_FOUND) message(FATAL_ERROR "assimp not found.\n" diff --git a/include/face.hpp b/include/face.hpp deleted file mode 100644 index febb23d..0000000 --- a/include/face.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include "vertex.hpp" -#include "material.hpp" - -#include - -namespace simple_renderer { - -class Face { -public: - // Default constructor - Face() = default; - // Copy constructor - Face(const Face& face) = default; - Face& operator=(const Face& face) = default; - // Move constructor - Face(Face&& face) = default; - Face& operator=(Face&& face) = default; - // Destructor - ~Face() = default; - - explicit Face(const Vertex& v0, const Vertex& v1, const Vertex& v2, Material material) - : vertices_{v0, v1, v2}, material_(std::move(material)) { - calculateNormal(); - } - - void transform(const glm::mat4 &tran) { - vertices_[0].transform(tran); - vertices_[1].transform(tran); - vertices_[2].transform(tran); - } - - const std::array& vertices() const { return vertices_; } - const Vertex& vertex(size_t index) const { return vertices_[index]; } - const glm::vec3& normal() const { return normal_; } - const Material& material() const { return material_; } - -private: - std::array vertices_; - glm::vec3 normal_; - Material material_; - - void calculateNormal() { - glm::vec3 edge1 = glm::vec3(vertices_[1].position()) - glm::vec3(vertices_[0].position()); - glm::vec3 edge2 = glm::vec3(vertices_[2].position()) - glm::vec3(vertices_[0].position()); - normal_ = glm::normalize(glm::cross(edge1, edge2)); - } -}; - -} \ No newline at end of file diff --git a/include/log_math.hpp b/include/log_math.hpp deleted file mode 100755 index 0f86926..0000000 --- a/include/log_math.hpp +++ /dev/null @@ -1,65 +0,0 @@ - -/** - * @file matrix.hpp - * @brief 矩阵 - * @author Zone.N (Zone.Niuzh@hotmail.com) - * @version 1.0 - * @date 2022-09-07 - * @copyright MIT LICENSE - * https://github.com/Simple-XX/SimpleRenderer - * @par change log: - * - *
DateAuthorDescription - *
2022-09-07Zone.N迁移到 doxygen - *
- */ - -#ifndef SIMPLERENDER_SRC_INCLUDE_MATRIX_HPP_ -#define SIMPLERENDER_SRC_INCLUDE_MATRIX_HPP_ - -#define GLM_ENABLE_EXPERIMENTAL -#include - -#include "log_system.h" - -/** - * spdlog 输出 Vector3f 实现 - */ -template <> -struct fmt::formatter : fmt::formatter { - auto format(const glm::vec3 &vector, fmt::format_context &ctx) const -> decltype(ctx.out()) { - std::string vector_string = glm::to_string(vector); - - // Format and output the string - return fmt::format_to(ctx.out(), "\n{}", vector_string); - } -}; - -/** - * spdlog 输出 Vector4f 实现 - */ -template <> -struct fmt::formatter : fmt::formatter { - auto format(const glm::vec4 &vector, fmt::format_context &ctx) const -> decltype(ctx.out()) { - std::string vector_string = glm::to_string(vector); - - // Format and output the string - return fmt::format_to(ctx.out(), "\n{}", vector_string); - } -}; - -/** - * spdlog 输出矩阵实现 - */ -template <> -struct fmt::formatter : fmt::formatter { - auto format(const glm::mat4 &matrix, fmt::format_context &ctx) const -> decltype(ctx.out()) { - // Convert the glm::mat4 to a string using glm::to_string - std::string matrix_str = glm::to_string(matrix); - - // Format and output the string - return fmt::format_to(ctx.out(), "\n{}", matrix_str); - } -}; - -#endif /* SIMPLERENDER_SRC_INCLUDE_MATRIX_HPP_ */ diff --git a/include/material.hpp b/include/material.hpp deleted file mode 100644 index ed489d1..0000000 --- a/include/material.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include - -class Material { -public: - // Default constructor - Material() = default; - // Copy constructor - Material(const Material& material) = default; - Material& operator=(const Material& material) = default; - // Move constructor - Material(Material&& material) = default; - Material& operator=(Material&& material) = default; - // Destructor - ~Material() = default; - - float shininess = 0.0f; - glm::vec3 ambient; - glm::vec3 diffuse; - glm::vec3 specular; -}; \ No newline at end of file diff --git a/include/model.hpp b/include/model.hpp deleted file mode 100755 index 3266c1c..0000000 --- a/include/model.hpp +++ /dev/null @@ -1,68 +0,0 @@ - -/** - * @file model.hpp - * @brief 模型抽象 - * @author Zone.N (Zone.Niuzh@hotmail.com) - * @version 1.0 - * @date 2022-06-06 - * @copyright MIT LICENSE - * https://github.com/Simple-XX/SimpleRenderer - * @par change log: - * - *
DateAuthorDescription - *
2022-09-04Zone.N迁移到 doxygen - *
- */ - -#ifndef SIMPLERENDER_SRC_INCLUDE_MODEL_HPP_ -#define SIMPLERENDER_SRC_INCLUDE_MODEL_HPP_ - -#include - -#include -#include - -#include "color.h" -#include "config.h" -#include "log_system.h" -#include "log_math.hpp" - -#include "vertex.hpp" -#include "face.hpp" - -namespace simple_renderer { - -class Model { -public: - - // Default constructor - Model() = default; - // Default copy constructor - Model(const Model& model) = default; - Model& operator=(const Model& model) = default; - // Default move constructor - Model(Model&& model) = default; - Model& operator=(Model&& model) = default; - ~Model() = default; - - Model(const std::string &model_path); - - void transform(const glm::mat4 &tran); - - const std::vector& faces() const { return faces_; }; - const std::string& modelPath() const { return directory_; }; - -private: - static constexpr const uint8_t kTriangleFaceVertexCount = 3; - std::string directory_; - - std::vector faces_; - - void loadModel(const std::string& path); - void processNode(aiNode* node, const aiScene* scene); - void processMesh(aiMesh* mesh, const aiScene* scene); - Material processMaterial(aiMaterial* material); -}; -} // namespace simple_renderer - -#endif /* SIMPLERENDER_SRC_INCLUDE_MODEL_HPP_ */ \ No newline at end of file diff --git a/include/vertex.hpp b/include/vertex.hpp deleted file mode 100644 index 2b74460..0000000 --- a/include/vertex.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include - -#include "color.h" - -namespace simple_renderer { - -class Vertex { -public: - - // Default constructor - Vertex() = default; - // Copy constructor - Vertex(const Vertex& vertex) = default; - Vertex& operator=(const Vertex& vertex) = default; - // Move constructor - Vertex(Vertex&& vertex) = default; - Vertex& operator=(Vertex&& vertex) = default; - // Destructor - ~Vertex() = default; - - // Constructor with parameters - explicit Vertex(const glm::vec4& pos, const glm::vec3& norm, const glm::vec2& tex, const Color& color_) - : position_(pos), normal_(norm), texCoords_(tex), color_(color_) {} - - // Transform the vertex with a matrix - void transform(const glm::mat4& matrix) { - position_ = matrix * position_; - } - - // Perspective divide to convert from clip space to normalized device coordinates - void perspectiveDivide() { - if (position_.w != 0) { - position_.x /= position_.w; - position_.y /= position_.w; - position_.z /= position_.w; - position_.w = 1.0f; // Homogenize - } - } - - glm::vec4 position() const { return position_; } - glm::vec3 normal() const { return normal_; } - glm::vec2 texCoords() const { return texCoords_; } - Color color() const { return color_; } - -private: - glm::vec4 position_; // Position of the vertex in homogenous coordinates - glm::vec3 normal_; // Normal vector for the vertex - glm::vec2 texCoords_; // Texture coordinates - Color color_; // Color of the vertex -}; - -} \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 912ee68..5b4fe72 100755 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,14 +12,14 @@ file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS add_library(${PROJECT_NAME} STATIC ${SRC_FILES}) target_include_directories(${PROJECT_NAME} PRIVATE - $ - $ + $ + $ ) target_compile_options(${PROJECT_NAME} PRIVATE - ${DEFAULT_COMPILE_OPTIONS} + ${DEFAULT_COMPILE_OPTIONS} ) target_link_libraries(${PROJECT_NAME} PRIVATE - ${DEFAULT_LINK_LIB} -) + ${DEFAULT_LINK_LIB} +) \ No newline at end of file diff --git a/src/default_shader.cpp b/src/default_shader.cpp index 5c8065a..ba1c34e 100644 --- a/src/default_shader.cpp +++ b/src/default_shader.cpp @@ -20,7 +20,7 @@ namespace simple_renderer { auto DefaultShader::InterpolateColor( const Color &color0, const Color &color1, const Color &color2, - const glm::vec3 &barycentric_coord) -> Color { + const Vector3f &barycentric_coord) -> Color { return Color( static_cast(static_cast(color0[Color::kColorIndexRed]) * barycentric_coord.x + @@ -47,10 +47,8 @@ auto DefaultShader::Vertex(const ShaderVertexIn &shader_vertex_in) const -> ShaderVertexOut { auto face(shader_vertex_in.face_); - face.transform( - shader_data_.project_matrix_ - * shader_data_.view_matrix_ - * shader_data_.model_matrix_); + face.transform(shader_data_.project_matrix_ * shader_data_.view_matrix_ * + shader_data_.model_matrix_); /// @todo 变换贴图 return ShaderVertexOut(face); @@ -58,7 +56,8 @@ auto DefaultShader::Vertex(const ShaderVertexIn &shader_vertex_in) const auto DefaultShader::Fragment(const ShaderFragmentIn &shader_fragment_in) const -> ShaderFragmentOut { - auto intensity = glm::dot(shader_fragment_in.normal_,shader_fragment_in.light_); + auto intensity = + glm::dot(shader_fragment_in.normal_, shader_fragment_in.light_); auto is_need_draw = true; // 光照方向为正,不绘制背面 if (intensity <= 0) { diff --git a/include/color.h b/src/include/color.h similarity index 100% rename from include/color.h rename to src/include/color.h diff --git a/include/config.h b/src/include/config.h similarity index 95% rename from include/config.h rename to src/include/config.h index 9427427..fcc39ed 100644 --- a/include/config.h +++ b/src/include/config.h @@ -27,7 +27,7 @@ static constexpr const size_t kNProc = 8; /// 日志文件路径 static const std::string kLogFilePath = - std::string("/Users/hezhohao/Programming/GitRepo/SimpleRenderer/build/logs/SimpleRendererLog.log"); + std::string("/Users/hezhohao/Programming/GitRepo/SimpleRenderer/build/bin/logs/SimpleRendererLog.log"); /// 日志文件大小 static constexpr const size_t kLogFileMaxSize = 1024*1024*4; /// 日志文件数量 diff --git a/include/default_shader.h b/src/include/default_shader.h similarity index 96% rename from include/default_shader.h rename to src/include/default_shader.h index a187577..717c802 100644 --- a/include/default_shader.h +++ b/src/include/default_shader.h @@ -64,7 +64,7 @@ class DefaultShader : public ShaderBase { */ static auto InterpolateColor(const Color &color0, const Color &color1, const Color &color2, - const glm::vec3 &barycentric_coord) -> Color; + const Vector3f &barycentric_coord) -> Color; }; } // namespace simple_renderer diff --git a/src/include/face.hpp b/src/include/face.hpp new file mode 100644 index 0000000..1c0e16f --- /dev/null +++ b/src/include/face.hpp @@ -0,0 +1,78 @@ +#pragma once + +#include + +#include "material.hpp" +#include "vertex.hpp" + +namespace simple_renderer { + +class Face { + public: + // Default constructor + // 默认构造函数 + Face() = default; + + // Copy constructor + // 拷贝构造函数 + Face(const Face& face) = default; + // Copy assignment operator + // 拷贝赋值操作符 + Face& operator=(const Face& face) = default; + + // Move constructor + // 移动构造函数 + Face(Face&& face) = default; + // Move assignment operator + // 移动赋值操作符 + Face& operator=(Face&& face) = default; + + // Destructor + // 析构函数 + ~Face() = default; + + // Constructor that initializes the Face with three vertices and a material + // 使用三个顶点和材质初始化 Face 的构造函数 + explicit Face(const Vertex& v0, const Vertex& v1, const Vertex& v2, + Material material) + : vertices_{v0, v1, v2}, material_(std::move(material)) { + // Calculate the normal vector when the face is created + // 创建 Face 时计算法向量 + calculateNormal(); + } + + // Apply a transformation matrix to the vertices + // 对顶点应用变换矩阵 + void transform(const Matrix4f& tran) { + vertices_[0].transform(tran); + vertices_[1].transform(tran); + vertices_[2].transform(tran); + } + + // Get functions + // 获取函数 + const std::array& vertices() const { return vertices_; } + const Vertex& vertex(size_t index) const { return vertices_[index]; } + const Vector3f& normal() const { return normal_; } + const Material& material() const { return material_; } + + private: + std::array vertices_; + Vector3f normal_; + Material material_; + + // Calculate the normal vector based on the vertices + // 根据顶点计算法向量 + void calculateNormal() { + Vector3f edge1 = + Vector3f(vertices_[1].position()) - Vector3f(vertices_[0].position()); + Vector3f edge2 = + Vector3f(vertices_[2].position()) - Vector3f(vertices_[0].position()); + normal_ = glm::normalize( + // Normalize the cross product to get the + // normal 归一化叉积以获得法向量 + glm::cross(edge1, edge2)); + } +}; + +} // namespace simple_renderer diff --git a/include/light.h b/src/include/light.h similarity index 89% rename from include/light.h rename to src/include/light.h index 52b6964..81fde8e 100644 --- a/include/light.h +++ b/src/include/light.h @@ -21,7 +21,7 @@ #include #include "color.h" -#include "log_math.hpp" +#include "math.hpp" namespace simple_renderer { @@ -33,9 +33,9 @@ class Light { /// 光照名称 std::string name_ = "default light name"; /// 位置 - glm::vec3 pos = kDefaultPos; + Vector3f pos = kDefaultPos; /// 方向 - glm::vec3 dir = kDefaultDir; + Vector3f dir = kDefaultDir; /// 颜色 Color color = kDefaultColor; @@ -57,9 +57,9 @@ class Light { private: /// 默认位置 - static const glm::vec3 kDefaultPos; + static const Vector3f kDefaultPos; /// 默认方向,左手系,x 向右,y 向下,z 正方向为屏幕由内向外 - static const glm::vec3 kDefaultDir; + static const Vector3f kDefaultDir; /// 默认颜色 static const Color kDefaultColor; }; diff --git a/include/log_system.h b/src/include/log_system.h similarity index 100% rename from include/log_system.h rename to src/include/log_system.h diff --git a/src/include/material.hpp b/src/include/material.hpp new file mode 100644 index 0000000..cc4cece --- /dev/null +++ b/src/include/material.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include + +namespace simple_renderer { + +class Material { + public: + // Default constructor + // 默认构造函数 + Material() = default; + + // Copy constructor + // 拷贝构造函数 + Material(const Material& material) = default; + + // Copy assignment operator + // 拷贝赋值操作符 + Material& operator=(const Material& material) = default; + + // Move constructor + // 移动构造函数 + Material(Material&& material) = default; + + // Move assignment operator + // 移动赋值操作符 + Material& operator=(Material&& material) = default; + + // Destructor + // 析构函数 + ~Material() = default; + + float shininess = 0.0f; + Vector3f ambient; + Vector3f diffuse; + Vector3f specular; +}; + +} // namespace simple_renderer \ No newline at end of file diff --git a/src/include/math.hpp b/src/include/math.hpp new file mode 100644 index 0000000..eb7d3f2 --- /dev/null +++ b/src/include/math.hpp @@ -0,0 +1,58 @@ +#pragma once + +#include + +#define GLM_ENABLE_EXPERIMENTAL +#include + +#include "log_system.h" + +namespace simple_renderer { +using Vector2f = glm::vec2; +using Vector3f = glm::vec3; +using Vector4f = glm::vec4; +using Matrix4f = glm::mat4; +} // namespace simple_renderer + +/** + * spdlog 输出 Vector3f 实现 + */ +template <> +struct fmt::formatter : fmt::formatter { + auto format(const simple_renderer::Vector3f &vector, + fmt::format_context &ctx) const -> decltype(ctx.out()) { + std::string vector_string = glm::to_string(vector); + + // Format and output the string + return fmt::format_to(ctx.out(), "\n{}", vector_string); + } +}; + +/** + * spdlog 输出 Vector4f 实现 + */ +template <> +struct fmt::formatter : fmt::formatter { + auto format(const simple_renderer::Vector4f &vector, + fmt::format_context &ctx) const -> decltype(ctx.out()) { + std::string vector_string = glm::to_string(vector); + + // Format and output the string + return fmt::format_to(ctx.out(), "\n{}", vector_string); + } +}; + +/** + * spdlog 输出矩阵实现 + */ +template <> +struct fmt::formatter : fmt::formatter { + auto format(const simple_renderer::Matrix4f &matrix, + fmt::format_context &ctx) const -> decltype(ctx.out()) { + // Convert the Matrix4f to a string using glm::to_string + std::string matrix_str = glm::to_string(matrix); + + // Format and output the string + return fmt::format_to(ctx.out(), "\n{}", matrix_str); + } +}; diff --git a/src/include/model.hpp b/src/include/model.hpp new file mode 100755 index 0000000..de8924b --- /dev/null +++ b/src/include/model.hpp @@ -0,0 +1,100 @@ + +/** + * @file model.hpp + * @brief 模型抽象 + * @author Zone.N (Zone.Niuzh@hotmail.com) + * @version 1.0 + * @date 2022-06-06 + * @copyright MIT LICENSE + * https://github.com/Simple-XX/SimpleRenderer + * @par change log: + * + *
DateAuthorDescription + *
2022-09-04Zone.N迁移到 doxygen + *
+ */ + +#ifndef SIMPLERENDER_SRC_INCLUDE_MODEL_HPP_ +#define SIMPLERENDER_SRC_INCLUDE_MODEL_HPP_ + +#include + +#include +#include + +#include "color.h" +#include "config.h" +#include "face.hpp" +#include "log_system.h" +#include "math.hpp" +#include "vertex.hpp" + +namespace simple_renderer { + +class Model { + public: + // Default constructor + // 默认构造函数 + Model() = default; + + // Default copy constructor + // 默认拷贝构造函数 + Model(const Model& model) = default; + // Default copy assignment operator + // 默认拷贝赋值运算符 + Model& operator=(const Model& model) = default; + + // Default move constructor + // 默认移动构造函数 + Model(Model&& model) = default; + // Default move assignment operator + // 默认移动赋值运算符 + Model& operator=(Model&& model) = default; + + // Destructor + // 析构函数 + ~Model() = default; + + // Constructor that loads a model from a file path + // 从文件路径加载模型的构造函数 + Model(const std::string& model_path); + + // Apply a transformation to the model + // 对模型应用变换 + void transform(const Matrix4f& tran); + + // Get functions + // 获取函数 + const std::vector& faces() const { return faces_; }; + const std::string& modelPath() const { return directory_; }; + + private: + // Number of vertices per triangle face + // 每个三角形面的顶点数 + static constexpr const uint8_t kTriangleFaceVertexCount = 3; + // Directory where the model is located + // 模型所在的目录 + std::string directory_; + // List of faces(triangles) that make up the model + // 构成模型的面(三角形)列表 + std::vector faces_; + + // Load the model from the specified file path + // 从指定的文件路径加载模型 + void loadModel(const std::string& path); + + // Process a node in the model + // 处理模型中的一个节点 + void processNode(aiNode* node, const aiScene* scene); + + // Process a mesh in the model + // 处理模型中的一个网格 + void processMesh(aiMesh* mesh, const aiScene* scene); + + // Process the material of the model + // 处理模型的材质 + Material processMaterial(aiMaterial* material); +}; +} // namespace simple_renderer + +#endif /* SIMPLERENDER_SRC_INCLUDE_MODEL_HPP_ */ \ No newline at end of file diff --git a/include/shader_base.h b/src/include/shader_base.h similarity index 91% rename from include/shader_base.h rename to src/include/shader_base.h index e2b7b0c..9f69382 100644 --- a/include/shader_base.h +++ b/src/include/shader_base.h @@ -17,8 +17,8 @@ #ifndef SIMPLERENDER_SRC_INCLUDE_SHADER_BASE_H_ #define SIMPLERENDER_SRC_INCLUDE_SHADER_BASE_H_ +#include "math.hpp" #include "model.hpp" -#include "log_math.hpp" namespace simple_renderer { @@ -55,7 +55,7 @@ class ShaderVertexIn { class ShaderVertexOut { public: /// 面信息 - Face face_; + Face face_; /** * 构造函数 @@ -82,11 +82,11 @@ class ShaderVertexOut { class ShaderFragmentIn { public: /// 重心坐标 - glm::vec3 barycentric_coord_; + Vector3f barycentric_coord_; /// 法线方向 - glm::vec3 normal_; + Vector3f normal_; /// 光照方向 - glm::vec3 light_; + Vector3f light_; /// @name 三个顶点的颜色 /// @{ @@ -104,8 +104,8 @@ class ShaderFragmentIn { * @param color1 顶点 1 颜色 * @param color2 顶点 2 颜色 */ - explicit ShaderFragmentIn(const glm::vec3 &_barycentric_coord, - const glm::vec3 &_normal, const glm::vec3 &_light, + explicit ShaderFragmentIn(const Vector3f &_barycentric_coord, + const Vector3f &_normal, const Vector3f &_light, const Color &_color0, const Color &_color1, const Color &_color2); @@ -159,11 +159,11 @@ class ShaderFragmentOut { class ShaderData { public: /// 模型变换矩阵 - glm::mat4 model_matrix_ = glm::mat4(1.0f); + Matrix4f model_matrix_ = Matrix4f(1.0f); /// 视图变换矩阵 - glm::mat4 view_matrix_ = glm::mat4(1.0f); + Matrix4f view_matrix_ = Matrix4f(1.0f); /// 正交变换矩阵 - glm::mat4 project_matrix_ = glm::mat4(1.0f); + Matrix4f project_matrix_ = Matrix4f(1.0f); /** * 构造函数 @@ -171,8 +171,8 @@ class ShaderData { * @param view_matrix 视图变换矩阵 * @param project_matrix 正交变换矩阵 */ - explicit ShaderData(const glm::mat4 &model_matrix, const glm::mat4 &view_matrix, - const glm::mat4 &project_matrix); + explicit ShaderData(const Matrix4f &model_matrix, const Matrix4f &view_matrix, + const Matrix4f &project_matrix); /// @name 默认构造/析构函数 /// @{ diff --git a/include/simple_renderer.h b/src/include/simple_renderer.h similarity index 91% rename from include/simple_renderer.h rename to src/include/simple_renderer.h index 3fc6bed..44e2ca6 100755 --- a/include/simple_renderer.h +++ b/src/include/simple_renderer.h @@ -23,9 +23,9 @@ #include "light.h" #include "log_system.h" +#include "math.hpp" #include "model.hpp" #include "shader_base.h" -#include "log_math.hpp" namespace simple_renderer { @@ -90,7 +90,7 @@ class SimpleRenderer { * @todo 多线程支持 */ void DrawTriangle(const ShaderBase &shader, const Light &light, - const glm::vec3 &normal, const Face &face); + const Vector3f &normal, const Face &face); /** * 绘制模型 @@ -127,9 +127,9 @@ class SimpleRenderer { * weight_B = s * weight_C = t */ - static auto GetBarycentricCoord(const glm::vec3 &p0, const glm::vec3 &p1, - const glm::vec3 &p2, const glm::vec3 &pa) - -> std::pair; + static auto GetBarycentricCoord(const Vector3f &p0, const Vector3f &p1, + const Vector3f &p2, const Vector3f &pa) + -> std::pair; /** * 深度插值,由重心坐标计算出对应点的深度值 @@ -140,7 +140,7 @@ class SimpleRenderer { * @return 深度值 */ static auto InterpolateDepth(float depth0, float depth1, float depth2, - const glm::vec3 &barycentric_coord) -> float; + const Vector3f &barycentric_coord) -> float; }; } // namespace simple_renderer diff --git a/src/include/vertex.hpp b/src/include/vertex.hpp new file mode 100644 index 0000000..1cd3084 --- /dev/null +++ b/src/include/vertex.hpp @@ -0,0 +1,66 @@ +#pragma once + +#include + +#include "color.h" + +namespace simple_renderer { + +class Vertex { + public: + // Default constructor + // 默认构造函数 + Vertex() = default; + + // Copy constructor + // 拷贝构造函数 + Vertex(const Vertex& vertex) = default; + // Copy assignment operator + // 拷贝赋值操作符 + Vertex& operator=(const Vertex& vertex) = default; + + // Move constructor + // 移动构造函数 + Vertex(Vertex&& vertex) = default; + // Move assignment operator + // 移动赋值操作符 + Vertex& operator=(Vertex&& vertex) = default; + + // Destructor + // 析构函数 + ~Vertex() = default; + + // Constructor with parameters 带参数的构造函数 + explicit Vertex(const Vector4f& pos, const Vector3f& norm, + const Vector2f& tex, const Color& color_) + : position_(pos), normal_(norm), texCoords_(tex), color_(color_) {} + + // Transform the vertex with a matrix 使用矩阵变换顶点 + void transform(const Matrix4f& matrix) { position_ = matrix * position_; } + + // Perspective divide to convert from clip space to normalized device + // coordinates 透视除法,将裁剪空间转换为标准化设备坐标 + void perspectiveDivide() { + if (position_.w != 0) { + position_.x /= position_.w; + position_.y /= position_.w; + position_.z /= position_.w; + position_.w = 1.0f; // Homogenize, 齐次坐标 + } + } + + // Get functions + // 获取函数 + Vector4f position() const { return position_; } + Vector3f normal() const { return normal_; } + Vector2f texCoords() const { return texCoords_; } + Color color() const { return color_; } + + private: + Vector4f position_; // 3D position, 3D顶点坐标 + Vector3f normal_; // Normal vector, 顶点法向量 + Vector2f texCoords_; // Texture coordinates, 顶点纹理坐标 + Color color_; +}; + +} // namespace simple_renderer \ No newline at end of file diff --git a/src/light.cpp b/src/light.cpp index 0686703..f25fb4c 100644 --- a/src/light.cpp +++ b/src/light.cpp @@ -18,12 +18,12 @@ #include "color.h" #include "log_system.h" -#include "log_math.hpp" +#include "math.hpp" namespace simple_renderer { -const glm::vec3 Light::kDefaultPos = glm::vec3(0, 0, 0); -const glm::vec3 Light::kDefaultDir = glm::vec3(0, 0, -1); +const Vector3f Light::kDefaultPos = Vector3f(0, 0, 0); +const Vector3f Light::kDefaultDir = Vector3f(0, 0, -1); const Color Light::kDefaultColor = Color::kWhite; Light::Light(const std::string &name) : name_(name) { diff --git a/src/log_system.cpp b/src/log_system.cpp index 6c81b14..e6e7218 100755 --- a/src/log_system.cpp +++ b/src/log_system.cpp @@ -16,20 +16,20 @@ #include "log_system.h" -#include - #include #include #include #include #include +#include + namespace simple_renderer { LogSystem::LogSystem(const std::string &log_file_path, size_t lig_file_max_size, size_t log_file_max_count) { spdlog::init_thread_pool(65536, 1); -// std::string log_file_paths = "./logs/simple_renderer.log"; + // std::string log_file_paths = "./logs/simple_renderer.log"; auto stdout_sink = std::make_shared(); auto rotating_sink = std::make_shared( log_file_path, lig_file_max_size, log_file_max_count); diff --git a/src/model.cpp b/src/model.cpp index 1f82d75..53b8bac 100755 --- a/src/model.cpp +++ b/src/model.cpp @@ -1,7 +1,6 @@ - /** * @file model.cpp - * @brief 模型抽象 + * @brief Model abstraction (模型抽象) * @author Zone.N (Zone.Niuzh@hotmail.com) * @version 1.0 * @date 2022-06-06 @@ -15,126 +14,148 @@ */ #include "model.hpp" -#include - -#include -#include #include #include +#include +#include +#include + #include "log_system.h" namespace simple_renderer { +// Constructor that loads a model from a file path +// 构造函数从文件路径加载模型 +Model::Model(const std::string& model_path) { loadModel(model_path); } -Model::Model(const std::string &model_path) { - loadModel(model_path); -} - +// Load the model using Assimp and process its nodes and meshes +// 使用 Assimp 加载模型并处理其节点和网格 void Model::loadModel(const std::string& path) { - Assimp::Importer importer; - const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs); - - if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) { - SPDLOG_ERROR("Assimp Error: {}", importer.GetErrorString()); - throw std::runtime_error("Failed to load model with Assimp"); - } - - directory_ = path.substr(0, path.find_last_of('/')); - - SPDLOG_INFO("Loaded model path: {}, Directory: {}, with meshes: {}, materials: {}", path, directory_, scene->mNumMeshes, scene->mNumMaterials); - - processNode(scene->mRootNode, scene); + Assimp::Importer importer; + const aiScene* scene = + importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs); + + // Check for errors in loading the model + // 检查加载模型时的错误 + if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || + !scene->mRootNode) { + SPDLOG_ERROR("Assimp Error: {}", importer.GetErrorString()); + throw std::runtime_error("Failed to load model with Assimp"); + } + + // Store the directory path of the model + // 存储模型的目录路径 + directory_ = path.substr(0, path.find_last_of('/')); + + SPDLOG_INFO( + "Loaded model path: {}, Directory: {}, with meshes: {}, materials: {}", + path, directory_, scene->mNumMeshes, scene->mNumMaterials); + + // Process the root node recursively + // 递归处理根节点 + processNode(scene->mRootNode, scene); } +// Recursively process nodes in the model +// 递归处理模型中的节点 void Model::processNode(aiNode* node, const aiScene* scene) { - for (unsigned int i = 0; i < node->mNumMeshes; i++) { - aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; - processMesh(mesh, scene); - } - - for (unsigned int i = 0; i < node->mNumChildren; i++) { - processNode(node->mChildren[i], scene); - } + // Process each mesh in the node + // 处理节点中的每个网格 + for (unsigned int i = 0; i < node->mNumMeshes; i++) { + aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; + processMesh(mesh, scene); + } + + // Recursively process each child node + // 递归处理每个子节点 + for (unsigned int i = 0; i < node->mNumChildren; i++) { + processNode(node->mChildren[i], scene); + } } +// Process a single mesh and extract vertices, normals, and faces +// 处理单个网格并提取顶点、法线和面 void Model::processMesh(aiMesh* mesh, const aiScene* scene) { - std::vector vertices; - - // Process vertices - for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { - glm::vec3 position( - mesh->mVertices[i].x, - mesh->mVertices[i].y, - mesh->mVertices[i].z - ); - glm::vec3 normal( - mesh->mNormals[i].x, - mesh->mNormals[i].y, - mesh->mNormals[i].z - ); - glm::vec2 texCoords(0.0f, 0.0f); - if (mesh->mTextureCoords[0]) { // Check if the mesh contains texture coordinates - texCoords = glm::vec2( - mesh->mTextureCoords[0][i].x, - mesh->mTextureCoords[0][i].y - ); - } - - Color color(255.f, 255.f, 255.f, 255.f); - - vertices.emplace_back(glm::vec4(position, 1.0f), normal, texCoords, color); + std::vector vertices; + + // Process vertices + // 处理顶点 + for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { + Vector3f position(mesh->mVertices[i].x, mesh->mVertices[i].y, + mesh->mVertices[i].z); + Vector3f normal(mesh->mNormals[i].x, mesh->mNormals[i].y, + mesh->mNormals[i].z); + Vector2f texCoords(0.0f, 0.0f); + // Check if the mesh has texture coordinates + // 检查网格是否有纹理坐标 + if (mesh->mTextureCoords[0]) { + texCoords = + Vector2f(mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y); } - // Process faces (assuming triangulation, so each face has 3 vertices) - for (unsigned int i = 0; i < mesh->mNumFaces; ++i) { - aiFace face = mesh->mFaces[i]; - if (face.mNumIndices == 3) { // Ensure we are working with triangles - Vertex v0 = vertices[face.mIndices[0]]; - Vertex v1 = vertices[face.mIndices[1]]; - Vertex v2 = vertices[face.mIndices[2]]; - - Material material = processMaterial(scene->mMaterials[mesh->mMaterialIndex]); - - faces_.emplace_back(v0, v1, v2, std::move(material)); - } + + Color color(255.f, 255.f, 255.f, 255.f); // Default color (white) + // 默认颜色(白色) + + vertices.emplace_back(Vector4f(position, 1.0f), normal, texCoords, color); + } + + // Process faces (assuming triangulation, so each face has 3 vertices) + // 处理面(假设三角化,因此每个面有3个顶点) + for (unsigned int i = 0; i < mesh->mNumFaces; ++i) { + aiFace face = mesh->mFaces[i]; + if (face.mNumIndices == 3) { // Triangle, 三角形 + Vertex v0 = vertices[face.mIndices[0]]; + Vertex v1 = vertices[face.mIndices[1]]; + Vertex v2 = vertices[face.mIndices[2]]; + + // Process the material associated with this mesh + // 处理与此网格关联的材质 + Material material = + processMaterial(scene->mMaterials[mesh->mMaterialIndex]); + + // Create a Face object and store it + // 创建一个 Face 对象并存储它 + faces_.emplace_back(v0, v1, v2, std::move(material)); } + } } +// Extract material properties from the Assimp material structure +// 从 Assimp 材质结构中提取材质属性 Material Model::processMaterial(aiMaterial* mat) { - Material material; + Material material; - // Extract ambient color - aiColor3D ambient(0.0f, 0.0f, 0.0f); - if (AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_AMBIENT, ambient)) { - material.ambient = glm::vec3(ambient.r, ambient.g, ambient.b); - } + aiColor3D ambient(0.0f, 0.0f, 0.0f); + if (AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_AMBIENT, ambient)) { + material.ambient = Vector3f(ambient.r, ambient.g, ambient.b); + } - // Extract diffuse color - aiColor3D diffuse(1.0f, 1.0f, 1.0f); // Default to white - if (AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse)) { - material.diffuse = glm::vec3(diffuse.r, diffuse.g, diffuse.b); - } + aiColor3D diffuse(1.0f, 1.0f, 1.0f); + if (AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse)) { + material.diffuse = Vector3f(diffuse.r, diffuse.g, diffuse.b); + } - // Extract specular color - aiColor3D specular(0.0f, 0.0f, 0.0f); - if (AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_SPECULAR, specular)) { - material.specular = glm::vec3(specular.r, specular.g, specular.b); - } + aiColor3D specular(0.0f, 0.0f, 0.0f); + if (AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_SPECULAR, specular)) { + material.specular = Vector3f(specular.r, specular.g, specular.b); + } - // Extract shininess - float shininess = 0.0f; - if (AI_SUCCESS == mat->Get(AI_MATKEY_SHININESS, shininess)) { - material.shininess = shininess; - } + float shininess = 0.0f; + if (AI_SUCCESS == mat->Get(AI_MATKEY_SHININESS, shininess)) { + material.shininess = shininess; + } - return material; + return material; } -void Model::transform(const glm::mat4 &tran) { - for (auto& face : faces_) { - face.transform(tran); - } +// Apply a transformation matrix to all faces in the model +// 对模型中的所有面应用变换矩阵 +void Model::transform(const Matrix4f& tran) { + for (auto& face : faces_) { + face.transform(tran); + } } } // namespace simple_renderer diff --git a/src/shader_base.cpp b/src/shader_base.cpp index 9d5f937..b5b1f39 100644 --- a/src/shader_base.cpp +++ b/src/shader_base.cpp @@ -22,9 +22,9 @@ ShaderVertexIn::ShaderVertexIn(const Face &face) : face_(face) {} ShaderVertexOut::ShaderVertexOut(const Face &face) : face_(face) {} -ShaderFragmentIn::ShaderFragmentIn(const glm::vec3 &barycentric_coord, - const glm::vec3 &normal, - const glm::vec3 &light, const Color &color0, +ShaderFragmentIn::ShaderFragmentIn(const Vector3f &barycentric_coord, + const Vector3f &normal, + const Vector3f &light, const Color &color0, const Color &color1, const Color &color2) : barycentric_coord_(barycentric_coord), normal_(normal), @@ -37,9 +37,9 @@ ShaderFragmentOut::ShaderFragmentOut(const bool &is_need_draw, const Color &color) : is_need_draw_(is_need_draw), color_(color) {} -ShaderData::ShaderData(const glm::mat4 &model_matrix, - const glm::mat4 &view_matrix, - const glm::mat4 &project_matrix) +ShaderData::ShaderData(const Matrix4f &model_matrix, + const Matrix4f &view_matrix, + const Matrix4f &project_matrix) : model_matrix_(model_matrix), view_matrix_(view_matrix), project_matrix_(project_matrix) {} diff --git a/src/simple_renderer.cpp b/src/simple_renderer.cpp index 93105ab..fafbc15 100755 --- a/src/simple_renderer.cpp +++ b/src/simple_renderer.cpp @@ -126,8 +126,7 @@ void SimpleRenderer::DrawLine(float x0, float y0, float x1, float y1, } void SimpleRenderer::DrawTriangle(const ShaderBase &shader, const Light &light, - const glm::vec3 &normal, - const Face &face) { + const Vector3f &normal, const Face &face) { auto v0 = face.vertex(0); auto v1 = face.vertex(1); auto v2 = face.vertex(2); @@ -135,17 +134,21 @@ void SimpleRenderer::DrawTriangle(const ShaderBase &shader, const Light &light, // 获取三角形的最小 box auto min = v0.position(); auto max = v1.position(); - auto max_x = std::max(face.vertex(0).position().x, - std::max(face.vertex(1).position().x, face.vertex(2).position().x)); - auto max_y = std::max(face.vertex(0).position().y, - std::max(face.vertex(1).position().y, face.vertex(2).position().y)); + auto max_x = std::max( + face.vertex(0).position().x, + std::max(face.vertex(1).position().x, face.vertex(2).position().x)); + auto max_y = std::max( + face.vertex(0).position().y, + std::max(face.vertex(1).position().y, face.vertex(2).position().y)); max.x = max_x > max.x ? max_x : max.x; max.y = max_y > max.y ? max_y : max.y; max.z = 0; - auto min_x = std::min(face.vertex(0).position().x, - std::min(face.vertex(1).position().x, face.vertex(2).position().x)); - auto min_y = std::min(face.vertex(0).position().y, - std::min(face.vertex(1).position().y, face.vertex(2).position().y)); + auto min_x = std::min( + face.vertex(0).position().x, + std::min(face.vertex(1).position().x, face.vertex(2).position().x)); + auto min_y = std::min( + face.vertex(0).position().y, + std::min(face.vertex(1).position().y, face.vertex(2).position().y)); min.x = min_x < min.x ? min_x : min.x; min.y = min_y < min.y ? min_y : min.y; min.z = 0; @@ -160,14 +163,14 @@ void SimpleRenderer::DrawTriangle(const ShaderBase &shader, const Light &light, } auto [is_inside, barycentric_coord] = GetBarycentricCoord( v0.position(), v1.position(), v2.position(), - glm::vec3(static_cast(x), static_cast(y), 0)); + Vector3f(static_cast(x), static_cast(y), 0)); // 如果点在三角形内再进行下一步 if (!is_inside) { continue; } // 计算该点的深度,通过重心坐标插值计算 - auto z = InterpolateDepth(v0.position().z, v1.position().z, v2.position().z, - barycentric_coord); + auto z = InterpolateDepth(v0.position().z, v1.position().z, + v2.position().z, barycentric_coord); // 深度在已有颜色之上 if (z < depth_buffer_[y * width_ + x]) { continue; @@ -202,12 +205,15 @@ void SimpleRenderer::DrawModel(const ShaderBase &shader, const Light &light, for (const auto &f : model.faces()) { /// @todo 巨大性能开销 auto face = shader.Vertex(ShaderVertexIn(f)).face_; - DrawLine(face.vertex(0).position().x, face.vertex(0).position().y, face.vertex(1).position().x, - face.vertex(1).position().y, Color::kRed); - DrawLine(face.vertex(1).position().x, face.vertex(1).position().y, face.vertex(2).position().x, - face.vertex(2).position().y, Color::kGreen); - DrawLine(face.vertex(2).position().x, face.vertex(2).position().y, face.vertex(0).position().x, - face.vertex(0).position().y, Color::kBlue); + DrawLine(face.vertex(0).position().x, face.vertex(0).position().y, + face.vertex(1).position().x, face.vertex(1).position().y, + Color::kRed); + DrawLine(face.vertex(1).position().x, face.vertex(1).position().y, + face.vertex(2).position().x, face.vertex(2).position().y, + Color::kGreen); + DrawLine(face.vertex(2).position().x, face.vertex(2).position().y, + face.vertex(0).position().x, face.vertex(0).position().y, + Color::kBlue); } } if (draw_triangle) { @@ -222,37 +228,37 @@ void SimpleRenderer::DrawModel(const ShaderBase &shader, const Light &light, } /// @todo 巨大性能开销 -auto SimpleRenderer::GetBarycentricCoord(const glm::vec3 &p0, const glm::vec3 &p1, - const glm::vec3 &p2, const glm::vec3 &pa) - -> std::pair { +auto SimpleRenderer::GetBarycentricCoord(const Vector3f &p0, const Vector3f &p1, + const Vector3f &p2, const Vector3f &pa) + -> std::pair { auto p1p0 = p1 - p0; auto p2p0 = p2 - p0; auto pap0 = pa - p0; auto deno = (p1p0.x * p2p0.y - p1p0.y * p2p0.x); if (std::abs(deno) < std::numeric_limits::epsilon()) { - return std::pair{false, glm::vec3()}; + return std::pair{false, Vector3f()}; } auto s = (p2p0.y * pap0.x - p2p0.x * pap0.y) / deno; if ((s > 1) || (s < 0)) { - return std::pair{false, glm::vec3()}; + return std::pair{false, Vector3f()}; } auto t = (p1p0.x * pap0.y - p1p0.y * pap0.x) / deno; if ((t > 1) || (t < 0)) { - return std::pair{false, glm::vec3()}; + return std::pair{false, Vector3f()}; } if ((1 - s - t > 1) || (1 - s - t < 0)) { - return std::pair{false, glm::vec3()}; + return std::pair{false, Vector3f()}; } - return std::pair{true, glm::vec3(1 - s - t, s, t)}; + return std::pair{true, Vector3f(1 - s - t, s, t)}; } auto SimpleRenderer::InterpolateDepth(float depth0, float depth1, float depth2, - const glm::vec3 &_barycentric_coord) + const Vector3f &_barycentric_coord) -> float { auto depth = depth0 * _barycentric_coord.x; depth += depth1 * _barycentric_coord.y; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index fa647ac..e8267a4 100755 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -14,50 +14,38 @@ enable_testing() include(GoogleTest) include_directories( - ${SimpleRenderer_SOURCE_DIR}/include + ${SimpleRenderer_SOURCE_DIR}/src/include ) list(APPEND DEFAULT_TEST_COMPILE_OPTIONS - ${DEFAULT_COMPILE_OPTIONS} - --coverage + ${DEFAULT_COMPILE_OPTIONS} + --coverage ) list(APPEND DEFAULT_TEST_LINK_OPTIONS - --coverage - $<$: - # -fsanitize=leak - > - # -fsanitize=address - -fno-omit-frame-pointer + --coverage + $<$: + # -fsanitize=leak + > + # -fsanitize=address + -fno-omit-frame-pointer ) link_libraries( - ${DEFAULT_LINK_LIB} - gtest_main - ${glog_LIBRARIES} - SimpleRenderer + ${DEFAULT_LINK_LIB} + gtest_main + ${glog_LIBRARIES} + SimpleRenderer ) -# Check if the platform is macOS -if(APPLE) - # Enable RPATH support on macOS - set(CMAKE_MACOSX_RPATH 1) - # Set the RPATH to look for frameworks relative to the executable path - set(CMAKE_INSTALL_RPATH "/Library/Frameworks") - - # Ensure that RPATH is used in the build - set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) -endif() - - -# add_subdirectory(unit_test) +add_subdirectory(unit_test) #add_subdirectory(integration_test) add_subdirectory(system_test) -# add_coverage_target( -# DEPENDS unit_test -# SOURCE_DIR ${SimpleRenderer_SOURCE_DIR} -# BINARY_DIR ${SimpleRenderer_BINARY_DIR} -# EXCLUDE_DIR ${SimpleRenderer_SOURCE_DIR}/3rd/* -# ) +add_coverage_target( + DEPENDS unit_test + SOURCE_DIR ${SimpleRenderer_SOURCE_DIR} + BINARY_DIR ${SimpleRenderer_BINARY_DIR} + EXCLUDE_DIR ${SimpleRenderer_SOURCE_DIR}/3rd/* +) \ No newline at end of file diff --git a/test/system_test/CMakeLists.txt b/test/system_test/CMakeLists.txt index 6d3b0f5..3e976e3 100755 --- a/test/system_test/CMakeLists.txt +++ b/test/system_test/CMakeLists.txt @@ -23,4 +23,4 @@ target_compile_options(system_test PRIVATE target_link_options(system_test PRIVATE ${DEFAULT_TEST_LINK_OPTIONS} -) +) \ No newline at end of file diff --git a/test/system_test/camera.h b/test/system_test/camera.h index 2694bdd..d64693d 100644 --- a/test/system_test/camera.h +++ b/test/system_test/camera.h @@ -21,7 +21,7 @@ #include #include "color.h" -#include "log_math.hpp" +#include "math.hpp" namespace simple_renderer { @@ -33,9 +33,9 @@ class Camera { /// 光照名称 std::string name_ = "default light name"; /// 位置 - glm::vec3 pos_; + Vector3f pos_; /// 方向 - glm::vec3 dir_; + Vector3f dir_; /** * 构造函数 diff --git a/test/system_test/main.cpp b/test/system_test/main.cpp index 013382c..d1024a8 100755 --- a/test/system_test/main.cpp +++ b/test/system_test/main.cpp @@ -59,16 +59,18 @@ int main(int argc, char **argv) { // objs.emplace_back(obj_path + "/african_head.obj"); objs.emplace_back(obj_path + "/utah-teapot/utah-teapot.obj"); - - auto matrix = - glm::mat4(1.0f); - glm::mat4 scale_matrix = glm::scale(glm::mat4(1.0f), glm::vec3(10.0f, 10.0f, 10.0f)); - -// Translation matrix - glm::mat4 translation_matrix = glm::translate(glm::mat4(1.0f), glm::vec3(kWidth / 2.0f, kHeight / 2.0f, 0.0f)); - - // Combined transformation matrix - matrix = translation_matrix * scale_matrix; + auto matrix = simple_renderer::Matrix4f(1.0f); + simple_renderer::Matrix4f scale_matrix = + glm::scale(simple_renderer::Matrix4f(1.0f), + simple_renderer::Vector3f(10.0f, 10.0f, 10.0f)); + + // Translation matrix + simple_renderer::Matrix4f translation_matrix = glm::translate( + simple_renderer::Matrix4f(1.0f), + simple_renderer::Vector3f(kWidth / 2.0f, kHeight / 2.0f, 0.0f)); + + // Combined transformation matrix + matrix = translation_matrix * scale_matrix; // 矩阵运算的顺序 // 归一化 diff --git a/test/unit_test/matrix_test.cpp b/test/unit_test/matrix_test.cpp index 045f4ba..4ddf650 100644 --- a/test/unit_test/matrix_test.cpp +++ b/test/unit_test/matrix_test.cpp @@ -15,8 +15,7 @@ * */ -#include "log_math.hpp" - #include "gtest/gtest.h" +#include "math.hpp" TEST(ttt1, todo1) { EXPECT_EQ(nullptr, nullptr); }