Hazel Game Engine (081) Scene Camera

If there are errors in the code, terminology, etc. in the text, please correct me

foreword

  • of this program

    When the size of the ImGui viewport changes, the cameras owned by all entities in the scene can correctly set the aspect ratio , so that the image will not be deformed .

  • In 080, update the vertices of the rendered graphics according to the camera of the entity camera component

    But there is no code to adjust the camera aspect ratio of the camera component , and there are few relative camera class behaviors, so

    • Made in this section

      • Created a new SceneCamera class inherited from the Camera class as the camera class property of the camera component
      • When the viewport changes, all cameras in the scene can update the aspect ratio
    • Graphic deformation bug

      Please add a picture description

  • difference from before

    Previously, the EditorLayer layer had an OrthographicCameraController m_CameraController orthographic camera . When the ImGui viewport changes size, this camera will adjust the aspect ratio.

    But Section 080 regards the camera class as an entity component, so it lacks the aspect ratio of updating the entity camera component

  • The comparison between this section and the previous one

    this section Before
    what changed Viewport Viewport
    who responded All camera components in the scene Camera of EditorLayer
    several cameras many 1

code flow

  • add an entity

    EditorLayer.h
    Entity m_CameraEntity;			// 摄像机实体
    
  • The entity adds the camera component, and the orthographic projection matrix is ​​calculated according to the default value in the constructor

    void EditorLayer::OnAttach(){
          
          
        m_CameraEntity = m_ActiveScene->CreateEntity("Camera Entity");
        m_CameraEntity.AddComponent<CameraComponent>();
     	.....   
    }
    
  • The size of the viewport and framebuffer is inconsistent, update all camera projection matrices in the scene

    void EditorLayer::OnUpdate(Timestep ts){
          
          
        // 窗口resize,在每一帧检测
        if (FramebufferSpecification spec = m_Framebuffer->GetSpecification();
            m_ViewportSize.x > 0.0f && m_ViewportSize.y > 0.0f &&
            (spec.Width != m_ViewportSize.x || spec.Height != m_ViewportSize.y)) {
          
          
            // 调整帧缓冲区大小
            m_Framebuffer->Resize((uint32_t)m_ViewportSize.x, (uint32_t)m_ViewportSize.y);
            // 调整摄像机投影:之前调整EditorLayer的摄像机宽高比代码
            m_CameraController.OnResize(m_ViewportSize.x, m_ViewportSize.y);
            //
            // 调整场景内的摄像机:此节所作
            m_ActiveScene->OnViewportResize((uint32_t)m_ViewportSize.x, (uint32_t)m_ViewportSize.y);
        }
        ......
    
        void Scene::OnViewportResize(uint32_t width, uint32_t height)
        {
          
          
            m_ViewportWidth = width;
            m_ViewportHeight = height;
    
            auto view = m_Registry.view<CameraComponent>();
            for (auto entity : view) {
          
          
                auto& cameraComponent = view.get<CameraComponent>(entity);
                if (!cameraComponent.fixedAspectRatio) {
          
          
                    cameraComponent.camera.SetViewportSize(width, height);
                }
            }
        }
    

related code

  • Modified Camera.h

    #pragma once
    #include <glm/glm.hpp>
    namespace Hazel {
          
          
    	class Camera {
          
          
    	public:
    		Camera() = default;
    		virtual ~Camera() = default;
    		Camera(const glm::mat4& projection)
    			: m_Projection(projection){
          
          }
    		const glm::mat4& GetProjection() const {
          
           return m_Projection; }
    		// TOOD:做透视投影
    	protected:
    		glm::mat4 m_Projection = glm::mat4(1.0f);
    	};
    }
    
  • Newly added SceneCamera

    #pragma once
    #include "Hazel/Renderer/Camera.h"
    
    namespace Hazel {
          
          
        class SceneCamera : public Camera
        {
          
          
        public:
            SceneCamera();
            virtual ~SceneCamera() = default;
            
            void SetOrthographic(float size, float nearClip, float farClip);
            
            void SetViewportSize(uint32_t width, uint32_t height);
    
            float GetOrthographicSize() const {
          
           return m_OrthographicSize; }
            void SetOrthographicSize(float size)  {
          
           m_OrthographicSize = size; RecalculateProjection();}
    
        private:
            void RecalculateProjection();
        private:
            float m_OrthographicSize = 10.0f;
            float m_OrthographicNear = -1.0f, m_OrthographicFar = 1.0f;
    
            float m_AspectRatio = 0.0f;
        };
    }
    
    #include "hzpch.h"
    #include "SceneCamera.h"
    
    #include <glm/gtc/matrix_transform.hpp>
    
    namespace Hazel {
          
          
    	SceneCamera::SceneCamera()
    	{
          
          
    		RecalculateProjection();
    	}
    	void SceneCamera::SetOrthographic(float size, float nearClip, float farClip)
    	{
          
          
    		m_OrthographicSize = size;
    		m_OrthographicNear = nearClip;
    		m_OrthographicFar = farClip;
    		RecalculateProjection();
    	}
    	void SceneCamera::SetViewportSize(uint32_t width, uint32_t height)
    	{
          
          
    		m_AspectRatio = (float)width / (float)height;
    		RecalculateProjection();
    	}
        
        // 根据m_OrthographicSize来计算宽高比与父类Camera的投影矩阵
    	void SceneCamera::RecalculateProjection()
    	{
          
          
            // TODO:根据父类的类型来计算正交投影矩阵还是透视投影矩阵
    		float orthoLeft = -m_OrthographicSize * m_AspectRatio * 0.5f;
    		float orthoRight = m_OrthographicSize * m_AspectRatio * 0.5f;
    		float orthoBottom = -m_OrthographicSize * 0.5f;
    		float orthoTop = m_OrthographicSize * 0.5f;
    		// 设置父类Camera的投影矩阵
    		m_Projection = glm::ortho(orthoLeft, orthoRight, orthoBottom,
    			orthoTop, m_OrthographicNear, m_OrthographicFar);
    	}
    }
    
  • Why keep the Camera class unchanged, and create a new SceneCamera class that inherits the Camera class

    Because Camera has an attribute m_Projection projection matrix , which is a common projection matrix attribute for orthogonal cameras and perspective cameras , so it is divided into the next level.

    In the RecalculateProjection function of the subclass

    • If the parent class is an orthographic camera

      Calculate the camera's orthographic projection matrix

    • If the parent class is a perspective camera

      Calculate the perspective projection matrix of the camera

ScenCamera compared with the previous OrthographicCamera

Initialize default values ​​and variable name substitution

  • OrthographicCamera

    m_AspectRatio = 1280.0f / 720.0f = 1.7
    
    m_ZoomLevel = 1.0f;	// 相当于ScenCamera的m_OrthographicSize
    m_Projection = glm::ortho(-m_AspectRatio * m_ZoomLevel, m_AspectRatio * m_ZoomLevel, -m_ZoomLevel, m_ZoomLevel, -1.0f, 1.0f);
    
  • ScenCamera

    // 这里初始化为0,是因为在layer层的onupdate中每帧会检测更新大小,这个值在窗口出现时计算
    float m_AspectRatio = 0.0f;
    // 相当于OrthographicCamera的m_ZoomLevel
    m_OrthographicSize=10.0f;// 用来放大还是放缩	
    // OrthographicCamera是默认值,这里用变量表示
    m_OrthographicNear=-1.0f,m_OrthographicFar = 1.0f;
    
    // 这里的m_OrthographicSize除了一半,相当于5,而OrthographicCamera的m_ZoomLevel不会除以一半
    float orthoLeft = -m_OrthographicSize * m_AspectRatio * 0.5f;
    float orthoRight = m_OrthographicSize * m_AspectRatio * 0.5f;
    float orthoBottom = -m_OrthographicSize * 0.5f;
    float orthoTop = m_OrthographicSize * 0.5f;
    
    m_Projection = glm::ortho(orthoLeft, orthoRight, orthoBottom,
    orthoTop, m_OrthographicNear, m_OrthographicFar);
    

renderings

Please add a picture description


Adjust the Viewport viewport size, the graphics will not be deformed

second camera

Please add a picture description

Guess you like

Origin blog.csdn.net/qq_34060370/article/details/132137420