step2:model + view matrix

This commit is contained in:
SepComet 2026-03-15 22:18:43 +08:00
parent e1dd23131c
commit 67e4855211
7 changed files with 502 additions and 20 deletions

View File

@ -58,16 +58,24 @@
<ImportGroup Label="Shared"> <ImportGroup Label="Shared">
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"
Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')"
Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"
Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')"
Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"
Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')"
Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"
Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')"
Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
@ -77,7 +85,8 @@
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard> <LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>$(ProjectDir)Asset;$(ProjectDir)Core;$(ProjectDir)Math;$(ProjectDir)Rasterizer;$(ProjectDir)RenderData;$(ProjectDir)Scene;$(ProjectDir)Shading;$(ProjectDir)libs\SDL2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>
$(ProjectDir)Asset;$(ProjectDir)Core;$(ProjectDir)Math;$(ProjectDir)Rasterizer;$(ProjectDir)RenderData;$(ProjectDir)Scene;$(ProjectDir)Shading;$(ProjectDir)libs\SDL2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
@ -95,7 +104,8 @@
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard> <LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>$(ProjectDir)Asset;$(ProjectDir)Core;$(ProjectDir)Math;$(ProjectDir)Rasterizer;$(ProjectDir)RenderData;$(ProjectDir)Scene;$(ProjectDir)Shading;$(ProjectDir)libs\SDL2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>
$(ProjectDir)Asset;$(ProjectDir)Core;$(ProjectDir)Math;$(ProjectDir)Rasterizer;$(ProjectDir)RenderData;$(ProjectDir)Scene;$(ProjectDir)Shading;$(ProjectDir)libs\SDL2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
@ -111,7 +121,8 @@
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard> <LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>$(ProjectDir)Asset;$(ProjectDir)Core;$(ProjectDir)Math;$(ProjectDir)Rasterizer;$(ProjectDir)RenderData;$(ProjectDir)Scene;$(ProjectDir)Shading;$(ProjectDir)libs\SDL2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>
$(ProjectDir)Asset;$(ProjectDir)Core;$(ProjectDir)Math;$(ProjectDir)Rasterizer;$(ProjectDir)RenderData;$(ProjectDir)Scene;$(ProjectDir)Shading;$(ProjectDir)libs\SDL2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
@ -129,7 +140,8 @@
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard> <LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>$(ProjectDir)Asset;$(ProjectDir)Core;$(ProjectDir)Math;$(ProjectDir)Rasterizer;$(ProjectDir)RenderData;$(ProjectDir)Scene;$(ProjectDir)Shading;$(ProjectDir)libs\SDL2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>
$(ProjectDir)Asset;$(ProjectDir)Core;$(ProjectDir)Math;$(ProjectDir)Rasterizer;$(ProjectDir)RenderData;$(ProjectDir)Scene;$(ProjectDir)Shading;$(ProjectDir)libs\SDL2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
@ -146,6 +158,7 @@
<ClCompile Include="main.cpp" /> <ClCompile Include="main.cpp" />
<ClCompile Include="Rasterizer\Rasterizer.cpp" /> <ClCompile Include="Rasterizer\Rasterizer.cpp" />
<ClCompile Include="Rasterizer\TriangleRasterizer.cpp" /> <ClCompile Include="Rasterizer\TriangleRasterizer.cpp" />
<ClCompile Include="Scene\Camera.cpp" />
<ClCompile Include="Shading\BlinnPhongShader.cpp" /> <ClCompile Include="Shading\BlinnPhongShader.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -178,4 +191,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
</ImportGroup> </ImportGroup>
</Project> </Project>

View File

@ -1,7 +1,96 @@
#pragma once #pragma once
#include "Matrix4x4.h"
#include "Vector3.h"
#include <cmath>
namespace Math 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
);
}
};
} }

View File

@ -1,7 +1,177 @@
#pragma once #pragma once
#include <cmath>
#include "Vector3.h"
#include "Vector4.h"
namespace Math namespace Math
{ {
class Matrix4x4 class Matrix4x4
{}; {
} 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;
}
}

View File

@ -12,9 +12,74 @@ namespace Math
Vector3() : x(0), y(0), z(0) {} Vector3() : x(0), y(0), z(0) {}
Vector3(float x, float y, float z) : x(x), y(y), z(z) {} 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 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);
} }
}; };
}
inline Vector3 operator* (float scalar, const Vector3& vector)
{
return vector * scalar;
}
}

View File

@ -1,7 +1,83 @@
#pragma once #pragma once
#include <cmath>
#include "Vector3.h"
namespace Math namespace Math
{ {
class Vector4 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;
}
}

View File

@ -0,0 +1,33 @@
#pragma once
#include "Matrix4x4.h"
#include "Camera.h"
#include <Vector3.h>
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(
);
}
}

View File

@ -1,7 +1,43 @@
#pragma once #pragma once
#include "Vector3.h"
#include "Matrix4x4.h"
namespace Scene namespace Scene
{ {
class Camera class Camera
{}; {
} 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;
};
}