Skip to content

Commit 79f64d9

Browse files
committed
fixed unreal bug, improved interface
1 parent dbe2992 commit 79f64d9

9 files changed

Lines changed: 180 additions & 12 deletions

File tree

include/omath/engines/cry_engine/camera.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99

1010
namespace omath::cry_engine
1111
{
12-
using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait, false, NDCDepthRange::ZERO_TO_ONE>;
12+
using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait, NDCDepthRange::ZERO_TO_ONE>;
1313
} // namespace omath::cry_engine

include/omath/engines/frostbite_engine/camera.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99

1010
namespace omath::frostbite_engine
1111
{
12-
using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait, false, NDCDepthRange::ZERO_TO_ONE>;
12+
using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait, NDCDepthRange::ZERO_TO_ONE>;
1313
} // namespace omath::unity_engine

include/omath/engines/iw_engine/camera.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99

1010
namespace omath::iw_engine
1111
{
12-
using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait, false, NDCDepthRange::ZERO_TO_ONE>;
12+
using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait, NDCDepthRange::ZERO_TO_ONE>;
1313
} // namespace omath::iw_engine

include/omath/engines/opengl_engine/camera.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@
88

99
namespace omath::opengl_engine
1010
{
11-
using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait, true, NDCDepthRange::NEGATIVE_ONE_TO_ONE>;
11+
using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait, NDCDepthRange::NEGATIVE_ONE_TO_ONE, {.inverted_forward = true}>;
1212
} // namespace omath::opengl_engine

include/omath/engines/source_engine/camera.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@
77
#include "traits/camera_trait.hpp"
88
namespace omath::source_engine
99
{
10-
using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait, false, NDCDepthRange::ZERO_TO_ONE>;
10+
using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait, NDCDepthRange::ZERO_TO_ONE>;
1111
} // namespace omath::source_engine

include/omath/engines/unity_engine/camera.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99

1010
namespace omath::unity_engine
1111
{
12-
using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait, true, NDCDepthRange::ZERO_TO_ONE>;
12+
using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait, NDCDepthRange::ZERO_TO_ONE, {.inverted_forward = true}>;
1313
} // namespace omath::unity_engine

include/omath/engines/unreal_engine/camera.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99

1010
namespace omath::unreal_engine
1111
{
12-
using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait, false, NDCDepthRange::ZERO_TO_ONE>;
12+
using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait, NDCDepthRange::ZERO_TO_ONE, {.inverted_right = true}>;
1313
} // namespace omath::unreal_engine

include/omath/projection/camera.hpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ namespace omath::projection
4242
AUTO,
4343
MANUAL,
4444
};
45+
struct CameraAxes
46+
{
47+
bool inverted_forward = false;
48+
bool inverted_right = false;
49+
};
50+
4551
template<class T, class MatType, class ViewAnglesType>
4652
concept CameraEngineConcept =
4753
requires(const Vector3<float>& cam_origin, const Vector3<float>& look_at, const ViewAnglesType& angles,
@@ -58,8 +64,9 @@ namespace omath::projection
5864
requires noexcept(T::calc_projection_matrix(fov, viewport, znear, zfar, ndc_depth_range));
5965
};
6066

