mirror of
https://github.com/orange-cpp/omath.git
synced 2026-04-19 07:23:27 +00:00
Compare commits
18 Commits
afb2a13dd6
...
v5.1.0.rc3
| Author | SHA1 | Date | |
|---|---|---|---|
| 3ccbb0b25b | |||
| 68993db48a | |||
| 337204b3bf | |||
| 1e601d2d8f | |||
| 2b4a75d011 | |||
| 99a30e8fdf | |||
| 0cdd1d021f | |||
| a79ac9743a | |||
| f26afb703b | |||
| f237ee5f6a | |||
| 9058ea9b39 | |||
| f707ac1adb | |||
| cbdabd3fc2 | |||
| 30e3feb4f8 | |||
| 0726fdef32 | |||
| 0ffe0c2bdc | |||
| e9600ad42b | |||
| 673835618c |
20
.github/workflows/cmake-multi-platform.yml
vendored
20
.github/workflows/cmake-multi-platform.yml
vendored
@@ -107,7 +107,7 @@ jobs:
|
||||
-DOMATH_BUILD_TESTS=ON \
|
||||
-DOMATH_BUILD_BENCHMARK=OFF \
|
||||
-DOMATH_ENABLE_COVERAGE=${{ matrix.coverage == true && 'ON' || 'OFF' }} \
|
||||
-DVCPKG_MANIFEST_FEATURES="imgui;avx2;tests"
|
||||
-DVCPKG_MANIFEST_FEATURES="imgui;avx2;tests;lua"
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
@@ -193,7 +193,7 @@ jobs:
|
||||
-DOMATH_BUILD_TESTS=ON \
|
||||
-DOMATH_BUILD_BENCHMARK=OFF \
|
||||
-DOMATH_ENABLE_COVERAGE=OFF \
|
||||
-DVCPKG_MANIFEST_FEATURES="imgui;avx2;tests"
|
||||
-DVCPKG_MANIFEST_FEATURES="imgui;avx2;tests;lua"
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
@@ -234,7 +234,7 @@ jobs:
|
||||
-DOMATH_ENABLE_COVERAGE=ON \
|
||||
-DOMATH_THREAT_WARNING_AS_ERROR=OFF \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DVCPKG_MANIFEST_FEATURES="imgui;avx2;tests"
|
||||
-DVCPKG_MANIFEST_FEATURES="imgui;avx2;tests;lua"
|
||||
cmake --build cmake-build/build/${{ matrix.preset }} --config Debug --target unit_tests omath
|
||||
|
||||
- name: Run Tests (Generates .profraw)
|
||||
@@ -373,7 +373,7 @@ jobs:
|
||||
-DOMATH_BUILD_TESTS=ON \
|
||||
-DOMATH_BUILD_BENCHMARK=OFF \
|
||||
-DOMATH_ENABLE_COVERAGE=${{ matrix.coverage == true && 'ON' || 'OFF' }} \
|
||||
-DVCPKG_MANIFEST_FEATURES="imgui;avx2;tests"
|
||||
-DVCPKG_MANIFEST_FEATURES="imgui;avx2;tests;lua"
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
@@ -450,7 +450,7 @@ jobs:
|
||||
-DVCPKG_INSTALL_OPTIONS="--allow-unsupported" \
|
||||
-DOMATH_BUILD_TESTS=ON \
|
||||
-DOMATH_BUILD_BENCHMARK=OFF \
|
||||
-DVCPKG_MANIFEST_FEATURES="imgui;tests"
|
||||
-DVCPKG_MANIFEST_FEATURES="imgui;tests;lua"
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
@@ -509,7 +509,7 @@ jobs:
|
||||
cmake --preset ${{ matrix.preset }} \
|
||||
-DOMATH_BUILD_TESTS=ON \
|
||||
-DOMATH_BUILD_BENCHMARK=OFF \
|
||||
-DVCPKG_MANIFEST_FEATURES="imgui;avx2;tests" \
|
||||
-DVCPKG_MANIFEST_FEATURES="imgui;avx2;tests;lua" \
|
||||
-DVCPKG_INSTALL_OPTIONS="--allow-unsupported"
|
||||
cmake --build cmake-build/build/${{ matrix.preset }} --target unit_tests omath
|
||||
./out/Release/unit_tests
|
||||
@@ -581,7 +581,7 @@ jobs:
|
||||
-DVCPKG_INSTALL_OPTIONS="--allow-unsupported" \
|
||||
-DOMATH_BUILD_TESTS=ON \
|
||||
-DOMATH_BUILD_BENCHMARK=OFF \
|
||||
-DVCPKG_MANIFEST_FEATURES="imgui;tests"
|
||||
-DVCPKG_MANIFEST_FEATURES="imgui;tests;lua"
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
@@ -650,7 +650,7 @@ jobs:
|
||||
-DVCPKG_INSTALL_OPTIONS="--allow-unsupported" \
|
||||
-DOMATH_BUILD_TESTS=ON \
|
||||
-DOMATH_BUILD_BENCHMARK=OFF \
|
||||
-DVCPKG_MANIFEST_FEATURES="imgui;tests"
|
||||
-DVCPKG_MANIFEST_FEATURES="imgui;tests;lua"
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
@@ -735,7 +735,7 @@ jobs:
|
||||
-DVCPKG_INSTALL_OPTIONS="--allow-unsupported" \
|
||||
-DOMATH_BUILD_TESTS=ON \
|
||||
-DOMATH_BUILD_BENCHMARK=OFF \
|
||||
-DVCPKG_MANIFEST_FEATURES="imgui;tests"
|
||||
-DVCPKG_MANIFEST_FEATURES="imgui;tests;lua"
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
@@ -800,7 +800,7 @@ jobs:
|
||||
-DOMATH_BUILD_TESTS=ON \
|
||||
-DOMATH_BUILD_BENCHMARK=ON \
|
||||
-DOMATH_ENABLE_VALGRIND=ON \
|
||||
-DVCPKG_MANIFEST_FEATURES="imgui;avx2;tests;benchmark"
|
||||
-DVCPKG_MANIFEST_FEATURES="imgui;avx2;lua;tests;benchmark"
|
||||
|
||||
- name: Build All Targets
|
||||
shell: bash
|
||||
|
||||
@@ -77,6 +77,7 @@ if(${PROJECT_IS_TOP_LEVEL})
|
||||
message(STATUS "[${PROJECT_NAME}]: Building using vcpkg ${OMATH_BUILD_VIA_VCPKG}")
|
||||
message(STATUS "[${PROJECT_NAME}]: Coverage feature status ${OMATH_ENABLE_COVERAGE}")
|
||||
message(STATUS "[${PROJECT_NAME}]: Valgrind feature status ${OMATH_ENABLE_VALGRIND}")
|
||||
message(STATUS "[${PROJECT_NAME}]: Lua feature status ${OMATH_ENABLE_LUA}")
|
||||
endif()
|
||||
|
||||
file(GLOB_RECURSE OMATH_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp")
|
||||
@@ -190,6 +191,12 @@ elseif(OMATH_THREAT_WARNING_AS_ERROR)
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Wpedantic -Werror)
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE /bigobj)
|
||||
endif()
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_HOST_SYSTEM_NAME EQUAL "Windows")
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE -mbig-obj)
|
||||
endif()
|
||||
# Windows SDK redefine min/max via preprocessor and break std::min and std::max
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
target_compile_definitions(${PROJECT_NAME} INTERFACE NOMINMAX)
|
||||
|
||||
@@ -235,7 +235,7 @@
|
||||
"hidden": true,
|
||||
"inherits": ["darwin-base", "vcpkg-base"],
|
||||
"cacheVariables": {
|
||||
"VCPKG_MANIFEST_FEATURES": "tests;imgui;avx2;examples"
|
||||
"VCPKG_MANIFEST_FEATURES": "tests;imgui;avx2;examples;lua"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
[](https://www.codefactor.io/repository/github/orange-cpp/omath)
|
||||

|
||||
[](https://repology.org/project/orange-math/versions)
|
||||

|
||||

|
||||
[](https://discord.gg/eDgdaWbqwZ)
|
||||
[](https://t.me/orangennotes)
|
||||
@@ -83,6 +84,7 @@ if (auto screen = camera.world_to_screen(world_position)) {
|
||||
- **Engine support**: Supports coordinate systems of **Source, Unity, Unreal, Frostbite, IWEngine, CryEngine and canonical OpenGL**.
|
||||
- **Cross platform**: Supports Windows, MacOS and Linux.
|
||||
- **Algorithms**: Has ability to scan for byte pattern with wildcards in ELF/Mach-O/PE files/modules, binary slices, works even with Wine apps.
|
||||
- **Scripting**: Supports to make scripts in Lua out of box
|
||||
- **Battle tested**: It's already used by some big players on the market like wraith.su and bluedream.ltd
|
||||
<div align = center>
|
||||
|
||||
|
||||
@@ -3,11 +3,23 @@
|
||||
//
|
||||
#pragma once
|
||||
#ifdef OMATH_ENABLE_LUA
|
||||
// ReSharper disable once CppInconsistentNaming
|
||||
struct lua_State;
|
||||
|
||||
#include <sol/forward.hpp>
|
||||
namespace omath::lua
|
||||
{
|
||||
void register_lib(lua_State* lua_state);
|
||||
class LuaInterpreter final
|
||||
{
|
||||
public:
|
||||
static void register_lib(lua_State* lua_state);
|
||||
|
||||
private:
|
||||
static void register_vec2(sol::table& omath_table);
|
||||
static void register_vec3(sol::table& omath_table);
|
||||
static void register_vec4(sol::table& omath_table);
|
||||
static void register_color(sol::table& omath_table);
|
||||
static void register_triangle(sol::table& omath_table);
|
||||
static void register_shared_types(sol::table& omath_table);
|
||||
static void register_engines(sol::table& omath_table);
|
||||
static void register_pattern_scan(sol::table& omath_table);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -3,432 +3,12 @@
|
||||
//
|
||||
#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/utility/color.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";
|
||||
}
|
||||
|
||||
void register_color(sol::table& omath_table)
|
||||
{
|
||||
omath_table.new_usertype<omath::Color>(
|
||||
"Color",
|
||||
sol::factories(
|
||||
[](float r, float g, float b, float a) { return omath::Color(r, g, b, a); },
|
||||
[]() { return omath::Color(); }),
|
||||
|
||||
"from_rgba", [](uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
|
||||
return omath::Color::from_rgba(r, g, b, a);
|
||||
},
|
||||
"from_hsv", sol::overload(
|
||||
[](float h, float s, float v) { return omath::Color::from_hsv(h, s, v); },
|
||||
[](const omath::Hsv& hsv) { return omath::Color::from_hsv(hsv); }),
|
||||
"red", []() { return omath::Color::red(); },
|
||||
"green", []() { return omath::Color::green(); },
|
||||
"blue", []() { return omath::Color::blue(); },
|
||||
|
||||
"r", sol::property([](const omath::Color& c) { return c.value().x; }),
|
||||
"g", sol::property([](const omath::Color& c) { return c.value().y; }),
|
||||
"b", sol::property([](const omath::Color& c) { return c.value().z; }),
|
||||
"a", sol::property([](const omath::Color& c) { return c.value().w; }),
|
||||
|
||||
"to_hsv", &omath::Color::to_hsv,
|
||||
"set_hue", &omath::Color::set_hue,
|
||||
"set_saturation", &omath::Color::set_saturation,
|
||||
"set_value", &omath::Color::set_value,
|
||||
"blend", &omath::Color::blend,
|
||||
|
||||
sol::meta_function::to_string, &omath::Color::to_string);
|
||||
|
||||
omath_table.new_usertype<omath::Hsv>(
|
||||
"Hsv", sol::constructors<omath::Hsv()>(),
|
||||
"hue", &omath::Hsv::hue,
|
||||
"saturation", &omath::Hsv::saturation,
|
||||
"value", &omath::Hsv::value);
|
||||
}
|
||||
|
||||
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
|
||||
#include "omath/lua/lua.hpp"
|
||||
|
||||
namespace omath::lua
|
||||
{
|
||||
void register_lib(lua_State* lua_state)
|
||||
void LuaInterpreter::register_lib(lua_State* lua_state)
|
||||
{
|
||||
sol::state_view lua(lua_state);
|
||||
|
||||
@@ -438,14 +18,10 @@ namespace omath::lua
|
||||
register_vec3(omath_table);
|
||||
register_vec4(omath_table);
|
||||
register_color(omath_table);
|
||||
register_triangle(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");
|
||||
register_engines(omath_table);
|
||||
register_pattern_scan(omath_table);
|
||||
}
|
||||
} // namespace omath::lua
|
||||
#endif
|
||||
#endif
|
||||
|
||||
46
source/lua/lua_color.cpp
Normal file
46
source/lua/lua_color.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// Created by orange on 07.03.2026.
|
||||
//
|
||||
#ifdef OMATH_ENABLE_LUA
|
||||
#include "omath/lua/lua.hpp"
|
||||
#include <sol/sol.hpp>
|
||||
#include <omath/utility/color.hpp>
|
||||
|
||||
namespace omath::lua
|
||||
{
|
||||
void LuaInterpreter::register_color(sol::table& omath_table)
|
||||
{
|
||||
omath_table.new_usertype<omath::Color>(
|
||||
"Color",
|
||||
sol::factories([](float r, float g, float b, float a) { return omath::Color(r, g, b, a); },
|
||||
[]() { return omath::Color(); }),
|
||||
|
||||
"from_rgba", [](uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
{ return omath::Color::from_rgba(r, g, b, a); }, "from_hsv",
|
||||
sol::overload([](float h, float s, float v) { return omath::Color::from_hsv(h, s, v); },
|
||||
[](const omath::Hsv& hsv) { return omath::Color::from_hsv(hsv); }),
|
||||
"red", []() { return omath::Color::red(); }, "green", []() { return omath::Color::green(); }, "blue",
|
||||
[]() { return omath::Color::blue(); },
|
||||
|
||||
"r", sol::property([](const omath::Color& c) { return c.value().x; }), "g",
|
||||
sol::property([](const omath::Color& c) { return c.value().y; }), "b",
|
||||
sol::property([](const omath::Color& c) { return c.value().z; }), "a",
|
||||
sol::property([](const omath::Color& c) { return c.value().w; }),
|
||||
|
||||
"to_hsv", &omath::Color::to_hsv, "set_hue", &omath::Color::set_hue, "set_saturation",
|
||||
&omath::Color::set_saturation, "set_value", &omath::Color::set_value, "blend", &omath::Color::blend,
|
||||
|
||||
sol::meta_function::to_string, &omath::Color::to_string);
|
||||
|
||||
omath_table.new_usertype<omath::Hsv>(
|
||||
"Hsv", sol::constructors<omath::Hsv()>(), "hue",
|
||||
sol::property([](const omath::Hsv& h) { return h.hue; }, [](omath::Hsv& h, float val) { h.hue = val; }),
|
||||
"saturation",
|
||||
sol::property([](const omath::Hsv& h) { return h.saturation; },
|
||||
[](omath::Hsv& h, float val) { h.saturation = val; }),
|
||||
"value",
|
||||
sol::property([](const omath::Hsv& h) { return h.value; },
|
||||
[](omath::Hsv& h, float val) { h.value = val; }));
|
||||
}
|
||||
} // namespace omath::lua::detail
|
||||
#endif
|
||||
227
source/lua/lua_engines.cpp
Normal file
227
source/lua/lua_engines.cpp
Normal file
@@ -0,0 +1,227 @@
|
||||
//
|
||||
// Created by orange on 07.03.2026.
|
||||
//
|
||||
#ifdef OMATH_ENABLE_LUA
|
||||
#include "omath/lua/lua.hpp"
|
||||
#include <omath/engines/cry_engine/camera.hpp>
|
||||
#include <omath/engines/frostbite_engine/camera.hpp>
|
||||
#include <omath/engines/iw_engine/camera.hpp>
|
||||
#include <omath/engines/opengl_engine/camera.hpp>
|
||||
#include <omath/engines/source_engine/camera.hpp>
|
||||
#include <omath/engines/unity_engine/camera.hpp>
|
||||
#include <omath/engines/unreal_engine/camera.hpp>
|
||||
#include <sol/sol.hpp>
|
||||
#include <string_view>
|
||||
|
||||
namespace
|
||||
{
|
||||
// ---- 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>;
|
||||
|
||||
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()); });
|
||||
}
|
||||
|
||||
// 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 LuaInterpreter::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",
|
||||
sol::property([](const omath::projection::ViewPort& vp) { return vp.m_width; },
|
||||
[](omath::projection::ViewPort& vp, float val) { vp.m_width = val; }),
|
||||
"height",
|
||||
sol::property([](const omath::projection::ViewPort& vp) { return vp.m_height; },
|
||||
[](omath::projection::ViewPort& vp, float val) { vp.m_height = val; }),
|
||||
"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",
|
||||
sol::property([](const ViewAngles90& va) { return va.pitch; },
|
||||
[](ViewAngles90& va, const PitchAngle90& val) { va.pitch = val; }),
|
||||
"yaw",
|
||||
sol::property([](const ViewAngles90& va) { return va.yaw; },
|
||||
[](ViewAngles90& va, const SharedYawRoll& val) { va.yaw = val; }),
|
||||
"roll",
|
||||
sol::property([](const ViewAngles90& va) { return va.roll; },
|
||||
[](ViewAngles90& va, const SharedYawRoll& val) { va.roll = val; }));
|
||||
|
||||
t.new_usertype<ViewAngles89>(
|
||||
"ViewAngles89",
|
||||
sol::factories([](PitchAngle89 p, SharedYawRoll y, SharedYawRoll r) { return ViewAngles89{p, y, r}; }),
|
||||
"pitch",
|
||||
sol::property([](const ViewAngles89& va) { return va.pitch; },
|
||||
[](ViewAngles89& va, const PitchAngle89& val) { va.pitch = val; }),
|
||||
"yaw",
|
||||
sol::property([](const ViewAngles89& va) { return va.yaw; },
|
||||
[](ViewAngles89& va, const SharedYawRoll& val) { va.yaw = val; }),
|
||||
"roll",
|
||||
sol::property([](const ViewAngles89& va) { return va.roll; },
|
||||
[](ViewAngles89& va, const SharedYawRoll& val) { va.roll = val; }));
|
||||
}
|
||||
|
||||
void LuaInterpreter::register_engines(sol::table& 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::detail
|
||||
#endif
|
||||
104
source/lua/lua_pattern_scan.cpp
Normal file
104
source/lua/lua_pattern_scan.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
//
|
||||
// Created by orange on 10.03.2026.
|
||||
//
|
||||
#ifdef OMATH_ENABLE_LUA
|
||||
#include "omath/lua/lua.hpp"
|
||||
#include <format>
|
||||
#include <omath/utility/elf_pattern_scan.hpp>
|
||||
#include <omath/utility/macho_pattern_scan.hpp>
|
||||
#include <omath/utility/pattern_scan.hpp>
|
||||
#include <omath/utility/pe_pattern_scan.hpp>
|
||||
#include <omath/utility/section_scan_result.hpp>
|
||||
#include <sol/sol.hpp>
|
||||
#endif
|
||||
|
||||
namespace omath::lua
|
||||
{
|
||||
void LuaInterpreter::register_pattern_scan(sol::table& omath_table)
|
||||
{
|
||||
omath_table.new_usertype<SectionScanResult>(
|
||||
"SectionScanResult", sol::no_constructor,
|
||||
"virtual_base_addr",
|
||||
sol::property([](const SectionScanResult& r) { return r.virtual_base_addr; }),
|
||||
"raw_base_addr",
|
||||
sol::property([](const SectionScanResult& r) { return r.raw_base_addr; }),
|
||||
"target_offset",
|
||||
sol::property([](const SectionScanResult& r) { return r.target_offset; }),
|
||||
sol::meta_function::to_string,
|
||||
[](const SectionScanResult& r)
|
||||
{
|
||||
return std::format("SectionScanResult(vbase=0x{:X}, raw_base=0x{:X}, offset={})",
|
||||
r.virtual_base_addr, r.raw_base_addr, r.target_offset);
|
||||
});
|
||||
|
||||
// Generic scanner: accepts a Lua string as a byte buffer
|
||||
auto ps_table = omath_table["PatternScanner"].get_or_create<sol::table>();
|
||||
ps_table["scan"] = [](const std::string& data, const std::string& pattern) -> sol::optional<std::ptrdiff_t>
|
||||
{
|
||||
const auto* begin = reinterpret_cast<const std::byte*>(data.data());
|
||||
const auto* end = begin + data.size();
|
||||
const auto* result = PatternScanner::scan_for_pattern(begin, end, pattern);
|
||||
if (result == end)
|
||||
return sol::nullopt;
|
||||
return std::distance(begin, result);
|
||||
};
|
||||
|
||||
auto pe_table = omath_table["PePatternScanner"].get_or_create<sol::table>();
|
||||
pe_table["scan_in_module"] = [](std::uintptr_t base_addr, const std::string& pattern,
|
||||
sol::optional<std::string> section) -> sol::optional<std::uintptr_t>
|
||||
{
|
||||
auto result = PePatternScanner::scan_for_pattern_in_loaded_module(reinterpret_cast<const void*>(base_addr),
|
||||
pattern, section.value_or(".text"));
|
||||
if (!result)
|
||||
return sol::nullopt;
|
||||
return *result;
|
||||
};
|
||||
pe_table["scan_in_file"] = [](const std::string& path, const std::string& pattern,
|
||||
sol::optional<std::string> section) -> sol::optional<SectionScanResult>
|
||||
{
|
||||
auto result = PePatternScanner::scan_for_pattern_in_file(std::filesystem::path(path), pattern,
|
||||
section.value_or(".text"));
|
||||
if (!result)
|
||||
return sol::nullopt;
|
||||
return *result;
|
||||
};
|
||||
auto elf_table = omath_table["ElfPatternScanner"].get_or_create<sol::table>();
|
||||
elf_table["scan_in_module"] = [](std::uintptr_t base_addr, const std::string& pattern,
|
||||
sol::optional<std::string> section) -> sol::optional<std::uintptr_t>
|
||||
{
|
||||
auto result = ElfPatternScanner::scan_for_pattern_in_loaded_module(reinterpret_cast<const void*>(base_addr),
|
||||
pattern, section.value_or(".text"));
|
||||
if (!result)
|
||||
return sol::nullopt;
|
||||
return *result;
|
||||
};
|
||||
elf_table["scan_in_file"] = [](const std::string& path, const std::string& pattern,
|
||||
sol::optional<std::string> section) -> sol::optional<SectionScanResult>
|
||||
{
|
||||
auto result = ElfPatternScanner::scan_for_pattern_in_file(std::filesystem::path(path), pattern,
|
||||
section.value_or(".text"));
|
||||
if (!result)
|
||||
return sol::nullopt;
|
||||
return *result;
|
||||
};
|
||||
auto macho_table = omath_table["MachOPatternScanner"].get_or_create<sol::table>();
|
||||
macho_table["scan_in_module"] = [](std::uintptr_t base_addr, const std::string& pattern,
|
||||
sol::optional<std::string> section) -> sol::optional<std::uintptr_t>
|
||||
{
|
||||
auto result = MachOPatternScanner::scan_for_pattern_in_loaded_module(
|
||||
reinterpret_cast<const void*>(base_addr), pattern, section.value_or("__text"));
|
||||
if (!result)
|
||||
return sol::nullopt;
|
||||
return *result;
|
||||
};
|
||||
macho_table["scan_in_file"] = [](const std::string& path, const std::string& pattern,
|
||||
sol::optional<std::string> section) -> sol::optional<SectionScanResult>
|
||||
{
|
||||
auto result = MachOPatternScanner::scan_for_pattern_in_file(std::filesystem::path(path), pattern,
|
||||
section.value_or("__text"));
|
||||
if (!result)
|
||||
return sol::nullopt;
|
||||
return *result;
|
||||
};
|
||||
}
|
||||
} // namespace omath::lua
|
||||
48
source/lua/lua_triangle.cpp
Normal file
48
source/lua/lua_triangle.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
//
|
||||
// Created by orange on 10.03.2026.
|
||||
//
|
||||
#ifdef OMATH_ENABLE_LUA
|
||||
#include "omath/lua/lua.hpp"
|
||||
#include <sol/sol.hpp>
|
||||
#include <omath/linear_algebra/triangle.hpp>
|
||||
|
||||
namespace omath::lua
|
||||
{
|
||||
void LuaInterpreter::register_triangle(sol::table& omath_table)
|
||||
{
|
||||
using Vec3f = omath::Vector3<float>;
|
||||
using Tri3f = omath::Triangle<Vec3f>;
|
||||
|
||||
omath_table.new_usertype<Tri3f>(
|
||||
"Triangle", sol::constructors<Tri3f(), Tri3f(const Vec3f&, const Vec3f&, const Vec3f&)>(),
|
||||
|
||||
"vertex1",
|
||||
sol::property([](const Tri3f& t) { return t.m_vertex1; },
|
||||
[](Tri3f& t, const Vec3f& v) { t.m_vertex1 = v; }),
|
||||
"vertex2",
|
||||
sol::property([](const Tri3f& t) { return t.m_vertex2; },
|
||||
[](Tri3f& t, const Vec3f& v) { t.m_vertex2 = v; }),
|
||||
"vertex3",
|
||||
sol::property([](const Tri3f& t) { return t.m_vertex3; },
|
||||
[](Tri3f& t, const Vec3f& v) { t.m_vertex3 = v; }),
|
||||
|
||||
"calculate_normal", &Tri3f::calculate_normal,
|
||||
"side_a_length", &Tri3f::side_a_length,
|
||||
"side_b_length", &Tri3f::side_b_length,
|
||||
"side_a_vector", &Tri3f::side_a_vector,
|
||||
"side_b_vector", &Tri3f::side_b_vector,
|
||||
"hypot", &Tri3f::hypot,
|
||||
"is_rectangular", &Tri3f::is_rectangular,
|
||||
"mid_point", &Tri3f::mid_point,
|
||||
|
||||
sol::meta_function::to_string,
|
||||
[](const Tri3f& t)
|
||||
{
|
||||
return std::format("Triangle(({}, {}, {}), ({}, {}, {}), ({}, {}, {}))",
|
||||
t.m_vertex1.x, t.m_vertex1.y, t.m_vertex1.z,
|
||||
t.m_vertex2.x, t.m_vertex2.y, t.m_vertex2.z,
|
||||
t.m_vertex3.x, t.m_vertex3.y, t.m_vertex3.z);
|
||||
});
|
||||
}
|
||||
} // namespace omath::lua
|
||||
#endif
|
||||
54
source/lua/lua_vec2.cpp
Normal file
54
source/lua/lua_vec2.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// Created by orange on 07.03.2026.
|
||||
//
|
||||
#ifdef OMATH_ENABLE_LUA
|
||||
#include "omath/lua/lua.hpp"
|
||||
#include <omath/linear_algebra/vector2.hpp>
|
||||
#include <sol/sol.hpp>
|
||||
|
||||
namespace omath::lua
|
||||
{
|
||||
void LuaInterpreter::register_vec2(sol::table& omath_table)
|
||||
{
|
||||
using Vec2f = omath::Vector2<float>;
|
||||
|
||||
omath_table.new_usertype<Vec2f>(
|
||||
"Vec2", sol::constructors<Vec2f(), Vec2f(float, float)>(),
|
||||
|
||||
"x", sol::property([](const Vec2f& v) { return v.x; }, [](Vec2f& v, const float val) { v.x = val; }),
|
||||
"y", sol::property([](const Vec2f& v) { return v.y; }, [](Vec2f& v, const float val) { v.y = val; }),
|
||||
|
||||
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;
|
||||
});
|
||||
}
|
||||
} // namespace omath::lua::detail
|
||||
#endif
|
||||
81
source/lua/lua_vec3.cpp
Normal file
81
source/lua/lua_vec3.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// Created by orange on 07.03.2026.
|
||||
//
|
||||
#ifdef OMATH_ENABLE_LUA
|
||||
#include "omath/lua/lua.hpp"
|
||||
#include <sol/sol.hpp>
|
||||
#include <omath/linear_algebra/vector3.hpp>
|
||||
|
||||
namespace omath::lua
|
||||
{
|
||||
void LuaInterpreter::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", sol::property([](const Vec3f& v) { return v.x; }, [](Vec3f& v, float val) { v.x = val; }),
|
||||
"y", sol::property([](const Vec3f& v) { return v.y; }, [](Vec3f& v, float val) { v.y = val; }),
|
||||
"z", sol::property([](const Vec3f& v) { return v.z; }, [](Vec3f& v, float val) { v.z = val; }),
|
||||
|
||||
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;
|
||||
});
|
||||
}
|
||||
} // namespace omath::lua::detail
|
||||
#endif
|
||||
62
source/lua/lua_vec4.cpp
Normal file
62
source/lua/lua_vec4.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// Created by orange on 07.03.2026.
|
||||
//
|
||||
#ifdef OMATH_ENABLE_LUA
|
||||
#include "omath/lua/lua.hpp"
|
||||
#include <sol/sol.hpp>
|
||||
#include <omath/linear_algebra/vector4.hpp>
|
||||
|
||||
namespace omath::lua
|
||||
{
|
||||
void LuaInterpreter::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", sol::property([](const Vec4f& v) { return v.x; }, [](Vec4f& v, float val) { v.x = val; }),
|
||||
"y", sol::property([](const Vec4f& v) { return v.y; }, [](Vec4f& v, float val) { v.y = val; }),
|
||||
"z", sol::property([](const Vec4f& v) { return v.z; }, [](Vec4f& v, float val) { v.z = val; }),
|
||||
"w", sol::property([](const Vec4f& v) { return v.w; }, [](Vec4f& v, float val) { v.w = val; }),
|
||||
|
||||
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;
|
||||
});
|
||||
}
|
||||
} // namespace omath::lua::detail
|
||||
#endif
|
||||
@@ -4,8 +4,8 @@ project(unit_tests)
|
||||
|
||||
include(GoogleTest)
|
||||
|
||||
file(GLOB_RECURSE UNIT_TESTS_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
|
||||
add_executable(${PROJECT_NAME} ${UNIT_TESTS_SOURCES})
|
||||
file(GLOB_RECURSE UNIT_TESTS_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/general/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/engines/*.cpp")
|
||||
add_executable(${PROJECT_NAME} ${UNIT_TESTS_SOURCES} main.cpp)
|
||||
|
||||
set_target_properties(
|
||||
${PROJECT_NAME}
|
||||
@@ -22,7 +22,15 @@ 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_LUA)
|
||||
file(GLOB_RECURSE UNIT_TESTS_SOURCES_LUA CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/lua/*.cpp")
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE LUA_SCRIPTS_DIR="${CMAKE_CURRENT_SOURCE_DIR}/lua")
|
||||
target_sources(${PROJECT_NAME} PRIVATE ${UNIT_TESTS_SOURCES_LUA})
|
||||
if (EMSCRIPTEN)
|
||||
target_link_options(${PROJECT_NAME} PRIVATE
|
||||
"SHELL:--embed-file ${CMAKE_CURRENT_SOURCE_DIR}/lua@${CMAKE_CURRENT_SOURCE_DIR}/lua")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(OMATH_ENABLE_COVERAGE)
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/Coverage.cmake)
|
||||
@@ -38,3 +46,4 @@ endif()
|
||||
if(NOT (ANDROID OR IOS OR EMSCRIPTEN))
|
||||
gtest_discover_tests(${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
|
||||
82
tests/lua/triangle_tests.lua
Normal file
82
tests/lua/triangle_tests.lua
Normal file
@@ -0,0 +1,82 @@
|
||||
local function approx(a, b, eps) return math.abs(a - b) < (eps or 1e-5) end
|
||||
|
||||
function Triangle_Constructor_default()
|
||||
local t = omath.Triangle.new()
|
||||
assert(t.vertex1.x == 0 and t.vertex1.y == 0 and t.vertex1.z == 0)
|
||||
assert(t.vertex2.x == 0 and t.vertex2.y == 0 and t.vertex2.z == 0)
|
||||
assert(t.vertex3.x == 0 and t.vertex3.y == 0 and t.vertex3.z == 0)
|
||||
end
|
||||
|
||||
function Triangle_Constructor_vertices()
|
||||
local v1 = omath.Vec3.new(1, 0, 0)
|
||||
local v2 = omath.Vec3.new(0, 1, 0)
|
||||
local v3 = omath.Vec3.new(0, 0, 1)
|
||||
local t = omath.Triangle.new(v1, v2, v3)
|
||||
assert(t.vertex1.x == 1 and t.vertex1.y == 0 and t.vertex1.z == 0)
|
||||
assert(t.vertex2.x == 0 and t.vertex2.y == 1 and t.vertex2.z == 0)
|
||||
assert(t.vertex3.x == 0 and t.vertex3.y == 0 and t.vertex3.z == 1)
|
||||
end
|
||||
|
||||
function Triangle_Vertex_mutation()
|
||||
local t = omath.Triangle.new()
|
||||
t.vertex1 = omath.Vec3.new(5, 6, 7)
|
||||
assert(t.vertex1.x == 5 and t.vertex1.y == 6 and t.vertex1.z == 7)
|
||||
end
|
||||
|
||||
-- Right triangle: v1=(0,3,0), v2=(0,0,0), v3=(4,0,0) — sides 3, 4, hypot 5
|
||||
function Triangle_SideALength()
|
||||
local t = omath.Triangle.new(omath.Vec3.new(0, 3, 0), omath.Vec3.new(0, 0, 0), omath.Vec3.new(4, 0, 0))
|
||||
assert(approx(t:side_a_length(), 3.0))
|
||||
end
|
||||
|
||||
function Triangle_SideBLength()
|
||||
local t = omath.Triangle.new(omath.Vec3.new(0, 3, 0), omath.Vec3.new(0, 0, 0), omath.Vec3.new(4, 0, 0))
|
||||
assert(approx(t:side_b_length(), 4.0))
|
||||
end
|
||||
|
||||
function Triangle_Hypot()
|
||||
local t = omath.Triangle.new(omath.Vec3.new(0, 3, 0), omath.Vec3.new(0, 0, 0), omath.Vec3.new(4, 0, 0))
|
||||
assert(approx(t:hypot(), 5.0))
|
||||
end
|
||||
|
||||
function Triangle_SideAVector()
|
||||
local t = omath.Triangle.new(omath.Vec3.new(0, 3, 0), omath.Vec3.new(0, 0, 0), omath.Vec3.new(4, 0, 0))
|
||||
local a = t:side_a_vector()
|
||||
assert(approx(a.x, 0) and approx(a.y, 3) and approx(a.z, 0))
|
||||
end
|
||||
|
||||
function Triangle_SideBVector()
|
||||
local t = omath.Triangle.new(omath.Vec3.new(0, 3, 0), omath.Vec3.new(0, 0, 0), omath.Vec3.new(4, 0, 0))
|
||||
local b = t:side_b_vector()
|
||||
assert(approx(b.x, 4) and approx(b.y, 0) and approx(b.z, 0))
|
||||
end
|
||||
|
||||
function Triangle_IsRectangular_true()
|
||||
local t = omath.Triangle.new(omath.Vec3.new(0, 3, 0), omath.Vec3.new(0, 0, 0), omath.Vec3.new(4, 0, 0))
|
||||
assert(t:is_rectangular() == true)
|
||||
end
|
||||
|
||||
function Triangle_IsRectangular_false()
|
||||
-- equilateral-ish triangle, not rectangular
|
||||
local t = omath.Triangle.new(omath.Vec3.new(0, 1, 0), omath.Vec3.new(-1, 0, 0), omath.Vec3.new(1, 0, 0))
|
||||
assert(t:is_rectangular() == false)
|
||||
end
|
||||
|
||||
function Triangle_MidPoint()
|
||||
local t = omath.Triangle.new(omath.Vec3.new(3, 0, 0), omath.Vec3.new(0, 3, 0), omath.Vec3.new(0, 0, 3))
|
||||
local m = t:mid_point()
|
||||
assert(approx(m.x, 1.0) and approx(m.y, 1.0) and approx(m.z, 1.0))
|
||||
end
|
||||
|
||||
function Triangle_CalculateNormal()
|
||||
-- flat triangle in XY plane — normal should be (0, 0, 1)
|
||||
local t = omath.Triangle.new(omath.Vec3.new(0, 1, 0), omath.Vec3.new(0, 0, 0), omath.Vec3.new(1, 0, 0))
|
||||
local n = t:calculate_normal()
|
||||
assert(approx(n.x, 0) and approx(n.y, 0) and approx(n.z, 1))
|
||||
end
|
||||
|
||||
function Triangle_ToString()
|
||||
local t = omath.Triangle.new(omath.Vec3.new(1, 0, 0), omath.Vec3.new(0, 1, 0), omath.Vec3.new(0, 0, 1))
|
||||
local s = tostring(t)
|
||||
assert(s == "Triangle((1, 0, 0), (0, 1, 0), (0, 0, 1))")
|
||||
end
|
||||
@@ -14,7 +14,7 @@ protected:
|
||||
{
|
||||
L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
omath::lua::register_lib(L);
|
||||
omath::lua::LuaInterpreter::register_lib(L);
|
||||
if (luaL_dofile(L, LUA_SCRIPTS_DIR "/color_tests.lua") != LUA_OK)
|
||||
FAIL() << lua_tostring(L, -1);
|
||||
}
|
||||
@@ -14,7 +14,7 @@ protected:
|
||||
{
|
||||
L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
omath::lua::register_lib(L);
|
||||
omath::lua::LuaInterpreter::register_lib(L);
|
||||
if (luaL_dofile(L, LUA_SCRIPTS_DIR "/source_engine_tests.lua") != LUA_OK)
|
||||
FAIL() << lua_tostring(L, -1);
|
||||
}
|
||||
47
tests/lua/unit_test_lua_triangle.cpp
Normal file
47
tests/lua/unit_test_lua_triangle.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// Created by orange on 10.03.2026.
|
||||
//
|
||||
#include <gtest/gtest.h>
|
||||
#include <lua.hpp>
|
||||
#include <omath/lua/lua.hpp>
|
||||
|
||||
class LuaTriangle : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
lua_State* L = nullptr;
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
omath::lua::LuaInterpreter::register_lib(L);
|
||||
if (luaL_dofile(L, LUA_SCRIPTS_DIR "/triangle_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(LuaTriangle, Constructor_default) { check("Triangle_Constructor_default"); }
|
||||
TEST_F(LuaTriangle, Constructor_vertices) { check("Triangle_Constructor_vertices"); }
|
||||
TEST_F(LuaTriangle, Vertex_mutation) { check("Triangle_Vertex_mutation"); }
|
||||
TEST_F(LuaTriangle, SideALength) { check("Triangle_SideALength"); }
|
||||
TEST_F(LuaTriangle, SideBLength) { check("Triangle_SideBLength"); }
|
||||
TEST_F(LuaTriangle, Hypot) { check("Triangle_Hypot"); }
|
||||
TEST_F(LuaTriangle, SideAVector) { check("Triangle_SideAVector"); }
|
||||
TEST_F(LuaTriangle, SideBVector) { check("Triangle_SideBVector"); }
|
||||
TEST_F(LuaTriangle, IsRectangular_true) { check("Triangle_IsRectangular_true"); }
|
||||
TEST_F(LuaTriangle, IsRectangular_false) { check("Triangle_IsRectangular_false"); }
|
||||
TEST_F(LuaTriangle, MidPoint) { check("Triangle_MidPoint"); }
|
||||
TEST_F(LuaTriangle, CalculateNormal) { check("Triangle_CalculateNormal"); }
|
||||
TEST_F(LuaTriangle, ToString) { check("Triangle_ToString"); }
|
||||
@@ -14,7 +14,7 @@ protected:
|
||||
{
|
||||
L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
omath::lua::register_lib(L);
|
||||
omath::lua::LuaInterpreter::register_lib(L);
|
||||
if (luaL_dofile(L, LUA_SCRIPTS_DIR "/vec2_tests.lua") != LUA_OK)
|
||||
FAIL() << lua_tostring(L, -1);
|
||||
}
|
||||
@@ -14,7 +14,7 @@ protected:
|
||||
{
|
||||
L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
omath::lua::register_lib(L);
|
||||
omath::lua::LuaInterpreter::register_lib(L);
|
||||
if (luaL_dofile(L, LUA_SCRIPTS_DIR "/vec3_tests.lua") != LUA_OK)
|
||||
FAIL() << lua_tostring(L, -1);
|
||||
}
|
||||
@@ -14,7 +14,7 @@ protected:
|
||||
{
|
||||
L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
omath::lua::register_lib(L);
|
||||
omath::lua::LuaInterpreter::register_lib(L);
|
||||
if (luaL_dofile(L, LUA_SCRIPTS_DIR "/vec4_tests.lua") != LUA_OK)
|
||||
FAIL() << lua_tostring(L, -1);
|
||||
}
|
||||
Reference in New Issue
Block a user