From fff40bbfe11c540eb76582375cd03fce19d23c8b Mon Sep 17 00:00:00 2001 From: xszAzy <3486170277@qq.com> Date: Tue, 14 Oct 2025 22:02:44 +0800 Subject: [PATCH] Update Camera --- MetalLearning/src/MEL/Camera/Camera.h | 7 ++- MetalLearning/src/MEL/Camera/Camera.mm | 67 ++++++++++++++------------ MetalLearning/src/Sandbox/Sandbox.mm | 59 ++++++++++++++++++----- 3 files changed, 89 insertions(+), 44 deletions(-) diff --git a/MetalLearning/src/MEL/Camera/Camera.h b/MetalLearning/src/MEL/Camera/Camera.h index 2b3583f..a648ae5 100644 --- a/MetalLearning/src/MEL/Camera/Camera.h +++ b/MetalLearning/src/MEL/Camera/Camera.h @@ -15,6 +15,10 @@ namespace MEL { void SetPosition(const simd::float3& position); void SetRotation(const simd::float3& eulerAngles); + void RotatePitch(float delta); + void RotateYaw(float delta); + void RotateRoll(float delta); + void SetTopDownView(); void LookAt(const simd::float3& target); @@ -30,9 +34,10 @@ namespace MEL { private: void UpdateViewMatrix(); void UpdateProjectionMatrix(); + void UpdateDirections(); simd::float3 m_Position={0.0f,0.0f,-1.0f}; - simd::float3 m_Rotation={0.0f,0.0f,0.0f}; + simd_quatf m_Orientation=simd_quaternion(0.0f, 0,0,-1); simd::float3 m_Forward={0.0f,0.0f,-1.0f}; simd::float3 m_Right={1.0f,0.0f,0.0f}; diff --git a/MetalLearning/src/MEL/Camera/Camera.mm b/MetalLearning/src/MEL/Camera/Camera.mm index 9eb4af7..dcf876d 100644 --- a/MetalLearning/src/MEL/Camera/Camera.mm +++ b/MetalLearning/src/MEL/Camera/Camera.mm @@ -37,55 +37,60 @@ namespace MEL { } void Camera::SetRotation(const simd::float3 &eulerAngles){ - m_Rotation=eulerAngles; + m_Orientation=simd_quaternion(0.0f,0.0f,0.0f,1.0f); - float cosPitch=cosf(m_Rotation.x); - float sinPitch=sinf(m_Rotation.x); - float cosYaw=cosf(m_Rotation.y); - float sinYaw=sinf(m_Rotation.y); - - m_Forward=simd::normalize(simd::float3{cosYaw*cosPitch,sinPitch,sinYaw*cosPitch}); - m_Right=simd::normalize(simd::cross(m_Forward, simd::float3{0,1,0})); - m_Up=simd::normalize(simd::cross(m_Right, m_Forward)); - - UpdateViewMatrix(); + RotateYaw(eulerAngles.y); + RotatePitch(eulerAngles.x); + RotateRoll(eulerAngles.z); } - void Camera::SetTopDownView(){ - m_Rotation=simd::float3{M_PI,M_PI/2,0.0f}; - - float cosPitch=cosf(m_Rotation.x); - float sinPitch=sinf(m_Rotation.x); - float cosYaw=cosf(m_Rotation.y); - float sinYaw=sinf(m_Rotation.y); - - m_Forward=simd::normalize(simd::float3{cosYaw*cosPitch,sinPitch,sinYaw*cosPitch}); - m_Right=simd::normalize(simd::cross(m_Forward, simd::float3{0,1,0})); - m_Up=simd::normalize(simd::cross(m_Right, m_Forward)); + void Camera::RotatePitch(float delta){ + simd_quatf rot=simd_quaternion(delta,-m_Right); + m_Orientation=simd::normalize(simd_mul(m_Orientation,rot)); + UpdateDirections(); + } + + void Camera::RotateYaw(float delta){ + simd_quatf rot=simd_quaternion(delta,simd::float3{0,1,0}); + m_Orientation=simd::normalize(simd_mul(m_Orientation,rot)); + UpdateDirections(); + } + + void Camera::RotateRoll(float delta){ + simd_quatf rot=simd_quaternion(delta,m_Forward); + m_Orientation=simd::normalize(simd_mul(m_Orientation,rot)); + UpdateDirections(); + } + + void Camera::UpdateDirections(){ + m_Right=simd::normalize(simd_act(m_Orientation, simd::float3{1,0,0})); + m_Up=simd::normalize(simd_act(m_Orientation, simd::float3{0,1,0})); + m_Forward=simd::normalize(simd_act(m_Orientation, simd::float3{0,0,-1})); UpdateViewMatrix(); } void Camera::LookAt(const simd::float3 &target){ + simd::float3 worldUp={0,1,0}; m_Forward=simd::normalize(target-m_Position); - m_Right=simd::normalize(simd::cross(m_Forward, simd::float3{0,1,0})); - m_Up=simd::normalize(simd::cross(m_Right, m_Forward)); + m_Right=simd::normalize(simd::cross(m_Forward,worldUp)); + m_Up=simd::normalize(simd::cross(m_Right,m_Forward)); UpdateViewMatrix(); } void Camera::UpdateViewMatrix(){ simd::float3 z=-simd::normalize(m_Forward); - simd::float3 x=simd::normalize(simd::cross(simd::float3{0,1,0}, z)); - simd::float3 y=simd::cross(z, x); + simd::float3 x=simd::normalize(m_Right); + simd::float3 y=simd::normalize(m_Up); simd::float3 p=m_Position; m_ViewMatrix=simd::float4x4{ - simd::float4{x.x,y.x,z.x,0}, - simd::float4{x.y,y.y,z.y,0}, - simd::float4{x.z,y.z,z.z,0}, - simd::float4{-simd::dot(x, p),-simd::dot(y, p),-simd::dot(z, p),1} + simd::float4{x.x,y.x,z.x,0.0f}, + simd::float4{x.y,y.y,z.y,0.0f}, + simd::float4{x.z,y.z,z.z,0.0f}, + simd::float4{-simd::dot(x,p),-simd::dot(y, p),-simd::dot(z, p),1.0f} }; m_ViewProjectionMatrix=m_ProjectionMatrix*m_ViewMatrix; } @@ -113,6 +118,6 @@ namespace MEL { -m_NearZ/(m_FarZ-m_NearZ),1.0f} }; } - m_ViewProjectionMatrix=m_ViewMatrix*m_ProjectionMatrix; + m_ViewProjectionMatrix=m_ProjectionMatrix*m_ViewMatrix; } } diff --git a/MetalLearning/src/Sandbox/Sandbox.mm b/MetalLearning/src/Sandbox/Sandbox.mm index 55b3b80..f714bf9 100644 --- a/MetalLearning/src/Sandbox/Sandbox.mm +++ b/MetalLearning/src/Sandbox/Sandbox.mm @@ -37,31 +37,66 @@ public: auto camera=m_Renderer->GetSceneCamera(); simd::float3 position=camera->GetPosition(); float moveSpeed=1.0f; + float rotateSpeed=1.0f; if(MEL::MacInput::IsKeyPressed(MEL::Key::W)){ if(camera){ - position.z+=moveSpeed*ts*2.0f; + position.z-=moveSpeed*ts*2.0f; MEL_INFO("Set Camera to position {:.2f},{:.2f},{:.2f}", (float)position[0],(float)position[1],(float)position[2]); } } else if (MEL::MacInput::IsKeyPressed(MEL::Key::S)){ if(camera){ - position.z-=moveSpeed*ts*2.0f; + position.z+=moveSpeed*ts*2.0f; MEL_INFO("Set Camera to position {:.2f},{:.2f},{:.2f}", (float)position[0],(float)position[1],(float)position[2]); } } + + if(MEL::MacInput::IsKeyPressed(MEL::Key::A)){ + if(camera){ + camera->RotateRoll(-rotateSpeed*ts); + } + } + else if(MEL::MacInput::IsKeyPressed(MEL::Key::D)){ + if(camera){ + camera->RotateRoll(rotateSpeed*ts); + } + } + + if(MEL::MacInput::IsKeyPressed(MEL::Key::J)){ + if(camera){ + camera->RotateYaw(-rotateSpeed*ts); + } + } + else if(MEL::MacInput::IsKeyPressed(MEL::Key::L)){ + if(camera){ + camera->RotateYaw(rotateSpeed*ts); + } + } + + if(MEL::MacInput::IsKeyPressed(MEL::Key::I)){ + if(camera){ + camera->RotatePitch(-rotateSpeed*ts); + } + } + else if(MEL::MacInput::IsKeyPressed(MEL::Key::K)){ + if(camera){ + camera->RotatePitch(rotateSpeed*ts); + } + } + if(MEL::MacInput::IsKeyPressed(MEL::Key::Left)){ if(camera){ - position.x-=moveSpeed*ts; + position-=camera->GetRight()*(moveSpeed*ts); MEL_INFO("Set Camera to position {:.2f},{:.2f},{:.2f}", (float)position[0],(float)position[1],(float)position[2]); } } else if (MEL::MacInput::IsKeyPressed(MEL::Key::Right)){ if(camera){ - position.x+=moveSpeed*ts; + position+=camera->GetRight()*(moveSpeed*ts); MEL_INFO("Set Camera to position {:.2f},{:.2f},{:.2f}", (float)position[0],(float)position[1],(float)position[2]); } @@ -69,27 +104,25 @@ public: if(MEL::MacInput::IsKeyPressed(MEL::Key::Up)){ if(camera){ - position.y+=moveSpeed*ts; + position+=camera->GetUp()*(moveSpeed*ts); MEL_INFO("Set Camera to position {:.2f},{:.2f},{:.2f}", (float)position[0],(float)position[1],(float)position[2]); } } else if (MEL::MacInput::IsKeyPressed(MEL::Key::Down)){ if(camera){ - position.y-=moveSpeed*ts; + position-=camera->GetUp()*(moveSpeed*ts); MEL_INFO("Set Camera to position {:.2f},{:.2f},{:.2f}", (float)position[0],(float)position[1],(float)position[2]); } } camera->SetPosition(position); - //camera->SetRotation({0.0f,0.0f,0.0f}); - m_Renderer->UpdateCameraUniform(); //draw - if(m_CurrentShader&&m_VertexArray) - MEL::RenderCommand::Submit(m_CurrentShader, m_VertexArray); + MEL::RenderCommand::Submit(m_CurrentShader, m_VertexArray); + MEL::RenderCommand::Submit(m_CurrentShader, m_TriangleVA); } void OnAttach() override{ @@ -97,6 +130,7 @@ public: m_Renderer=MEL::Application::Get().GetRenderer(); //shadersource + /* const char* ShaderSource=R"( #include using namespace metal; @@ -122,6 +156,7 @@ public: return in.color; } )"; + */ m_VertexArray=MEL::VertexArray::Create(); //set buffers struct Vertex{ @@ -133,7 +168,7 @@ public: //*camera=MEL::Camera::CreateOrthographic(-1.0f, 1.0f, -1.0f, 1.0f, 0.1f, 100.f); *camera=MEL::Camera::CreatePerspective(60.0f, 16.0f/9.0f, 0.1f, 100.0f); camera->SetPosition({0.0f,0.0f,3.0f}); - camera->SetTopDownView(); + //camera->LookAt({.0f,.0f,.0f}); m_Renderer->SetSceneCamera(camera); @@ -180,7 +215,7 @@ public: {{0.5f,-0.5f,0.0f}, {0.1f,0.7f,0.1f,1.0f}}, - {{0.0f,0.8f,0.0f}, + {{0.0f,0.5f,0.0f}, {0.0f,0.2f,0.8f,1.0f}} };