add swig generation to lib_comnmon

This commit is contained in:
Walter Julius Hennecke 2020-02-07 20:28:46 +01:00
parent 268b4b0942
commit 42251d4180
22 changed files with 812 additions and 298 deletions

2
.gitignore vendored
View file

@ -696,3 +696,5 @@ ASALocalRun/
healthchecksdb
# End of https://www.gitignore.io/api/clion,macos,linux,python,eclipse,windows,kdevelop4,visualstudio,visualstudiocode
*_wrap.cxx

View file

@ -4,7 +4,7 @@ set(CMAKE_CXX_STANDARD 17)
file(GLOB BASE_GAME_SRC "*.h" "*.c" "*.cpp")
add_library(base_game OBJECT ${BASE_GAME_SRC})
add_library(base_game STATIC ${BASE_GAME_SRC})
target_compile_options(base_game PUBLIC -Wno-write-strings)
target_include_directories(base_game PUBLIC ..)
set_property(TARGET base_game PROPERTY POSITION_INDEPENDENT_CODE ON)

View file

@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 17)
add_library(catch2_main OBJECT runner.cpp)
set_property(TARGET catch2_main PROPERTY POSITION_INDEPENDENT_CODE ON)
add_library(catch2_main STATIC runner.cpp)
#set_property(TARGET catch2_main PROPERTY POSITION_INDEPENDENT_CODE ON)
add_library(catch2_symbols OBJECT UnitTest.cpp)
add_library(catch2_symbols STATIC UnitTest.cpp)
set_property(TARGET catch2_symbols PROPERTY POSITION_INDEPENDENT_CODE ON)

View file

