From 67e4855211279796e949e560a8f2e55a29c3513c Mon Sep 17 00:00:00 2001 From: SepComet <202308010230@stu.csust.edu.cn> Date: Sun, 15 Mar 2026 22:18:43 +0800 Subject: [PATCH] =?UTF-8?q?step2=EF=BC=9Amodel=20+=20view=20matrix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CPU-Software-Renderer.vcxproj | 31 +++- CPU-Software-Renderer/Math/MathUtil.h | 93 +++++++++- CPU-Software-Renderer/Math/Matrix4x4.h | 174 +++++++++++++++++- CPU-Software-Renderer/Math/Vector3.h | 69 ++++++- CPU-Software-Renderer/Math/Vector4.h | 82 ++++++++- CPU-Software-Renderer/Scene/Camera.cpp | 33 ++++ CPU-Software-Renderer/Scene/Camera.h | 40 +++- 7 files changed, 502 insertions(+), 20 deletions(-) create mode 100644 CPU-Software-Renderer/Scene/Camera.cpp diff --git a/CPU-Software-Renderer/CPU-Software-Renderer.vcxproj b/CPU-Software-Renderer/CPU-Software-Renderer.vcxproj index 5c6484c..e92ba6e 100644 --- a/CPU-Software-Renderer/CPU-Software-Renderer.vcxproj +++ b/CPU-Software-Renderer/CPU-Software-Renderer.vcxproj @@ -58,16 +58,24 @@ - + - + - + - + @@ -77,7 +85,8 @@ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp20 - $(ProjectDir)Asset;$(ProjectDir)Core;$(ProjectDir)Math;$(ProjectDir)Rasterizer;$(ProjectDir)RenderData;$(ProjectDir)Scene;$(ProjectDir)Shading;$(ProjectDir)libs\SDL2\include;%(AdditionalIncludeDirectories) + + $(ProjectDir)Asset;$(ProjectDir)Core;$(ProjectDir)Math;$(ProjectDir)Rasterizer;$(ProjectDir)RenderData;$(ProjectDir)Scene;$(ProjectDir)Shading;$(ProjectDir)libs\SDL2\include;%(AdditionalIncludeDirectories) Console @@ -95,7 +104,8 @@ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp20 - $(ProjectDir)Asset;$(ProjectDir)Core;$(ProjectDir)Math;$(ProjectDir)Rasterizer;$(ProjectDir)RenderData;$(ProjectDir)Scene;$(ProjectDir)Shading;$(ProjectDir)libs\SDL2\include;%(AdditionalIncludeDirectories) + + $(ProjectDir)Asset;$(ProjectDir)Core;$(ProjectDir)Math;$(ProjectDir)Rasterizer;$(ProjectDir)RenderData;$(ProjectDir)Scene;$(ProjectDir)Shading;$(ProjectDir)libs\SDL2\include;%(AdditionalIncludeDirectories) Console @@ -111,7 +121,8 @@ _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp20 - $(ProjectDir)Asset;$(ProjectDir)Core;$(ProjectDir)Math;$(ProjectDir)Rasterizer;$(ProjectDir)RenderData;$(ProjectDir)Scene;$(ProjectDir)Shading;$(ProjectDir)libs\SDL2\include;%(AdditionalIncludeDirectories) + + $(ProjectDir)Asset;$(ProjectDir)Core;$(ProjectDir)Math;$(ProjectDir)Rasterizer;$(ProjectDir)RenderData;$(ProjectDir)Scene;$(ProjectDir)Shading;$(ProjectDir)libs\SDL2\include;%(AdditionalIncludeDirectories) Console @@ -129,7 +140,8 @@ NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp20 - $(ProjectDir)Asset;$(ProjectDir)Core;$(ProjectDir)Math;$(ProjectDir)Rasterizer;$(ProjectDir)RenderData;$(ProjectDir)Scene;$(ProjectDir)Shading;$(ProjectDir)libs\SDL2\include;%(AdditionalIncludeDirectories) + + $(ProjectDir)Asset;$(ProjectDir)Core;$(ProjectDir)Math;$(ProjectDir)Rasterizer;$(ProjectDir)RenderData;$(ProjectDir)Scene;$(ProjectDir)Shading;$(ProjectDir)libs\SDL2\include;%(AdditionalIncludeDirectories) Console @@ -146,6 +158,7 @@ + @@ -178,4 +191,4 @@ - + \ No newline at end of file diff --git a/CPU-Software-Renderer/Math/MathUtil.h b/CPU-Software-Renderer/Math/MathUtil.h index fefaf5a..8d1208b 100644 --- a/CPU-Software-Renderer/Math/MathUtil.h +++ b/CPU-Software-Renderer/Math/MathUtil.h @@ -1,7 +1,96 @@ #pragma once +#include "Matrix4x4.h" +#include "Vector3.h" +#include namespace Math { - class MathUtil - {}; + static class MathUtil + { + public: + static Matrix4x4 get_translate_matrix(const float x, const float y, const float z) { return get_translate_matrix(Vector3(x, y, z)); } + + static Matrix4x4 get_translate_matrix(const Vector3& translation) + { + return Matrix4x4( + 1, 0, 0, translation.x, + 0, 1, 0, translation.y, + 0, 0, 1, translation.z, + 0, 0, 0, 0 + ); + } + + static Matrix4x4 get_scale_matrix(const float x, const float y, const float z) { return get_scale_matrix(Vector3(x, y, z)); } + + static Matrix4x4 get_scale_matrix(const Vector3& scale) + { + return Matrix4x4( + scale.x, 0, 0, 0, + 0, scale.y, 0, 0, + 0, 0, scale.z, 0, + 0, 0, 0, 1 + ); + } + + static Matrix4x4 get_rotation_matrix_x(const float radians) + { + const float cosValue = std::cos(radians); + const float sinValue = std::sin(radians); + + return Matrix4x4( + 1, 0, 0, 0, + 0, cosValue, -sinValue, 0, + 0, sinValue, cosValue, 0, + 0, 0, 0, 1 + ); + } + + static Matrix4x4 get_rotation_matrix_y(const float radians) + { + const float cosValue = std::cos(radians); + const float sinValue = std::sin(radians); + + return Matrix4x4( + cosValue, sinValue, 0, 0, + 0, 1, 0, 0, + -sinValue, cosValue, 0, 0, + 0, 0, 0, 1 + ); + } + + static Matrix4x4 get_rotation_matrix_z(const float radians) + { + const float cosValue = std::cos(radians); + const float sinValue = std::sin(radians); + + return Matrix4x4( + cosValue, -sinValue, 0, 0, + sinValue, cosValue, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ); + } + + static Matrix4x4 get_rotation_matrix(const Vector3& rotation) + { + return get_rotation_matrix_z(rotation.z) * get_rotation_matrix_y(rotation.y) * get_rotation_matrix_x(rotation.x); + } + + static Matrix4x4 get_rodrigues_rotation_matrix(const Vector3& axis, const float radians) + { + const float cosValue = std::cos(radians); + const float sinValue = std::sin(radians); + const float oneMinusCos = 1.0f - cosValue; + const float powX = axis.x * axis.x; + const float powY = axis.y * axis.y; + const float powZ = axis.z * axis.z; + + return Matrix4x4( + 1 + 0 + oneMinusCos * (-powZ - powY), 0 + sinValue * (-axis.z) + oneMinusCos * axis.x * axis.y, 0 + sinValue * axis.z + oneMinusCos * axis.x * axis.z, 0, + 0 + sinValue * axis.z + oneMinusCos * axis.x * axis.y, 1 + 0 + oneMinusCos * (-powZ - powX), 0 + sinValue * (-axis.x) + oneMinusCos * axis.y * axis.z, 0, + 0 + sinValue * (-axis.y) + oneMinusCos * axis.x * axis.z, 0 + sinValue * axis.x + oneMinusCos * axis.y * axis.z, 1 + 0 + oneMinusCos * (-powY - powX), 0, + 0, 0, 0, 1 + ); + } + }; } \ No newline at end of file diff --git a/CPU-Software-Renderer/Math/Matrix4x4.h b/CPU-Software-Renderer/Math/Matrix4x4.h index 555a649..96adc0c 100644 --- a/CPU-Software-Renderer/Math/Matrix4x4.h +++ b/CPU-Software-Renderer/Math/Matrix4x4.h @@ -1,7 +1,177 @@ #pragma once +#include +#include "Vector3.h" +#include "Vector4.h" namespace Math { class Matrix4x4 - {}; -} \ No newline at end of file + { + public: + // 约定: + // - 图形转换使用列向量语义 + // - 图形变换按列向量语义做,写法是 M * v + // - 元素访问是 matrix[row][col] + // - data() 暴露的是 row-major 连续内存 + // - 平移放在最后一列 + Matrix4x4() + { + *this = Identity(); + } + + Matrix4x4( + float m00, float m01, float m02, float m03, + float m10, float m11, float m12, float m13, + float m20, float m21, float m22, float m23, + float m30, float m31, float m32, float m33) + { + values[0][0] = m00; values[0][1] = m01; values[0][2] = m02; values[0][3] = m03; + values[1][0] = m10; values[1][1] = m11; values[1][2] = m12; values[1][3] = m13; + values[2][0] = m20; values[2][1] = m21; values[2][2] = m22; values[2][3] = m23; + values[3][0] = m30; values[3][1] = m31; values[3][2] = m32; values[3][3] = m33; + } + + static Matrix4x4 Zero() + { + return Matrix4x4( + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f + ); + } + + static Matrix4x4 Identity() + { + return Matrix4x4( + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + ); + } + + float* operator[](size_t row) + { + return values[row]; + } + + const float* operator[](size_t row) const + { + return values[row]; + } + + float* data() + { + return &values[0][0]; + } + + const float* data() const + { + return &values[0][0]; + } + + Matrix4x4 operator+ (const Matrix4x4& other) const + { + Matrix4x4 result = Zero(); + for (size_t row = 0; row < 4; ++row) + { + for (size_t col = 0; col < 4; ++col) + { + result[row][col] = values[row][col] + other[row][col]; + } + } + + return result; + } + + Matrix4x4 operator- (const Matrix4x4& other) const + { + Matrix4x4 result = Zero(); + for (size_t row = 0; row < 4; ++row) + { + for (size_t col = 0; col < 4; ++col) + { + result[row][col] = values[row][col] - other[row][col]; + } + } + + return result; + } + + Matrix4x4 operator* (float scalar) const + { + Matrix4x4 result = Zero(); + for (size_t row = 0; row < 4; ++row) + { + for (size_t col = 0; col < 4; ++col) + { + result[row][col] = values[row][col] * scalar; + } + } + + return result; + } + + // 结果为 this x other(调用方 乘以 参数)。 + Matrix4x4 operator* (const Matrix4x4& other) const + { + Matrix4x4 result = Zero(); + for (size_t row = 0; row < 4; ++row) + { + for (size_t col = 0; col < 4; ++col) + { + for (size_t k = 0; k < 4; ++k) + { + result[row][col] += values[row][k] * other[k][col]; + } + } + } + + return result; + } + + // 结果为 this x other(调用方 乘以 参数)。 + Vector4 operator* (const Vector4& vector) const + { + return Vector4( + values[0][0] * vector.x + values[0][1] * vector.y + values[0][2] * vector.z + values[0][3] * vector.w, + values[1][0] * vector.x + values[1][1] * vector.y + values[1][2] * vector.z + values[1][3] * vector.w, + values[2][0] * vector.x + values[2][1] * vector.y + values[2][2] * vector.z + values[2][3] * vector.w, + values[3][0] * vector.x + values[3][1] * vector.y + values[3][2] * vector.z + values[3][3] * vector.w + ); + } + + Vector4 TransformPoint(const Vector3& point) const + { + return *this * Vector4::Point(point); + } + + Vector4 TransformDirection(const Vector3& direction) const + { + return *this * Vector4::Direction(direction); + } + + Matrix4x4 Transposed() const + { + Matrix4x4 result = Zero(); + for (size_t row = 0; row < 4; ++row) + { + for (size_t col = 0; col < 4; ++col) + { + result[row][col] = values[col][row]; + } + } + + return result; + } + + private: + float values[4][4] = {}; + }; + + inline Matrix4x4 operator* (float scalar, const Matrix4x4& matrix) + { + return matrix * scalar; + } +} diff --git a/CPU-Software-Renderer/Math/Vector3.h b/CPU-Software-Renderer/Math/Vector3.h index acff28b..ec37339 100644 --- a/CPU-Software-Renderer/Math/Vector3.h +++ b/CPU-Software-Renderer/Math/Vector3.h @@ -12,9 +12,74 @@ namespace Math Vector3() : x(0), y(0), z(0) {} Vector3(float x, float y, float z) : x(x), y(y), z(z) {} + float sqrMagnitude() const + { + return x * x + y * y + z * z; + } + float magnitude() const { - return std::sqrt(x * x + y * y + z * z); + return std::sqrt(sqrMagnitude()); + } + + Vector3 normalized() const + { + const float length = magnitude(); + if (length <= 0.0f) + { + return Vector3(); + } + + return *this / length; + } + + float dot(const Vector3& other) const + { + return x * other.x + y * other.y + z * other.z; + } + + // Returns this x other. + // Order matters: + // - a.cross(b) == -(b.cross(a)) + // - the result follows the right-hand rule + // - cross product is not associative + Vector3 cross(const Vector3& other) const + { + return Vector3( + y * other.z - z * other.y, + z * other.x - x * other.z, + x * other.y - y * other.x + ); + } + + Vector3 operator+ (const Vector3& other) const + { + return Vector3(x + other.x, y + other.y, z + other.z); + } + + Vector3 operator- (const Vector3& other) const + { + return Vector3(x - other.x, y - other.y, z - other.z); + } + + Vector3 operator- () const + { + return Vector3(-x, -y, -z); + } + + Vector3 operator* (float scalar) const + { + return Vector3(x * scalar, y * scalar, z * scalar); + } + + Vector3 operator/ (float scalar) const + { + return Vector3(x / scalar, y / scalar, z / scalar); } }; -} \ No newline at end of file + + inline Vector3 operator* (float scalar, const Vector3& vector) + { + return vector * scalar; + } +} diff --git a/CPU-Software-Renderer/Math/Vector4.h b/CPU-Software-Renderer/Math/Vector4.h index 1d8d84e..113c188 100644 --- a/CPU-Software-Renderer/Math/Vector4.h +++ b/CPU-Software-Renderer/Math/Vector4.h @@ -1,7 +1,83 @@ #pragma once +#include +#include "Vector3.h" namespace Math { - class Vector4 - {}; -} \ No newline at end of file + struct Vector4 + { + float x = 0.0f; + float y = 0.0f; + float z = 0.0f; + float w = 0.0f; + + Vector4() : x(0), y(0), z(0), w(0) {} + Vector4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {} + + static Vector4 Point(const Vector3& point) + { + return Vector4(point.x, point.y, point.z, 1.0f); + } + + static Vector4 Direction(const Vector3& direction) + { + return Vector4(direction.x, direction.y, direction.z, 0.0f); + } + + Vector3 to_vector3() const + { + return Vector3(x, y, z); + } + + float sqrMagnitude() const + { + return x * x + y * y + z * z + w * w; + } + + float magnitude() const + { + return std::sqrt(sqrMagnitude()); + } + + Vector4 normalized() const + { + const float length = magnitude(); + if (length <= 0.0f) + { + return Vector4(); + } + + return *this / length; + } + + float dot(const Vector4& other) const + { + return x * other.x + y * other.y + z * other.z + w * other.w; + } + + Vector4 operator+ (const Vector4& other) const + { + return Vector4(x + other.x, y + other.y, z + other.z, w + other.w); + } + + Vector4 operator- (const Vector4& other) const + { + return Vector4(x - other.x, y - other.y, z - other.z, w - other.w); + } + + Vector4 operator* (float scalar) const + { + return Vector4(x * scalar, y * scalar, z * scalar, w * scalar); + } + + Vector4 operator/ (float scalar) const + { + return Vector4(x / scalar, y / scalar, z / scalar, w / scalar); + } + }; + + inline Vector4 operator* (float scalar, const Vector4& vector) + { + return vector * scalar; + } +} diff --git a/CPU-Software-Renderer/Scene/Camera.cpp b/CPU-Software-Renderer/Scene/Camera.cpp new file mode 100644 index 0000000..d838be8 --- /dev/null +++ b/CPU-Software-Renderer/Scene/Camera.cpp @@ -0,0 +1,33 @@ +#pragma once +#include "Matrix4x4.h" +#include "Camera.h" +#include + +namespace Scene +{ + Math::Matrix4x4 Camera::get_view_matrix() const + { + using namespace Math; + + Vector3 forward = (target - position).normalized(); + Vector3 right = forward.cross(up).normalized(); + if (right.magnitude() < 1e-5) right = forward.cross(Vector3(0, 1, 0)); + Vector3 cameraUp = right.cross(forward); + + return Matrix4x4( + right.x, right.y, right.z, -right.dot(position), + cameraUp.x, cameraUp.y, cameraUp.z, -cameraUp.dot(position), + -forward.x, -forward.y, -forward.z, forward.dot(position), + 0, 0, 0, 1 + ); + } + + Math::Matrix4x4 Camera::get_projection_matrix(float aspectRatio) const + { + using namespace Math; + + return Matrix4x4( + + ); + } +} diff --git a/CPU-Software-Renderer/Scene/Camera.h b/CPU-Software-Renderer/Scene/Camera.h index 2e3c3c6..5643cc8 100644 --- a/CPU-Software-Renderer/Scene/Camera.h +++ b/CPU-Software-Renderer/Scene/Camera.h @@ -1,7 +1,43 @@ #pragma once +#include "Vector3.h" +#include "Matrix4x4.h" namespace Scene { class Camera - {}; -} \ No newline at end of file + { + private: + Math::Vector3 position = Math::Vector3(0.0f, 0.0f, 0.0f); + Math::Vector3 target = Math::Vector3(0.0f, 0.0f, -1.0f); + Math::Vector3 up = Math::Vector3(0.0f, 1.0f, 0.0f); + + float verticalFovRadians = 1.0471975512f; + float nearPlane = 0.1f; + float farPlane = 100.0f; + + public: + Camera() = default; + + Math::Vector3 get_position() const { return position; } + void set_position(const Math::Vector3& pos) { position = pos; } + + Math::Vector3 get_target() const { return target; } + void set_target(const Math::Vector3& t) { target = t; } + + Math::Vector3 get_up() const { return up; } + void set_up(const Math::Vector3& u) { up = u; } + + float get_vertical_fov_radians() const { return verticalFovRadians; } + void set_vertical_fov_radians(float fov) { verticalFovRadians = fov; } + + float get_near_plane() const { return nearPlane; } + void set_near_plane(float nearP) { nearPlane = nearP; } + + float get_far_plane() const { return farPlane; } + void set_far_plane(float farP) { farPlane = farP; } + + Math::Matrix4x4 get_view_matrix() const; + + Math::Matrix4x4 get_projection_matrix(float aspectRatio) const; + }; +}