mirror of
https://github.com/orange-cpp/omath.git
synced 2026-08-07 21:42:05 +00:00
fix
This commit is contained in:
@@ -13,11 +13,16 @@ namespace omath::algorithm
|
|||||||
Vector3<float> world_to_radar(const Camera& camera, const Vector3<FloatingType>& position, const FloatingType scale)
|
Vector3<float> world_to_radar(const Camera& camera, const Vector3<FloatingType>& position, const FloatingType scale)
|
||||||
{
|
{
|
||||||
const auto origin = static_cast<Vector3<FloatingType>>(camera.get_origin());
|
const auto origin = static_cast<Vector3<FloatingType>>(camera.get_origin());
|
||||||
const auto forward = static_cast<Vector3<FloatingType>>(camera.get_abs_forward());
|
auto current_angles = camera.get_view_angles();
|
||||||
const auto right = static_cast<Vector3<FloatingType>>(camera.get_abs_right());
|
auto look_at_angles = camera.calc_look_at_angles(position);
|
||||||
const auto direction = position - origin;
|
auto yaw = look_at_angles.yaw - current_angles.yaw;
|
||||||
|
|
||||||
return {static_cast<float>(direction.dot(right) * scale), static_cast<float>(-direction.dot(forward) * scale),
|
const auto right = origin + static_cast<Vector3<FloatingType>>(camera.get_abs_right());
|
||||||
0.f};
|
auto right_yaw = camera.calc_look_at_angles(right).yaw - current_angles.yaw;
|
||||||
|
const auto right_sign = right_yaw.sin() < FloatingType{0} ? FloatingType{-1} : FloatingType{1};
|
||||||
|
const auto radar_distance = position.distance_to(origin) * scale;
|
||||||
|
|
||||||
|
return {static_cast<float>(yaw.sin() * right_sign * radar_distance),
|
||||||
|
static_cast<float>(-yaw.cos() * radar_distance), 0.f};
|
||||||
}
|
}
|
||||||
} // namespace omath::algorithm
|
} // namespace omath::algorithm
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
using namespace omath;
|
using namespace omath;
|
||||||
|
|
||||||
template<class CameraType, class NumericType>
|
template<class CameraType, class NumericType>
|
||||||
static void verify_world_to_radar_uses_camera_axes()
|
static void verify_world_to_radar_uses_engine_world_axes(const Vector3<NumericType>& world_forward,
|
||||||
|
const Vector3<NumericType>& world_right)
|
||||||
{
|
{
|
||||||
const Vector3<NumericType> origin{NumericType{10}, NumericType{-20}, NumericType{5}};
|
const Vector3<NumericType> origin{NumericType{10}, NumericType{-20}, NumericType{5}};
|
||||||
const NumericType world_distance = NumericType{20};
|
const NumericType world_distance = NumericType{20};
|
||||||
@@ -23,14 +24,14 @@ static void verify_world_to_radar_uses_camera_axes()
|
|||||||
origin, {}, {1280.f, 720.f}, projection::FieldOfView::from_degrees(90.f), NumericType{0.01},
|
origin, {}, {1280.f, 720.f}, projection::FieldOfView::from_degrees(90.f), NumericType{0.01},
|
||||||
NumericType{1000}};
|
NumericType{1000}};
|
||||||
|
|
||||||
const auto forward_position = origin + camera.get_abs_forward() * world_distance;
|
const auto forward_position = origin + world_forward * world_distance;
|
||||||
const auto forward_radar = algorithm::world_to_radar(camera, forward_position, scale);
|
const auto forward_radar = algorithm::world_to_radar(camera, forward_position, scale);
|
||||||
|
|
||||||
EXPECT_NEAR(forward_radar.x, 0.f, 1e-4f);
|
EXPECT_NEAR(forward_radar.x, 0.f, 1e-4f);
|
||||||
EXPECT_NEAR(forward_radar.y, -radar_distance, 1e-4f);
|
EXPECT_NEAR(forward_radar.y, -radar_distance, 1e-4f);
|
||||||
EXPECT_NEAR(forward_radar.z, 0.f, 1e-6f);
|
EXPECT_NEAR(forward_radar.z, 0.f, 1e-6f);
|
||||||
|
|
||||||
const auto right_position = origin + camera.get_abs_right() * world_distance;
|
const auto right_position = origin + world_right * world_distance;
|
||||||
const auto right_radar = algorithm::world_to_radar(camera, right_position, scale);
|
const auto right_radar = algorithm::world_to_radar(camera, right_position, scale);
|
||||||
|
|
||||||
EXPECT_NEAR(right_radar.x, radar_distance, 1e-4f);
|
EXPECT_NEAR(right_radar.x, radar_distance, 1e-4f);
|
||||||
@@ -38,42 +39,131 @@ static void verify_world_to_radar_uses_camera_axes()
|
|||||||
EXPECT_NEAR(right_radar.z, 0.f, 1e-6f);
|
EXPECT_NEAR(right_radar.z, 0.f, 1e-6f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class CameraType, class NumericType>
|
||||||
|
static void verify_world_to_radar_uses_changed_camera_yaw(const float yaw_degrees,
|
||||||
|
const Vector3<NumericType>& world_forward,
|
||||||
|
const Vector3<NumericType>& world_right)
|
||||||
|
{
|
||||||
|
const Vector3<NumericType> origin{NumericType{10}, NumericType{-20}, NumericType{5}};
|
||||||
|
const NumericType world_distance = NumericType{20};
|
||||||
|
const NumericType scale = NumericType{0.5};
|
||||||
|
const auto radar_distance = static_cast<float>(world_distance * scale);
|
||||||
|
|
||||||
|
CameraType camera{
|
||||||
|
origin, {}, {1280.f, 720.f}, projection::FieldOfView::from_degrees(90.f), NumericType{0.01},
|
||||||
|
NumericType{1000}};
|
||||||
|
|
||||||
|
auto angles = camera.get_view_angles();
|
||||||
|
angles.yaw = decltype(angles.yaw)::from_degrees(yaw_degrees);
|
||||||
|
camera.set_view_angles(angles);
|
||||||
|
|
||||||
|
const auto forward_position = origin + world_right * world_distance;
|
||||||
|
const auto forward_radar = algorithm::world_to_radar(camera, forward_position, scale);
|
||||||
|
|
||||||
|
EXPECT_NEAR(forward_radar.x, 0.f, 1e-4f);
|
||||||
|
EXPECT_NEAR(forward_radar.y, -radar_distance, 1e-4f);
|
||||||
|
EXPECT_NEAR(forward_radar.z, 0.f, 1e-6f);
|
||||||
|
|
||||||
|
const auto left_position = origin + world_forward * world_distance;
|
||||||
|
const auto left_radar = algorithm::world_to_radar(camera, left_position, scale);
|
||||||
|
|
||||||
|
EXPECT_NEAR(left_radar.x, -radar_distance, 1e-4f);
|
||||||
|
EXPECT_NEAR(left_radar.y, 0.f, 1e-4f);
|
||||||
|
EXPECT_NEAR(left_radar.z, 0.f, 1e-6f);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class CameraType, class NumericType>
|
||||||
|
static void verify_world_to_radar_ignores_camera_pitch(const Vector3<NumericType>& world_forward)
|
||||||
|
{
|
||||||
|
const Vector3<NumericType> origin{NumericType{10}, NumericType{-20}, NumericType{5}};
|
||||||
|
const NumericType world_distance = NumericType{20};
|
||||||
|
const NumericType scale = NumericType{0.5};
|
||||||
|
const auto radar_distance = static_cast<float>(world_distance * scale);
|
||||||
|
|
||||||
|
CameraType camera{
|
||||||
|
origin, {}, {1280.f, 720.f}, projection::FieldOfView::from_degrees(90.f), NumericType{0.01},
|
||||||
|
NumericType{1000}};
|
||||||
|
|
||||||
|
auto angles = camera.get_view_angles();
|
||||||
|
angles.pitch = decltype(angles.pitch)::from_degrees(45.f);
|
||||||
|
camera.set_view_angles(angles);
|
||||||
|
|
||||||
|
const auto forward_position = origin + world_forward * world_distance;
|
||||||
|
const auto forward_radar = algorithm::world_to_radar(camera, forward_position, scale);
|
||||||
|
|
||||||
|
EXPECT_NEAR(forward_radar.x, 0.f, 1e-4f);
|
||||||
|
EXPECT_NEAR(forward_radar.y, -radar_distance, 1e-4f);
|
||||||
|
EXPECT_NEAR(forward_radar.z, 0.f, 1e-6f);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(WorldToRadarTests, SourceEngineCamera)
|
TEST(WorldToRadarTests, SourceEngineCamera)
|
||||||
{
|
{
|
||||||
verify_world_to_radar_uses_camera_axes<source_engine::Camera, float>();
|
verify_world_to_radar_uses_engine_world_axes<source_engine::Camera, float>(source_engine::k_abs_forward,
|
||||||
|
source_engine::k_abs_right);
|
||||||
|
verify_world_to_radar_uses_changed_camera_yaw<source_engine::Camera, float>(-90.f, source_engine::k_abs_forward,
|
||||||
|
source_engine::k_abs_right);
|
||||||
|
verify_world_to_radar_ignores_camera_pitch<source_engine::Camera, float>(source_engine::k_abs_forward);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(WorldToRadarTests, IWEngineCamera)
|
TEST(WorldToRadarTests, IWEngineCamera)
|
||||||
{
|
{
|
||||||
verify_world_to_radar_uses_camera_axes<iw_engine::Camera, float>();
|
verify_world_to_radar_uses_engine_world_axes<iw_engine::Camera, float>(iw_engine::k_abs_forward,
|
||||||
|
iw_engine::k_abs_right);
|
||||||
|
verify_world_to_radar_uses_changed_camera_yaw<iw_engine::Camera, float>(-90.f, iw_engine::k_abs_forward,
|
||||||
|
iw_engine::k_abs_right);
|
||||||
|
verify_world_to_radar_ignores_camera_pitch<iw_engine::Camera, float>(iw_engine::k_abs_forward);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(WorldToRadarTests, FrostbiteEngineCamera)
|
TEST(WorldToRadarTests, FrostbiteEngineCamera)
|
||||||
{
|
{
|
||||||
verify_world_to_radar_uses_camera_axes<frostbite_engine::Camera, float>();
|
verify_world_to_radar_uses_engine_world_axes<frostbite_engine::Camera, float>(frostbite_engine::k_abs_forward,
|
||||||
|
frostbite_engine::k_abs_right);
|
||||||
|
verify_world_to_radar_uses_changed_camera_yaw<frostbite_engine::Camera, float>(
|
||||||
|
90.f, frostbite_engine::k_abs_forward, frostbite_engine::k_abs_right);
|
||||||
|
verify_world_to_radar_ignores_camera_pitch<frostbite_engine::Camera, float>(frostbite_engine::k_abs_forward);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(WorldToRadarTests, OpenGLEngineCamera)
|
TEST(WorldToRadarTests, OpenGLEngineCamera)
|
||||||
{
|
{
|
||||||
verify_world_to_radar_uses_camera_axes<opengl_engine::Camera, float>();
|
verify_world_to_radar_uses_engine_world_axes<opengl_engine::Camera, float>(opengl_engine::k_abs_forward,
|
||||||
|
opengl_engine::k_abs_right);
|
||||||
|
verify_world_to_radar_uses_changed_camera_yaw<opengl_engine::Camera, float>(-90.f, opengl_engine::k_abs_forward,
|
||||||
|
opengl_engine::k_abs_right);
|
||||||
|
verify_world_to_radar_ignores_camera_pitch<opengl_engine::Camera, float>(opengl_engine::k_abs_forward);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(WorldToRadarTests, UnityEngineCamera)
|
TEST(WorldToRadarTests, UnityEngineCamera)
|
||||||
{
|
{
|
||||||
verify_world_to_radar_uses_camera_axes<unity_engine::Camera, float>();
|
verify_world_to_radar_uses_engine_world_axes<unity_engine::Camera, float>(unity_engine::k_abs_forward,
|
||||||
|
unity_engine::k_abs_right);
|
||||||
|
verify_world_to_radar_uses_changed_camera_yaw<unity_engine::Camera, float>(90.f, unity_engine::k_abs_forward,
|
||||||
|
unity_engine::k_abs_right);
|
||||||
|
verify_world_to_radar_ignores_camera_pitch<unity_engine::Camera, float>(unity_engine::k_abs_forward);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(WorldToRadarTests, CryEngineCamera)
|
TEST(WorldToRadarTests, CryEngineCamera)
|
||||||
{
|
{
|
||||||
verify_world_to_radar_uses_camera_axes<cry_engine::Camera, float>();
|
verify_world_to_radar_uses_engine_world_axes<cry_engine::Camera, float>(cry_engine::k_abs_forward,
|
||||||
|
cry_engine::k_abs_right);
|
||||||
|
verify_world_to_radar_uses_changed_camera_yaw<cry_engine::Camera, float>(-90.f, cry_engine::k_abs_forward,
|
||||||
|
cry_engine::k_abs_right);
|
||||||
|
verify_world_to_radar_ignores_camera_pitch<cry_engine::Camera, float>(cry_engine::k_abs_forward);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(WorldToRadarTests, RageEngineCamera)
|
TEST(WorldToRadarTests, RageEngineCamera)
|
||||||
{
|
{
|
||||||
verify_world_to_radar_uses_camera_axes<rage_engine::Camera, float>();
|
verify_world_to_radar_uses_engine_world_axes<rage_engine::Camera, float>(rage_engine::k_abs_forward,
|
||||||
|
rage_engine::k_abs_right);
|
||||||
|
verify_world_to_radar_uses_changed_camera_yaw<rage_engine::Camera, float>(-90.f, rage_engine::k_abs_forward,
|
||||||
|
rage_engine::k_abs_right);
|
||||||
|
verify_world_to_radar_ignores_camera_pitch<rage_engine::Camera, float>(rage_engine::k_abs_forward);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(WorldToRadarTests, UnrealEngineCamera)
|
TEST(WorldToRadarTests, UnrealEngineCamera)
|
||||||
{
|
{
|
||||||
verify_world_to_radar_uses_camera_axes<unreal_engine::Camera, double>();
|
verify_world_to_radar_uses_engine_world_axes<unreal_engine::Camera, double>(unreal_engine::k_abs_forward,
|
||||||
|
unreal_engine::k_abs_right);
|
||||||
|
verify_world_to_radar_uses_changed_camera_yaw<unreal_engine::Camera, double>(90.f, unreal_engine::k_abs_forward,
|
||||||
|
unreal_engine::k_abs_right);
|
||||||
|
verify_world_to_radar_ignores_camera_pitch<unreal_engine::Camera, double>(unreal_engine::k_abs_forward);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user