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;
+ };
+}