mirror of
https://github.com/orange-cpp/omath.git
synced 2026-04-18 15:23:26 +00:00
migrated to sol2
decomposed method added vector2, vector4 refactored tests added opengl engine to lua added other engines added source tests removed tons of lua files
This commit is contained in:
5
.luarc.json
Normal file
5
.luarc.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"diagnostics.globals": [
|
||||
"omath"
|
||||
]
|
||||
}
|
||||
@@ -31,6 +31,9 @@ option(OMATH_SUPRESS_SAFETY_CHECKS
|
||||
option(OMATH_ENABLE_COVERAGE "Enable coverage" OFF)
|
||||
option(OMATH_ENABLE_FORCE_INLINE
|
||||
"Will for compiler to make some functions to be force inlined no matter what" ON)
|
||||
|
||||
option(OMATH_ENABLE_LUA
|
||||
"omath bindings for lua" OFF)
|
||||
if(VCPKG_MANIFEST_FEATURES)
|
||||
foreach(omath_feature IN LISTS VCPKG_MANIFEST_FEATURES)
|
||||
if(omath_feature STREQUAL "imgui")
|
||||
@@ -43,6 +46,8 @@ if(VCPKG_MANIFEST_FEATURES)
|
||||
set(OMATH_BUILD_BENCHMARK ON)
|
||||
elseif(omath_feature STREQUAL "examples")
|
||||
set(OMATH_BUILD_EXAMPLES ON)
|
||||
elseif(omath_feature STREQUAL "lua")
|
||||
set(OMATH_ENABLE_LUA ON)
|
||||
endif()
|
||||
|
||||
endforeach()
|
||||
@@ -83,6 +88,17 @@ else()
|
||||
add_library(${PROJECT_NAME} STATIC ${OMATH_SOURCES} ${OMATH_HEADERS})
|
||||
endif()
|
||||
|
||||
if (OMATH_ENABLE_LUA)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC OMATH_ENABLE_LUA)
|
||||
|
||||
find_package(Lua REQUIRED)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE ${LUA_INCLUDE_DIR})
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ${LUA_LIBRARIES})
|
||||
|
||||
find_path(SOL2_INCLUDE_DIRS "sol/abort.hpp")
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE ${SOL2_INCLUDE_DIRS})
|
||||
endif ()
|
||||
|
||||
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC OMATH_VERSION="${PROJECT_VERSION}")
|
||||
|
||||
@@ -145,7 +145,7 @@
|
||||
"hidden": true,
|
||||
"inherits": ["linux-base", "vcpkg-base"],
|
||||
"cacheVariables": {
|
||||
"VCPKG_MANIFEST_FEATURES": "tests;imgui;avx2"
|
||||
"VCPKG_MANIFEST_FEATURES": "tests;imgui;avx2;lua"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
13
include/omath/lua/lua.hpp
Normal file
13
include/omath/lua/lua.hpp
Normal file
@@ -0,0 +1,13 @@
|
||||
//
|
||||
// Created by orange on 07.03.2026.
|
||||
//
|
||||
#pragma once
|
||||
#ifdef OMATH_ENABLE_LUA
|
||||
// ReSharper disable once CppInconsistentNaming
|
||||
struct lua_State;
|
||||
|
||||
namespace omath::lua
|
||||
{
|
||||
void register_lib(lua_State* lua_state);
|
||||
}
|
||||
#endif
|
||||
411
source/lua/lua.cpp
Normal file
411
source/lua/lua.cpp
Normal file
@@ -0,0 +1,411 @@
|
||||
//
|
||||
// Created by orange on 07.03.2026.
|
||||
//
|
||||
#ifdef OMATH_ENABLE_LUA
|
||||
#include "lua.hpp"
|
||||
#include "omath/lua/lua.hpp"
|
||||
#include <omath/engines/cry_engine/camera.hpp>
|
||||
#include <omath/engines/cry_engine/constants.hpp>
|
||||
#include <omath/engines/frostbite_engine/camera.hpp>
|
||||
#include <omath/engines/frostbite_engine/constants.hpp>
|
||||
#include <omath/engines/iw_engine/camera.hpp>
|
||||
#include <omath/engines/iw_engine/constants.hpp>
|
||||
#include <omath/engines/opengl_engine/camera.hpp>
|
||||
#include <omath/engines/opengl_engine/constants.hpp>
|
||||
#include <omath/engines/opengl_engine/formulas.hpp>
|
||||
#include <omath/engines/source_engine/camera.hpp>
|
||||
#include <omath/engines/source_engine/constants.hpp>
|
||||
#include <omath/engines/unity_engine/camera.hpp>
|
||||
#include <omath/engines/unity_engine/constants.hpp>
|
||||
#include <omath/engines/unreal_engine/camera.hpp>
|
||||
#include <omath/engines/unreal_engine/constants.hpp>
|
||||
#include <omath/linear_algebra/vector2.hpp>
|
||||
#include <omath/linear_algebra/vector3.hpp>
|
||||
#include <omath/linear_algebra/vector4.hpp>
|
||||
#include <omath/projection/camera.hpp>
|
||||
#include <omath/projection/error_codes.hpp>
|
||||
#include <sol/sol.hpp>
|
||||
#include <string_view>
|
||||
namespace
|
||||
{
|
||||
void register_vec2(sol::table& omath_table)
|
||||
{
|
||||
using Vec2f = omath::Vector2<float>;
|
||||
|
||||
omath_table.new_usertype<Vec2f>(
|
||||
"Vec2", sol::constructors<Vec2f(), Vec2f(float, float)>(),
|
||||
|
||||
"x", &Vec2f::x, "y", &Vec2f::y,
|
||||
|
||||
sol::meta_function::addition, sol::resolve<Vec2f(const Vec2f&) const>(&Vec2f::operator+),
|
||||
sol::meta_function::subtraction, sol::resolve<Vec2f(const Vec2f&) const>(&Vec2f::operator-),
|
||||
sol::meta_function::unary_minus, sol::resolve<Vec2f() const>(&Vec2f::operator-),
|
||||
sol::meta_function::equal_to, &Vec2f::operator==,
|
||||
sol::meta_function::less_than, sol::resolve<bool(const Vec2f&) const>(&Vec2f::operator<),
|
||||
sol::meta_function::less_than_or_equal_to, sol::resolve<bool(const Vec2f&) const>(&Vec2f::operator<=),
|
||||
sol::meta_function::to_string,
|
||||
[](const Vec2f& v) { return std::format("Vec2({}, {})", v.x, v.y); },
|
||||
|
||||
sol::meta_function::multiplication,
|
||||
sol::overload(sol::resolve<Vec2f(const float&) const>(&Vec2f::operator*),
|
||||
[](const float s, const Vec2f& v) { return v * s; }),
|
||||
|
||||
sol::meta_function::division,
|
||||
sol::resolve<Vec2f(const float&) const>(&Vec2f::operator/),
|
||||
|
||||
"length", &Vec2f::length,
|
||||
"length_sqr", &Vec2f::length_sqr,
|
||||
"normalized", &Vec2f::normalized,
|
||||
"dot", &Vec2f::dot,
|
||||
"distance_to", &Vec2f::distance_to,
|
||||
"distance_to_sqr", &Vec2f::distance_to_sqr,
|
||||
"sum", &Vec2f::sum,
|
||||
|
||||
"abs",
|
||||
[](const Vec2f& v)
|
||||
{
|
||||
Vec2f copy = v;
|
||||
copy.abs();
|
||||
return copy;
|
||||
});
|
||||
}
|
||||
|
||||
void register_vec4(sol::table& omath_table)
|
||||
{
|
||||
using Vec4f = omath::Vector4<float>;
|
||||
|
||||
omath_table.new_usertype<Vec4f>(
|
||||
"Vec4", sol::constructors<Vec4f(), Vec4f(float, float, float, float)>(),
|
||||
|
||||
"x", &Vec4f::x, "y", &Vec4f::y, "z", &Vec4f::z, "w", &Vec4f::w,
|
||||
|
||||
sol::meta_function::addition, sol::resolve<Vec4f(const Vec4f&) const>(&Vec4f::operator+),
|
||||
sol::meta_function::subtraction, sol::resolve<Vec4f(const Vec4f&) const>(&Vec4f::operator-),
|
||||
sol::meta_function::unary_minus, sol::resolve<Vec4f() const>(&Vec4f::operator-),
|
||||
sol::meta_function::equal_to, &Vec4f::operator==,
|
||||
sol::meta_function::less_than, sol::resolve<bool(const Vec4f&) const>(&Vec4f::operator<),
|
||||
sol::meta_function::less_than_or_equal_to, sol::resolve<bool(const Vec4f&) const>(&Vec4f::operator<=),
|
||||
sol::meta_function::to_string,
|
||||
[](const Vec4f& v) { return std::format("Vec4({}, {}, {}, {})", v.x, v.y, v.z, v.w); },
|
||||
|
||||
sol::meta_function::multiplication,
|
||||
sol::overload(sol::resolve<Vec4f(const float&) const>(&Vec4f::operator*),
|
||||
sol::resolve<Vec4f(const Vec4f&) const>(&Vec4f::operator*),
|
||||
[](const float s, const Vec4f& v) { return v * s; }),
|
||||
|
||||
sol::meta_function::division,
|
||||
sol::overload(sol::resolve<Vec4f(const float&) const>(&Vec4f::operator/),
|
||||
sol::resolve<Vec4f(const Vec4f&) const>(&Vec4f::operator/)),
|
||||
|
||||
"length", &Vec4f::length,
|
||||
"length_sqr", &Vec4f::length_sqr,
|
||||
"dot", &Vec4f::dot,
|
||||
"sum", &Vec4f::sum,
|
||||
|
||||
"abs",
|
||||
[](const Vec4f& v)
|
||||
{
|
||||
Vec4f copy = v;
|
||||
copy.abs();
|
||||
return copy;
|
||||
},
|
||||
|
||||
"clamp",
|
||||
[](Vec4f& v, float mn, float mx)
|
||||
{
|
||||
v.clamp(mn, mx);
|
||||
return v;
|
||||
});
|
||||
}
|
||||
|
||||
void register_vec3(sol::table& omath_table)
|
||||
{
|
||||
using Vec3f = omath::Vector3<float>;
|
||||
|
||||
omath_table.new_usertype<Vec3f>(
|
||||
"Vec3", sol::constructors<Vec3f(), Vec3f(float, float, float)>(),
|
||||
|
||||
"x", &Vec3f::x, "y", &Vec3f::y, "z", &Vec3f::z,
|
||||
|
||||
sol::meta_function::addition, sol::resolve<Vec3f(const Vec3f&) const>(&Vec3f::operator+),
|
||||
sol::meta_function::subtraction, sol::resolve<Vec3f(const Vec3f&) const>(&Vec3f::operator-),
|
||||
sol::meta_function::unary_minus, sol::resolve<Vec3f() const>(&Vec3f::operator-),
|
||||
sol::meta_function::equal_to, &Vec3f::operator==, sol::meta_function::less_than,
|
||||
sol::resolve<bool(const Vec3f&) const>(&Vec3f::operator<), sol::meta_function::less_than_or_equal_to,
|
||||
sol::resolve<bool(const Vec3f&) const>(&Vec3f::operator<=), sol::meta_function::to_string,
|
||||
[](const Vec3f& v) { return std::format("Vec3({}, {}, {})", v.x, v.y, v.z); },
|
||||
|
||||
sol::meta_function::multiplication,
|
||||
sol::overload(sol::resolve<Vec3f(const float&) const>(&Vec3f::operator*),
|
||||
sol::resolve<Vec3f(const Vec3f&) const>(&Vec3f::operator*),
|
||||
[](const float s, const Vec3f& v) { return v * s; }),
|
||||
|
||||
sol::meta_function::division,
|
||||
sol::overload(sol::resolve<Vec3f(const float&) const>(&Vec3f::operator/),
|
||||
sol::resolve<Vec3f(const Vec3f&) const>(&Vec3f::operator/)),
|
||||
|
||||
"length", &Vec3f::length, "length_2d", &Vec3f::length_2d, "length_sqr", &Vec3f::length_sqr,
|
||||
"normalized", &Vec3f::normalized, "dot", &Vec3f::dot, "cross", &Vec3f::cross, "distance_to",
|
||||
&Vec3f::distance_to, "distance_to_sqr", &Vec3f::distance_to_sqr, "sum",
|
||||
sol::resolve<float() const>(&Vec3f::sum), "sum_2d", &Vec3f::sum_2d, "point_to_same_direction",
|
||||
&Vec3f::point_to_same_direction, "as_array", &Vec3f::as_array,
|
||||
|
||||
"abs",
|
||||
[](const Vec3f& v)
|
||||
{
|
||||
Vec3f copy = v;
|
||||
copy.abs();
|
||||
return copy;
|
||||
},
|
||||
|
||||
"angle_between",
|
||||
[](const Vec3f& self,
|
||||
const Vec3f& other) -> std::tuple<sol::optional<float>, sol::optional<std::string>>
|
||||
{
|
||||
auto result = self.angle_between(other);
|
||||
if (result)
|
||||
return std::make_tuple(sol::optional<float>(result->as_degrees()),
|
||||
sol::optional<std::string>(sol::nullopt));
|
||||
return std::make_tuple(sol::optional<float>(sol::nullopt),
|
||||
sol::optional<std::string>("impossible angle (zero-length vector)"));
|
||||
},
|
||||
|
||||
"is_perpendicular",
|
||||
[](const Vec3f& self, const Vec3f& other, sol::optional<float> eps)
|
||||
{ return self.is_perpendicular(other, eps.value_or(0.0001f)); },
|
||||
|
||||
"as_table",
|
||||
[](const Vec3f& v, sol::this_state s) -> sol::table
|
||||
{
|
||||
sol::state_view lua(s);
|
||||
sol::table t = lua.create_table();
|
||||
t["x"] = v.x;
|
||||
t["y"] = v.y;
|
||||
t["z"] = v.z;
|
||||
return t;
|
||||
});
|
||||
}
|
||||
static 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";
|
||||
}
|
||||
|
||||
template<class AngleType>
|
||||
void register_angle(sol::table& table, const char* name)
|
||||
{
|
||||
table.new_usertype<AngleType>(
|
||||
name, sol::no_constructor,
|
||||
"from_degrees", &AngleType::from_degrees,
|
||||
"from_radians", &AngleType::from_radians,
|
||||
"as_degrees", &AngleType::as_degrees,
|
||||
"as_radians", &AngleType::as_radians,
|
||||
"sin", &AngleType::sin,
|
||||
"cos", &AngleType::cos,
|
||||
"tan", &AngleType::tan,
|
||||
"cot", &AngleType::cot,
|
||||
sol::meta_function::addition,
|
||||
[](const AngleType& a, const AngleType& b)
|
||||
{ return AngleType::from_degrees(a.as_degrees() + b.as_degrees()); },
|
||||
sol::meta_function::subtraction,
|
||||
[](const AngleType& a, const AngleType& b)
|
||||
{ return AngleType::from_degrees(a.as_degrees() - b.as_degrees()); },
|
||||
sol::meta_function::unary_minus,
|
||||
[](const AngleType& a) { return AngleType::from_degrees(-a.as_degrees()); },
|
||||
sol::meta_function::equal_to,
|
||||
[](const AngleType& a, const AngleType& b) { return a == b; },
|
||||
sol::meta_function::to_string,
|
||||
[](const AngleType& a) { return std::format("{}deg", a.as_degrees()); });
|
||||
}
|
||||
|
||||
// ---- Canonical shared C++ type aliases ----------------------------------
|
||||
// Each unique template instantiation must be registered exactly once.
|
||||
|
||||
using PitchAngle90 = omath::Angle<float, -90.f, 90.f, omath::AngleFlags::Clamped>;
|
||||
using PitchAngle89 = omath::Angle<float, -89.f, 89.f, omath::AngleFlags::Clamped>;
|
||||
using SharedYawRoll = omath::Angle<float, -180.f, 180.f, omath::AngleFlags::Normalized>;
|
||||
using SharedFoV = omath::Angle<float, 0.f, 180.f, omath::AngleFlags::Clamped>;
|
||||
using ViewAngles90 = omath::ViewAngles<PitchAngle90, SharedYawRoll, SharedYawRoll>;
|
||||
using ViewAngles89 = omath::ViewAngles<PitchAngle89, SharedYawRoll, SharedYawRoll>;
|
||||
|
||||
// Register every shared C++ type exactly once under omath._types
|
||||
void register_shared_types(sol::table& omath_table)
|
||||
{
|
||||
auto t = omath_table["_types"].get_or_create<sol::table>();
|
||||
|
||||
register_angle<PitchAngle90>(t, "PitchAngle90");
|
||||
register_angle<PitchAngle89>(t, "PitchAngle89");
|
||||
register_angle<SharedYawRoll>(t, "YawRoll");
|
||||
register_angle<SharedFoV>(t, "FieldOfView");
|
||||
|
||||
t.new_usertype<omath::projection::ViewPort>(
|
||||
"ViewPort",
|
||||
sol::factories([](float w, float h) { return omath::projection::ViewPort{w, h}; }),
|
||||
"width", &omath::projection::ViewPort::m_width,
|
||||
"height", &omath::projection::ViewPort::m_height,
|
||||
"aspect_ratio", &omath::projection::ViewPort::aspect_ratio);
|
||||
|
||||
t.new_usertype<ViewAngles90>(
|
||||
"ViewAngles90",
|
||||
sol::factories([](PitchAngle90 p, SharedYawRoll y, SharedYawRoll r)
|
||||
{ return ViewAngles90{p, y, r}; }),
|
||||
"pitch", &ViewAngles90::pitch,
|
||||
"yaw", &ViewAngles90::yaw,
|
||||
"roll", &ViewAngles90::roll);
|
||||
|
||||
t.new_usertype<ViewAngles89>(
|
||||
"ViewAngles89",
|
||||
sol::factories([](PitchAngle89 p, SharedYawRoll y, SharedYawRoll r)
|
||||
{ return ViewAngles89{p, y, r}; }),
|
||||
"pitch", &ViewAngles89::pitch,
|
||||
"yaw", &ViewAngles89::yaw,
|
||||
"roll", &ViewAngles89::roll);
|
||||
}
|
||||
|
||||
// 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())};
|
||||
});
|
||||
}
|
||||
|
||||
// ---- Engine trait structs -----------------------------------------------
|
||||
|
||||
struct OpenGLEngineTraits
|
||||
{
|
||||
using PitchAngle = omath::opengl_engine::PitchAngle;
|
||||
using ViewAngles = omath::opengl_engine::ViewAngles;
|
||||
using Camera = omath::opengl_engine::Camera;
|
||||
};
|
||||
struct FrostbiteEngineTraits
|
||||
{
|
||||
using PitchAngle = omath::frostbite_engine::PitchAngle;
|
||||
using ViewAngles = omath::frostbite_engine::ViewAngles;
|
||||
using Camera = omath::frostbite_engine::Camera;
|
||||
};
|
||||
struct IWEngineTraits
|
||||
{
|
||||
using PitchAngle = omath::iw_engine::PitchAngle;
|
||||
using ViewAngles = omath::iw_engine::ViewAngles;
|
||||
using Camera = omath::iw_engine::Camera;
|
||||
};
|
||||
struct SourceEngineTraits
|
||||
{
|
||||
using PitchAngle = omath::source_engine::PitchAngle;
|
||||
using ViewAngles = omath::source_engine::ViewAngles;
|
||||
using Camera = omath::source_engine::Camera;
|
||||
};
|
||||
struct UnityEngineTraits
|
||||
{
|
||||
using PitchAngle = omath::unity_engine::PitchAngle;
|
||||
using ViewAngles = omath::unity_engine::ViewAngles;
|
||||
using Camera = omath::unity_engine::Camera;
|
||||
};
|
||||
struct UnrealEngineTraits
|
||||
{
|
||||
using PitchAngle = omath::unreal_engine::PitchAngle;
|
||||
using ViewAngles = omath::unreal_engine::ViewAngles;
|
||||
using Camera = omath::unreal_engine::Camera;
|
||||
};
|
||||
struct CryEngineTraits
|
||||
{
|
||||
using PitchAngle = omath::cry_engine::PitchAngle;
|
||||
using ViewAngles = omath::cry_engine::ViewAngles;
|
||||
using Camera = omath::cry_engine::Camera;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace omath::lua
|
||||
{
|
||||
void register_lib(lua_State* lua_state)
|
||||
{
|
||||
sol::state_view lua(lua_state);
|
||||
|
||||
auto omath_table = lua["omath"].get_or_create<sol::table>();
|
||||
|
||||
register_vec2(omath_table);
|
||||
register_vec3(omath_table);
|
||||
register_vec4(omath_table);
|
||||
register_shared_types(omath_table);
|
||||
register_engine<OpenGLEngineTraits>(omath_table, "opengl");
|
||||
register_engine<FrostbiteEngineTraits>(omath_table, "frostbite");
|
||||
register_engine<IWEngineTraits>(omath_table, "iw");
|
||||
register_engine<SourceEngineTraits>(omath_table, "source");
|
||||
register_engine<UnityEngineTraits>(omath_table, "unity");
|
||||
register_engine<UnrealEngineTraits>(omath_table, "unreal");
|
||||
register_engine<CryEngineTraits>(omath_table, "cry");
|
||||
}
|
||||
} // namespace omath::lua
|
||||
#endif
|
||||
@@ -22,6 +22,8 @@ else() # GTest is being linked as vcpkg package
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE GTest::gtest GTest::gtest_main omath::omath)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE LUA_SCRIPTS_DIR="${CMAKE_CURRENT_SOURCE_DIR}/lua")
|
||||
|
||||
if(OMATH_ENABLE_COVERAGE)
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/Coverage.cmake)
|
||||
omath_setup_coverage(${PROJECT_NAME})
|
||||
|
||||
79
tests/general/unit_test_lua_source_engine.cpp
Normal file
79
tests/general/unit_test_lua_source_engine.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
//
|
||||
// Created by orange on 07.03.2026.
|
||||
//
|
||||
#include <gtest/gtest.h>
|
||||
#include <lua.hpp>
|
||||
#include <omath/lua/lua.hpp>
|
||||
|
||||
class LuaSourceEngine : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
lua_State* L = nullptr;
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
omath::lua::register_lib(L);
|
||||
if (luaL_dofile(L, LUA_SCRIPTS_DIR "/source_engine_tests.lua") != LUA_OK)
|
||||
FAIL() << lua_tostring(L, -1);
|
||||
}
|
||||
|
||||
void TearDown() override { lua_close(L); }
|
||||
|
||||
void check(const char* func_name)
|
||||
{
|
||||
lua_getglobal(L, func_name);
|
||||
if (lua_pcall(L, 0, 0, 0) != LUA_OK)
|
||||
{
|
||||
FAIL() << lua_tostring(L, -1);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// PitchAngle
|
||||
TEST_F(LuaSourceEngine, PitchAngle_from_degrees) { check("Source_PitchAngle_from_degrees"); }
|
||||
TEST_F(LuaSourceEngine, PitchAngle_clamping_max) { check("Source_PitchAngle_clamping_max"); }
|
||||
TEST_F(LuaSourceEngine, PitchAngle_clamping_min) { check("Source_PitchAngle_clamping_min"); }
|
||||
TEST_F(LuaSourceEngine, PitchAngle_from_radians) { check("Source_PitchAngle_from_radians"); }
|
||||
TEST_F(LuaSourceEngine, PitchAngle_as_radians) { check("Source_PitchAngle_as_radians"); }
|
||||
TEST_F(LuaSourceEngine, PitchAngle_sin) { check("Source_PitchAngle_sin"); }
|
||||
TEST_F(LuaSourceEngine, PitchAngle_cos) { check("Source_PitchAngle_cos"); }
|
||||
TEST_F(LuaSourceEngine, PitchAngle_tan) { check("Source_PitchAngle_tan"); }
|
||||
TEST_F(LuaSourceEngine, PitchAngle_addition) { check("Source_PitchAngle_addition"); }
|
||||
TEST_F(LuaSourceEngine, PitchAngle_addition_clamped) { check("Source_PitchAngle_addition_clamped"); }
|
||||
TEST_F(LuaSourceEngine, PitchAngle_subtraction) { check("Source_PitchAngle_subtraction"); }
|
||||
TEST_F(LuaSourceEngine, PitchAngle_unary_minus) { check("Source_PitchAngle_unary_minus"); }
|
||||
TEST_F(LuaSourceEngine, PitchAngle_equal_to) { check("Source_PitchAngle_equal_to"); }
|
||||
TEST_F(LuaSourceEngine, PitchAngle_to_string) { check("Source_PitchAngle_to_string"); }
|
||||
|
||||
// YawAngle
|
||||
TEST_F(LuaSourceEngine, YawAngle_from_degrees) { check("Source_YawAngle_from_degrees"); }
|
||||
TEST_F(LuaSourceEngine, YawAngle_normalization) { check("Source_YawAngle_normalization"); }
|
||||
|
||||
// RollAngle
|
||||
TEST_F(LuaSourceEngine, RollAngle_from_degrees) { check("Source_RollAngle_from_degrees"); }
|
||||
|
||||
// FieldOfView
|
||||
TEST_F(LuaSourceEngine, FieldOfView_from_degrees) { check("Source_FieldOfView_from_degrees"); }
|
||||
TEST_F(LuaSourceEngine, FieldOfView_clamping) { check("Source_FieldOfView_clamping"); }
|
||||
|
||||
// ViewAngles
|
||||
TEST_F(LuaSourceEngine, ViewAngles_new) { check("Source_ViewAngles_new"); }
|
||||
TEST_F(LuaSourceEngine, ViewAngles_field_mutation) { check("Source_ViewAngles_field_mutation"); }
|
||||
|
||||
// Camera
|
||||
TEST_F(LuaSourceEngine, Camera_constructor) { check("Source_Camera_constructor"); }
|
||||
TEST_F(LuaSourceEngine, Camera_get_set_origin) { check("Source_Camera_get_set_origin"); }
|
||||
TEST_F(LuaSourceEngine, Camera_get_set_near_plane) { check("Source_Camera_get_set_near_plane"); }
|
||||
TEST_F(LuaSourceEngine, Camera_get_set_far_plane) { check("Source_Camera_get_set_far_plane"); }
|
||||
TEST_F(LuaSourceEngine, Camera_get_set_fov) { check("Source_Camera_get_set_fov"); }
|
||||
TEST_F(LuaSourceEngine, Camera_get_set_view_angles) { check("Source_Camera_get_set_view_angles"); }
|
||||
TEST_F(LuaSourceEngine, Camera_look_at) { check("Source_Camera_look_at"); }
|
||||
TEST_F(LuaSourceEngine, Camera_get_forward) { check("Source_Camera_get_forward"); }
|
||||
TEST_F(LuaSourceEngine, Camera_get_right) { check("Source_Camera_get_right"); }
|
||||
TEST_F(LuaSourceEngine, Camera_get_up) { check("Source_Camera_get_up"); }
|
||||
TEST_F(LuaSourceEngine, Camera_world_to_screen_success) { check("Source_Camera_world_to_screen_success"); }
|
||||
TEST_F(LuaSourceEngine, Camera_world_to_screen_error) { check("Source_Camera_world_to_screen_error"); }
|
||||
TEST_F(LuaSourceEngine, Camera_screen_to_world) { check("Source_Camera_screen_to_world"); }
|
||||
56
tests/general/unit_test_lua_vector2.cpp
Normal file
56
tests/general/unit_test_lua_vector2.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
//
|
||||
// Created by orange on 07.03.2026.
|
||||
//
|
||||
#include <gtest/gtest.h>
|
||||
#include <lua.hpp>
|
||||
#include <omath/lua/lua.hpp>
|
||||
|
||||
class LuaVec2 : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
lua_State* L = nullptr;
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
omath::lua::register_lib(L);
|
||||
if (luaL_dofile(L, LUA_SCRIPTS_DIR "/vec2_tests.lua") != LUA_OK)
|
||||
FAIL() << lua_tostring(L, -1);
|
||||
}
|
||||
|
||||
void TearDown() override { lua_close(L); }
|
||||
|
||||
void check(const char* func_name)
|
||||
{
|
||||
lua_getglobal(L, func_name);
|
||||
if (lua_pcall(L, 0, 0, 0) != LUA_OK)
|
||||
{
|
||||
FAIL() << lua_tostring(L, -1);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(LuaVec2, Constructor_default) { check("Vec2_Constructor_default"); }
|
||||
TEST_F(LuaVec2, Constructor_xy) { check("Vec2_Constructor_xy"); }
|
||||
TEST_F(LuaVec2, Field_mutation) { check("Vec2_Field_mutation"); }
|
||||
TEST_F(LuaVec2, Addition) { check("Vec2_Addition"); }
|
||||
TEST_F(LuaVec2, Subtraction) { check("Vec2_Subtraction"); }
|
||||
TEST_F(LuaVec2, UnaryMinus) { check("Vec2_UnaryMinus"); }
|
||||
TEST_F(LuaVec2, Multiplication_scalar) { check("Vec2_Multiplication_scalar"); }
|
||||
TEST_F(LuaVec2, Multiplication_scalar_reversed) { check("Vec2_Multiplication_scalar_reversed"); }
|
||||
TEST_F(LuaVec2, Division_scalar) { check("Vec2_Division_scalar"); }
|
||||
TEST_F(LuaVec2, EqualTo_true) { check("Vec2_EqualTo_true"); }
|
||||
TEST_F(LuaVec2, EqualTo_false) { check("Vec2_EqualTo_false"); }
|
||||
TEST_F(LuaVec2, LessThan) { check("Vec2_LessThan"); }
|
||||
TEST_F(LuaVec2, LessThanOrEqual) { check("Vec2_LessThanOrEqual"); }
|
||||
TEST_F(LuaVec2, ToString) { check("Vec2_ToString"); }
|
||||
TEST_F(LuaVec2, Length) { check("Vec2_Length"); }
|
||||
TEST_F(LuaVec2, LengthSqr) { check("Vec2_LengthSqr"); }
|
||||
TEST_F(LuaVec2, Normalized) { check("Vec2_Normalized"); }
|
||||
TEST_F(LuaVec2, Dot) { check("Vec2_Dot"); }
|
||||
TEST_F(LuaVec2, DistanceTo) { check("Vec2_DistanceTo"); }
|
||||
TEST_F(LuaVec2, DistanceToSqr) { check("Vec2_DistanceToSqr"); }
|
||||
TEST_F(LuaVec2, Sum) { check("Vec2_Sum"); }
|
||||
TEST_F(LuaVec2, Abs) { check("Vec2_Abs"); }
|
||||
69
tests/general/unit_test_lua_vector3.cpp
Normal file
69
tests/general/unit_test_lua_vector3.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// Created by orange on 07.03.2026.
|
||||
//
|
||||
#include <gtest/gtest.h>
|
||||
#include <lua.hpp>
|
||||
#include <omath/lua/lua.hpp>
|
||||
|
||||
class LuaVec3 : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
lua_State* L = nullptr;
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
omath::lua::register_lib(L);
|
||||
if (luaL_dofile(L, LUA_SCRIPTS_DIR "/vec3_tests.lua") != LUA_OK)
|
||||
FAIL() << lua_tostring(L, -1);
|
||||
}
|
||||
|
||||
void TearDown() override { lua_close(L); }
|
||||
|
||||
void check(const char* func_name)
|
||||
{
|
||||
lua_getglobal(L, func_name);
|
||||
if (lua_pcall(L, 0, 0, 0) != LUA_OK)
|
||||
{
|
||||
FAIL() << lua_tostring(L, -1);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(LuaVec3, Constructor_default) { check("Vec3_Constructor_default"); }
|
||||
TEST_F(LuaVec3, Constructor_xyz) { check("Vec3_Constructor_xyz"); }
|
||||
TEST_F(LuaVec3, Field_mutation) { check("Vec3_Field_mutation"); }
|
||||
TEST_F(LuaVec3, Addition) { check("Vec3_Addition"); }
|
||||
TEST_F(LuaVec3, Subtraction) { check("Vec3_Subtraction"); }
|
||||
TEST_F(LuaVec3, UnaryMinus) { check("Vec3_UnaryMinus"); }
|
||||
TEST_F(LuaVec3, Multiplication_scalar) { check("Vec3_Multiplication_scalar"); }
|
||||
TEST_F(LuaVec3, Multiplication_scalar_reversed) { check("Vec3_Multiplication_scalar_reversed"); }
|
||||
TEST_F(LuaVec3, Multiplication_vec) { check("Vec3_Multiplication_vec"); }
|
||||
TEST_F(LuaVec3, Division_scalar) { check("Vec3_Division_scalar"); }
|
||||
TEST_F(LuaVec3, Division_vec) { check("Vec3_Division_vec"); }
|
||||
TEST_F(LuaVec3, EqualTo_true) { check("Vec3_EqualTo_true"); }
|
||||
TEST_F(LuaVec3, EqualTo_false) { check("Vec3_EqualTo_false"); }
|
||||
TEST_F(LuaVec3, LessThan) { check("Vec3_LessThan"); }
|
||||
TEST_F(LuaVec3, LessThanOrEqual) { check("Vec3_LessThanOrEqual"); }
|
||||
TEST_F(LuaVec3, ToString) { check("Vec3_ToString"); }
|
||||
TEST_F(LuaVec3, Length) { check("Vec3_Length"); }
|
||||
TEST_F(LuaVec3, Length2d) { check("Vec3_Length2d"); }
|
||||
TEST_F(LuaVec3, LengthSqr) { check("Vec3_LengthSqr"); }
|
||||
TEST_F(LuaVec3, Normalized) { check("Vec3_Normalized"); }
|
||||
TEST_F(LuaVec3, Dot_perpendicular) { check("Vec3_Dot_perpendicular"); }
|
||||
TEST_F(LuaVec3, Dot_parallel) { check("Vec3_Dot_parallel"); }
|
||||
TEST_F(LuaVec3, Cross) { check("Vec3_Cross"); }
|
||||
TEST_F(LuaVec3, DistanceTo) { check("Vec3_DistanceTo"); }
|
||||
TEST_F(LuaVec3, DistanceToSqr) { check("Vec3_DistanceToSqr"); }
|
||||
TEST_F(LuaVec3, Sum) { check("Vec3_Sum"); }
|
||||
TEST_F(LuaVec3, Sum2d) { check("Vec3_Sum2d"); }
|
||||
TEST_F(LuaVec3, Abs) { check("Vec3_Abs"); }
|
||||
TEST_F(LuaVec3, PointToSameDirection_true) { check("Vec3_PointToSameDirection_true"); }
|
||||
TEST_F(LuaVec3, PointToSameDirection_false) { check("Vec3_PointToSameDirection_false"); }
|
||||
TEST_F(LuaVec3, IsPerpendicular_true) { check("Vec3_IsPerpendicular_true"); }
|
||||
TEST_F(LuaVec3, IsPerpendicular_false) { check("Vec3_IsPerpendicular_false"); }
|
||||
TEST_F(LuaVec3, AngleBetween_90deg) { check("Vec3_AngleBetween_90deg"); }
|
||||
TEST_F(LuaVec3, AngleBetween_zero_vector_error) { check("Vec3_AngleBetween_zero_vector_error"); }
|
||||
TEST_F(LuaVec3, AsTable) { check("Vec3_AsTable"); }
|
||||
57
tests/general/unit_test_lua_vector4.cpp
Normal file
57
tests/general/unit_test_lua_vector4.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// Created by orange on 07.03.2026.
|
||||
//
|
||||
#include <gtest/gtest.h>
|
||||
#include <lua.hpp>
|
||||
#include <omath/lua/lua.hpp>
|
||||
|
||||
class LuaVec4 : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
lua_State* L = nullptr;
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
omath::lua::register_lib(L);
|
||||
if (luaL_dofile(L, LUA_SCRIPTS_DIR "/vec4_tests.lua") != LUA_OK)
|
||||
FAIL() << lua_tostring(L, -1);
|
||||
}
|
||||
|
||||
void TearDown() override { lua_close(L); }
|
||||
|
||||
void check(const char* func_name)
|
||||
{
|
||||
lua_getglobal(L, func_name);
|
||||
if (lua_pcall(L, 0, 0, 0) != LUA_OK)
|
||||
{
|
||||
FAIL() << lua_tostring(L, -1);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(LuaVec4, Constructor_default) { check("Vec4_Constructor_default"); }
|
||||
TEST_F(LuaVec4, Constructor_xyzw) { check("Vec4_Constructor_xyzw"); }
|
||||
TEST_F(LuaVec4, Field_mutation) { check("Vec4_Field_mutation"); }
|
||||
TEST_F(LuaVec4, Addition) { check("Vec4_Addition"); }
|
||||
TEST_F(LuaVec4, Subtraction) { check("Vec4_Subtraction"); }
|
||||
TEST_F(LuaVec4, UnaryMinus) { check("Vec4_UnaryMinus"); }
|
||||
TEST_F(LuaVec4, Multiplication_scalar) { check("Vec4_Multiplication_scalar"); }
|
||||
TEST_F(LuaVec4, Multiplication_scalar_reversed) { check("Vec4_Multiplication_scalar_reversed"); }
|
||||
TEST_F(LuaVec4, Multiplication_vec) { check("Vec4_Multiplication_vec"); }
|
||||
TEST_F(LuaVec4, Division_scalar) { check("Vec4_Division_scalar"); }
|
||||
TEST_F(LuaVec4, Division_vec) { check("Vec4_Division_vec"); }
|
||||
TEST_F(LuaVec4, EqualTo_true) { check("Vec4_EqualTo_true"); }
|
||||
TEST_F(LuaVec4, EqualTo_false) { check("Vec4_EqualTo_false"); }
|
||||
TEST_F(LuaVec4, LessThan) { check("Vec4_LessThan"); }
|
||||
TEST_F(LuaVec4, LessThanOrEqual) { check("Vec4_LessThanOrEqual"); }
|
||||
TEST_F(LuaVec4, ToString) { check("Vec4_ToString"); }
|
||||
TEST_F(LuaVec4, Length) { check("Vec4_Length"); }
|
||||
TEST_F(LuaVec4, LengthSqr) { check("Vec4_LengthSqr"); }
|
||||
TEST_F(LuaVec4, Dot) { check("Vec4_Dot"); }
|
||||
TEST_F(LuaVec4, Dot_perpendicular) { check("Vec4_Dot_perpendicular"); }
|
||||
TEST_F(LuaVec4, Sum) { check("Vec4_Sum"); }
|
||||
TEST_F(LuaVec4, Abs) { check("Vec4_Abs"); }
|
||||
TEST_F(LuaVec4, Clamp) { check("Vec4_Clamp"); }
|
||||
197
tests/lua/source_engine_tests.lua
Normal file
197
tests/lua/source_engine_tests.lua
Normal file
@@ -0,0 +1,197 @@
|
||||
local function approx(a, b, eps) return math.abs(a - b) < (eps or 1e-4) end
|
||||
|
||||
local function make_camera()
|
||||
local pos = omath.Vec3.new(0, 0, 0)
|
||||
local pitch = omath.source.PitchAngle.from_degrees(0)
|
||||
local yaw = omath.source.YawAngle.from_degrees(0)
|
||||
local roll = omath.source.RollAngle.from_degrees(0)
|
||||
local angles = omath.source.ViewAngles.new(pitch, yaw, roll)
|
||||
local vp = omath.opengl.ViewPort.new(1920, 1080)
|
||||
local fov = omath.source.FieldOfView.from_degrees(90)
|
||||
return omath.source.Camera.new(pos, angles, vp, fov, 0.1, 1000)
|
||||
end
|
||||
|
||||
-- PitchAngle
|
||||
function Source_PitchAngle_from_degrees()
|
||||
assert(omath.source.PitchAngle.from_degrees(45):as_degrees() == 45)
|
||||
end
|
||||
|
||||
function Source_PitchAngle_clamping_max()
|
||||
assert(omath.source.PitchAngle.from_degrees(100):as_degrees() == 89)
|
||||
end
|
||||
|
||||
function Source_PitchAngle_clamping_min()
|
||||
assert(omath.source.PitchAngle.from_degrees(-100):as_degrees() == -89)
|
||||
end
|
||||
|
||||
function Source_PitchAngle_from_radians()
|
||||
assert(approx(omath.source.PitchAngle.from_radians(math.pi / 4):as_degrees(), 45))
|
||||
end
|
||||
|
||||
function Source_PitchAngle_as_radians()
|
||||
assert(approx(omath.source.PitchAngle.from_degrees(0):as_radians(), 0))
|
||||
end
|
||||
|
||||
function Source_PitchAngle_sin()
|
||||
assert(approx(omath.source.PitchAngle.from_degrees(30):sin(), 0.5))
|
||||
end
|
||||
|
||||
function Source_PitchAngle_cos()
|
||||
assert(approx(omath.source.PitchAngle.from_degrees(60):cos(), 0.5))
|
||||
end
|
||||
|
||||
function Source_PitchAngle_tan()
|
||||
assert(approx(omath.source.PitchAngle.from_degrees(45):tan(), 1.0))
|
||||
end
|
||||
|
||||
function Source_PitchAngle_addition()
|
||||
local c = omath.source.PitchAngle.from_degrees(20) + omath.source.PitchAngle.from_degrees(15)
|
||||
assert(c:as_degrees() == 35)
|
||||
end
|
||||
|
||||
function Source_PitchAngle_addition_clamped()
|
||||
local c = omath.source.PitchAngle.from_degrees(80) + omath.source.PitchAngle.from_degrees(20)
|
||||
assert(c:as_degrees() == 89)
|
||||
end
|
||||
|
||||
function Source_PitchAngle_subtraction()
|
||||
local c = omath.source.PitchAngle.from_degrees(50) - omath.source.PitchAngle.from_degrees(20)
|
||||
assert(c:as_degrees() == 30)
|
||||
end
|
||||
|
||||
function Source_PitchAngle_unary_minus()
|
||||
assert((-omath.source.PitchAngle.from_degrees(45)):as_degrees() == -45)
|
||||
end
|
||||
|
||||
function Source_PitchAngle_equal_to()
|
||||
local a = omath.source.PitchAngle.from_degrees(45)
|
||||
assert(a == omath.source.PitchAngle.from_degrees(45))
|
||||
assert(not (a == omath.source.PitchAngle.from_degrees(30)))
|
||||
end
|
||||
|
||||
function Source_PitchAngle_to_string()
|
||||
assert(tostring(omath.source.PitchAngle.from_degrees(45)) == "45deg")
|
||||
end
|
||||
|
||||
-- YawAngle
|
||||
function Source_YawAngle_from_degrees()
|
||||
assert(omath.source.YawAngle.from_degrees(90):as_degrees() == 90)
|
||||
end
|
||||
|
||||
function Source_YawAngle_normalization()
|
||||
assert(approx(omath.source.YawAngle.from_degrees(200):as_degrees(), -160))
|
||||
end
|
||||
|
||||
-- RollAngle
|
||||
function Source_RollAngle_from_degrees()
|
||||
assert(omath.source.RollAngle.from_degrees(45):as_degrees() == 45)
|
||||
end
|
||||
|
||||
-- FieldOfView
|
||||
function Source_FieldOfView_from_degrees()
|
||||
assert(omath.source.FieldOfView.from_degrees(90):as_degrees() == 90)
|
||||
end
|
||||
|
||||
function Source_FieldOfView_clamping()
|
||||
assert(omath.source.FieldOfView.from_degrees(200):as_degrees() == 180)
|
||||
end
|
||||
|
||||
-- ViewAngles
|
||||
function Source_ViewAngles_new()
|
||||
local angles = omath.source.ViewAngles.new(
|
||||
omath.source.PitchAngle.from_degrees(30),
|
||||
omath.source.YawAngle.from_degrees(90),
|
||||
omath.source.RollAngle.from_degrees(0))
|
||||
assert(angles.pitch:as_degrees() == 30)
|
||||
assert(angles.yaw:as_degrees() == 90)
|
||||
assert(angles.roll:as_degrees() == 0)
|
||||
end
|
||||
|
||||
function Source_ViewAngles_field_mutation()
|
||||
local angles = omath.source.ViewAngles.new(
|
||||
omath.source.PitchAngle.from_degrees(0),
|
||||
omath.source.YawAngle.from_degrees(0),
|
||||
omath.source.RollAngle.from_degrees(0))
|
||||
angles.pitch = omath.source.PitchAngle.from_degrees(45)
|
||||
assert(angles.pitch:as_degrees() == 45)
|
||||
end
|
||||
|
||||
-- Camera
|
||||
function Source_Camera_constructor()
|
||||
assert(make_camera() ~= nil)
|
||||
end
|
||||
|
||||
function Source_Camera_get_set_origin()
|
||||
local cam = make_camera()
|
||||
cam:set_origin(omath.Vec3.new(1, 2, 3))
|
||||
local o = cam:get_origin()
|
||||
assert(approx(o.x, 1) and approx(o.y, 2) and approx(o.z, 3))
|
||||
end
|
||||
|
||||
function Source_Camera_get_set_near_plane()
|
||||
local cam = make_camera()
|
||||
cam:set_near_plane(0.5)
|
||||
assert(approx(cam:get_near_plane(), 0.5))
|
||||
end
|
||||
|
||||
function Source_Camera_get_set_far_plane()
|
||||
local cam = make_camera()
|
||||
cam:set_far_plane(500)
|
||||
assert(approx(cam:get_far_plane(), 500))
|
||||
end
|
||||
|
||||
function Source_Camera_get_set_fov()
|
||||
local cam = make_camera()
|
||||
cam:set_field_of_view(omath.source.FieldOfView.from_degrees(60))
|
||||
assert(approx(cam:get_field_of_view():as_degrees(), 60))
|
||||
end
|
||||
|
||||
function Source_Camera_get_set_view_angles()
|
||||
local cam = make_camera()
|
||||
cam:set_view_angles(omath.source.ViewAngles.new(
|
||||
omath.source.PitchAngle.from_degrees(30),
|
||||
omath.source.YawAngle.from_degrees(90),
|
||||
omath.source.RollAngle.from_degrees(0)))
|
||||
assert(approx(cam:get_view_angles().pitch:as_degrees(), 30))
|
||||
assert(approx(cam:get_view_angles().yaw:as_degrees(), 90))
|
||||
end
|
||||
|
||||
function Source_Camera_look_at()
|
||||
local cam = make_camera()
|
||||
cam:look_at(omath.Vec3.new(10, 0, 0))
|
||||
assert(cam:get_view_angles() ~= nil)
|
||||
end
|
||||
|
||||
function Source_Camera_get_forward()
|
||||
local fwd = make_camera():get_forward()
|
||||
assert(approx(fwd:length(), 1.0))
|
||||
end
|
||||
|
||||
function Source_Camera_get_right()
|
||||
assert(approx(make_camera():get_right():length(), 1.0))
|
||||
end
|
||||
|
||||
function Source_Camera_get_up()
|
||||
assert(approx(make_camera():get_up():length(), 1.0))
|
||||
end
|
||||
|
||||
function Source_Camera_world_to_screen_success()
|
||||
local cam = make_camera()
|
||||
cam:look_at(omath.Vec3.new(1, 0, 0))
|
||||
local screen, err = cam:world_to_screen(omath.Vec3.new(5, 0, 0))
|
||||
assert(screen ~= nil, "expected screen pos, got: " .. tostring(err))
|
||||
end
|
||||
|
||||
function Source_Camera_world_to_screen_error()
|
||||
local cam = make_camera()
|
||||
cam:look_at(omath.Vec3.new(1, 0, 0))
|
||||
local screen, err = cam:world_to_screen(omath.Vec3.new(-100, 0, 0))
|
||||
assert(screen == nil and err ~= nil)
|
||||
end
|
||||
|
||||
function Source_Camera_screen_to_world()
|
||||
local cam = make_camera()
|
||||
cam:look_at(omath.Vec3.new(1, 0, 0))
|
||||
local world, err = cam:screen_to_world(omath.Vec3.new(960, 540, 1))
|
||||
assert(world ~= nil, "expected world pos, got: " .. tostring(err))
|
||||
end
|
||||
102
tests/lua/vec2_tests.lua
Normal file
102
tests/lua/vec2_tests.lua
Normal file
@@ -0,0 +1,102 @@
|
||||
local function approx(a, b) return math.abs(a - b) < 1e-5 end
|
||||
|
||||
function Vec2_Constructor_default()
|
||||
local v = omath.Vec2.new()
|
||||
assert(v.x == 0 and v.y == 0)
|
||||
end
|
||||
|
||||
function Vec2_Constructor_xy()
|
||||
local v = omath.Vec2.new(3, 4)
|
||||
assert(v.x == 3 and v.y == 4)
|
||||
end
|
||||
|
||||
function Vec2_Field_mutation()
|
||||
local v = omath.Vec2.new(1, 2)
|
||||
v.x = 9; v.y = 8
|
||||
assert(v.x == 9 and v.y == 8)
|
||||
end
|
||||
|
||||
function Vec2_Addition()
|
||||
local c = omath.Vec2.new(1, 2) + omath.Vec2.new(3, 4)
|
||||
assert(c.x == 4 and c.y == 6)
|
||||
end
|
||||
|
||||
function Vec2_Subtraction()
|
||||
local c = omath.Vec2.new(5, 7) - omath.Vec2.new(2, 3)
|
||||
assert(c.x == 3 and c.y == 4)
|
||||
end
|
||||
|
||||
function Vec2_UnaryMinus()
|
||||
local b = -omath.Vec2.new(1, 2)
|
||||
assert(b.x == -1 and b.y == -2)
|
||||
end
|
||||
|
||||
function Vec2_Multiplication_scalar()
|
||||
local b = omath.Vec2.new(2, 3) * 2.0
|
||||
assert(b.x == 4 and b.y == 6)
|
||||
end
|
||||
|
||||
function Vec2_Multiplication_scalar_reversed()
|
||||
local b = 2.0 * omath.Vec2.new(2, 3)
|
||||
assert(b.x == 4 and b.y == 6)
|
||||
end
|
||||
|
||||
function Vec2_Division_scalar()
|
||||
local b = omath.Vec2.new(4, 6) / 2.0
|
||||
assert(b.x == 2 and b.y == 3)
|
||||
end
|
||||
|
||||
function Vec2_EqualTo_true()
|
||||
assert(omath.Vec2.new(1, 2) == omath.Vec2.new(1, 2))
|
||||
end
|
||||
|
||||
function Vec2_EqualTo_false()
|
||||
assert(not (omath.Vec2.new(1, 2) == omath.Vec2.new(9, 9)))
|
||||
end
|
||||
|
||||
function Vec2_LessThan()
|
||||
assert(omath.Vec2.new(1, 0) < omath.Vec2.new(3, 4))
|
||||
end
|
||||
|
||||
function Vec2_LessThanOrEqual()
|
||||
-- (3,4) and (4,3) both have length 5
|
||||
assert(omath.Vec2.new(3, 4) <= omath.Vec2.new(4, 3))
|
||||
end
|
||||
|
||||
function Vec2_ToString()
|
||||
assert(tostring(omath.Vec2.new(1, 2)) == "Vec2(1, 2)")
|
||||
end
|
||||
|
||||
function Vec2_Length()
|
||||
assert(approx(omath.Vec2.new(3, 4):length(), 5.0))
|
||||
end
|
||||
|
||||
function Vec2_LengthSqr()
|
||||
assert(omath.Vec2.new(3, 4):length_sqr() == 25.0)
|
||||
end
|
||||
|
||||
function Vec2_Normalized()
|
||||
local n = omath.Vec2.new(3, 4):normalized()
|
||||
assert(approx(n.x, 0.6) and approx(n.y, 0.8))
|
||||
end
|
||||
|
||||
function Vec2_Dot()
|
||||
assert(omath.Vec2.new(1, 2):dot(omath.Vec2.new(3, 4)) == 11.0)
|
||||
end
|
||||
|
||||
function Vec2_DistanceTo()
|
||||
assert(approx(omath.Vec2.new(0, 0):distance_to(omath.Vec2.new(3, 4)), 5.0))
|
||||
end
|
||||
|
||||
function Vec2_DistanceToSqr()
|
||||
assert(omath.Vec2.new(0, 0):distance_to_sqr(omath.Vec2.new(3, 4)) == 25.0)
|
||||
end
|
||||
|
||||
function Vec2_Sum()
|
||||
assert(omath.Vec2.new(3, 4):sum() == 7.0)
|
||||
end
|
||||
|
||||
function Vec2_Abs()
|
||||
local a = omath.Vec2.new(-3, -4):abs()
|
||||
assert(a.x == 3 and a.y == 4)
|
||||
end
|
||||
163
tests/lua/vec3_tests.lua
Normal file
163
tests/lua/vec3_tests.lua
Normal file
@@ -0,0 +1,163 @@
|
||||
local function approx(a, b, eps) return math.abs(a - b) < (eps or 1e-5) end
|
||||
|
||||
function Vec3_Constructor_default()
|
||||
local v = omath.Vec3.new()
|
||||
assert(v.x == 0 and v.y == 0 and v.z == 0)
|
||||
end
|
||||
|
||||
function Vec3_Constructor_xyz()
|
||||
local v = omath.Vec3.new(1, 2, 3)
|
||||
assert(v.x == 1 and v.y == 2 and v.z == 3)
|
||||
end
|
||||
|
||||
function Vec3_Field_mutation()
|
||||
local v = omath.Vec3.new(1, 2, 3)
|
||||
v.x = 9; v.y = 8; v.z = 7
|
||||
assert(v.x == 9 and v.y == 8 and v.z == 7)
|
||||
end
|
||||
|
||||
function Vec3_Addition()
|
||||
local c = omath.Vec3.new(1, 2, 3) + omath.Vec3.new(4, 5, 6)
|
||||
assert(c.x == 5 and c.y == 7 and c.z == 9)
|
||||
end
|
||||
|
||||
function Vec3_Subtraction()
|
||||
local c = omath.Vec3.new(4, 5, 6) - omath.Vec3.new(1, 2, 3)
|
||||
assert(c.x == 3 and c.y == 3 and c.z == 3)
|
||||
end
|
||||
|
||||
function Vec3_UnaryMinus()
|
||||
local b = -omath.Vec3.new(1, 2, 3)
|
||||
assert(b.x == -1 and b.y == -2 and b.z == -3)
|
||||
end
|
||||
|
||||
function Vec3_Multiplication_scalar()
|
||||
local b = omath.Vec3.new(1, 2, 3) * 2.0
|
||||
assert(b.x == 2 and b.y == 4 and b.z == 6)
|
||||
end
|
||||
|
||||
function Vec3_Multiplication_scalar_reversed()
|
||||
local b = 2.0 * omath.Vec3.new(1, 2, 3)
|
||||
assert(b.x == 2 and b.y == 4 and b.z == 6)
|
||||
end
|
||||
|
||||
function Vec3_Multiplication_vec()
|
||||
local c = omath.Vec3.new(2, 3, 4) * omath.Vec3.new(2, 2, 2)
|
||||
assert(c.x == 4 and c.y == 6 and c.z == 8)
|
||||
end
|
||||
|
||||
function Vec3_Division_scalar()
|
||||
local b = omath.Vec3.new(2, 4, 6) / 2.0
|
||||
assert(b.x == 1 and b.y == 2 and b.z == 3)
|
||||
end
|
||||
|
||||
function Vec3_Division_vec()
|
||||
local c = omath.Vec3.new(4, 6, 8) / omath.Vec3.new(2, 2, 2)
|
||||
assert(c.x == 2 and c.y == 3 and c.z == 4)
|
||||
end
|
||||
|
||||
function Vec3_EqualTo_true()
|
||||
assert(omath.Vec3.new(1, 2, 3) == omath.Vec3.new(1, 2, 3))
|
||||
end
|
||||
|
||||
function Vec3_EqualTo_false()
|
||||
assert(not (omath.Vec3.new(1, 2, 3) == omath.Vec3.new(9, 9, 9)))
|
||||
end
|
||||
|
||||
function Vec3_LessThan()
|
||||
assert(omath.Vec3.new(1, 0, 0) < omath.Vec3.new(3, 4, 0))
|
||||
end
|
||||
|
||||
function Vec3_LessThanOrEqual()
|
||||
-- (0,3,4) and (0,4,3) both have length 5
|
||||
assert(omath.Vec3.new(0, 3, 4) <= omath.Vec3.new(0, 4, 3))
|
||||
end
|
||||
|
||||
function Vec3_ToString()
|
||||
assert(tostring(omath.Vec3.new(1, 2, 3)) == "Vec3(1, 2, 3)")
|
||||
end
|
||||
|
||||
function Vec3_Length()
|
||||
assert(approx(omath.Vec3.new(1, 2, 2):length(), 3.0))
|
||||
end
|
||||
|
||||
function Vec3_Length2d()
|
||||
assert(approx(omath.Vec3.new(3, 4, 99):length_2d(), 5.0))
|
||||
end
|
||||
|
||||
function Vec3_LengthSqr()
|
||||
assert(omath.Vec3.new(1, 2, 2):length_sqr() == 9.0)
|
||||
end
|
||||
|
||||
function Vec3_Normalized()
|
||||
local n = omath.Vec3.new(3, 0, 0):normalized()
|
||||
assert(approx(n.x, 1.0) and approx(n.y, 0.0) and approx(n.z, 0.0))
|
||||
end
|
||||
|
||||
function Vec3_Dot_perpendicular()
|
||||
assert(omath.Vec3.new(1, 0, 0):dot(omath.Vec3.new(0, 1, 0)) == 0.0)
|
||||
end
|
||||
|
||||
function Vec3_Dot_parallel()
|
||||
local a = omath.Vec3.new(1, 2, 3)
|
||||
assert(a:dot(a) == 14.0)
|
||||
end
|
||||
|
||||
function Vec3_Cross()
|
||||
local c = omath.Vec3.new(1, 0, 0):cross(omath.Vec3.new(0, 1, 0))
|
||||
assert(approx(c.x, 0) and approx(c.y, 0) and approx(c.z, 1))
|
||||
end
|
||||
|
||||
function Vec3_DistanceTo()
|
||||
assert(approx(omath.Vec3.new(0, 0, 0):distance_to(omath.Vec3.new(1, 2, 2)), 3.0))
|
||||
end
|
||||
|
||||
function Vec3_DistanceToSqr()
|
||||
assert(omath.Vec3.new(0, 0, 0):distance_to_sqr(omath.Vec3.new(1, 2, 2)) == 9.0)
|
||||
end
|
||||
|
||||
function Vec3_Sum()
|
||||
assert(omath.Vec3.new(1, 2, 3):sum() == 6.0)
|
||||
end
|
||||
|
||||
function Vec3_Sum2d()
|
||||
assert(omath.Vec3.new(1, 2, 3):sum_2d() == 3.0)
|
||||
end
|
||||
|
||||
function Vec3_Abs()
|
||||
local a = omath.Vec3.new(-1, -2, -3):abs()
|
||||
assert(a.x == 1 and a.y == 2 and a.z == 3)
|
||||
end
|
||||
|
||||
function Vec3_PointToSameDirection_true()
|
||||
assert(omath.Vec3.new(1, 1, 0):point_to_same_direction(omath.Vec3.new(2, 2, 0)) == true)
|
||||
end
|
||||
|
||||
function Vec3_PointToSameDirection_false()
|
||||
assert(omath.Vec3.new(1, 0, 0):point_to_same_direction(omath.Vec3.new(-1, 0, 0)) == false)
|
||||
end
|
||||
|
||||
function Vec3_IsPerpendicular_true()
|
||||
assert(omath.Vec3.new(1, 0, 0):is_perpendicular(omath.Vec3.new(0, 1, 0)) == true)
|
||||
end
|
||||
|
||||
function Vec3_IsPerpendicular_false()
|
||||
local a = omath.Vec3.new(1, 0, 0)
|
||||
assert(a:is_perpendicular(a) == false)
|
||||
end
|
||||
|
||||
function Vec3_AngleBetween_90deg()
|
||||
local angle, err = omath.Vec3.new(1, 0, 0):angle_between(omath.Vec3.new(0, 1, 0))
|
||||
assert(angle ~= nil, err)
|
||||
assert(math.abs(angle - 90.0) < 1e-3)
|
||||
end
|
||||
|
||||
function Vec3_AngleBetween_zero_vector_error()
|
||||
local angle, err = omath.Vec3.new(0, 0, 0):angle_between(omath.Vec3.new(1, 0, 0))
|
||||
assert(angle == nil and err ~= nil)
|
||||
end
|
||||
|
||||
function Vec3_AsTable()
|
||||
local t = omath.Vec3.new(1, 2, 3):as_table()
|
||||
assert(t.x == 1 and t.y == 2 and t.z == 3)
|
||||
end
|
||||
110
tests/lua/vec4_tests.lua
Normal file
110
tests/lua/vec4_tests.lua
Normal file
@@ -0,0 +1,110 @@
|
||||
local function approx(a, b) return math.abs(a - b) < 1e-5 end
|
||||
|
||||
function Vec4_Constructor_default()
|
||||
local v = omath.Vec4.new()
|
||||
assert(v.x == 0 and v.y == 0 and v.z == 0 and v.w == 0)
|
||||
end
|
||||
|
||||
function Vec4_Constructor_xyzw()
|
||||
local v = omath.Vec4.new(1, 2, 3, 4)
|
||||
assert(v.x == 1 and v.y == 2 and v.z == 3 and v.w == 4)
|
||||
end
|
||||
|
||||
function Vec4_Field_mutation()
|
||||
local v = omath.Vec4.new(1, 2, 3, 4)
|
||||
v.w = 99
|
||||
assert(v.w == 99)
|
||||
end
|
||||
|
||||
function Vec4_Addition()
|
||||
local c = omath.Vec4.new(1, 2, 3, 4) + omath.Vec4.new(4, 3, 2, 1)
|
||||
assert(c.x == 5 and c.y == 5 and c.z == 5 and c.w == 5)
|
||||
end
|
||||
|
||||
function Vec4_Subtraction()
|
||||
local c = omath.Vec4.new(5, 5, 5, 5) - omath.Vec4.new(1, 2, 3, 4)
|
||||
assert(c.x == 4 and c.y == 3 and c.z == 2 and c.w == 1)
|
||||
end
|
||||
|
||||
function Vec4_UnaryMinus()
|
||||
local b = -omath.Vec4.new(1, 2, 3, 4)
|
||||
assert(b.x == -1 and b.y == -2 and b.z == -3 and b.w == -4)
|
||||
end
|
||||
|
||||
function Vec4_Multiplication_scalar()
|
||||
local b = omath.Vec4.new(1, 2, 3, 4) * 2.0
|
||||
assert(b.x == 2 and b.y == 4 and b.z == 6 and b.w == 8)
|
||||
end
|
||||
|
||||
function Vec4_Multiplication_scalar_reversed()
|
||||
local b = 2.0 * omath.Vec4.new(1, 2, 3, 4)
|
||||
assert(b.x == 2 and b.y == 4 and b.z == 6 and b.w == 8)
|
||||
end
|
||||
|
||||
function Vec4_Multiplication_vec()
|
||||
local c = omath.Vec4.new(2, 3, 4, 5) * omath.Vec4.new(2, 2, 2, 2)
|
||||
assert(c.x == 4 and c.y == 6 and c.z == 8 and c.w == 10)
|
||||
end
|
||||
|
||||
function Vec4_Division_scalar()
|
||||
local b = omath.Vec4.new(2, 4, 6, 8) / 2.0
|
||||
assert(b.x == 1 and b.y == 2 and b.z == 3 and b.w == 4)
|
||||
end
|
||||
|
||||
function Vec4_Division_vec()
|
||||
local c = omath.Vec4.new(4, 6, 8, 10) / omath.Vec4.new(2, 2, 2, 2)
|
||||
assert(c.x == 2 and c.y == 3 and c.z == 4 and c.w == 5)
|
||||
end
|
||||
|
||||
function Vec4_EqualTo_true()
|
||||
assert(omath.Vec4.new(1, 2, 3, 4) == omath.Vec4.new(1, 2, 3, 4))
|
||||
end
|
||||
|
||||
function Vec4_EqualTo_false()
|
||||
assert(not (omath.Vec4.new(1, 2, 3, 4) == omath.Vec4.new(9, 9, 9, 9)))
|
||||
end
|
||||
|
||||
function Vec4_LessThan()
|
||||
assert(omath.Vec4.new(1, 0, 0, 0) < omath.Vec4.new(0, 0, 3, 4))
|
||||
end
|
||||
|
||||
function Vec4_LessThanOrEqual()
|
||||
-- (0,0,3,4) and (0,0,4,3) both have length 5
|
||||
assert(omath.Vec4.new(0, 0, 3, 4) <= omath.Vec4.new(0, 0, 4, 3))
|
||||
end
|
||||
|
||||
function Vec4_ToString()
|
||||
assert(tostring(omath.Vec4.new(1, 2, 3, 4)) == "Vec4(1, 2, 3, 4)")
|
||||
end
|
||||
|
||||
function Vec4_Length()
|
||||
assert(approx(omath.Vec4.new(0, 0, 3, 4):length(), 5.0))
|
||||
end
|
||||
|
||||
function Vec4_LengthSqr()
|
||||
assert(omath.Vec4.new(0, 0, 3, 4):length_sqr() == 25.0)
|
||||
end
|
||||
|
||||
function Vec4_Dot()
|
||||
local a = omath.Vec4.new(1, 2, 3, 4)
|
||||
assert(a:dot(a) == 30.0)
|
||||
end
|
||||
|
||||
function Vec4_Dot_perpendicular()
|
||||
assert(omath.Vec4.new(1, 0, 0, 0):dot(omath.Vec4.new(0, 1, 0, 0)) == 0.0)
|
||||
end
|
||||
|
||||
function Vec4_Sum()
|
||||
assert(omath.Vec4.new(1, 2, 3, 4):sum() == 10.0)
|
||||
end
|
||||
|
||||
function Vec4_Abs()
|
||||
local a = omath.Vec4.new(-1, -2, -3, -4):abs()
|
||||
assert(a.x == 1 and a.y == 2 and a.z == 3 and a.w == 4)
|
||||
end
|
||||
|
||||
function Vec4_Clamp()
|
||||
local v = omath.Vec4.new(5, -3, 10, 99)
|
||||
v:clamp(0, 7)
|
||||
assert(v.x == 5 and v.y == 0 and v.z == 7)
|
||||
end
|
||||
29
tests/lua/vector2_test.lua
Normal file
29
tests/lua/vector2_test.lua
Normal file
@@ -0,0 +1,29 @@
|
||||
local a = omath.Vec2.new(1, 2)
|
||||
local b = omath.Vec2.new(10, 20)
|
||||
|
||||
-- Operators
|
||||
local c = a + b
|
||||
local d = a - b
|
||||
local e = a * 2.0
|
||||
local f = -a
|
||||
print("a + b = " .. tostring(c))
|
||||
print("a - b = " .. tostring(d))
|
||||
print("a * 2 = " .. tostring(e))
|
||||
print("-a = " .. tostring(f))
|
||||
print("a == Vec2(1,2): " .. tostring(a == omath.Vec2.new(1, 2)))
|
||||
print("a < b: " .. tostring(a < b))
|
||||
|
||||
-- Field access + mutation
|
||||
print("c.x = " .. c.x .. ", c.y = " .. c.y)
|
||||
c.x = 99
|
||||
print("c.x after mutation = " .. c.x)
|
||||
|
||||
-- Methods
|
||||
print("a:length() = " .. a:length())
|
||||
print("a:length_sqr() = " .. a:length_sqr())
|
||||
print("a:normalized() = " .. tostring(a:normalized()))
|
||||
print("a:dot(b) = " .. a:dot(b))
|
||||
print("a:distance_to(b) = " .. a:distance_to(b))
|
||||
print("a:distance_to_sqr(b) = " .. a:distance_to_sqr(b))
|
||||
print("a:sum() = " .. a:sum())
|
||||
print("a:abs() = " .. tostring(a:abs()))
|
||||
55
tests/lua/vector3_test.lua
Normal file
55
tests/lua/vector3_test.lua
Normal file
@@ -0,0 +1,55 @@
|
||||
local a = omath.Vec3.new(1, 0, 0)
|
||||
local b = omath.Vec3.new(0, 1, 0)
|
||||
|
||||
-- Operators
|
||||
local c = a + b
|
||||
local d = a - b
|
||||
local e = a * 2.0
|
||||
local f = -a
|
||||
print("a + b = " .. tostring(c))
|
||||
print("a - b = " .. tostring(d))
|
||||
print("a * 2 = " .. tostring(e))
|
||||
print("-a = " .. tostring(f))
|
||||
print("a == Vec3(1,2,3): " .. tostring(a == omath.Vec3.new(1, 2, 3)))
|
||||
print("a < b: " .. tostring(a < b))
|
||||
|
||||
-- Field access + mutation
|
||||
print("c.x = " .. c.x .. ", c.y = " .. c.y .. ", c.z = " .. c.z)
|
||||
c.x = 99
|
||||
print("c.x after mutation = " .. c.x)
|
||||
|
||||
-- Methods
|
||||
print("a:length() = " .. a:length())
|
||||
print("a:length_2d() = " .. a:length_2d())
|
||||
print("a:length_sqr() = " .. a:length_sqr())
|
||||
print("a:normalized() = " .. tostring(a:normalized()))
|
||||
print("a:dot(b) = " .. a:dot(b))
|
||||
print("a:cross(b) = " .. tostring(a:cross(b)))
|
||||
print("a:distance_to(b) = " .. a:distance_to(b))
|
||||
print("a:distance_to_sqr(b) = " .. a:distance_to_sqr(b))
|
||||
print("a:abs() = " .. tostring(a:abs()))
|
||||
print("a:sum() = " .. a:sum())
|
||||
print("a:sum_2d() = " .. a:sum_2d())
|
||||
print("a:point_to_same_direction(b) = " .. tostring(a:point_to_same_direction(b)))
|
||||
print("a:is_perpendicular(b) = " .. tostring(a:is_perpendicular(b)))
|
||||
|
||||
-- angle_between
|
||||
local angle, err = a:angle_between(b)
|
||||
if angle then
|
||||
print("angle_between = " .. angle .. " degrees")
|
||||
else
|
||||
print("angle_between error: " .. err)
|
||||
end
|
||||
|
||||
-- Zero vector edge case
|
||||
local zero = omath.Vec3.new(0, 0, 0)
|
||||
local ang2, err2 = zero:angle_between(a)
|
||||
if ang2 then
|
||||
print("zero angle = " .. ang2)
|
||||
else
|
||||
print("zero angle error: " .. err2)
|
||||
end
|
||||
|
||||
-- as_table
|
||||
local t = a:as_table()
|
||||
print("as_table: x=" .. t.x .. " y=" .. t.y .. " z=" .. t.z)
|
||||
31
tests/lua/vector4_test.lua
Normal file
31
tests/lua/vector4_test.lua
Normal file
@@ -0,0 +1,31 @@
|
||||
local a = omath.Vec4.new(1, 2, 3, 4)
|
||||
local b = omath.Vec4.new(10, 20, 30, 40)
|
||||
|
||||
-- Operators
|
||||
local c = a + b
|
||||
local d = a - b
|
||||
local e = a * 2.0
|
||||
local f = -a
|
||||
print("a + b = " .. tostring(c))
|
||||
print("a - b = " .. tostring(d))
|
||||
print("a * 2 = " .. tostring(e))
|
||||
print("-a = " .. tostring(f))
|
||||
print("a == Vec4(1,2,3,4): " .. tostring(a == omath.Vec4.new(1, 2, 3, 4)))
|
||||
print("a < b: " .. tostring(a < b))
|
||||
|
||||
-- Field access + mutation
|
||||
print("c.x=" .. c.x .. " c.y=" .. c.y .. " c.z=" .. c.z .. " c.w=" .. c.w)
|
||||
c.w = 99
|
||||
print("c.w after mutation = " .. c.w)
|
||||
|
||||
-- Methods
|
||||
print("a:length() = " .. a:length())
|
||||
print("a:length_sqr() = " .. a:length_sqr())
|
||||
print("a:dot(b) = " .. a:dot(b))
|
||||
print("a:sum() = " .. a:sum())
|
||||
print("a:abs() = " .. tostring(a:abs()))
|
||||
|
||||
-- clamp
|
||||
local clamped = omath.Vec4.new(5, -3, 10, 1)
|
||||
clamped:clamp(0, 7)
|
||||
print("clamp([5,-3,10,1], 0, 7).x=" .. clamped.x .. " .y=" .. clamped.y .. " .z=" .. clamped.z)
|
||||
11
vcpkg.json
11
vcpkg.json
@@ -17,7 +17,7 @@
|
||||
],
|
||||
"features": {
|
||||
"avx2": {
|
||||
"description": "Omath will use AVX2 to boost performance",
|
||||
"description": "omath will use AVX2 to boost performance",
|
||||
"supports": "!arm"
|
||||
},
|
||||
"benchmark": {
|
||||
@@ -35,7 +35,7 @@
|
||||
]
|
||||
},
|
||||
"imgui": {
|
||||
"description": "Omath will define method to convert omath types to imgui types",
|
||||
"description": "omath will define method to convert omath types to imgui types",
|
||||
"dependencies": [
|
||||
"imgui"
|
||||
]
|
||||
@@ -45,6 +45,13 @@
|
||||
"dependencies": [
|
||||
"gtest"
|
||||
]
|
||||
},
|
||||
"lua": {
|
||||
"description": "lua support for omath",
|
||||
"dependencies": [
|
||||
"lua",
|
||||
"sol2"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user