mirror of
https://github.com/orange-cpp/omath.git
synced 2026-02-13 07:03:25 +00:00
improved camera
This commit is contained in:
@@ -36,8 +36,8 @@ namespace omath::projection
|
|||||||
m_viewPort(viewPort), m_fieldOfView(fov), m_farPlaneDistance(far), m_nearPlaneDistance(near),
|
m_viewPort(viewPort), m_fieldOfView(fov), m_farPlaneDistance(far), m_nearPlaneDistance(near),
|
||||||
m_viewAngles(viewAngles), m_origin(position)
|
m_viewAngles(viewAngles), m_origin(position)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void LookAt(const Vector3<float>& target) = 0;
|
virtual void LookAt(const Vector3<float>& target) = 0;
|
||||||
|
|
||||||
@@ -49,8 +49,8 @@ namespace omath::projection
|
|||||||
{
|
{
|
||||||
return CalcProjectionMatrix() * CalcViewMatrix();
|
return CalcProjectionMatrix() * CalcViewMatrix();
|
||||||
}
|
}
|
||||||
public:
|
|
||||||
|
|
||||||
|
public:
|
||||||
[[nodiscard]] const Mat4x4Type& GetViewProjectionMatrix() const
|
[[nodiscard]] const Mat4x4Type& GetViewProjectionMatrix() const
|
||||||
{
|
{
|
||||||
if (!m_viewProjectionMatrix.has_value())
|
if (!m_viewProjectionMatrix.has_value())
|
||||||
@@ -116,10 +116,18 @@ namespace omath::projection
|
|||||||
|
|
||||||
[[nodiscard]] std::expected<Vector3<float>, Error> WorldToScreen(const Vector3<float>& worldPosition) const
|
[[nodiscard]] std::expected<Vector3<float>, Error> WorldToScreen(const Vector3<float>& worldPosition) const
|
||||||
{
|
{
|
||||||
const auto& viewProjMatrix = GetViewProjectionMatrix();
|
auto normalizedCords = WorldToViewPort(worldPosition);
|
||||||
const auto cameraCord = CalcViewMatrix() * MatColumnFromVector<float, Mat4x4Type::GetStoreOrdering()>(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)
|
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);
|
||||||
@@ -129,10 +137,7 @@ namespace omath::projection
|
|||||||
if (IsNdcOutOfBounds(projected))
|
if (IsNdcOutOfBounds(projected))
|
||||||
return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS);
|
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;
|
return Vector3<float>{projected.At(0, 0), projected.At(1, 0), projected.At(2, 0)};
|
||||||
const auto screenPositionY = (projected.At(1,0)+1.f) / 2.f * m_viewPort.m_height;
|
|
||||||
|
|
||||||
return Vector3{screenPositionX, screenPositionY, projected.At(2,0)};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -153,7 +158,17 @@ namespace omath::projection
|
|||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr static bool IsNdcOutOfBounds(const Type& ndc)
|
constexpr static bool IsNdcOutOfBounds(const Type& ndc)
|
||||||
{
|
{
|
||||||
return std::ranges::any_of( ndc.RawArray(), [](const auto& val) { return val < -1 || val > 1; });
|
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
|
} // namespace omath::projection
|
||||||
|
|||||||
@@ -26,10 +26,10 @@ namespace omath::iw_engine
|
|||||||
|
|
||||||
return {vec.At(0, 0), vec.At(1, 0), vec.At(2, 0)};
|
return {vec.At(0, 0), vec.At(1, 0), vec.At(2, 0)};
|
||||||
}
|
}
|
||||||
|
|
||||||
Mat4x4 CalcViewMatrix(const ViewAngles& angles, const Vector3<float>& cam_origin)
|
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,
|
Mat4x4 CalcPerspectiveProjectionMatrix(const float fieldOfView, const float aspectRatio, const float near,
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ namespace omath::opengl_engine
|
|||||||
{0, 1.f / (fovHalfTan), 0, 0},
|
{0, 1.f / (fovHalfTan), 0, 0},
|
||||||
{0, 0, -(far + near) / (far - near), -(2.f * far * near) / (far - near)},
|
{0, 0, -(far + near) / (far - near), -(2.f * far * near) / (far - near)},
|
||||||
{0, 0, -1, 0},
|
{0, 0, -1, 0},
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} // namespace omath::opengl_engine
|
} // namespace omath::opengl_engine
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace omath::source_engine
|
|||||||
|
|
||||||
Mat4x4 CalcViewMatrix(const ViewAngles& angles, const Vector3<float>& cam_origin)
|
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,
|
Mat4x4 CalcPerspectiveProjectionMatrix(const float fieldOfView, const float aspectRatio, const float near,
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ namespace omath::unity_engine
|
|||||||
{1.f / (aspectRatio * fovHalfTan), 0, 0, 0},
|
{1.f / (aspectRatio * fovHalfTan), 0, 0, 0},
|
||||||
{0, 1.f / (fovHalfTan), 0, 0},
|
{0, 1.f / (fovHalfTan), 0, 0},
|
||||||
{0, 0, (far + near) / (far - near), -(2.f * far * near) / (far - near)},
|
{0, 0, (far + near) / (far - near), -(2.f * far * near) / (far - near)},
|
||||||
{0, 0, 1.f, 0},
|
{0, 0, -1.f, 0},
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,28 +9,28 @@
|
|||||||
|
|
||||||
TEST(UnitTestEwEngine, ForwardVector)
|
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)
|
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)
|
TEST(UnitTestEwEngine, UpVector)
|
||||||
{
|
{
|
||||||
const auto up = omath::source_engine::UpVector({});
|
const auto up = omath::iw_engine::UpVector({});
|
||||||
EXPECT_EQ(up, omath::source_engine::kAbsUp);
|
EXPECT_EQ(up, omath::iw_engine::kAbsUp);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(UnitTestEwEngine, ProjectTargetMovedFromCamera)
|
TEST(UnitTestEwEngine, ProjectTargetMovedFromCamera)
|
||||||
{
|
{
|
||||||
constexpr auto fov = omath::projection::FieldOfView::FromDegrees(90.f);
|
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)
|
for (float distance = 0.02f; distance < 1000.f; distance += 0.01f)
|
||||||
@@ -50,7 +50,7 @@ TEST(UnitTestEwEngine, ProjectTargetMovedFromCamera)
|
|||||||
TEST(UnitTestEwEngine, CameraSetAndGetFov)
|
TEST(UnitTestEwEngine, CameraSetAndGetFov)
|
||||||
{
|
{
|
||||||
constexpr auto fov = omath::projection::FieldOfView::FromDegrees(90.f);
|
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);
|
EXPECT_EQ(cam.GetFieldOfView().AsDegrees(), 90.f);
|
||||||
cam.SetFieldOfView(omath::projection::FieldOfView::FromDegrees(50.f));
|
cam.SetFieldOfView(omath::projection::FieldOfView::FromDegrees(50.f));
|
||||||
@@ -60,7 +60,7 @@ TEST(UnitTestEwEngine, CameraSetAndGetFov)
|
|||||||
|
|
||||||
TEST(UnitTestEwEngine, CameraSetAndGetOrigin)
|
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>{});
|
EXPECT_EQ(cam.GetOrigin(), omath::Vector3<float>{});
|
||||||
cam.SetFieldOfView(omath::projection::FieldOfView::FromDegrees(50.f));
|
cam.SetFieldOfView(omath::projection::FieldOfView::FromDegrees(50.f));
|
||||||
|
|||||||
Reference in New Issue
Block a user