If there are errors in the code, terminology, etc. in the text, please correct me
Article directory
foreword
-
The bug in the previous section
Initialize Entity's m_EntityHandle to null instead of 0
entt::entity m_EntityHandle{ entt::null }; operator bool() const { return m_EntityHandle != entt::null; }
-
Contents of this section
-
Design a Camera component
That is, an entity can use the Camera component
-
This Camera component needs to have a Camera class pointer
The properties and behaviors of the Camera class
-
Set to perspective projection projection matrix or orthogonal projection projection matrix (not done)
-
Whether the main camera
-
Get the projection projection matrix
Pay attention to the distinction: Camera component and Camera class, the entity adds the Camera component, the Camera component has the Camera class, so the entity can obtain the Camera through the component
-
-
Camera class and Camera component design
-
Newly added Camera.h
#pragma once #include <glm/glm.hpp> namespace Hazel { class Camera { public: Camera(const glm::mat4& projection) : m_Projection(projection){ } const glm::mat4& GetProjection() const { return m_Projection; } // TOOD:做透视投影 private: glm::mat4 m_Projection; }; }
-
Components.h
struct CameraComponent { Camera camera; bool primary = true; CameraComponent() = default; CameraComponent(const CameraComponent&) = default; CameraComponent(const glm::mat4 & projection) : camera(projection) { } };
Scene switching to the main camera perspective code flow
-
Add an entity to the EditorLayer layer
EditorLayer.h Entity m_CameraEntity; // 摄像机实体
-
The entity adds the camera component and initializes the orthographic projection matrix
EditorLayer.cpp // 初始化摄像机实体 m_CameraEntity = m_ActiveScene->CreateEntity("Camera Entity"); m_CameraEntity.AddComponent<CameraComponent>(glm::ortho(-16.0f, 16.0f, -9.0f, 9.0f, -1.0f, 1.0f));
-
Find the main camera in the scene onupdate method , and get the transform of the main camera to calculate the view matrix
Scene.cpp void Scene::OnUpdate(Timestep ts) { // 获取到主摄像机,并且获取到摄像机的位置,用来计算投影矩阵projection Camera* mainCamera = nullptr; glm::mat4* cameraTransform = nullptr; { auto group = m_Registry.view<TransformComponent, CameraComponent>(); for (auto entity : group){ auto &[transform, camera] = group.get<TransformComponent, CameraComponent>(entity); if (camera.primary) { mainCamera = &camera.camera; cameraTransform = &transform.Transform; } } } /// // 注意这,BeginScene中传入主摄像机的投影矩阵与主摄像机的transform矩阵 if (mainCamera) { Renderer2D::BeginScene(mainCamera->GetProjection(), *cameraTransform); auto group = m_Registry.group<TransformComponent>(entt::get<SpriteRendererComponent>); for (auto entity : group) { auto& [transform, sprite] = group.get<TransformComponent, SpriteRendererComponent>(entity); Renderer2D::DrawQuad(transform, sprite.Color); } Renderer2D::EndScene(); } }
-
In the renderer's beginscene method, the projection matrix*view matrix is uploaded to opengl
Renderer2D.cpp void Renderer2D::BeginScene(const Camera& camera, const glm::mat4& transform) { // 投影矩阵projection * 视图矩阵 glm::mat4 viewProj = camera.GetProjection() * glm::inverse(transform); s_Data.TextureShader->Bind(); // 绑定shader s_Data.TextureShader->SetMat4("u_ViewProjection", viewProj);
Two entities, each entity has the effect of the Camera component
-
Entity (camera) 1 is regarded as the main camera
-
Entity (camera) 2 is regarded as the main camera
question
-
Question Details
Why modifying the fourth column of the transform matrix can change the position of the scene's camera
/* 一开始以为:Transform[3]是第四行 后面查资料才发现Transform[3]应该是第四列 */ ImGui::DragFloat3("Camera Transform", glm::value_ptr(m_CameraEntity.GetComponent<TransformComponent>().Transform[3]));
The transform matrix is a combination of translation matrix * rotation matrix * scaling matrix, since there is no rotation and scaling matrix set, so
It can be considered here that the transform matrix is the translate translation matrix
-
translateTranslation Matrix Diagram References
-
The fourth column is the position of the camera
-
The transform matrix is the translate translation matrix
-
The fourth column is represented by Transform[3], so changing Transform[3] can change the position of the camera
-
-
In addition, some principle reference materials
-
From subsection 034, the interface of the camera moving to the left actually shows that the object is moving to the right
-
So changing the fourth column of the camera's transform here doesn't actually change the camera's position
-
Instead, calculate the camera's view matrix in Renderer2D::BeginScene, multiply it with the projection matrix and upload it to OpenGL
-
In the OpenGL shader, the projection matrix * view matrix * vertex position of the object is used
-
Transform the vertex position of the object to the observation space through the view matrix
(The vertex position of the object is transformed to a specific position according to the transform matrix. This section is to translate the vertex to the specified position according to the translate matrix)
So modifying the value of transform[3] in this section will take effect here
-
Then through the projection matrix transformation to the clipping space , to the standardized device coordinates, to the screen coordinates (displayed on the screen)
-
-
On the surface, the camera is moving, but in fact it is the movement of all the vertices that make up the object.
void Renderer2D::BeginScene(const Camera& camera, const glm::mat4& transform){ // 投影矩阵projection * 视图矩阵 glm::mat4 viewProj = camera.GetProjection() * glm::inverse(transform); s_Data.TextureShader->Bind(); // 绑定shader s_Data.TextureShader->SetMat4("u_ViewProjection", viewProj);
-