61-
template<class Mat4X4Type, class ViewAnglesType, class TraitClass, bool inverted_z = false,
62-
NDCDepthRange depth_range = NDCDepthRange::NEGATIVE_ONE_TO_ONE>
67+
template<class Mat4X4Type, class ViewAnglesType, class TraitClass,
68+
NDCDepthRange depth_range = NDCDepthRange::NEGATIVE_ONE_TO_ONE,
69+
CameraAxes axes = {}>
6370
requires CameraEngineConcept<TraitClass, Mat4X4Type, ViewAnglesType>
6471
class Camera final
6572
{
@@ -87,7 +94,7 @@ namespace omath::projection
8794
static ViewAnglesType calc_view_angles_from_view_matrix(const Mat4X4Type& view_matrix) noexcept
8895
{
8996
Vector3<float> forward_vector = {view_matrix[2, 0], view_matrix[2, 1], view_matrix[2, 2]};
90-
if constexpr (inverted_z)
97+
if constexpr (axes.inverted_forward)
9198
forward_vector = -forward_vector;
9299
return TraitClass::calc_look_at_angle({}, forward_vector);
93100
}
@@ -121,7 +128,7 @@ namespace omath::projection
121128
{
122129
const auto& view_matrix = get_view_matrix();
123130

124-
if constexpr (inverted_z)
131+
if constexpr (axes.inverted_forward)
125132
return -Vector3<float>{view_matrix[2, 0], view_matrix[2, 1], view_matrix[2, 2]};
126133
return {view_matrix[2, 0], view_matrix[2, 1], view_matrix[2, 2]};
127134
}
@@ -130,6 +137,8 @@ namespace omath::projection
130137
Vector3<float> get_right() const noexcept
131138
{
132139
const auto& view_matrix = get_view_matrix();
140+
if constexpr (axes.inverted_right)
141+
return -Vector3<float>{view_matrix[0, 0], view_matrix[0, 1], view_matrix[0, 2]};
133142
return {view_matrix[0, 0], view_matrix[0, 1], view_matrix[0, 2]};
134143
}
135144

tests/general/unit_test_projection.cpp

Lines changed: 160 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@
55
#include <complex>
66
#include <gtest/gtest.h>
77
#include <omath/3d_primitives/aabb.hpp>
8+
#include <omath/engines/cry_engine/camera.hpp>
9+
#include <omath/engines/frostbite_engine/camera.hpp>
10+
#include <omath/engines/iw_engine/camera.hpp>
811
#include <omath/engines/opengl_engine/camera.hpp>
912
#include <omath/engines/source_engine/camera.hpp>
13+
#include <omath/engines/unreal_engine/camera.hpp>
1014
#include <omath/projection/camera.hpp>
1115
#include <print>
1216
#include <random>
@@ -781,4 +785,159 @@ TEST(UnitTestProjection, Unity_CalcOriginFromViewMatrix_WithRotation)
781785
EXPECT_NEAR(origin.x, 300.f, k_eps);
782786
EXPECT_NEAR(origin.y, -100.f, k_eps);
783787
EXPECT_NEAR(origin.z, 75.f, k_eps);
784-
}
788+
}
789+
// ---- Camera basis vectors at zero angles ----
790+
791+
TEST(UnitTestProjection, SourceEngine_ZeroAngles_BasisVectors)
792+
{
793+
constexpr float k_eps = 1e-5f;
794+
const auto cam = omath::source_engine::Camera({}, {}, {1920.f, 1080.f},
795+
omath::projection::FieldOfView::from_degrees(90.f), 0.01f, 1000.f);
796+
const auto fwd = cam.get_forward();
797+
const auto right = cam.get_right();
798+
const auto up = cam.get_up();
799+
800+
EXPECT_NEAR(fwd.x, omath::source_engine::k_abs_forward.x, k_eps);
801+
EXPECT_NEAR(fwd.y, omath::source_engine::k_abs_forward.y, k_eps);
802+
EXPECT_NEAR(fwd.z, omath::source_engine::k_abs_forward.z, k_eps);
803+
804+
EXPECT_NEAR(right.x, omath::source_engine::k_abs_right.x, k_eps);
805+
EXPECT_NEAR(right.y, omath::source_engine::k_abs_right.y, k_eps);
806+
EXPECT_NEAR(right.z, omath::source_engine::k_abs_right.z, k_eps);
807+
808+
EXPECT_NEAR(up.x, omath::source_engine::k_abs_up.x, k_eps);
809+
EXPECT_NEAR(up.y, omath::source_engine::k_abs_up.y, k_eps);
810+
EXPECT_NEAR(up.z, omath::source_engine::k_abs_up.z, k_eps);
811+
}
812+
813+
TEST(UnitTestProjection, UnityEngine_ZeroAngles_BasisVectors)
814+
{
815+
constexpr float k_eps = 1e-5f;
816+
const auto cam = omath::unity_engine::Camera({}, {}, {1280.f, 720.f},
817+
omath::projection::FieldOfView::from_degrees(60.f), 0.03f, 1000.f);
818+
const auto fwd = cam.get_forward();
819+
const auto right = cam.get_right();
820+
const auto up = cam.get_up();
821+
822+
EXPECT_NEAR(fwd.x, omath::unity_engine::k_abs_forward.x, k_eps);
823+
EXPECT_NEAR(fwd.y, omath::unity_engine::k_abs_forward.y, k_eps);
824+
EXPECT_NEAR(fwd.z, omath::unity_engine::k_abs_forward.z, k_eps);
825+
826+
EXPECT_NEAR(right.x, omath::unity_engine::k_abs_right.x, k_eps);
827+
EXPECT_NEAR(right.y, omath::unity_engine::k_abs_right.y, k_eps);
828+
EXPECT_NEAR(right.z, omath::unity_engine::k_abs_right.z, k_eps);
829+
830+
EXPECT_NEAR(up.x, omath::unity_engine::k_abs_up.x, k_eps);
831+
EXPECT_NEAR(up.y, omath::unity_engine::k_abs_up.y, k_eps);
832+
EXPECT_NEAR(up.z, omath::unity_engine::k_abs_up.z, k_eps);
833+
}
834+
835+
TEST(UnitTestProjection, OpenGLEngine_ZeroAngles_BasisVectors)
836+
{
837+
constexpr float k_eps = 1e-5f;
838+
const auto cam = omath::opengl_engine::Camera({}, {}, {1920.f, 1080.f},
839+
omath::projection::FieldOfView::from_degrees(90.f), 0.01f, 1000.f);
840+
const auto fwd = cam.get_forward();
841+
const auto right = cam.get_right();
842+
const auto up = cam.get_up();
843+
844+
EXPECT_NEAR(fwd.x, omath::opengl_engine::k_abs_forward.x, k_eps);
845+
EXPECT_NEAR(fwd.y, omath::opengl_engine::k_abs_forward.y, k_eps);
846+
EXPECT_NEAR(fwd.z, omath::opengl_engine::k_abs_forward.z, k_eps);
847+
848+
EXPECT_NEAR(right.x, omath::opengl_engine::k_abs_right.x, k_eps);
849+
EXPECT_NEAR(right.y, omath::opengl_engine::k_abs_right.y, k_eps);
850+
EXPECT_NEAR(right.z, omath::opengl_engine::k_abs_right.z, k_eps);
851+
852+
EXPECT_NEAR(up.x, omath::opengl_engine::k_abs_up.x, k_eps);
853+
EXPECT_NEAR(up.y, omath::opengl_engine::k_abs_up.y, k_eps);
854+
EXPECT_NEAR(up.z, omath::opengl_engine::k_abs_up.z, k_eps);
855+
}
856+
857+
TEST(UnitTestProjection, UnrealEngine_ZeroAngles_BasisVectors)
858+
{
859+
constexpr float k_eps = 1e-5f;
860+
const auto cam = omath::unreal_engine::Camera({}, {}, {1920.f, 1080.f},
861+
omath::projection::FieldOfView::from_degrees(90.f), 0.01f, 1000.f);
862+
const auto fwd = cam.get_forward();
863+
const auto right = cam.get_right();
864+
const auto up = cam.get_up();
865+
866+
EXPECT_NEAR(fwd.x, omath::unreal_engine::k_abs_forward.x, k_eps);
867+
EXPECT_NEAR(fwd.y, omath::unreal_engine::k_abs_forward.y, k_eps);
868+
EXPECT_NEAR(fwd.z, omath::unreal_engine::k_abs_forward.z, k_eps);
869+
870+
EXPECT_NEAR(right.x, omath::unreal_engine::k_abs_right.x, k_eps);
871+
EXPECT_NEAR(right.y, omath::unreal_engine::k_abs_right.y, k_eps);
872+
EXPECT_NEAR(right.z, omath::unreal_engine::k_abs_right.z, k_eps);
873+
874+
EXPECT_NEAR(up.x, omath::unreal_engine::k_abs_up.x, k_eps);
875+
EXPECT_NEAR(up.y, omath::unreal_engine::k_abs_up.y, k_eps);
876+
EXPECT_NEAR(up.z, omath::unreal_engine::k_abs_up.z, k_eps);
877+
}
878+
879+
TEST(UnitTestProjection, FrostbiteEngine_ZeroAngles_BasisVectors)
880+
{
881+
constexpr float k_eps = 1e-5f;
882+
const auto cam = omath::frostbite_engine::Camera({}, {}, {1920.f, 1080.f},
883+
omath::projection::FieldOfView::from_degrees(90.f), 0.01f, 1000.f);
884+
const auto fwd = cam.get_forward();
885+
const auto right = cam.get_right();
886+
const auto up = cam.get_up();
887+
888+
EXPECT_NEAR(fwd.x, omath::frostbite_engine::k_abs_forward.x, k_eps);
889+
EXPECT_NEAR(fwd.y, omath::frostbite_engine::k_abs_forward.y, k_eps);
890+
EXPECT_NEAR(fwd.z, omath::frostbite_engine::k_abs_forward.z, k_eps);
891+
892+
EXPECT_NEAR(right.x, omath::frostbite_engine::k_abs_right.x, k_eps);
893+
EXPECT_NEAR(right.y, omath::frostbite_engine::k_abs_right.y, k_eps);
894+
EXPECT_NEAR(right.z, omath::frostbite_engine::k_abs_right.z, k_eps);
895+
896+
EXPECT_NEAR(up.x, omath::frostbite_engine::k_abs_up.x, k_eps);
897+
EXPECT_NEAR(up.y, omath::frostbite_engine::k_abs_up.y, k_eps);
898+
EXPECT_NEAR(up.z, omath::frostbite_engine::k_abs_up.z, k_eps);
899+
}
900+
901+
TEST(UnitTestProjection, CryEngine_ZeroAngles_BasisVectors)
902+
{
903+
constexpr float k_eps = 1e-5f;
904+
const auto cam = omath::cry_engine::Camera({}, {}, {1920.f, 1080.f},
905+
omath::projection::FieldOfView::from_degrees(90.f), 0.01f, 1000.f);
906+
const auto fwd = cam.get_forward();
907+
const auto right = cam.get_right();
908+
const auto up = cam.get_up();
909+
910+
EXPECT_NEAR(fwd.x, omath::cry_engine::k_abs_forward.x, k_eps);
911+
EXPECT_NEAR(fwd.y, omath::cry_engine::k_abs_forward.y, k_eps);
912+
EXPECT_NEAR(fwd.z, omath::cry_engine::k_abs_forward.z, k_eps);
913+
914+
EXPECT_NEAR(right.x, omath::cry_engine::k_abs_right.x, k_eps);
915+
EXPECT_NEAR(right.y, omath::cry_engine::k_abs_right.y, k_eps);
916+
EXPECT_NEAR(right.z, omath::cry_engine::k_abs_right.z, k_eps);
917+
918+
EXPECT_NEAR(up.x, omath::cry_engine::k_abs_up.x, k_eps);
919+
EXPECT_NEAR(up.y, omath::cry_engine::k_abs_up.y, k_eps);
920+
EXPECT_NEAR(up.z, omath::cry_engine::k_abs_up.z, k_eps);
921+
}
922+
923+
TEST(UnitTestProjection, IWEngine_ZeroAngles_BasisVectors)
924+
{
925+
constexpr float k_eps = 1e-5f;
926+
const auto cam = omath::iw_engine::Camera({}, {}, {1920.f, 1080.f},
927+
omath::projection::FieldOfView::from_degrees(90.f), 0.01f, 1000.f);
928+
const auto fwd = cam.get_forward();
929+
const auto right = cam.get_right();
930+
const auto up = cam.get_up();
931+
932+
EXPECT_NEAR(fwd.x, omath::iw_engine::k_abs_forward.x, k_eps);
933+
EXPECT_NEAR(fwd.y, omath::iw_engine::k_abs_forward.y, k_eps);
934+
EXPECT_NEAR(fwd.z, omath::iw_engine::k_abs_forward.z, k_eps);
935+
936+
EXPECT_NEAR(right.x, omath::iw_engine::k_abs_right.x, k_eps);
937+
EXPECT_NEAR(right.y, omath::iw_engine::k_abs_right.y, k_eps);
938+
EXPECT_NEAR(right.z, omath::iw_engine::k_abs_right.z, k_eps);
939+
940+
EXPECT_NEAR(up.x, omath::iw_engine::k_abs_up.x, k_eps);
941+
EXPECT_NEAR(up.y, omath::iw_engine::k_abs_up.y, k_eps);
942+
EXPECT_NEAR(up.z, omath::iw_engine::k_abs_up.z, k_eps);
943+
}

0 commit comments

Comments
 (0)