mirror of
https://github.com/orange-cpp/omath.git
synced 2026-02-14 07:23:26 +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,
|
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);
|
const Angle<float, 0.f, 180.f, AngleFlags::Clamped>& fov, float near, float far);
|
||||||
void LookAt(const Vector3& target) override;
|
void LookAt(const Vector3& target) override;
|
||||||
[[nodiscard]] Mat4x4 GetViewMatrix() const override;
|
[[nodiscard]] Mat4x4 CalcViewMatrix() const override;
|
||||||
[[nodiscard]] Mat4x4 GetProjectionMatrix() const override;
|
[[nodiscard]] Mat4x4 CalcProjectionMatrix() const override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,6 @@ namespace omath::projection
|
|||||||
template<class Mat4x4Type, class ViewAnglesType>
|
template<class Mat4x4Type, class ViewAnglesType>
|
||||||
class Camera
|
class Camera
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~Camera() = default;
|
virtual ~Camera() = default;
|
||||||
Camera(const Vector3& position, const ViewAnglesType& viewAngles, const ViewPort& viewPort,
|
Camera(const Vector3& position, const ViewAnglesType& viewAngles, const ViewPort& viewPort,
|
||||||
@@ -42,18 +41,82 @@ namespace omath::projection
|
|||||||
|
|
||||||
virtual void LookAt(const Vector3& target) = 0;
|
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)
|
if (projected.At(3, 0) == 0.0f)
|
||||||
return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS);
|
return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS);
|
||||||
@@ -70,6 +133,8 @@ namespace omath::projection
|
|||||||
ViewPort m_viewPort{};
|
ViewPort m_viewPort{};
|
||||||
Angle<float, 0.f, 180.f, AngleFlags::Clamped> m_fieldOfView;
|
Angle<float, 0.f, 180.f, AngleFlags::Clamped> m_fieldOfView;
|
||||||
|
|
||||||
|
mutable std::optional<Mat4x4Type> m_viewProjectionMatrix;
|
||||||
|
|
||||||
float m_farPlaneDistance;
|
float m_farPlaneDistance;
|
||||||
float m_nearPlaneDistance;
|
float m_nearPlaneDistance;
|
||||||
|
|
||||||
|
|||||||
@@ -24,12 +24,12 @@ namespace omath::source
|
|||||||
m_viewAngles.roll = RollAngle::FromRadians(0.f);
|
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);
|
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);
|
EXPECT_EQ(up, omath::source::kAbsUp);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(UnitTestSourceEngine, PerpectiveProjectionAtCenter)
|
TEST(UnitTestSourceEngine, ProjectTargetMovedFromCamera)
|
||||||
{
|
{
|
||||||
constexpr auto fov = omath::projection::FieldOfView::FromDegrees(90.f);
|
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);
|
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)
|
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());
|
EXPECT_TRUE(projected.has_value());
|
||||||
|
|
||||||
@@ -48,3 +46,24 @@ TEST(UnitTestSourceEngine, PerpectiveProjectionAtCenter)
|
|||||||
EXPECT_NEAR(projected->y, 540, 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)
|
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);
|
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);
|
std::print("{} {} {}", projected->x, projected->y, projected->z);
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user