Files
omath/source/lua/engine_utils.hpp
2026-03-10 17:51:02 +03:00

98 lines
4.2 KiB
C++

//
// Created by orange on 07.03.2026.
//
#pragma once
#ifdef OMATH_ENABLE_LUA
#include "engine_types.hpp"
#include <omath/linear_algebra/vector3.hpp>
#include <omath/projection/error_codes.hpp>
namespace
{
std::string projection_error_to_string(omath::projection::Error e)
{
switch (e)
{
case omath::projection::Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS:
return "world position is out of screen bounds";
case omath::projection::Error::INV_VIEW_PROJ_MAT_DET_EQ_ZERO:
return "inverse view-projection matrix determinant is zero";
}
return "unknown error";
}
// Set aliases in an engine subtable pointing to the already-registered shared types
template<class PitchAngleType, class ViewAnglesType>
void set_engine_aliases(sol::table& engine_table, sol::table& types)
{
if constexpr (std::is_same_v<PitchAngleType, PitchAngle90>)
engine_table["PitchAngle"] = types["PitchAngle90"];
else
engine_table["PitchAngle"] = types["PitchAngle89"];
engine_table["YawAngle"] = types["YawRoll"];
engine_table["RollAngle"] = types["YawRoll"];
engine_table["FieldOfView"] = types["FieldOfView"];
engine_table["ViewPort"] = types["ViewPort"];
if constexpr (std::is_same_v<ViewAnglesType, ViewAngles90>)
engine_table["ViewAngles"] = types["ViewAngles90"];
else
engine_table["ViewAngles"] = types["ViewAngles89"];
}
// Register an engine: alias shared types, register unique Camera
template<class EngineTraits>
void register_engine(sol::table& omath_table, const char* subtable_name)
{
using PitchAngle = typename EngineTraits::PitchAngle;
using ViewAngles = typename EngineTraits::ViewAngles;
using Camera = typename EngineTraits::Camera;
auto engine_table = omath_table[subtable_name].get_or_create<sol::table>();
auto types = omath_table["_types"].get<sol::table>();
set_engine_aliases<PitchAngle, ViewAngles>(engine_table, types);
engine_table.new_usertype<Camera>(
"Camera",
sol::constructors<Camera(const omath::Vector3<float>&, const ViewAngles&,
const omath::projection::ViewPort&,
const omath::projection::FieldOfView&, float, float)>(),
"look_at", &Camera::look_at,
"get_forward", &Camera::get_forward,
"get_right", &Camera::get_right,
"get_up", &Camera::get_up,
"get_origin", &Camera::get_origin,
"get_view_angles", &Camera::get_view_angles,
"get_near_plane", &Camera::get_near_plane,
"get_far_plane", &Camera::get_far_plane,
"get_field_of_view", &Camera::get_field_of_view,
"set_origin", &Camera::set_origin,
"set_view_angles", &Camera::set_view_angles,
"set_view_port", &Camera::set_view_port,
"set_field_of_view", &Camera::set_field_of_view,
"set_near_plane", &Camera::set_near_plane,
"set_far_plane", &Camera::set_far_plane,
"world_to_screen",
[](const Camera& cam, const omath::Vector3<float>& pos)
-> std::tuple<sol::optional<omath::Vector3<float>>, sol::optional<std::string>>
{
auto result = cam.world_to_screen(pos);
if (result) return {*result, sol::nullopt};
return {sol::nullopt, projection_error_to_string(result.error())};
},
"screen_to_world",
[](const Camera& cam, const omath::Vector3<float>& pos)
-> std::tuple<sol::optional<omath::Vector3<float>>, sol::optional<std::string>>
{
auto result = cam.screen_to_world(pos);
if (result) return {*result, sol::nullopt};
return {sol::nullopt, projection_error_to_string(result.error())};
});
}
} // namespace
#endif