@ -2,13 +2,44 @@ cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 17)
# check for swig
find_package(SWIG 4.0)
if (NOT ${SWIG_FOUND})
message(STATUS test)
endif (NOT ${SWIG_FOUND})
# setup swig generation
file(GLOB_RECURSE SWIG_INTERFACES "${CMAKE_CURRENT_SOURCE_DIR}/*.i")
foreach (SWIG_INTERFACE ${SWIG_INTERFACES})
execute_process(
COMMAND ${SWIG_EXECUTABLE} -c++ -lua ${SWIG_INTERFACE}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
RESULT_VARIABLE SWIG_RESULT
ERROR_VARIABLE SWIG_ERROR
)
if (NOT ${SWIG_RESULT} EQUAL "0")
message(FATAL_ERROR ${SWIG_ERROR})
endif (NOT ${SWIG_RESULT} EQUAL "0")
get_filename_component(SWIG_DIR ${SWIG_INTERFACE} DIRECTORY)
get_filename_component(SWIG_BASENAME ${SWIG_INTERFACE} NAME_WE)
add_custom_command(
OUTPUT ${SWIG_DIR}/${SWIG_BASENAME}_wrap.cxx
COMMAND ${SWIG_EXECUTABLE} -c++ -lua ${SWIG_INTERFACE}
DEPENDS ${SWIG_INTERFACE}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
set(SWIG_IMPL_SOURCES ${SWIG_IMPL_SOURCES} ${SWIG_DIR}/${SWIG_BASENAME}.h ${SWIG_DIR}/${SWIG_BASENAME}.cpp)
endforeach (SWIG_INTERFACE ${SWIG_INTERFACES})
file(GLOB_RECURSE SWIG_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*_wrap.cxx")
file(GLOB COMMON_SRC "*.h" "*.c" "*.cpp")
add_library(common OBJECT ${COMMON_SRC})
add_library(common STATIC ${COMMON_SRC} ${SWIG_SOURCES})
target_include_directories(common PUBLIC ..)
set_property(TARGET common PROPERTY POSITION_INDEPENDENT_CODE ON)
add_executable(unittest_common ${COMMON_SRC} $<TARGET_OBJECTS:catch2_main>)
add_executable(unittest_common ${COMMON_SRC})
target_link_libraries(unittest_common PUBLIC catch2_main)
target_include_directories(unittest_common PUBLIC ..)
target_compile_definitions(unittest_common PUBLIC UNIT_TEST)
set_property(TARGET unittest_common PROPERTY POSITION_INDEPENDENT_CODE ON)

View file

@ -1,5 +1,70 @@
#include "Color.h"
namespace common {
const Color Color::None = Color{0.0f, 0.0f, 0.0f, 0.0f};
const Color Color::Black = Color{0, 0, 0, 1};
const Color Color::Red = Color{1, 0, 0, 1};
const Color Color::Green = Color{0, 1, 0, 1};
const Color Color::Blue = Color{0, 0, 1, 1};
const Color Color::Yellow = Color{1, 1, 0, 1};
const Color Color::Magenta = Color{1, 0, 1, 1};
const Color Color::Cyan = Color{0, 1, 1, 1};
const Color Color::Teal = Color{0.071f, 0.271f, 0.29f, 1};
const Color Color::Gold = Color{0.529f, 0.373f, 0.017f, 1};
const Color Color::White = Color{1, 1, 1, 1};
const Color Color::LightGrey = Color{0.75f, 0.75f, 0.75f, 1};
const Color Color::MediumGrey = Color{0.50f, 0.50f, 0.50f, 1};
const Color Color::DarkGrey = Color{0.25f, 0.25f, 0.25f, 1};
const Color Color::DarkGrey2 = Color{0.15f, 0.15f, 0.15f, 1};
const Color Color::VeryLightOrange = Color{0.688f, 0.797f, 1, 1};
const Color Color::LightOrange = Color{0.688f, 0.797f, 1, 1};
const Color Color::DarkOrange = Color{0.620f, 0.710f, 0.894f, 1};
const Color Color::VeryDarkOrange = Color{0.463f, 0.525f, 0.671f, 1};
const Color Color::VeryLightBlue = Color{0.616f, 0.718f, 0.898f, 1};
const Color Color::LightBlue = Color{0.286f, 0.506f, 0.898f, 1};
const Color Color::DarkBlue = Color{0.082f, 0.388f, 0.898f, 1};
const Color Color::VeryDarkBlue = Color{0.063f, 0.278f, 0.514f, 1};
const Color Color::VeryLightBlue2 = Color{0.302f, 0.380f, 0.612f, 1};
const Color Color::LightBlue2 = Color{0.196f, 0.314f, 0.612f, 1};
const Color Color::DarkBlue2 = Color{0.060f, 0.227f, 0.611f, 1};
const Color Color::VeryDarkBlue2 = Color{0.043f, 0.161f, 0.459f, 1};
const Color Color::VeryLightBrown = Color{0.082f, 0.388f, 0.898f, 1};
const Color Color::LightBrown = Color{0.082f, 0.388f, 0.898f, 1};
const Color Color::DarkBrown = Color{0.078f, 0.320f, 0.813f, 1};
const Color Color::VeryDarkBrown = Color{0.060f, 0.227f, 0.611f, 1};
const Color Color::VeryLightGold = Color{1, 0.784f, 0.365f, 1};
const Color Color::LightGold = Color{1, 0.706f, 0.153f, 1};
const Color Color::DarkGold = Color{0.733f, 0.514f, 0.086f, 1};
const Color Color::VeryDarkGold = Color{0.549f, 0.384f, 0.063f, 1};
const Color Color::VeryLightPurple = Color{0.688f, 0.797f, 1, 1};
const Color Color::LightPurple = Color{0.688f, 0.797f, 1, 1};
const Color Color::DarkPurple = Color{0.313f, 0.578f, 1, 1};
const Color Color::VeryDarkPurple = Color{0.031f, 0.110f, 0.341f, 1};
const Color Color::VeryLightPurple2 = Color{0.688f, 0.797f, 1, 1};
const Color Color::LightPurple2 = Color{0.688f, 0.797f, 1, 1};
const Color Color::DarkPurple2 = Color{0.688f, 0.797f, 1, 1};
const Color Color::VeryDarkPurple2 = Color{0.031f, 0.110f, 0.341f, 1};
const Color Color::VeryLightPurple3 = Color{0.686f, 0.808f, 0.1f, 1};
const Color Color::LightPurple3 = Color{0.188f, 0.494f, 1, 1};
const Color Color::DarkPurple3 = Color{0.094f, 0.471f, 1, 1};
const Color Color::VeryDarkPurple3 = Color{0.067f, 0.325f, 0.749f, 1};
const Color Color::VeryLightRed = Color{1, 0.612f, 0.325f, 1};
const Color Color::LightRed = Color{1, 0.478f, 0.098f, 1};
const Color Color::DarkRed = Color{1, 0.438f, 0, 1};
const Color Color::VeryDarkRed = Color{0.784f, 0.329f, 0, 1};
} // namespace common
#include <catch2/catch.hpp>
static_assert(common::detail::color_check_bounds(-0.1f) == 0.0f);
@ -20,32 +85,32 @@ static_assert(common::detail::color_check_bounds(0) == 0.0f);
static_assert(common::detail::color_check_bounds(255) == 255.0f);
static_assert(common::detail::color_check_bounds(43) == 43.0f);
static_assert(common::Color(1.0f).r_ == 1.0f);
static_assert(common::Color(1.0f).g_ == 0.0f);
static_assert(common::Color(1.0f).b_ == 0.0f);
static_assert(common::Color(1.0f).a_ == 0.0f);
static_assert(common::Color(1.0f).r == 1.0f);
static_assert(common::Color(1.0f).g == 0.0f);
static_assert(common::Color(1.0f).b == 0.0f);
static_assert(common::Color(1.0f).a == 0.0f);
static_assert(common::Color(1.0f, 2.4f).r_ == 1.0f);
static_assert(common::Color(1.0f, 2.4f).g_ == 2.4f);
static_assert(common::Color(1.0f, 2.4f).b_ == 0.0f);
static_assert(common::Color(1.0f, 2.4f).a_ == 0.0f);
static_assert(common::Color(1.0f, 2.4f).r == 1.0f);
static_assert(common::Color(1.0f, 2.4f).g == 2.4f);
static_assert(common::Color(1.0f, 2.4f).b == 0.0f);
static_assert(common::Color(1.0f, 2.4f).a == 0.0f);
static_assert(common::Color(1.0f, 2.4f, 3.5f).r_ == 1.0f);
static_assert(common::Color(1.0f, 2.4f, 3.5f).g_ == 2.4f);
static_assert(common::Color(1.0f, 2.4f, 3.5f).b_ == 3.5f);
static_assert(common::Color(1.0f, 2.4f, 3.5f).a_ == 0.0f);
static_assert(common::Color(1.0f, 2.4f, 3.5f).r == 1.0f);
static_assert(common::Color(1.0f, 2.4f, 3.5f).g == 2.4f);
static_assert(common::Color(1.0f, 2.4f, 3.5f).b == 3.5f);
static_assert(common::Color(1.0f, 2.4f, 3.5f).a == 0.0f);
static_assert(common::Color(1.0f, 2.4f, 3.5f, 54.43f).r_ == 1.0f);
static_assert(common::Color(1.0f, 2.4f, 3.5f, 54.43f).g_ == 2.4f);
static_assert(common::Color(1.0f, 2.4f, 3.5f, 54.43f).b_ == 3.5f);
static_assert(common::Color(1.0f, 2.4f, 3.5f, 54.43f).a_ == 54.43f);
static_assert(common::Color(1.0f, 2.4f, 3.5f, 54.43f).r == 1.0f);
static_assert(common::Color(1.0f, 2.4f, 3.5f, 54.43f).g == 2.4f);
static_assert(common::Color(1.0f, 2.4f, 3.5f, 54.43f).b == 3.5f);
static_assert(common::Color(1.0f, 2.4f, 3.5f, 54.43f).a == 54.43f);
TEST_CASE("default construct", "[common::Color]") {
auto color = common::Color();
REQUIRE_THAT(color.r_, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.g_, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.b_, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.a_, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.r, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.g, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.b, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.a, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.values[0], Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.values[1], Catch::WithinAbs(0.0f, 0.0001));
@ -55,44 +120,44 @@ TEST_CASE("default construct", "[common::Color]") {
TEST_CASE("construct from numbers", "[common::Color]") {
auto color = common::Color(42);
REQUIRE_THAT(color.r_, Catch::WithinAbs(42.0f, 0.0001));
REQUIRE_THAT(color.g_, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.b_, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.a_, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.r, Catch::WithinAbs(42.0f, 0.0001));
REQUIRE_THAT(color.g, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.b, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.a, Catch::WithinAbs(0.0f, 0.0001));
color = common::Color(42, -42);
REQUIRE_THAT(color.r_, Catch::WithinAbs(42.0f, 0.0001));
REQUIRE_THAT(color.g_, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.b_, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.a_, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.r, Catch::WithinAbs(42.0f, 0.0001));
REQUIRE_THAT(color.g, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.b, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.a, Catch::WithinAbs(0.0f, 0.0001));
color = common::Color(42, -42, 24, -22);
REQUIRE_THAT(color.r_, Catch::WithinAbs(42.0f, 0.0001));
REQUIRE_THAT(color.g_, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.b_, Catch::WithinAbs(24.0f, 0.0001));
REQUIRE_THAT(color.a_, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.r, Catch::WithinAbs(42.0f, 0.0001));
REQUIRE_THAT(color.g, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.b, Catch::WithinAbs(24.0f, 0.0001));
REQUIRE_THAT(color.a, Catch::WithinAbs(0.0f, 0.0001));
color = common::Color(42.3, -42, 24, -22);
REQUIRE_THAT(color.r_, Catch::WithinAbs(42.3f, 0.0001));
REQUIRE_THAT(color.g_, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.b_, Catch::WithinAbs(24.0f, 0.0001));
REQUIRE_THAT(color.a_, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.r, Catch::WithinAbs(42.3f, 0.0001));
REQUIRE_THAT(color.g, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.b, Catch::WithinAbs(24.0f, 0.0001));
REQUIRE_THAT(color.a, Catch::WithinAbs(0.0f, 0.0001));
color = common::Color(42.3, -42.2, 24, -22);
REQUIRE_THAT(color.r_, Catch::WithinAbs(42.3f, 0.0001));
REQUIRE_THAT(color.g_, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.b_, Catch::WithinAbs(24.0f, 0.0001));
REQUIRE_THAT(color.a_, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.r, Catch::WithinAbs(42.3f, 0.0001));
REQUIRE_THAT(color.g, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.b, Catch::WithinAbs(24.0f, 0.0001));
REQUIRE_THAT(color.a, Catch::WithinAbs(0.0f, 0.0001));
color = common::Color(42.3, -42.2, 24, -22.7f);
REQUIRE_THAT(color.r_, Catch::WithinAbs(42.3f, 0.0001));
REQUIRE_THAT(color.g_, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.b_, Catch::WithinAbs(24.0f, 0.0001));
REQUIRE_THAT(color.a_, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.r, Catch::WithinAbs(42.3f, 0.0001));
REQUIRE_THAT(color.g, Catch::WithinAbs(0.0f, 0.0001));
REQUIRE_THAT(color.b, Catch::WithinAbs(24.0f, 0.0001));
REQUIRE_THAT(color.a, Catch::WithinAbs(0.0f, 0.0001));
color = common::Color(42.3, 42.2, 24, 22.7f);
REQUIRE_THAT(color.r_, Catch::WithinAbs(42.3f, 0.0001));
REQUIRE_THAT(color.g_, Catch::WithinAbs(42.2f, 0.0001));
REQUIRE_THAT(color.b_, Catch::WithinAbs(24.0f, 0.0001));
REQUIRE_THAT(color.a_, Catch::WithinAbs(22.7f, 0.0001));
REQUIRE_THAT(color.r, Catch::WithinAbs(42.3f, 0.0001));
REQUIRE_THAT(color.g, Catch::WithinAbs(42.2f, 0.0001));
REQUIRE_THAT(color.b, Catch::WithinAbs(24.0f, 0.0001));
REQUIRE_THAT(color.a, Catch::WithinAbs(22.7f, 0.0001));
}

View file

@ -16,7 +16,7 @@ static constexpr float color_check_bounds(R value) {
class Color {
public:
constexpr Color() noexcept : r_{0.f}, g_{0.f}, b_{0.f}, a_{0.f} {}
constexpr Color() noexcept : r{0.f}, g{0.f}, b{0.f}, a{0.f} {}
template <
typename R, typename G = float, typename B = float, typename A = float,
@ -24,9 +24,8 @@ public:
std::is_convertible_v<R, float> && std::is_convertible_v<G, float> &&
std::is_convertible_v<B, float> && std::is_convertible_v<A, float>>>
constexpr explicit Color(R _r, G _g = 0, B _b = 0, A _a = 0) noexcept
: r_{detail::color_check_bounds(_r)}, g_{detail::color_check_bounds(_g)},
b_{detail::color_check_bounds(_b)}, a_{detail::color_check_bounds(_a)} {
}
: r{detail::color_check_bounds(_r)}, g{detail::color_check_bounds(_g)},
b{detail::color_check_bounds(_b)}, a{detail::color_check_bounds(_a)} {}
constexpr Color(const Color &) = default;
constexpr Color(Color &&) = default;
@ -34,17 +33,78 @@ public:
constexpr Color &operator=(const Color &) = default;
constexpr Color &operator=(Color &&) = default;
constexpr Color(vec4_t v) noexcept : r_{v[0]}, g_{v[1]}, b_{v[2]}, a_{v[3]} {}
constexpr Color(vec4_t v) noexcept : r{v[0]}, g{v[1]}, b{v[2]}, a{v[3]} {}
union {
vec4_t values{};
struct {
float r_;
float g_;
float b_;
float a_;
float r;
float g;
float b;
float a;
};
};
static const Color None;
static const Color Black;
static const Color Red;
static const Color Green;
static const Color Blue;
static const Color Yellow;
static const Color Magenta;
static const Color Cyan;
static const Color Teal;
static const Color Gold;
static const Color White;
static const Color LightGrey;
static const Color MediumGrey;
static const Color DarkGrey;
static const Color DarkGrey2;
static const Color VeryLightOrange;
static const Color LightOrange;
static const Color DarkOrange;
static const Color VeryDarkOrange;
static const Color VeryLightBlue;
static const Color LightBlue;
static const Color DarkBlue;
static const Color VeryDarkBlue;
static const Color VeryLightBlue2;
static const Color LightBlue2;
static const Color DarkBlue2;
static const Color VeryDarkBlue2;
static const Color VeryLightBrown;
static const Color LightBrown;
static const Color DarkBrown;
static const Color VeryDarkBrown;
static const Color VeryLightGold;
static const Color LightGold;
static const Color DarkGold;
static const Color VeryDarkGold;
static const Color VeryLightPurple;
static const Color LightPurple;
static const Color DarkPurple;
static const Color VeryDarkPurple;
static const Color VeryLightPurple2;
static const Color LightPurple2;
static const Color DarkPurple2;
static const Color VeryDarkPurple2;
static const Color VeryLightPurple3;
static const Color LightPurple3;
static const Color DarkPurple3;
static const Color VeryDarkPurple3;
static const Color VeryLightRed;
static const Color LightRed;
static const Color DarkRed;
static const Color VeryDarkRed;
};
} // namespace common

83
code/common/Color.i Normal file
View file

@ -0,0 +1,83 @@
%module common
%{
#include "Color.h"
%}
namespace common {
class Color {
public:
constexpr Color();
constexpr explicit Color(float _r, float _g = 0, float _b = 0, float _a = 0);
constexpr Color &operator=(const Color &);
constexpr Color &operator=(Color &&);
float r;
float g;
float b;
float a;
static const Color None;
static const Color Black;
static const Color Red;
static const Color Green;
static const Color Blue;
static const Color Yellow;
static const Color Magenta;
static const Color Cyan;
static const Color Teal;
static const Color Gold;
static const Color White;
static const Color LightGrey;
static const Color MediumGrey;
static const Color DarkGrey;
static const Color DarkGrey2;
static const Color VeryLightOrange;
static const Color LightOrange;
static const Color DarkOrange;
static const Color VeryDarkOrange;
static const Color VeryLightBlue;
static const Color LightBlue;
static const Color DarkBlue;
static const Color VeryDarkBlue;
static const Color VeryLightBlue2;
static const Color LightBlue2;
static const Color DarkBlue2;
static const Color VeryDarkBlue2;
static const Color VeryLightBrown;
static const Color LightBrown;
static const Color DarkBrown;
static const Color VeryDarkBrown;
static const Color VeryLightGold;
static const Color LightGold;
static const Color DarkGold;
static const Color VeryDarkGold;
static const Color VeryLightPurple;
static const Color LightPurple;
static const Color DarkPurple;
static const Color VeryDarkPurple;
static const Color VeryLightPurple2;
static const Color LightPurple2;
static const Color DarkPurple2;
static const Color VeryDarkPurple2;
static const Color VeryLightPurple3;
static const Color LightPurple3;
static const Color DarkPurple3;
static const Color VeryDarkPurple3;
static const Color VeryLightRed;
static const Color LightRed;
static const Color DarkRed;
static const Color VeryDarkRed;
};
} // namespace common

View file

@ -4,14 +4,14 @@
namespace common {
float rsqrt(float number) {
float x2 = number * 0.5F;
float y = number;
double rsqrt(double number) {
float x2 = static_cast<float>(number) * 0.5F;
float y = static_cast<float>(number);
long i = *(long *)&y;
i = 0x5f3759df - (i >> 1);
y = *(float *)&i;
y = y * (1.5F - (x2 * y * y));
return y;
return static_cast<double>(y);
}
} // namespace common
@ -19,3 +19,23 @@ float rsqrt(float number) {
TEST_CASE("math_rsqrt") {
REQUIRE(common::rsqrt(4) == Approx(0.5f).epsilon(0.01));
}
static_assert(common::equal(1.0f, 1.0f));
static_assert(common::equal(-1.0f, -1.0f));
static_assert(common::equal(42.231f, 42.231f));
static_assert(!common::equal(1.0f, -1.0f));
static_assert(!common::equal(1.0001f, 1.0002f));
static_assert(!common::equal(1.0000f, 1.0001f));
static_assert(!common::equal(1.1f, 1.2f, 0.1));
static_assert(!common::equal(1.1f, 1.2f, 0.01));
TEST_CASE("equal") {
REQUIRE(common::equal(1.0f, 1.0f));
REQUIRE(common::equal(-1.0f, -1.0f));
REQUIRE(common::equal(42.231f, 42.231f));
REQUIRE(!common::equal(1.0f, -1.0f));
REQUIRE(!common::equal(1.0001f, 1.0002f));
REQUIRE(!common::equal(1.0000f, 1.0001f));
REQUIRE(!common::equal(1.1f, 1.2f, 0.1));
REQUIRE(!common::equal(1.1f, 1.2f, 0.01));
}

View file

@ -1,8 +1,13 @@
#pragma once
#include <cmath>
namespace common {
float rsqrt(float number);
double rsqrt(double number);
constexpr bool equal(double a, double b, double delta = 0.0001) {
return std::abs(a - b) <= delta;
}
}; // namespace common

13
code/common/Math.i Normal file
View file

@ -0,0 +1,13 @@
%module common
%{
#include "Math.h"
%}
namespace common {
double rsqrt(double number);
constexpr bool equal(double a, double b);
constexpr bool equal(double a, double b, double delta);
}; // namespace common

30
code/common/Point2d.i Normal file
View file

@ -0,0 +1,30 @@
%module common
%{
#include "Point2d.h"
%}
namespace common {
class Point2dI {
public:
Point2dI(int32_t x, int32_t y);
Point2dI(double x, double y);
Point2dI(int32_t x, double y);
Point2dI(double y, int32_t);
int x_;
int y_;
};
class Point2dD {
public:
Point2dD(int32_t x, int32_t y);
Point2dD(double x, double y);
Point2dD(int32_t x, double y);
Point2dD(double y, int32_t);
double x_;
double y_;
};
} // namespace common

View file

@ -3,16 +3,16 @@
TEST_CASE("random_int", "[common::getRandom]") {
for (auto x = 0; x < 1000; x++) {
auto i = common::getRandom<int>();
auto a = common::getRandom<int>();
auto i = common::getRandomInt<int>();
auto a = common::getRandomInt<int>();
REQUIRE(i != a);
}
}
TEST_CASE("random_int_limit", "[common::getRandom]") {
for (auto j = 0; j < 10; j++) {
auto min = common::getRandom<int>();
auto max = common::getRandom<int>();
auto min = common::getRandomInt<int>();
auto max = common::getRandomInt<int>();
if (min > max) {
std::swap(min, max);
}
@ -25,7 +25,7 @@ TEST_CASE("random_int_limit", "[common::getRandom]") {
}
for (auto x = 0; x < 100; x++) {
auto a = common::getRandom(min, max);
auto a = common::getRandomInt(min, max);
REQUIRE(a >= min);
REQUIRE(a <= max);
}
@ -34,16 +34,16 @@ TEST_CASE("random_int_limit", "[common::getRandom]") {
TEST_CASE("random_real", "[common::getRandom]") {
for (auto x = 0; x < 1000; x++) {
auto a = common::getRandom<double>();
auto b = common::getRandom<double>();
auto a = common::getRandomDouble<double>();
auto b = common::getRandomDouble<double>();
REQUIRE(a != b);
}
}
TEST_CASE("random_real_limit", "[common::getRandom]") {
for (auto j = 0; j < 10; j++) {
auto min = common::getRandom<double>();
auto max = common::getRandom<double>();
auto min = common::getRandomDouble<double>();
auto max = common::getRandomDouble<double>();
if (min > max) {
std::swap(min, max);
}
@ -56,7 +56,7 @@ TEST_CASE("random_real_limit", "[common::getRandom]") {
}
for (auto x = 0; x < 100; x++) {
auto a = common::getRandom(min, max);
auto a = common::getRandomDouble(min, max);
REQUIRE(a >= min);
REQUIRE(a <= max);
}

View file

@ -5,22 +5,52 @@
namespace common {
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
T getRandom(T min = std::numeric_limits<T>::min(),
T max = std::numeric_limits<T>::max()) {
T getRandomInt(T min, T max) {
static auto seeder = std::random_device();
static auto engine = std::mt19937_64(seeder());
std::uniform_int_distribution<T> dist(min, max);
return dist(engine);
}
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
T getRandomInt(T min) {
return getRandomInt(min, std::numeric_limits<T>::max());
}
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
T getRandomInt() {
return getRandomInt(std::numeric_limits<T>::min(),
std::numeric_limits<T>::max());
}
int getRandomInt() {
return getRandomInt<int>();
}
template <typename T, bool Dummy = true,
typename = std::enable_if_t<std::is_floating_point_v<T> && Dummy>>
T getRandom(T min = std::numeric_limits<T>::min(),
T max = std::numeric_limits<T>::max()) {
T getRandomDouble(T min, T max) {
static auto seeder = std::random_device();
static auto engine = std::mt19937_64(seeder());
std::uniform_real_distribution<T> dist(min, max);
return dist(engine);
}
template <typename T, bool Dummy = true,
typename = std::enable_if_t<std::is_floating_point_v<T> && Dummy>>
T getRandomDouble(T min) {
return getRandomDouble(min, std::numeric_limits<T>::max());
}
template <typename T, bool Dummy = true,
typename = std::enable_if_t<std::is_floating_point_v<T> && Dummy>>
T getRandomDouble() {
return getRandomDouble(std::numeric_limits<T>::min(),
std::numeric_limits<T>::max());
}
double getRandomDouble() {
return getRandomDouble<double>();
}
} // namespace common

16
code/common/Random.i Normal file
View file

@ -0,0 +1,16 @@
%module common
%{
#include "Random.h"
%}
namespace common {
int getRandomInt();
int getRandomInt(int min);
int getRandomInt(int min, int max);
double getRandomDouble();
double getRandomDouble(double min);
double getRandomDouble(double min, double max);
} // namespace common

View file

@ -208,48 +208,48 @@ TEST_CASE("rectangle_intersection", "[common::Rectangle]") {
auto rect_e = common::Rectangle<int>{4, 7, 2, 2};
auto intersectopn_d_e = common::intersection(rect_d, rect_e);
REQUIRE(intersectopn_d_e);
REQUIRE(intersectopn_d_e->left == rect_e.left);
REQUIRE(intersectopn_d_e->top == rect_e.top);
REQUIRE(intersectopn_d_e->right == rect_e.right);
REQUIRE(intersectopn_d_e->bottom == rect_e.bottom);
REQUIRE(!intersectopn_d_e.empty());
REQUIRE(intersectopn_d_e.left == rect_e.left);
REQUIRE(intersectopn_d_e.top == rect_e.top);
REQUIRE(intersectopn_d_e.right == rect_e.right);
REQUIRE(intersectopn_d_e.bottom == rect_e.bottom);
auto intersection_e_d = common::intersection(rect_e, rect_d);
REQUIRE(intersection_e_d);
REQUIRE(intersection_e_d->left == rect_e.left);
REQUIRE(intersection_e_d->top == rect_e.top);
REQUIRE(intersection_e_d->right == rect_e.right);
REQUIRE(intersection_e_d->bottom == rect_e.bottom);
REQUIRE(!intersection_e_d.empty());
REQUIRE(intersection_e_d.left == rect_e.left);
REQUIRE(intersection_e_d.top == rect_e.top);
REQUIRE(intersection_e_d.right == rect_e.right);
REQUIRE(intersection_e_d.bottom == rect_e.bottom);
auto rect_a = common::Rectangle<int>{1, 1, 2, 2};
auto rect_b = common::Rectangle<int>{4, 3, 2, 2};
auto rect_c = common::Rectangle<int>{2, 2, 3, 2};
auto intersection_a_b = common::intersection(rect_a, rect_b);
REQUIRE(!intersection_a_b);
REQUIRE(intersection_a_b.empty());
auto intersection_b_a = common::intersection(rect_b, rect_a);
REQUIRE(!intersection_b_a);
REQUIRE(intersection_b_a.empty());
auto intersection_a_c = common::intersection(rect_a, rect_c);
REQUIRE(intersection_a_c);
REQUIRE(intersection_a_c->left == 2);
REQUIRE(intersection_a_c->top == 2);
REQUIRE(intersection_a_c->right == 3);
REQUIRE(intersection_a_c->bottom == 3);
REQUIRE(!intersection_a_c.empty());
REQUIRE(intersection_a_c.left == 2);
REQUIRE(intersection_a_c.top == 2);
REQUIRE(intersection_a_c.right == 3);
REQUIRE(intersection_a_c.bottom == 3);
auto intersection_c_a = common::intersection(rect_c, rect_a);
REQUIRE(intersection_c_a);
REQUIRE(intersection_c_a->left == 2);
REQUIRE(intersection_c_a->top == 2);
REQUIRE(intersection_c_a->right == 3);
REQUIRE(intersection_c_a->bottom == 3);
REQUIRE(!intersection_c_a.empty());
REQUIRE(intersection_c_a.left == 2);
REQUIRE(intersection_c_a.top == 2);
REQUIRE(intersection_c_a.right == 3);
REQUIRE(intersection_c_a.bottom == 3);
auto intersection_a_a = common::intersection(rect_a, rect_a);
REQUIRE(intersection_a_a);
REQUIRE(intersection_a_a->left == 1);
REQUIRE(intersection_a_a->top == 1);
REQUIRE(intersection_a_a->right == 3);
REQUIRE(intersection_a_a->bottom == 3);
REQUIRE(!intersection_a_a.empty());
REQUIRE(intersection_a_a.left == 1);
REQUIRE(intersection_a_a.top == 1);
REQUIRE(intersection_a_a.right == 3);
REQUIRE(intersection_a_a.bottom == 3);
}
TEST_CASE("rectangle_bounds", "[common::Rectangle]") {

View file

@ -1,5 +1,6 @@
#pragma once
#include "Math.h"
#include <algorithm>
#include <cstdint>
#include <optional>
@ -39,6 +40,11 @@ public:
return !(rhs == *this);
}
[[nodiscard]] constexpr bool empty() const {
return equal(left, 0) && equal(top, 0) && equal(right, 0) &&
equal(bottom, 0);
}
T left;
T top;
T right;
@ -52,16 +58,20 @@ bool intersect(const Rectangle<A> &a, const Rectangle<B> &b) {
}
template <typename A, typename B, typename ResultType = A>
std::optional<Rectangle<ResultType>> intersection(const Rectangle<A> &a,
const Rectangle<B> &b) {
Rectangle<ResultType> intersection(const Rectangle<A> &a,
const Rectangle<B> &b) {
if (!intersect(a, b)) {
return {};
}
auto left = std::max(a.left, b.left);
auto bottom = std::min(a.bottom, b.bottom);
auto right = std::min(a.right, b.right);
auto top = std::max(a.top, b.top);
auto left = std::max(static_cast<ResultType>(a.left),
static_cast<ResultType>(b.left));
auto bottom = std::min(static_cast<ResultType>(a.bottom),
static_cast<ResultType>(b.bottom));
auto right = std::min(static_cast<ResultType>(a.right),
static_cast<ResultType>(b.right));
auto top =
std::max(static_cast<ResultType>(a.top), static_cast<ResultType>(b.top));
return Rectangle<ResultType>(left, top, right - left, bottom - top);
}
@ -70,9 +80,13 @@ template <typename A, typename... Args>
constexpr Rectangle<A> bounds(const Rectangle<A> &a, Args &&... args) {
if constexpr (sizeof...(args) > 0) {
auto b = bounds(std::forward<Args>(args)...);
return Rectangle<A>{std::min(a.left, b.left), std::min(a.top, b.top),
std::max(a.right, b.right) - std::min(a.left, b.left),
std::max(a.bottom, b.bottom) - std::min(a.top, b.top)};
return Rectangle<A>{
std::min(static_cast<A>(a.left), static_cast<A>(b.left)),
std::min(static_cast<A>(a.top), static_cast<A>(b.top)),
std::max(static_cast<A>(a.right), static_cast<A>(b.right)) -
std::min(static_cast<A>(a.left), static_cast<A>(b.left)),
std::max(static_cast<A>(a.bottom), static_cast<A>(b.bottom)) -
std::min(static_cast<A>(a.top), static_cast<A>(b.top))};
}
return a;

91
code/common/Rectangle.i Normal file
View file

@ -0,0 +1,91 @@
%module common
%{
#include "Rectangle.h"
%}
namespace common {
class RectangleI {
public:
RectangleI(int32_t left, int32_t top, int32_t width, double height);
RectangleI(int32_t left, int32_t top, double width, int32_t height);
RectangleI(int32_t left, int32_t top, double width, double height);
RectangleI(int32_t left, double top, int32_t width, int32_t height);
RectangleI(int32_t left, double top, int32_t width, double height);
RectangleI(int32_t left, double top, double width, int32_t height);
RectangleI(int32_t left, double top, double width, double height);
RectangleI(double left, int32_t top, int32_t width, double height);
RectangleI(double left, int32_t top, double width, int32_t height);
RectangleI(double left, int32_t top, double width, double height);
RectangleI(double left, double top, int32_t width, int32_t height);
RectangleI(double left, double top, int32_t width, double height);
RectangleI(double left, double top, double width, int32_t height);
RectangleI(double left, double top, double width, double height);
RectangleI(const RectangleI &);
RectangleI &operator=(const RectangleI &);
bool operator==(const RectangleI &);
bool operator!=(const RectangleI &);
int32_t width() const;
int32_t height() const;
int32_t area() const;
int32_t left;
int32_t top;
int32_t right;
int32_t bottom;
};
class RectangleD {
public:
RectangleD(int32_t left, int32_t top, int32_t width, double height);
RectangleD(int32_t left, int32_t top, double width, int32_t height);
RectangleD(int32_t left, int32_t top, double width, double height);
RectangleD(int32_t left, double top, int32_t width, int32_t height);
RectangleD(int32_t left, double top, int32_t width, double height);
RectangleD(int32_t left, double top, double width, int32_t height);
RectangleD(int32_t left, double top, double width, double height);
RectangleD(double left, int32_t top, int32_t width, double height);
RectangleD(double left, int32_t top, double width, int32_t height);
RectangleD(double left, int32_t top, double width, double height);
RectangleD(double left, double top, int32_t width, int32_t height);
RectangleD(double left, double top, int32_t width, double height);
RectangleD(double left, double top, double width, int32_t height);
RectangleD(double left, double top, double width, double height);
RectangleD(const RectangleD &);
RectangleI &operator=(const RectangleI &);
bool operator==(const RectangleD &);
bool operator!=(const RectangleD &);
int32_t width() const;
int32_t height() const;
int32_t area() const;
int32_t left;
int32_t top;
int32_t right;
int32_t bottom;
};
bool intersect(const RectangleI &, const RectangleI &);
bool intersect(const RectangleI &, const RectangleD &);
bool intersect(const RectangleD &, const RectangleI &);
bool intersect(const RectangleD &, const RectangleD &);
RectangleI intersection(const RectangleI &a, const RectangleI &b);
RectangleD intersection(const RectangleD &a, const RectangleI &b);
RectangleI intersection(const RectangleI &a, const RectangleD &b);
RectangleD intersection(const RectangleD &a, const RectangleD &b);
RectangleI bounds(const RectangleI &a, const RectangleI &b);
RectangleI bounds(const RectangleI &a, const RectangleD &b);
RectangleD bounds(const RectangleD &a, const RectangleI &b);
RectangleD bounds(const RectangleD &a, const RectangleD &b);
} // namespace common

View file

@ -6,27 +6,16 @@
namespace common {
constexpr Vector &Vector::clear() {
x_ = 0;
y_ = 0;
z_ = 0;
return *this;
}
float Vector::length() const { return sqrt(dotProduct(*this, *this)); }
constexpr float Vector::length_squared() const {
return dotProduct(*this, *this);
}
float Vector::normalize() {
const auto len = length();
if (len < 0 || len > 0) {
const auto ilen = 1 / len;
x_ *= ilen;
y_ *= ilen;
z_ *= ilen;
x *= ilen;
y *= ilen;
z *= ilen;
}
return len;
@ -40,9 +29,9 @@ Vector Vector::normalized() const {
void Vector::normalizeFast() {
const auto ilen = common::rsqrt(length_squared());
x_ *= ilen;
y_ *= ilen;
z_ *= ilen;
x *= ilen;
y *= ilen;
z *= ilen;
}
Vector Vector::normalizedFast() const {
@ -51,12 +40,6 @@ Vector Vector::normalizedFast() const {
return result;
}
constexpr void Vector::invert() {
x_ = -x_;
y_ = -y_;
z_ = -z_;
}
Vector Vector::inverted() const {
auto result = *this;
result.invert();
@ -67,18 +50,14 @@ float distance(const Vector &a, const Vector &b) {
return sqrt(dotProduct(b - a, b - a));
}
constexpr float distance_squared(const Vector &a, const Vector &b) {
return dotProduct(b - a, b - a);
}
float normalize2(const Vector &v, Vector &out) {
const auto len = v.length();
if (len < 0 || len > 0) {
const auto ilen = 1 / len;
out.x_ = v.x_ * ilen;
out.y_ = v.y_ * ilen;
out.z_ = v.z_ * ilen;
out.x = v.x * ilen;
out.y = v.y * ilen;
out.z = v.z * ilen;
} else {
out.clear();
}
@ -273,43 +252,43 @@ Vector byteToDir(std::int32_t b) {
} // namespace common
static_assert(common::Vector().x_ == 0.0f);
static_assert(common::Vector().y_ == 0.0f);
static_assert(common::Vector().z_ == 0.0f);
static_assert(common::Vector().x == 0.0f);
static_assert(common::Vector().y == 0.0f);
static_assert(common::Vector().z == 0.0f);
static_assert(common::Vector(1, 2, 3).x_ == 1.0f);
static_assert(common::Vector(1, 2, 3).y_ == 2.0f);
static_assert(common::Vector(1, 2, 3).z_ == 3.0f);
static_assert(common::Vector(1, 2, 3).x == 1.0f);
static_assert(common::Vector(1, 2, 3).y == 2.0f);
static_assert(common::Vector(1, 2, 3).z == 3.0f);
static_assert(common::Vector(1.0f, 2.5f, -3.123f).x_ == 1.0f);
static_assert(common::Vector(1.0f, 2.5f, -3.123f).y_ == 2.5f);
static_assert(common::Vector(1.0f, 2.5f, -3.123f).z_ == -3.123f);
static_assert(common::Vector(1.0f, 2.5f, -3.123f).x == 1.0f);
static_assert(common::Vector(1.0f, 2.5f, -3.123f).y == 2.5f);
static_assert(common::Vector(1.0f, 2.5f, -3.123f).z == -3.123f);
static_assert(common::Vector(1.0, 2.5, -3.123).x_ == 1.0f);
static_assert(common::Vector(1.0, 2.5, -3.123).y_ == 2.5f);
static_assert(common::Vector(1.0, 2.5, -3.123).z_ == -3.123f);
static_assert(common::Vector(1.0, 2.5, -3.123).x == 1.0f);
static_assert(common::Vector(1.0, 2.5, -3.123).y == 2.5f);
static_assert(common::Vector(1.0, 2.5, -3.123).z == -3.123f);
TEST_CASE("vector_construct", "[common::Vector]") {
REQUIRE(common::Vector().x_ == Approx(0.0f));
REQUIRE(common::Vector().y_ == Approx(0.0f));
REQUIRE(common::Vector().z_ == Approx(0.0f));
REQUIRE(common::Vector().x == Approx(0.0f));
REQUIRE(common::Vector().y == Approx(0.0f));
REQUIRE(common::Vector().z == Approx(0.0f));
REQUIRE(common::Vector(1, 2, 3).x_ == Approx(1.0f));
REQUIRE(common::Vector(1, 2, 3).y_ == Approx(2.0f));
REQUIRE(common::Vector(1, 2, 3).z_ == Approx(3.0f));
REQUIRE(common::Vector(1, 2, 3).x == Approx(1.0f));
REQUIRE(common::Vector(1, 2, 3).y == Approx(2.0f));
REQUIRE(common::Vector(1, 2, 3).z == Approx(3.0f));
REQUIRE(common::Vector(1.0f, 2.5f, -3.123f).x_ == Approx(1.0f));
REQUIRE(common::Vector(1.0f, 2.5f, -3.123f).y_ == Approx(2.5f));
REQUIRE(common::Vector(1.0f, 2.5f, -3.123f).z_ == Approx(-3.123f));
REQUIRE(common::Vector(1.0f, 2.5f, -3.123f).x == Approx(1.0f));
REQUIRE(common::Vector(1.0f, 2.5f, -3.123f).y == Approx(2.5f));
REQUIRE(common::Vector(1.0f, 2.5f, -3.123f).z == Approx(-3.123f));
REQUIRE(common::Vector(1.0, 2.5, -3.123).x_ == Approx(1.0f));
REQUIRE(common::Vector(1.0, 2.5, -3.123).y_ == Approx(2.5f));
REQUIRE(common::Vector(1.0, 2.5, -3.123).z_ == Approx(-3.123f));
REQUIRE(common::Vector(1.0, 2.5, -3.123).x == Approx(1.0f));
REQUIRE(common::Vector(1.0, 2.5, -3.123).y == Approx(2.5f));
REQUIRE(common::Vector(1.0, 2.5, -3.123).z == Approx(-3.123f));
vec3_t vec_3{1, 2, 3};
REQUIRE(common::Vector(vec_3).x_ == Approx(1.0f));
REQUIRE(common::Vector(vec_3).y_ == Approx(2.0f));
REQUIRE(common::Vector(vec_3).z_ == Approx(3.0f));
REQUIRE(common::Vector(vec_3).x == Approx(1.0f));
REQUIRE(common::Vector(vec_3).y == Approx(2.0f));
REQUIRE(common::Vector(vec_3).z == Approx(3.0f));
}
static_assert(common::dotProduct({1, 2, 3}, {3, 2, 1}) == 10.0f);
@ -320,108 +299,108 @@ TEST_CASE("vector_dotproduct", "[common::Vector]") {
REQUIRE(common::dotProduct({1, 5, 3}, {3, 2, 1}) == Approx(16.0f));
for (auto i = 0; i < 100; i++) {
auto v1 = common::Vector{common::getRandom<float>(-100000, 100000),
common::getRandom<float>(-100000, 100000),
common::getRandom<float>(-100000, 100000)};
auto v2 = common::Vector{common::getRandom<float>(-100000, 100000),
common::getRandom<float>(-100000, 100000),
common::getRandom<float>(-100000, 100000)};
auto v1 = common::Vector{common::getRandomDouble<float>(-100000, 100000),
common::getRandomDouble<float>(-100000, 100000),
common::getRandomDouble<float>(-100000, 100000)};
auto v2 = common::Vector{common::getRandomDouble<float>(-100000, 100000),
common::getRandomDouble<float>(-100000, 100000),
common::getRandomDouble<float>(-100000, 100000)};
REQUIRE(common::dotProduct(v1, v2) ==
Approx(v1.x_ * v2.x_ + v1.y_ * v2.y_ + v1.z_ * v2.z_));
Approx(v1.x * v2.x + v1.y * v2.y + v1.z * v2.z));
}
}
static_assert((common::Vector{2, 5, 4} - common::Vector{1, -2, 4}).x_ == 1.0f);
static_assert((common::Vector{2, 5, 4} - common::Vector{1, -2, 4}).y_ == 7.0f);
static_assert((common::Vector{2, 5, 4} - common::Vector{1, -2, 4}).z_ == 0.0f);
static_assert((common::Vector{2, 5, 4} - common::Vector{1, -2, 4}).x == 1.0f);
static_assert((common::Vector{2, 5, 4} - common::Vector{1, -2, 4}).y == 7.0f);
static_assert((common::Vector{2, 5, 4} - common::Vector{1, -2, 4}).z == 0.0f);
TEST_CASE("vector_substract", "[common::Vector}") {
REQUIRE((common::Vector{2, 5, 4} - common::Vector{1, -2, 4}).x_ == 1.0f);
REQUIRE((common::Vector{2, 5, 4} - common::Vector{1, -2, 4}).y_ == 7.0f);
REQUIRE((common::Vector{2, 5, 4} - common::Vector{1, -2, 4}).z_ == 0.0f);
REQUIRE((common::Vector{2, 5, 4} - common::Vector{1, -2, 4}).x == 1.0f);
REQUIRE((common::Vector{2, 5, 4} - common::Vector{1, -2, 4}).y == 7.0f);
REQUIRE((common::Vector{2, 5, 4} - common::Vector{1, -2, 4}).z == 0.0f);
for (auto i = 0; i < 100; i++) {
auto v1 = common::Vector{common::getRandom<float>(-100000, 100000),
common::getRandom<float>(-100000, 100000),
common::getRandom<float>(-100000, 100000)};
auto v2 = common::Vector{common::getRandom<float>(-100000, 100000),
common::getRandom<float>(-100000, 100000),
common::getRandom<float>(-100000, 100000)};
auto v1 = common::Vector{common::getRandomDouble<float>(-100000, 100000),
common::getRandomDouble<float>(-100000, 100000),
common::getRandomDouble<float>(-100000, 100000)};
auto v2 = common::Vector{common::getRandomDouble<float>(-100000, 100000),
common::getRandomDouble<float>(-100000, 100000),
common::getRandomDouble<float>(-100000, 100000)};
auto res = v1 - v2;
REQUIRE(res.x_ == v1.x_ - v2.x_);
REQUIRE(res.y_ == v1.y_ - v2.y_);
REQUIRE(res.z_ == v1.z_ - v2.z_);
REQUIRE(res.x == v1.x - v2.x);
REQUIRE(res.y == v1.y - v2.y);
REQUIRE(res.z == v1.z - v2.z);
}
}
static_assert((common::Vector{2, 5, 4} + common::Vector{1, -2, 4}).x_ == 3.0f);
static_assert((common::Vector{2, 5, 4} + common::Vector{1, -2, 4}).y_ == 3.0f);
static_assert((common::Vector{2, 5, 4} + common::Vector{1, -2, 4}).z_ == 8.0f);
static_assert((common::Vector{2, 5, 4} + common::Vector{1, -2, 4}).x == 3.0f);
static_assert((common::Vector{2, 5, 4} + common::Vector{1, -2, 4}).y == 3.0f);
static_assert((common::Vector{2, 5, 4} + common::Vector{1, -2, 4}).z == 8.0f);
TEST_CASE("vector_add", "[common::Vector]") {
REQUIRE((common::Vector{2, 5, 4} + common::Vector{1, -2, 4}).x_ == 3.0f);
REQUIRE((common::Vector{2, 5, 4} + common::Vector{1, -2, 4}).y_ == 3.0f);
REQUIRE((common::Vector{2, 5, 4} + common::Vector{1, -2, 4}).z_ == 8.0f);
REQUIRE((common::Vector{2, 5, 4} + common::Vector{1, -2, 4}).x == 3.0f);
REQUIRE((common::Vector{2, 5, 4} + common::Vector{1, -2, 4}).y == 3.0f);
REQUIRE((common::Vector{2, 5, 4} + common::Vector{1, -2, 4}).z == 8.0f);
for (auto i = 0; i < 100; i++) {
auto v1 = common::Vector{common::getRandom<float>(-100000, 100000),
common::getRandom<float>(-100000, 100000),
common::getRandom<float>(-100000, 100000)};
auto v2 = common::Vector{common::getRandom<float>(-100000, 100000),
common::getRandom<float>(-100000, 100000),
common::getRandom<float>(-100000, 100000)};
auto v1 = common::Vector{common::getRandomDouble<float>(-100000, 100000),
common::getRandomDouble<float>(-100000, 100000),
common::getRandomDouble<float>(-100000, 100000)};
auto v2 = common::Vector{common::getRandomDouble<float>(-100000, 100000),
common::getRandomDouble<float>(-100000, 100000),
common::getRandomDouble<float>(-100000, 100000)};
auto res = v1 + v2;
REQUIRE(res.x_ == v1.x_ + v2.x_);
REQUIRE(res.y_ == v1.y_ + v2.y_);
REQUIRE(res.z_ == v1.z_ + v2.z_);
REQUIRE(res.x == v1.x + v2.x);
REQUIRE(res.y == v1.y + v2.y);
REQUIRE(res.z == v1.z + v2.z);
}
}
static_assert(common::Vector{1, 2, 3}.clear().x_ == 0.0f);
static_assert(common::Vector{1, 2, 3}.clear().y_ == 0.0f);
static_assert(common::Vector{1, 2, 3}.clear().z_ == 0.0f);
static_assert(common::Vector{1, 2, 3}.clear().x == 0.0f);
static_assert(common::Vector{1, 2, 3}.clear().y == 0.0f);
static_assert(common::Vector{1, 2, 3}.clear().z == 0.0f);
TEST_CASE("vector_clear", "[common::Vector]") {
REQUIRE(common::Vector{1, 2, 3}.clear().x_ == 0.0f);
REQUIRE(common::Vector{1, 2, 3}.clear().y_ == 0.0f);
REQUIRE(common::Vector{1, 2, 3}.clear().z_ == 0.0f);
REQUIRE(common::Vector{1, 2, 3}.clear().x == 0.0f);
REQUIRE(common::Vector{1, 2, 3}.clear().y == 0.0f);
REQUIRE(common::Vector{1, 2, 3}.clear().z == 0.0f);
}
static_assert(common::ma(common::Vector{1, 2, 3}, 2, common::Vector{4, 5, 6})
.x_ == 9.00f);
.x == 9.00f);
static_assert(common::ma(common::Vector{1, 2, 3}, 2, common::Vector{4, 5, 6})
.y_ == 12.0f);
.y == 12.0f);
static_assert(common::ma(common::Vector{1, 2, 3}, 2, common::Vector{4, 5, 6})
.z_ == 15.0f);
.z == 15.0f);
TEST_CASE("vector_ma", "[common::Vector]") {
REQUIRE(common::ma(common::Vector{1, 2, 3}, 2, common::Vector{4, 5, 6}).x_ ==
REQUIRE(common::ma(common::Vector{1, 2, 3}, 2, common::Vector{4, 5, 6}).x ==
9.00f);
REQUIRE(common::ma(common::Vector{1, 2, 3}, 2, common::Vector{4, 5, 6}).y_ ==
REQUIRE(common::ma(common::Vector{1, 2, 3}, 2, common::Vector{4, 5, 6}).y ==
12.0f);
REQUIRE(common::ma(common::Vector{1, 2, 3}, 2, common::Vector{4, 5, 6}).z_ ==
REQUIRE(common::ma(common::Vector{1, 2, 3}, 2, common::Vector{4, 5, 6}).z ==
15.0f);
}
static_assert((-common::Vector{1, 2, -5}).x_ == -1.0f);
static_assert((-common::Vector{1, 2, -5}).y_ == -2.0f);
static_assert((-common::Vector{1, 2, -5}).z_ == 5.0f);
static_assert((-common::Vector{1, 2, -5}).x == -1.0f);
static_assert((-common::Vector{1, 2, -5}).y == -2.0f);
static_assert((-common::Vector{1, 2, -5}).z == 5.0f);
static_assert((-common::Vector{-1, -2, 5}).x_ == 1.0f);
static_assert((-common::Vector{-1, -2, 5}).y_ == 2.0f);
static_assert((-common::Vector{-1, -2, 5}).z_ == -5.0f);
static_assert((-common::Vector{-1, -2, 5}).x == 1.0f);
static_assert((-common::Vector{-1, -2, 5}).y == 2.0f);
static_assert((-common::Vector{-1, -2, 5}).z == -5.0f);
TEST_CASE("vector_negate", "[common::Vector]") {
REQUIRE((-common::Vector{1, 2, -5}).x_ == -1.0f);
REQUIRE((-common::Vector{1, 2, -5}).y_ == -2.0f);
REQUIRE((-common::Vector{1, 2, -5}).z_ == 5.0f);
REQUIRE((-common::Vector{1, 2, -5}).x == -1.0f);
REQUIRE((-common::Vector{1, 2, -5}).y == -2.0f);
REQUIRE((-common::Vector{1, 2, -5}).z == 5.0f);
REQUIRE((-common::Vector{-1, -2, 5}).x_ == 1.0f);
REQUIRE((-common::Vector{-1, -2, 5}).y_ == 2.0f);
REQUIRE((-common::Vector{-1, -2, 5}).z_ == -5.0f);
REQUIRE((-common::Vector{-1, -2, 5}).x == 1.0f);
REQUIRE((-common::Vector{-1, -2, 5}).y == 2.0f);
REQUIRE((-common::Vector{-1, -2, 5}).z == -5.0f);
}
TEST_CASE("vector_length", "[common::Vector]") {
@ -475,14 +454,14 @@ TEST_CASE("vector_to_vector_distance", "[common::Vector]") {
Approx(58.3180932472f));
}
static_assert(common::crossProduct({1, 2, 3}, {4, 5, 6}).x_ == -3.0f);
static_assert(common::crossProduct({1, 2, 3}, {4, 5, 6}).y_ == 6.0f);
static_assert(common::crossProduct({1, 2, 3}, {4, 5, 6}).z_ == -3.0f);
static_assert(common::crossProduct({1, 2, 3}, {4, 5, 6}).x == -3.0f);
static_assert(common::crossProduct({1, 2, 3}, {4, 5, 6}).y == 6.0f);
static_assert(common::crossProduct({1, 2, 3}, {4, 5, 6}).z == -3.0f);
TEST_CASE("vector_cross_product", "[common::Vector]") {
REQUIRE(common::crossProduct({1, 2, 3}, {4, 5, 6}).x_ == -3.0f);
REQUIRE(common::crossProduct({1, 2, 3}, {4, 5, 6}).y_ == 6.0f);
REQUIRE(common::crossProduct({1, 2, 3}, {4, 5, 6}).z_ == -3.0f);
REQUIRE(common::crossProduct({1, 2, 3}, {4, 5, 6}).x == -3.0f);
REQUIRE(common::crossProduct({1, 2, 3}, {4, 5, 6}).y == 6.0f);
REQUIRE(common::crossProduct({1, 2, 3}, {4, 5, 6}).z == -3.0f);
}
TEST_CASE("vector_normalize", "[common::Vector]") {
@ -519,15 +498,15 @@ TEST_CASE("vector_normalize2", "[common::Vector]") {
TEST_CASE("vector_invert", "[common::Vector]") {
auto vec = common::Vector{1, -1, 1};
vec.invert();
REQUIRE(vec.x_ == Approx(-1.0f));
REQUIRE(vec.y_ == Approx(1.0f));
REQUIRE(vec.z_ == Approx(-1.0f));
REQUIRE(vec.x == Approx(-1.0f));
REQUIRE(vec.y == Approx(1.0f));
REQUIRE(vec.z == Approx(-1.0f));
}
TEST_CASE("vector_inverted", "[common::Vector]") {
REQUIRE(common::Vector{1, -1, 1}.inverted().x_ == Approx(-1.0f));
REQUIRE(common::Vector{1, -1, 1}.inverted().y_ == Approx(1.0f));
REQUIRE(common::Vector{1, -1, 1}.inverted().z_ == Approx(-1.0f));
REQUIRE(common::Vector{1, -1, 1}.inverted().x == Approx(-1.0f));
REQUIRE(common::Vector{1, -1, 1}.inverted().y == Approx(1.0f));
REQUIRE(common::Vector{1, -1, 1}.inverted().z == Approx(-1.0f));
}
TEST_CASE("vector_rotate", "[common::Vector]") {
@ -535,9 +514,9 @@ TEST_CASE("vector_rotate", "[common::Vector]") {
auto rotated = common::rotate(
vec, std::array<common::Vector, 3>{
common::Vector{4.5, 3, -6}, {1, 0, 7.6}, {1.3, -65, 7.5}});
REQUIRE(rotated.x_ == Approx(97.5));
REQUIRE(rotated.y_ == Approx(-15.4));
REQUIRE(rotated.z_ == Approx(-140.5));
REQUIRE(rotated.x == Approx(97.5));
REQUIRE(rotated.y == Approx(-15.4));
REQUIRE(rotated.z == Approx(-140.5));
}
TEST_CASE("byte_to_dir", "[common::Vector]") {

View file

@ -7,23 +7,28 @@ namespace common {
class Vector {
public:
constexpr Vector() noexcept : x_{0}, y_{0}, z_{0} {}
constexpr Vector() noexcept : x{0}, y{0}, z{0} {}
template <typename X, typename Y = float, typename Z = float,
typename = std::enable_if_t<std::is_convertible_v<X, float> &&
std::is_convertible_v<Y, float> &&
std::is_convertible_v<Z, float>>>
constexpr Vector(X x, Y y, Z z) noexcept
: x_{static_cast<float>(x)}, y_{static_cast<float>(y)},
z_{static_cast<float>(z)} {}
: x{static_cast<float>(x)}, y{static_cast<float>(y)},
z{static_cast<float>(z)} {}
constexpr Vector(vec3_t v) noexcept : x_{v[0]}, y_{v[1]}, z_{v[2]} {}
constexpr Vector(vec3_t v) noexcept : x{v[0]}, y{v[1]}, z{v[2]} {}
constexpr Vector &clear();
constexpr Vector &clear() {
x = y = z = 0;
return *this;
}
[[nodiscard]] float length() const;
[[nodiscard]] constexpr float length_squared() const;
[[nodiscard]] constexpr float length_squared() const {
return x * x + y * y + z * z;
}
float normalize();
@ -33,55 +38,61 @@ public:
[[nodiscard]] Vector normalizedFast() const;
constexpr void invert();
constexpr void invert() {
values[0] = -values[0];
values[1] = -values[1];
values[2] = -values[2];
}
[[nodiscard]] Vector inverted() const;
union {
vec3_t values{};
struct {
float x_;
float y_;
float z_;
float x;
float y;
float z;
};
};
};
inline constexpr float dotProduct(const Vector &a, const Vector &b) {
return a.x_ * b.x_ + a.y_ * b.y_ + a.z_ * b.z_;
return a.x * b.x + a.y * b.y + a.z * b.z;
}
inline constexpr Vector operator-(const Vector &a, const Vector &b) {
return {a.x_ - b.x_, a.y_ - b.y_, a.z_ - b.z_};
return {a.x - b.x, a.y - b.y, a.z - b.z};
}
inline constexpr Vector operator+(const Vector &a, const Vector &b) {
return {a.x_ + b.x_, a.y_ + b.y_, a.z_ + b.z_};
return {a.x + b.x, a.y + b.y, a.z + b.z};
}
inline constexpr Vector operator*(const Vector &a, float factor) {
return {a.x_ * factor, a.y_ * factor, a.z_ * factor};
return {a.x * factor, a.y * factor, a.z * factor};
}
inline constexpr Vector operator*(float factor, const Vector &a) {
return {a.x_ * factor, a.y_ * factor, a.z_ * factor};
return {a.x * factor, a.y * factor, a.z * factor};
}
inline constexpr Vector ma(const Vector &v, float s, const Vector &b) {
return {v.x_ + b.x_ * s, v.y_ + b.y_ * s, v.z_ + b.z_ * s};
return {v.x + b.x * s, v.y + b.y * s, v.z + b.z * s};
}
inline constexpr Vector operator-(const Vector &a) {
return {-a.x_, -a.y_, -a.z_};
return {-a.x, -a.y, -a.z};
}
float distance(const Vector &a, const Vector &b);
constexpr float distance_squared(const Vector &a, const Vector &b);
constexpr float distance_squared(const Vector &a, const Vector &b) {
return dotProduct(b - a, b - a);
}
inline constexpr Vector crossProduct(const Vector &v1, const Vector &v2) {
return {v1.y_ * v2.z_ - v1.z_ * v2.y_, v1.z_ * v2.x_ - v1.x_ * v2.z_,
v1.x_ * v2.y_ - v1.y_ * v2.x_};
return {v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z,
v1.x * v2.y - v1.y * v2.x};
}
float normalize2(const Vector &v, Vector &out);
@ -91,7 +102,7 @@ constexpr Vector rotate(const Vector &v, const std::array<Vector, 3> &matrix) {
dotProduct(v, matrix[2])};
}
std::int32_t dirToByte(const Vector& dir);
std::int32_t dirToByte(const Vector &dir);
Vector byteToDir(std::int32_t b);

64
code/common/Vector.i Normal file
View file

@ -0,0 +1,64 @@
%module common
%{
#include "Vector.h"
%}
namespace common {
class Vector {
public:
constexpr Vector();
constexpr Vector(float x, float y, float z);
constexpr Vector &clear();
float length() const;
constexpr float length_squared() const;
float normalize();
void normalizeFast();
Vector normalized() const;
Vector normalizedFast() const;
constexpr void invert();
Vector inverted() const;
float x;
float y;
float z;
};
constexpr float dotProduct(const Vector &a, const Vector &b);
constexpr Vector operator-(const Vector &a, const Vector &b);
constexpr Vector operator+(const Vector &a, const Vector &b);
constexpr Vector operator*(const Vector &a, float factor);
constexpr Vector operator*(float factor, const Vector &a);
constexpr Vector ma(const Vector &v, float s, const Vector &b);
constexpr Vector operator-(const Vector &a);
float distance(const Vector &a, const Vector &b);
constexpr float distance_squared(const Vector &a, const Vector &b);
constexpr Vector crossProduct(const Vector &v1, const Vector &v2);
float normalize2(const Vector &v, Vector &out);
Vector rotate(const Vector &v, const std::array<Vector, 3> &matrix);
std::int32_t dirToByte(const Vector &dir);
Vector byteToDir(std::int32_t b);
} // namespace common

View file

@ -1442,7 +1442,7 @@ void Atoms::DrawBannerString(Point2dI pos, std::string_view str, int32_t style,
}
if (style & UI_DROPSHADOW) {
auto drawcolor = common::Color{0, 0, 0, color.a_};
auto drawcolor = common::Color{0, 0, 0, color.a};
DrawBannerString2({pos.x_ + 2, pos.y_ + 2}, str, drawcolor);
}
@ -1709,32 +1709,32 @@ void Atoms::DrawProportionalString(common::Point2dI pos, std::string_view str,
}
if (style & UI_DROPSHADOW) {
drawcolor.r_ = drawcolor.g_ = drawcolor.b_ = 0;
drawcolor.a_ = color.a_;
drawcolor.r = drawcolor.g = drawcolor.b = 0;
drawcolor.a = color.a;
DrawProportionalString2({pos.x_ + 2, pos.y_ + 2}, str, drawcolor, sizeScale,
uis.charsetProp);
}
if (style & UI_INVERSE) {
drawcolor.r_ = color.r_ * 0.7f;
drawcolor.g_ = color.g_ * 0.7f;
drawcolor.b_ = color.b_ * 0.7f;
drawcolor.a_ = color.a_;
drawcolor.r = color.r * 0.7f;
drawcolor.g = color.g * 0.7f;
drawcolor.b = color.b * 0.7f;
drawcolor.a = color.a;
DrawProportionalString2(pos, str, drawcolor, sizeScale, uis.charsetProp);
return;
}
if (style & UI_PULSE) {
drawcolor.r_ = color.a_ * 0.7f;
drawcolor.g_ = color.g_ * 0.7f;
drawcolor.b_ = color.b_ * 0.7f;
drawcolor.a_ = color.a_;
drawcolor.r = color.a * 0.7f;
drawcolor.g = color.g * 0.7f;
drawcolor.b = color.b * 0.7f;
drawcolor.a = color.a;
DrawProportionalString2(pos, str, color, sizeScale, uis.charsetProp);
drawcolor.r_ = color.r_;
drawcolor.g_ = color.g_;
drawcolor.b_ = color.b_;
drawcolor.a_ = static_cast<float>(
drawcolor.r = color.r;
drawcolor.g = color.g;
drawcolor.b = color.b;
drawcolor.a = static_cast<float>(
0.5f + 0.5f * std::sin(uis.realtime / PULSE_DIVISOR));
DrawProportionalString2(pos, str, drawcolor, sizeScale, uis.charsetProp);
return;
@ -1787,7 +1787,7 @@ void Atoms::DrawString2(common::Point2dI pos, std::string_view str,
if (Q_IsColorString(it)) {
if (!forceColor) {
tempcolor = g_color_table[ColorIndex(*(it + 1))];
tempcolor.a_ = color.a_;
tempcolor.a = color.a;
trap_R_SetColor(tempcolor.values);
}
it += 2;
@ -1844,10 +1844,10 @@ void Atoms::DrawString(common::Point2dI pos, std::string_view str,
}
if (style & UI_PULSE) {
lowlight.r_ = 0.8 * color.r_;
lowlight.g_ = 0.8 * color.g_;
lowlight.b_ = 0.8 * color.b_;
lowlight.a_ = 0.8 * color.a_;
lowlight.r = 0.8 * color.r;
lowlight.g = 0.8 * color.g;
lowlight.b = 0.8 * color.b;
lowlight.a = 0.8 * color.a;
LerpColor(color, lowlight, newcolor,
0.5 + 0.5 * sin(uis.realtime / PULSE_DIVISOR));
drawcolor = newcolor;
@ -1879,8 +1879,8 @@ void Atoms::DrawString(common::Point2dI pos, std::string_view str,
}
if (style & UI_DROPSHADOW) {
dropcolor.r_ = dropcolor.g_ = dropcolor.b_ = 0;
dropcolor.a_ = drawcolor.a_;
dropcolor.r = dropcolor.g = dropcolor.b = 0;
dropcolor.a = drawcolor.a;
if (highRes)
DrawProportionalString({pos.x_ + 2, pos.y_ + 2}, str, style, dropcolor);

View file

@ -32,9 +32,9 @@ set(UI_LIB_NAME "ui${ARCH}")
file(GLOB_RECURSE UI_SRC "*.h" "*.c" "*.cpp")
add_library(ui SHARED ${UI_SRC} $<TARGET_OBJECTS:common> $<TARGET_OBJECTS:base_game> $<TARGET_OBJECTS:catch2_symbols>)
add_library(ui SHARED ${UI_SRC})
target_include_directories(ui PUBLIC ../json/include ..)
target_link_libraries(ui ${UI_LINKER_OPTIONS})
target_link_libraries(ui ${UI_LINKER_OPTIONS} common base_game catch2_symbols)
target_compile_options(ui PUBLIC -Wno-narrowing -Wno-write-strings)
target_compile_definitions(ui PUBLIC -DUI_DLL)
set_target_properties(ui PROPERTIES PREFIX "")