improved camera

This commit is contained in:
2025-03-22 17:39:40 +03:00
parent 2b59fb6aa2
commit 481d7b85df
6 changed files with 38 additions and 24 deletions

View File

@@ -36,8 +36,8 @@ namespace omath::projection
m_viewPort(viewPort), m_fieldOfView(fov), m_farPlaneDistance(far), m_nearPlaneDistance(near),
m_viewAngles(viewAngles), m_origin(position)
{
}
protected:
virtual void LookAt(const Vector3<float>& target) = 0;
@@ -49,8 +49,8 @@ namespace omath::projection
{
return CalcProjectionMatrix() * CalcViewMatrix();
}
public:
public:
[[nodiscard]] const Mat4x4Type& GetViewProjectionMatrix() const
{
if (!m_viewProjectionMatrix.has_value())
@@ -116,10 +116,18 @@ namespace omath::projection
[[nodiscard]] std::expected<Vector3<float>, Error> WorldToScreen(const Vector3<float>& worldPosition) const
{
const auto& viewProjMatrix = GetViewProjectionMatrix();
const auto cameraCord = CalcViewMatrix() * MatColumnFromVector<float, Mat4x4Type::GetStoreOrdering()>(worldPosition);;
auto normalizedCords = WorldToViewPort(worldPosition);
auto projected = CalcProjectionMatrix() * cameraCord;
if (!normalizedCords.has_value())
return normalizedCords;
return NdcToScreenPosition(*normalizedCords);
}
[[nodiscard]] std::expected<Vector3<float>, Error> WorldToViewPort(const Vector3<float>& worldPosition) const
{
auto projected = GetViewProjectionMatrix() *
MatColumnFromVector<float, Mat4x4Type::GetStoreOrdering()>(worldPosition);
if (projected.At(3, 0) == 0.0f)
return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS);
@@ -129,10 +137,7 @@ namespace omath::projection
if (IsNdcOutOfBounds(projected))
return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS);
const auto screenPositionX = (projected.At(0,0)+1.f) / 2.f * m_viewPort.m_width;
const auto screenPositionY = (projected.At(1,0)+1.f) / 2.f * m_viewPort.m_height;
return Vector3{screenPositionX, screenPositionY, projected.At(2,0)};
return Vector3<float>{projected.At(0, 0), projected.At(1, 0), projected.At(2, 0)};
}
protected:
@@ -155,5 +160,15 @@ namespace omath::projection
{
return std::ranges::any_of(ndc.RawArray(), [](const auto& val) { return val < -1 || val > 1; });
}
[[nodiscard]] Vector3<float> NdcToScreenPosition(const Vector3<float>& ndc) const
{
return
{
(ndc.x + 1.f) / 2.f * m_viewPort.m_width,
(1.f - ndc.y) / 2.f * m_viewPort.m_height,
ndc.z
};
}
};
} // namespace omath::projection

View File

@@ -29,7 +29,7 @@ namespace omath::iw_engine
Mat4x4 CalcViewMatrix(const ViewAngles& angles, const Vector3<float>& cam_origin)
{
return MatCameraView(ForwardVector(angles), RightVector(angles), -UpVector(angles), cam_origin);
return MatCameraView(ForwardVector(angles), RightVector(angles), UpVector(angles), cam_origin);
}
Mat4x4 CalcPerspectiveProjectionMatrix(const float fieldOfView, const float aspectRatio, const float near,

View File

@@ -40,7 +40,6 @@ namespace omath::opengl_engine
{0, 1.f / (fovHalfTan), 0, 0},
{0, 0, -(far + near) / (far - near), -(2.f * far * near) / (far - near)},
{0, 0, -1, 0},
};
}
} // namespace omath::opengl_engine

View File

@@ -28,7 +28,7 @@ namespace omath::source_engine
Mat4x4 CalcViewMatrix(const ViewAngles& angles, const Vector3<float>& cam_origin)
{
return MatCameraView(ForwardVector(angles), RightVector(angles), -UpVector(angles), cam_origin);
return MatCameraView(ForwardVector(angles), RightVector(angles), UpVector(angles), cam_origin);
}
Mat4x4 CalcPerspectiveProjectionMatrix(const float fieldOfView, const float aspectRatio, const float near,

View File

@@ -39,7 +39,7 @@ namespace omath::unity_engine
{1.f / (aspectRatio * fovHalfTan), 0, 0, 0},
{0, 1.f / (fovHalfTan), 0, 0},
{0, 0, (far + near) / (far - near), -(2.f * far * near) / (far - near)},
{0, 0, 1.f, 0},
{0, 0, -1.f, 0},
};
}

View File

@@ -9,28 +9,28 @@
TEST(UnitTestEwEngine, ForwardVector)
{
const auto forward = omath::source_engine::ForwardVector({});
const auto forward = omath::iw_engine::ForwardVector({});
EXPECT_EQ(forward, omath::source_engine::kAbsForward);
EXPECT_EQ(forward, omath::iw_engine::kAbsForward);
}
TEST(UnitTestEwEngine, RightVector)
{
const auto right = omath::source_engine::RightVector({});
const auto right = omath::iw_engine::RightVector({});
EXPECT_EQ(right, omath::source_engine::kAbsRight);
EXPECT_EQ(right, omath::iw_engine::kAbsRight);
}
TEST(UnitTestEwEngine, UpVector)
{
const auto up = omath::source_engine::UpVector({});
EXPECT_EQ(up, omath::source_engine::kAbsUp);
const auto up = omath::iw_engine::UpVector({});
EXPECT_EQ(up, omath::iw_engine::kAbsUp);
}
TEST(UnitTestEwEngine, ProjectTargetMovedFromCamera)
{
constexpr auto fov = omath::projection::FieldOfView::FromDegrees(90.f);
const auto cam = omath::source_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f);
const auto cam = omath::iw_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f);
for (float distance = 0.02f; distance < 1000.f; distance += 0.01f)
@@ -50,7 +50,7 @@ TEST(UnitTestEwEngine, ProjectTargetMovedFromCamera)
TEST(UnitTestEwEngine, CameraSetAndGetFov)
{
constexpr auto fov = omath::projection::FieldOfView::FromDegrees(90.f);
auto cam = omath::source_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f);
auto cam = omath::iw_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f);
EXPECT_EQ(cam.GetFieldOfView().AsDegrees(), 90.f);
cam.SetFieldOfView(omath::projection::FieldOfView::FromDegrees(50.f));
@@ -60,7 +60,7 @@ TEST(UnitTestEwEngine, CameraSetAndGetFov)
TEST(UnitTestEwEngine, CameraSetAndGetOrigin)
{
auto cam = omath::source_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, {}, 0.01f, 1000.f);
auto cam = omath::iw_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, {}, 0.01f, 1000.f);
EXPECT_EQ(cam.GetOrigin(), omath::Vector3<float>{});
cam.SetFieldOfView(omath::projection::FieldOfView::FromDegrees(50.f));