mirror of
https://github.com/orange-cpp/omath.git
synced 2026-02-13 07:03:25 +00:00
added methods
This commit is contained in:
@@ -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;
|
||||
};
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user