mirror of
https://github.com/orange-cpp/omath.git
synced 2026-02-13 07:03:25 +00:00
improved some code
This commit is contained in:
@@ -144,5 +144,11 @@ namespace omath
|
||||
{
|
||||
return operator+(-other);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Angle operator-() const
|
||||
{
|
||||
return {-m_angle};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -349,7 +349,7 @@ namespace omath
|
||||
|
||||
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR, class Angle>
|
||||
[[nodiscard]]
|
||||
Mat<4, 4, Type, St> RotationMatAxisX(const Angle& angle) noexcept
|
||||
Mat<4, 4, Type, St> MatRotationAxisX(const Angle& angle) noexcept
|
||||
{
|
||||
return
|
||||
{
|
||||
@@ -362,7 +362,7 @@ namespace omath
|
||||
|
||||
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR, class Angle>
|
||||
[[nodiscard]]
|
||||
Mat<4, 4, Type, St> RotationMatAxisY(const Angle& angle) noexcept
|
||||
Mat<4, 4, Type, St> MatRotationAxisY(const Angle& angle) noexcept
|
||||
{
|
||||
return
|
||||
{
|
||||
@@ -375,7 +375,7 @@ namespace omath
|
||||
|
||||
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR, class Angle>
|
||||
[[nodiscard]]
|
||||
Mat<4, 4, Type, St> RotationMatAxisZ(const Angle& angle) noexcept
|
||||
Mat<4, 4, Type, St> MatRotationAxisZ(const Angle& angle) noexcept
|
||||
{
|
||||
return
|
||||
{
|
||||
@@ -386,10 +386,25 @@ namespace omath
|
||||
};
|
||||
}
|
||||
|
||||
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR>
|
||||
[[nodiscard]]
|
||||
static Mat<4, 4, Type, St> MatCameraView(const Vector3& forward, const Vector3& right, const Vector3& up,
|
||||
const Vector3& cameraOrigin) noexcept
|
||||
{
|
||||
return Mat<4, 4, Type, St>
|
||||
{
|
||||
{right.x, right.y, right.z, 0},
|
||||
{up.x, up.y, up.z, 0},
|
||||
{forward.x, forward.y, forward.z, 0},
|
||||
{0, 0, 0, 1},
|
||||
|
||||
} * MatTranslation<Type, St>(-cameraOrigin);
|
||||
}
|
||||
|
||||
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR, class ViewAngles>
|
||||
[[nodiscard]]
|
||||
Mat<4, 4, Type, St> RotationMat(const ViewAngles& angles) noexcept
|
||||
Mat<4, 4, Type, St> MatRotation(const ViewAngles& angles) noexcept
|
||||
{
|
||||
return RotationMatAxisZ(angles.yaw) * RotationMatAxisY(angles.pitch) * RotationMatAxisX(angles.roll);
|
||||
return MatRotationAxisZ(angles.yaw) * MatRotationAxisY(angles.pitch) * MatRotationAxisX(angles.roll);
|
||||
}
|
||||
} // namespace omath
|
||||
|
||||
14
include/omath/engines/OpenGL/Constants.hpp
Normal file
14
include/omath/engines/OpenGL/Constants.hpp
Normal file
@@ -0,0 +1,14 @@
|
||||
//
|
||||
// Created by Orange on 12/4/2024.
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include <omath/Vector3.h>
|
||||
|
||||
|
||||
namespace omath::opengl
|
||||
{
|
||||
constexpr Vector3 kAbsUp = {0, 1, 0};
|
||||
constexpr Vector3 kAbsRight = {1, 0, 0};
|
||||
constexpr Vector3 kAbsForward = {0, 0, -1};
|
||||
}
|
||||
4
include/omath/engines/OpenGL/Formulas.hpp
Normal file
4
include/omath/engines/OpenGL/Formulas.hpp
Normal file
@@ -0,0 +1,4 @@
|
||||
//
|
||||
// Created by Orange on 12/4/2024.
|
||||
//
|
||||
#pragma once
|
||||
@@ -10,11 +10,8 @@ namespace omath::source
|
||||
class Camera final : public projection::Camera<Mat4x4, ViewAngles>
|
||||
{
|
||||
public:
|
||||
Camera(const Vector3& position, const ViewAngles& viewAngles,
|
||||
const projection::ViewPort& viewPort, const Angle<float, 0, 180, AngleFlags::Clamped>& fov, float near, const float far) :
|
||||
projection::Camera<Mat4x4, ViewAngles>(position, viewAngles, viewPort, fov, near, far)
|
||||
{
|
||||
}
|
||||
Camera(const Vector3& position, const ViewAngles& viewAngles, const projection::ViewPort& viewPort,
|
||||
const Angle<float, 0, 180, AngleFlags::Clamped>& fov, float near, float far);
|
||||
void LookAt(const Vector3& target) override;
|
||||
[[nodiscard]] Mat4x4 GetViewMatrix() const override;
|
||||
[[nodiscard]] Mat4x4 GetProjectionMatrix() const override;
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace omath::source
|
||||
|
||||
using Mat4x4 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>;
|
||||
using Mat3x3 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>;
|
||||
|
||||
using Mat1x3 = Mat<1, 3, float, MatStoreType::ROW_MAJOR>;
|
||||
using PitchAngle = Angle<float, -89.f, 89.f, AngleFlags::Clamped>;
|
||||
using YawAngle = Angle<float, -180.f, 180.f, AngleFlags::Normalized>;
|
||||
using RollAngle = Angle<float, -180.f, 180.f, AngleFlags::Normalized>;
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace omath::source
|
||||
[[nodiscard]]
|
||||
inline Vector3 ForwardVector(const ViewAngles& angles)
|
||||
{
|
||||
const auto vec = RotationMat(angles) * MatColumnFromVector(kAbsForward);
|
||||
const auto vec = MatRotation(angles) * MatColumnFromVector(kAbsForward);
|
||||
|
||||
return {vec.At(0, 0), vec.At(1, 0), vec.At(2, 0)};
|
||||
}
|
||||
@@ -18,7 +18,7 @@ namespace omath::source
|
||||
[[nodiscard]]
|
||||
inline Vector3 RightVector(const ViewAngles& angles)
|
||||
{
|
||||
const auto vec = RotationMat(angles) * MatColumnFromVector(kAbsRight);
|
||||
const auto vec = MatRotation(angles) * MatColumnFromVector(kAbsRight);
|
||||
|
||||
return {vec.At(0, 0), vec.At(1, 0), vec.At(2, 0)};
|
||||
}
|
||||
@@ -26,33 +26,23 @@ namespace omath::source
|
||||
[[nodiscard]]
|
||||
inline Vector3 UpVector(const ViewAngles& angles)
|
||||
{
|
||||
const auto vec = RotationMat(angles) * MatColumnFromVector(kAbsUp);
|
||||
const auto vec = MatRotation(angles) * MatColumnFromVector(kAbsUp);
|
||||
|
||||
return {vec.At(0, 0), vec.At(1, 0), vec.At(2, 0)};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Mat4x4 ViewMatrixFromVecs(const Vector3& forward, const Vector3& right, const Vector3& up,
|
||||
const Vector3& camera_pos)
|
||||
[[nodiscard]] inline Mat4x4 CalcViewMatrix(const ViewAngles& angles, const Vector3& cam_origin)
|
||||
{
|
||||
return Mat4x4{
|
||||
{right.x, right.y, right.z, 0},
|
||||
{-up.x, -up.y, -up.z, 0},
|
||||
{forward.x, forward.y, forward.z, 0},
|
||||
{0, 0, 0, 1},
|
||||
} *
|
||||
MatTranslation<float, MatStoreType::ROW_MAJOR>(-camera_pos);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline Mat4x4 ViewMatrix(const ViewAngles& angles, const Vector3& cam_origin)
|
||||
{
|
||||
return ViewMatrixFromVecs(ForwardVector(angles), RightVector(angles), UpVector(angles), cam_origin);
|
||||
return MatCameraView(ForwardVector(angles), RightVector(angles), UpVector(angles), cam_origin);
|
||||
}
|
||||
|
||||
|
||||
[[nodiscard]]
|
||||
inline Mat4x4 PerspectiveProjectionMatrix(const float fieldOfView, const float aspectRatio, const float near, const float far)
|
||||
inline Mat4x4 CalcPerspectiveProjectionMatrix(const float fieldOfView, const float aspectRatio, const float near,
|
||||
const float far)
|
||||
{
|
||||
// NOTE: Needed tp make thing draw normal, since source is wierd
|
||||
// and use tricky projection matrix formula.
|
||||
constexpr auto kMultiplyFactor = 0.75f;
|
||||
|
||||
const float fovHalfTan = std::tan(angles::DegreesToRadians(fieldOfView) / 2.f) * kMultiplyFactor;
|
||||
@@ -62,6 +52,7 @@ namespace omath::source
|
||||
{0, 1.f / (fovHalfTan), 0, 0},
|
||||
{0, 0, (far + near) / (far - near), -(2.f * far * near) / (far - near)},
|
||||
{0, 0, 1, 0},
|
||||
|
||||
};
|
||||
}
|
||||
} // namespace omath::source
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace omath::projection
|
||||
return m_width / m_height;
|
||||
}
|
||||
};
|
||||
using FieldOfView = const Angle<float, 0.f, 180.f, AngleFlags::Clamped>;
|
||||
|
||||
template<class Mat4x4Type, class ViewAnglesType>
|
||||
class Camera
|
||||
@@ -33,7 +34,7 @@ namespace omath::projection
|
||||
public:
|
||||
virtual ~Camera() = default;
|
||||
Camera(const Vector3& position, const ViewAnglesType& viewAngles, const ViewPort& viewPort,
|
||||
const Angle<float, 0.f, 180.f, AngleFlags::Clamped>& fov, const float near, const float far) :
|
||||
const FieldOfView& fov, const float near, const float far) :
|
||||
m_viewPort(viewPort), m_fieldOfView(fov), m_farPlaneDistance(far), m_nearPlaneDistance(near),
|
||||
m_viewAngles(viewAngles), m_origin(position)
|
||||
{
|
||||
@@ -48,15 +49,12 @@ namespace omath::projection
|
||||
|
||||
[[nodiscard]] Mat4x4Type GetViewProjectionMatrix()
|
||||
{
|
||||
if (!m_viewProjectionMatrix)
|
||||
m_viewProjectionMatrix = GetProjectionMatrix() * GetViewMatrix();
|
||||
|
||||
return m_viewProjectionMatrix.value();
|
||||
return GetProjectionMatrix() * GetViewMatrix();
|
||||
}
|
||||
|
||||
[[nodiscard]] std::expected<Vector3, Error> WorldToScreen(const Vector3& worldPosition)
|
||||
[[nodiscard]] std::expected<Vector3, Error> WorldToScreen(const Mat4x4Type& viewProj, const Vector3& worldPosition) const
|
||||
{
|
||||
auto projected = GetViewProjectionMatrix() * MatColumnFromVector<float, Mat4x4Type::GetStoreOrdering()>(worldPosition);
|
||||
auto projected = viewProj * MatColumnFromVector<float, Mat4x4Type::GetStoreOrdering()>(worldPosition);
|
||||
|
||||
if (projected.At(3, 0) == 0.0f)
|
||||
return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS);
|
||||
@@ -66,7 +64,7 @@ namespace omath::projection
|
||||
if (IsNdcOutOfBounds(projected))
|
||||
return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS);
|
||||
|
||||
return Vector3{++projected.At(0,0) / 2 * m_viewPort.m_width , ++projected.At(1,0) / 2 * m_viewPort.m_height, projected.At(2,0)};
|
||||
return Vector3{(projected.At(0,0)+1) / 2 * m_viewPort.m_width , (-projected.At(1,0)+1) / 2 * m_viewPort.m_height, projected.At(2,0)};
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -81,7 +79,6 @@ namespace omath::projection
|
||||
Vector3 m_origin;
|
||||
|
||||
private:
|
||||
std::optional<Mat4x4Type> m_viewProjectionMatrix = std::nullopt;
|
||||
template<class Type>
|
||||
[[nodiscard]]
|
||||
constexpr static bool IsNdcOutOfBounds(const Type& ndc)
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
namespace omath::source
|
||||
{
|
||||
|
||||
Camera::Camera(const Vector3& position, const ViewAngles& viewAngles, const projection::ViewPort& viewPort,
|
||||
const projection::FieldOfView& fov, const float near, const float far) :
|
||||
projection::Camera<Mat4x4, ViewAngles>(position, viewAngles, viewPort, fov, near, far)
|
||||
{
|
||||
}
|
||||
void Camera::LookAt(const Vector3& target)
|
||||
{
|
||||
const float distance = m_origin.DistTo(target);
|
||||
@@ -15,17 +20,17 @@ namespace omath::source
|
||||
|
||||
|
||||
m_viewAngles.pitch = PitchAngle::FromRadians(std::asin(delta.z / distance));
|
||||
m_viewAngles.yaw = YawAngle::FromRadians(std::atan2(delta.y, delta.x));
|
||||
m_viewAngles.yaw = -YawAngle::FromRadians(std::atan2(delta.y, delta.x));
|
||||
m_viewAngles.roll = RollAngle::FromRadians(0.f);
|
||||
}
|
||||
|
||||
Mat4x4 Camera::GetViewMatrix() const
|
||||
{
|
||||
return ViewMatrix(m_viewAngles, m_origin);
|
||||
return CalcViewMatrix(m_viewAngles, m_origin);
|
||||
}
|
||||
|
||||
Mat4x4 Camera::GetProjectionMatrix() const
|
||||
{
|
||||
return PerspectiveProjectionMatrix(m_fieldOfView.AsDegrees(), m_viewPort.AspectRatio(), m_nearPlaneDistance, m_farPlaneDistance);
|
||||
return CalcPerspectiveProjectionMatrix(m_fieldOfView.AsDegrees(), m_viewPort.AspectRatio(), m_nearPlaneDistance, m_farPlaneDistance);
|
||||
}
|
||||
} // namespace omath::source
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <omath/Matrix.hpp>
|
||||
#include <print>
|
||||
#include <omath/engines/OpenGL.hpp>
|
||||
|
||||
// #include <glm/glm.hpp>
|
||||
|
||||
// #include "glm/ext/matrix_clip_space.hpp"
|
||||
@@ -35,13 +35,3 @@ TEST(UnitTestOpenGL, Projection)
|
||||
// ndc_omath /= ndc_omath.At(3, 0);
|
||||
*/
|
||||
}
|
||||
TEST(UnitTestOpenGL, Projection2)
|
||||
{
|
||||
const auto orient = omath::opengl::ViewMatrix(omath::opengl::kAbsForward, -omath::opengl::kAbsRight, omath::opengl::kAbsUp, {});
|
||||
|
||||
const omath::Mat<4, 1,float, omath::MatStoreType::COLUMN_MAJOR> cords_omath =
|
||||
{
|
||||
{0}, {0}, {-10}, {1}
|
||||
};
|
||||
std::cout << (orient * cords_omath).ToString();
|
||||
}
|
||||
@@ -2,16 +2,14 @@
|
||||
// Created by Orange on 11/23/2024.
|
||||
//
|
||||
#include <gtest/gtest.h>
|
||||
#include <omath/engines/Source/Camera.hpp>
|
||||
#include <omath/engines/Source/Constants.h>
|
||||
#include <omath/engines/Source/Formulas.hpp>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
TEST(UnitTestSourceEngine, ForwardVector)
|
||||
{
|
||||
const auto forward = omath::source::ForwardVector({});
|
||||
const auto forward = omath::source::ForwardVector({{}, {}, {}});
|
||||
|
||||
EXPECT_EQ(forward, omath::source::kAbsForward);
|
||||
}
|
||||
@@ -28,3 +26,25 @@ TEST(UnitTestSourceEngine, UpVector)
|
||||
const auto up = omath::source::UpVector({});
|
||||
EXPECT_EQ(up, omath::source::kAbsUp);
|
||||
}
|
||||
|
||||
TEST(UnitTestSourceEngine, PerpectiveProjectionAtCenter)
|
||||
{
|
||||
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});
|
||||
|
||||
EXPECT_TRUE(projected.has_value());
|
||||
|
||||
if (!projected.has_value())
|
||||
continue;
|
||||
|
||||
EXPECT_NEAR(projected->x, 960, 0.00001f);
|
||||
EXPECT_NEAR(projected->y, 540, 0.00001f);
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,8 @@
|
||||
TEST(UnitTestProjection, Projection)
|
||||
{
|
||||
auto x = omath::Angle<float, 0.f, 180.f, omath::AngleFlags::Clamped>::FromDegrees(90.f);
|
||||
auto cam = omath::source::Camera({-10, 0, 0}, omath::source::ViewAngles{}, {1920.f, 1080.f}, x, 0.1f, 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({10, 0, 0});
|
||||
const auto projected = cam.WorldToScreen(cam.GetViewProjectionMatrix(), {1000, 0, 50});
|
||||
std::print("{} {} {}", projected->x, projected->y, projected->z);
|
||||
}
|
||||
Reference in New Issue
Block a user