added methods

This commit is contained in:
2024-12-23 15:34:38 +03:00
parent c3bfd12971
commit af880be056
5 changed files with 102 additions and 18 deletions

View File

@@ -13,7 +13,7 @@ namespace omath::source
Camera(const Vector3& position, const ViewAngles& viewAngles, const projection::ViewPort& viewPort,
const Angle<float, 0.f, 180.f, AngleFlags::Clamped>& fov, float near, float far);
void LookAt(const Vector3& target) override;
[[nodiscard]] Mat4x4 GetViewMatrix() const override;
[[nodiscard]] Mat4x4 GetProjectionMatrix() const override;
[[nodiscard]] Mat4x4 CalcViewMatrix() const override;
[[nodiscard]] Mat4x4 CalcProjectionMatrix() const override;
};
}

View File

@@ -29,7 +29,6 @@ namespace omath::projection
template<class Mat4x4Type, class ViewAnglesType>
class Camera
{
public:
virtual ~Camera() = default;
Camera(const Vector3& position, const ViewAnglesType& viewAngles, const ViewPort& viewPort,
@@ -42,18 +41,82 @@ namespace omath::projection
virtual void LookAt(const Vector3& target) = 0;
[[nodiscard]] virtual Mat4x4Type GetViewMatrix() const = 0;
[[nodiscard]] virtual Mat4x4Type CalcViewMatrix() const = 0;
[[nodiscard]] virtual Mat4x4Type GetProjectionMatrix() const = 0;
[[nodiscard]] virtual Mat4x4Type CalcProjectionMatrix() const = 0;
[[nodiscard]] Mat4x4Type GetViewProjectionMatrix()
[[nodiscard]] Mat4x4Type CalcViewProjectionMatrix() const
{
return GetProjectionMatrix() * GetViewMatrix();
return CalcProjectionMatrix() * CalcViewMatrix();
}
[[nodiscard]] std::expected<Vector3, Error> WorldToScreen(const Mat4x4Type& viewProj, const Vector3& worldPosition) const
void SetFieldOfView(const FieldOfView& fov)
{
auto projected = viewProj * MatColumnFromVector<float, Mat4x4Type::GetStoreOrdering()>(worldPosition);
m_fieldOfView = fov;
m_viewProjectionMatrix = CalcViewProjectionMatrix();
}
void SetNearPlane(const float near)
{
m_nearPlaneDistance = near;
m_viewProjectionMatrix = CalcViewProjectionMatrix();
}
void SetFarPlane(const float far)
{
m_farPlaneDistance = far;
m_viewProjectionMatrix = CalcViewProjectionMatrix();
}
void SetViewAngles(const ViewAnglesType& viewAngles)
{
m_viewAngles = viewAngles;
m_viewProjectionMatrix = CalcViewProjectionMatrix();
}
void SetOrigin(const Vector3& origin)
{
m_origin = origin;
m_viewProjectionMatrix = CalcViewProjectionMatrix();
}
void SetViewPort(const ViewPort& viewPort)
{
m_viewPort = viewPort;
m_viewProjectionMatrix = CalcViewProjectionMatrix();
}
[[nodiscard]] const FieldOfView& GetFieldOfView() const
{
return m_fieldOfView;
}
[[nodiscard]] const float& GetNearPlane() const
{
return m_nearPlaneDistance;
}
[[nodiscard]] const float& GetFarPlane() const
{
return m_farPlaneDistance;
}
[[nodiscard]] const ViewAnglesType& GetViewAngles() const
{
return m_viewAngles;
}
[[nodiscard]] const Vector3& GetOrigin() const
{
return m_origin;
}
[[nodiscard]] std::expected<Vector3, Error> WorldToScreen(const Vector3& worldPosition) const
{
if (!m_viewProjectionMatrix.has_value())
m_viewProjectionMatrix = CalcViewProjectionMatrix();
auto projected = m_viewProjectionMatrix.value() * MatColumnFromVector<float, Mat4x4Type::GetStoreOrdering()>(worldPosition);
if (projected.At(3, 0) == 0.0f)
return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS);
@@ -70,6 +133,8 @@ namespace omath::projection
ViewPort m_viewPort{};
Angle<float, 0.f, 180.f, AngleFlags::Clamped> m_fieldOfView;
mutable std::optional<Mat4x4Type> m_viewProjectionMatrix;
float m_farPlaneDistance;
float m_nearPlaneDistance;

View File

@@ -24,12 +24,12 @@ namespace omath::source
m_viewAngles.roll = RollAngle::FromRadians(0.f);
}
Mat4x4 Camera::GetViewMatrix() const
Mat4x4 Camera::CalcViewMatrix() const
{
return CalcViewMatrix(m_viewAngles, m_origin);
return source::CalcViewMatrix(m_viewAngles, m_origin);
}
Mat4x4 Camera::GetProjectionMatrix() const
Mat4x4 Camera::CalcProjectionMatrix() const
{
return CalcPerspectiveProjectionMatrix(m_fieldOfView.AsDegrees(), m_viewPort.AspectRatio(), m_nearPlaneDistance, m_farPlaneDistance);
}

View File

@@ -27,17 +27,15 @@ TEST(UnitTestSourceEngine, UpVector)
EXPECT_EQ(up, omath::source::kAbsUp);
}
TEST(UnitTestSourceEngine, PerpectiveProjectionAtCenter)
TEST(UnitTestSourceEngine, ProjectTargetMovedFromCamera)
{
constexpr auto fov = omath::projection::FieldOfView::FromDegrees(90.f);
auto cam = omath::source::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f);
const auto viewProjMatrix = cam.GetViewProjectionMatrix();
for (float distance = 0.02f; distance < 1000.f; distance += 0.01f)
{
const auto projected = cam.WorldToScreen(viewProjMatrix, {distance, 0, 0});
const auto projected = cam.WorldToScreen({distance, 0, 0});
EXPECT_TRUE(projected.has_value());
@@ -47,4 +45,25 @@ TEST(UnitTestSourceEngine, PerpectiveProjectionAtCenter)
EXPECT_NEAR(projected->x, 960, 0.00001f);
EXPECT_NEAR(projected->y, 540, 0.00001f);
}
}
TEST(UnitTestSourceEngine, CameraSetAndGetFov)
{
constexpr auto fov = omath::projection::FieldOfView::FromDegrees(90.f);
auto cam = omath::source::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));
EXPECT_EQ(cam.GetFieldOfView().AsDegrees(), 50.f);
}
TEST(UnitTestSourceEngine, CameraSetAndGetOrigin)
{
auto cam = omath::source::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, {}, 0.01f, 1000.f);
EXPECT_EQ(cam.GetOrigin(), omath::Vector3{});
cam.SetFieldOfView(omath::projection::FieldOfView::FromDegrees(50.f));
EXPECT_EQ(cam.GetFieldOfView().AsDegrees(), 50.f);
}

View File

@@ -10,9 +10,9 @@
TEST(UnitTestProjection, Projection)
{
auto x = omath::Angle<float, 0.f, 180.f, omath::AngleFlags::Clamped>::FromDegrees(90.f);
const auto x = omath::Angle<float, 0.f, 180.f, omath::AngleFlags::Clamped>::FromDegrees(90.f);
auto cam = omath::source::Camera({0, 0, 0}, omath::source::ViewAngles{}, {1920.f, 1080.f}, x, 0.01f, 1000.f);
const auto projected = cam.WorldToScreen(cam.GetViewProjectionMatrix(), {1000, 0, 50});
const auto projected = cam.WorldToScreen({1000, 0, 50});
std::print("{} {} {}", projected->x, projected->y, projected->z);
}