- 修正上一版"全量暴力重算":UE 实为 dirty 标记 + 惰性计算,前提是 字段私有(SetRelativeLocation 等 setter 标脏 + 子级传播) - TransformComponent:SRT 字段私有化,Set/Get/World()/IsDirty 访问器; Set* 变更才标脏;AddRotationY 便捷接口 - Scene::UpdateTransforms 只重算脏实体——静止实体零成本; 层级(父子)传播在脏标记基础上扩展 - 迁移 Camera/SceneRenderer/main.cpp 到封装 API
73 lines
2.9 KiB
C++
73 lines
2.9 KiB
C++
//
|
||
// Created by atdunbg on 2026/9/22.
|
||
//
|
||
|
||
#include <Engine/Renderer/Camera.h>
|
||
#include <Engine/Core/Window.h>
|
||
#include <Engine/ECS/Components.h>
|
||
|
||
#include <glm/gtc/matrix_transform.hpp>
|
||
|
||
#include "GLFW/glfw3.h"
|
||
|
||
namespace Engine {
|
||
|
||
void Camera::Update(Window& window, ECS::TransformComponent& t, f32 deltaTime)
|
||
{
|
||
// 鼠标旋转:直接写实体旋转(yaw → rotation.y,pitch → rotation.x)
|
||
if (m_MouseLookEnabled)
|
||
{
|
||
f32 mouseDX = 0, mouseDY = 0;
|
||
window.GetMouseDelta(mouseDX, mouseDY);
|
||
|
||
if (mouseDX != 0 || mouseDY != 0)
|
||
{
|
||
glm::vec3 rot = t.GetRotation();
|
||
rot.y += mouseDX * m_MouseSensitivity;
|
||
rot.x = glm::clamp(
|
||
rot.x - mouseDY * m_MouseSensitivity, -89.0f, 89.0f);
|
||
t.SetRotation(rot);
|
||
}
|
||
}
|
||
|
||
// 基向量由实体旋转决定(本地 -Z 为视线方向;应用顺序 Y→X,
|
||
// 与 TransformComponent::Compose 一致;roll 不参与 FPS 相机)
|
||
const glm::vec3& rot = t.GetRotation();
|
||
const glm::mat3 r = static_cast<glm::mat3>(
|
||
glm::rotate(glm::mat4(1.0f), glm::radians(rot.y),
|
||
glm::vec3(0, 1, 0)) *
|
||
glm::rotate(glm::mat4(1.0f), glm::radians(rot.x),
|
||
glm::vec3(1, 0, 0)));
|
||
const glm::vec3 forward = r * glm::vec3(0, 0, -1);
|
||
const glm::vec3 right = r * glm::vec3(1, 0, 0);
|
||
|
||
f32 speed = m_MoveSpeed * deltaTime;
|
||
if (window.IsKeyPressed(GLFW_KEY_W)) { t.SetPosition(t.GetPosition() + forward * speed); }
|
||
if (window.IsKeyPressed(GLFW_KEY_S)) { t.SetPosition(t.GetPosition() - forward * speed); }
|
||
if (window.IsKeyPressed(GLFW_KEY_A)) { t.SetPosition(t.GetPosition() - right * speed); }
|
||
if (window.IsKeyPressed(GLFW_KEY_D)) { t.SetPosition(t.GetPosition() + right * speed); }
|
||
if (window.IsKeyPressed(GLFW_KEY_SPACE)) { t.SetPosition(t.GetPosition() + glm::vec3(0, speed, 0)); }
|
||
if (window.IsKeyPressed(GLFW_KEY_LEFT_SHIFT)) { t.SetPosition(t.GetPosition() - glm::vec3(0, speed, 0)); }
|
||
}
|
||
|
||
glm::mat4 Camera::GetView(const ECS::TransformComponent& t) const
|
||
{
|
||
// 相机作为实体:视图 = 世界矩阵的逆(无重复位姿状态)
|
||
return glm::inverse(t.World());
|
||
}
|
||
|
||
glm::mat4 Camera::GetProjection(f32 aspect, f32 nearZ, f32 farZ) const
|
||
{
|
||
auto proj = glm::perspective(glm::radians(45.0f), aspect, nearZ, farZ);
|
||
proj[1][1] *= -1.0f; // Vulkan Y 翻转
|
||
|
||
// Vulkan clip 深度 [0,1]:z' = 0.5*z_clip + 0.5*w_clip。
|
||
// perspective 的 w_clip = -z_eye,偏移折算进 z 系数
|
||
//(注意:与 ortho 的公式不同,ortho 的 w=1 才能直接加到 [3][2])
|
||
proj[2][2] = proj[2][2] * 0.5f - 0.5f;
|
||
proj[3][2] *= 0.5f;
|
||
return proj;
|
||
}
|
||
|
||
} // namespace Engine
|