diff --git a/CMakeLists.txt b/CMakeLists.txt index d516876..55db635 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,6 @@ option(VERSION_STRING "Project version string" "0.0.0") project(antkeeper VERSION ${VERSION_STRING} LANGUAGES CXX) # Find dependency packages -find_package(vmq REQUIRED CONFIG) find_package(dr_wav REQUIRED CONFIG) find_package(stb REQUIRED CONFIG) find_package(glad REQUIRED CONFIG) @@ -15,10 +14,8 @@ find_package(SDL2 REQUIRED COMPONENTS SDL2::SDL2-static SDL2::SDL2main CONFIG) find_package(OpenAL REQUIRED CONFIG) find_library(physfs REQUIRED NAMES physfs-static PATHS "${CMAKE_PREFIX_PATH}/lib") - # Determine dependencies set(STATIC_LIBS - vmq dr_wav stb glad diff --git a/src/animation/ease.hpp b/src/animation/ease.hpp index 73875c6..06d61e1 100644 --- a/src/animation/ease.hpp +++ b/src/animation/ease.hpp @@ -51,9 +51,8 @@ #ifndef ANTKEEPER_EASE_HPP #define ANTKEEPER_EASE_HPP -#include +#include "math/math.hpp" #include -#include /** * Container for templated easing functions. @@ -62,7 +61,7 @@ * * value_type operator+(const value_type&, const value_type&); * value_type operator-(const value_type&, const value_type&); - * value_type operator*(const value_type&, scalar_type) const; + * value_type operator*(const value_type&, scalar_type); * * @tparam T Value type. * @tparam S Scalar type. @@ -72,12 +71,6 @@ struct ease { typedef T value_type; typedef S scalar_type; - - /// Linearly interpolates between @p x and @p y. - static T linear(const T& x, const T& y, S a); - - /// Logarithmically interpolates between @p x and @p y. - static T log(const T& x, const T& y, S a); static T in_sine(const T& x, const T& y, S a); static T out_sine(const T& x, const T& y, S a); @@ -120,101 +113,88 @@ struct ease static T in_out_bounce(const T& x, const T& y, S a); }; -template -inline T ease::linear(const T& x, const T& y, S a) -{ - return (y - x) * a + x; -} - -template -inline T ease::log(const T& x, const T& y, S a) -{ - //return std::exp(linear(std::log(x), std::log(y), a)); - return x * std::pow(y / x, a); -} - template T ease::in_sine(const T& x, const T& y, S a) { - return linear(y, x, std::cos(a * vmq::half_pi)); + return math::lerp(y, x, std::cos(a * math::half_pi)); } template T ease::out_sine(const T& x, const T& y, S a) { - return linear(x, y, std::sin(a * vmq::half_pi)); + return math::lerp(x, y, std::sin(a * math::half_pi)); } template T ease::in_out_sine(const T& x, const T& y, S a) { - return linear(x, y, -(std::cos(a * vmq::pi) - S(1)) * S(0.5)); + return math::lerp(x, y, -(std::cos(a * math::pi) - S(1)) * S(0.5)); } template T ease::in_quad(const T& x, const T& y, S a) { - return linear(x, y, a * a); + return math::lerp(x, y, a * a); } template T ease::out_quad(const T& x, const T& y, S a) { - return linear(x, y, (S(2) - a) * a); + return math::lerp(x, y, (S(2) - a) * a); } template T ease::in_out_quad(const T& x, const T& y, S a) { - return linear(x, y, (a < S(0.5)) ? S(2) * a * a : -(S(2) * a * a - S(4) * a + S(1))); + return math::lerp(x, y, (a < S(0.5)) ? S(2) * a * a : -(S(2) * a * a - S(4) * a + S(1))); } template T ease::in_cubic(const T& x, const T& y, S a) { - return linear(x, y, a * a * a); + return math::lerp(x, y, a * a * a); } template T ease::out_cubic(const T& x, const T& y, S a) { - return linear(x, y, a * ((a - S(3)) * a + S(3))); + return math::lerp(x, y, a * ((a - S(3)) * a + S(3))); } template T ease::in_out_cubic(const T& x, const T& y, S a) { - return linear(x, y, (a < S(0.5)) ? S(4) * a * a * a : S(4) * a * a * a - S(12) * a * a + S(12) * a - 3); + return math::lerp(x, y, (a < S(0.5)) ? S(4) * a * a * a : S(4) * a * a * a - S(12) * a * a + S(12) * a - 3); } template T ease::in_quart(const T& x, const T& y, S a) { - return linear(x, y, a * a * a * a); + return math::lerp(x, y, a * a * a * a); } template T ease::out_quart(const T& x, const T& y, S a) { - return linear(x, y, a * (a * ((S(4) - a) * a - S(6)) + S(4))); + return math::lerp(x, y, a * (a * ((S(4) - a) * a - S(6)) + S(4))); } template T ease::in_out_quart(const T& x, const T& y, S a) { - return linear(x, y, (a < S(0.5)) ? S(8) * a * a * a * a : a * (a * ((S(32) - S(8) * a) * a - S(48)) + S(32)) - S(7)); + return math::lerp(x, y, (a < S(0.5)) ? S(8) * a * a * a * a : a * (a * ((S(32) - S(8) * a) * a - S(48)) + S(32)) - S(7)); } template T ease::in_quint(const T& x, const T& y, S a) { - return linear(x, y, a * a * a * a * a); + return math::lerp(x, y, a * a * a * a * a); } template T ease::out_quint(const T& x, const T& y, S a) { - return linear(x, y, a * (a * (a * ((a - S(5)) * a + S(10)) - S(10)) + S(5))); + return math::lerp(x, y, a * (a * (a * ((a - S(5)) * a + S(10)) - S(10)) + S(5))); } template @@ -222,25 +202,25 @@ T ease::in_out_quint(const T& x, const T& y, S a) { if (a < S(0.5)) { - return linear(x, y, S(16) * a * a * a * a * a); + return math::lerp(x, y, S(16) * a * a * a * a * a); } else { a = S(2) * (S(1) - a); - return linear(x, y, S(0.5) * (S(2) - a * a * a * a * a)); + return math::lerp(x, y, S(0.5) * (S(2) - a * a * a * a * a)); } } template T ease::in_expo(const T& x, const T& y, S a) { - return (a == S(0)) ? x : linear(x, y, std::pow(S(1024), a - S(1))); + return (a == S(0)) ? x : math::lerp(x, y, std::pow(S(1024), a - S(1))); } template T ease::out_expo(const T& x, const T& y, S a) { - return (a == S(1)) ? y : linear(y, x, std::pow(S(2), S(-10) * a)); + return (a == S(1)) ? y : math::lerp(y, x, std::pow(S(2), S(-10) * a)); } template @@ -255,19 +235,19 @@ T ease::in_out_expo(const T& x, const T& y, S a) return y; } - return linear(x, y, (a < S(0.5)) ? std::pow(S(2), S(20) * a - S(11)) : S(1) - std::pow(S(2), S(9) - S(20) * a)); + return math::lerp(x, y, (a < S(0.5)) ? std::pow(S(2), S(20) * a - S(11)) : S(1) - std::pow(S(2), S(9) - S(20) * a)); } template T ease::in_circ(const T& x, const T& y, S a) { - return linear(y, x, std::sqrt(S(1) - a * a)); + return math::lerp(y, x, std::sqrt(S(1) - a * a)); } template T ease::out_circ(const T& x, const T& y, S a) { - return linear(x, y, std::sqrt(-(a - S(2)) * a)); + return math::lerp(x, y, std::sqrt(-(a - S(2)) * a)); } template @@ -275,11 +255,11 @@ T ease::in_out_circ(const T& x, const T& y, S a) { if (a < S(0.5)) { - return linear(x, y, S(0.5) - S(0.5) * std::sqrt(S(1) - S(4) * a * a)); + return math::lerp(x, y, S(0.5) - S(0.5) * std::sqrt(S(1) - S(4) * a * a)); } else { - return linear(x, y, S(0.5) * (std::sqrt(S(-4) * (a - S(2)) * a - S(3)) + S(1))); + return math::lerp(x, y, S(0.5) * (std::sqrt(S(-4) * (a - S(2)) * a - S(3)) + S(1))); } } @@ -287,7 +267,7 @@ template T ease::in_back(const T& x, const T& y, S a) { const S c = S(1.70158); - return linear(x, y, a * a * (a * c + a - c)); + return math::lerp(x, y, a * a * (a * c + a - c)); } template @@ -295,7 +275,7 @@ T ease::out_back(const T& x, const T& y, S a) { const S c = S(1.70158); a -= S(1); - return linear(x, y, a * a * (a * c + a + c) + S(1)); + return math::lerp(x, y, a * a * (a * c + a + c) + S(1)); } template @@ -305,12 +285,12 @@ T ease::in_out_back(const T& x, const T& y, S a) if (a < S(0.5)) { - return linear(x, y, a * a * (a * (S(4) * c + S(4)) - S(2) * c)); + return math::lerp(x, y, a * a * (a * (S(4) * c + S(4)) - S(2) * c)); } else { S b = S(1) - S(2) * a; - return linear(x, y, b * b * (a * c + a - c * S(0.5) - S(1)) + S(1)); + return math::lerp(x, y, b * b * (a * c + a - c * S(0.5) - S(1)) + S(1)); } } @@ -326,7 +306,7 @@ T ease::in_elastic(const T& x, const T& y, S a) return y; } - return linear(x, y, -std::pow(S(1024), a - S(1)) * std::sin(S(20.944) * (a - S(1.075)))); + return math::lerp(x, y, -std::pow(S(1024), a - S(1)) * std::sin(S(20.944) * (a - S(1.075)))); } template @@ -341,7 +321,7 @@ T ease::out_elastic(const T& x, const T& y, S a) return y; } - return linear(x, y, std::pow(S(2), S(-10) * a) * std::sin(S(20.944) * (a - S(0.075))) + S(1)); + return math::lerp(x, y, std::pow(S(2), S(-10) * a) * std::sin(S(20.944) * (a - S(0.075))) + S(1)); } template @@ -358,19 +338,19 @@ T ease::in_out_elastic(const T& x, const T& y, S a) if (a < S(0.5)) { - return linear(x, y, std::pow(S(2), S(20) * a - S(11)) * std::sin(S(15.5334) - S(27.5293) * a)); + return math::lerp(x, y, std::pow(S(2), S(20) * a - S(11)) * std::sin(S(15.5334) - S(27.5293) * a)); } else { - return linear(y, x, std::pow(2, S(9) - S(20) * a) * std::sin(S(15.5334) - S(27.5293) * a)); + return math::lerp(y, x, std::pow(2, S(9) - S(20) * a) * std::sin(S(15.5334) - S(27.5293) * a)); } } template T ease::in_bounce(const T& x, const T& y, S a) { - return linear(x, y, S(1) - ease::out_bounce(S(0), S(1), S(1) - a)); + return math::lerp(x, y, S(1) - ease::out_bounce(S(0), S(1), S(1) - a)); } template @@ -399,7 +379,7 @@ T ease::out_bounce(const T& x, const T& y, S a) a = n * a * a + S(0.984375); } - return linear(x, y, a); + return math::lerp(x, y, a); } template @@ -407,11 +387,11 @@ T ease::in_out_bounce(const T& x, const T& y, S a) { if (a < S(0.5)) { - return linear(x, y, (S(1) - ease::out_bounce(S(0), S(1), S(1) - S(2) * a)) * S(0.5)); + return math::lerp(x, y, (S(1) - ease::out_bounce(S(0), S(1), S(1) - S(2) * a)) * S(0.5)); } else { - return linear(x, y, (S(1) + ease::out_bounce(S(0), S(1), S(2) * a - S(1))) * S(0.5)); + return math::lerp(x, y, (S(1) + ease::out_bounce(S(0), S(1), S(2) * a - S(1))) * S(0.5)); } } diff --git a/src/application.cpp b/src/application.cpp index bb025c0..187aaec 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -20,7 +20,6 @@ #include "application.hpp" #include "configuration.hpp" #include "state/application-states.hpp" -#include "math.hpp" // STL #include @@ -42,6 +41,9 @@ #include "debug/ansi-codes.hpp" #include "debug/console-commands.hpp" +// Math +#include "math/math.hpp" + // Resources #include "resources/resource-manager.hpp" @@ -109,8 +111,7 @@ // Utilities #include "utility/paths.hpp" #include "utility/timestamp.hpp" - -using namespace vmq::operators; +#include "utility/fundamental-types.hpp" application::application(int argc, char** argv): closed(false), @@ -177,7 +178,7 @@ application::application(int argc, char** argv): // Load configuration //load_config(); fullscreen = true; - vsync = false; + vsync = true; // Parse command line options parse_options(argc, argv); @@ -518,7 +519,7 @@ application::application(int argc, char** argv): overworld_compositor.add_pass(final_pass); // Setup overworld camera - overworld_camera.set_perspective(45.0f * vmq::pi / 180.0f, (float)window_width / (float)window_height, 0.1f, 1000.0f); + overworld_camera.set_perspective(math::radians(45.0f), (float)window_width / (float)window_height, 0.1f, 1000.0f); overworld_camera.set_compositor(&overworld_compositor); overworld_camera.set_composite_index(0); overworld_camera.set_active(true); @@ -548,7 +549,7 @@ application::application(int argc, char** argv): underworld_compositor.add_pass(underworld_final_pass); // Setup underworld camera - underworld_camera.set_perspective(45.0f * vmq::pi / 180.0f, (float)window_width / (float)window_height, 0.1f, 1000.0f); + underworld_camera.set_perspective(math::radians(45.0f), (float)window_width / (float)window_height, 0.1f, 1000.0f); underworld_camera.look_at({0, 50, 0}, {0, 0, 0}, {0, 0, -1}); underworld_camera.set_compositor(&underworld_compositor); underworld_camera.set_composite_index(0); @@ -751,11 +752,11 @@ application::application(int argc, char** argv): ecs::cavity_component cavity; cavity.position = { - frand(-r, r), - frand(-r * 2, r), - frand(-r, r) + math::random(-r, r), + math::random(-r * 2, r), + math::random(-r, r) }; - cavity.radius = frand(0.75f, 1.25f); + cavity.radius = math::random(0.75f, 1.25f); ecs_registry.assign(ecs_registry.create(), cavity); }); @@ -800,7 +801,7 @@ application::application(int argc, char** argv): spotlight.set_color({1, 1, 1}); spotlight.set_intensity(1.0f); spotlight.set_attenuation({1.0f, 0.09f, 0.032f}); - spotlight.set_cutoff({vmq::radians(15.0f), vmq::radians(30.0f)}); + spotlight.set_cutoff({math::radians(15.0f), math::radians(30.0f)}); spotlight.update_tweens(); spotlight.set_active(false); @@ -875,12 +876,9 @@ application::application(int argc, char** argv): //model_instance* larva = new model_instance(resource_manager->load("larva.obj")); //underworld_scene.add_object(larva); - quaternion flashlight_rotation = vmq::angle_axis(vmq::half_pi, {0.0f, 1.0f, 0.0f}); model_instance* flashlight = new model_instance(resource_manager->load("flashlight.obj")); - flashlight->set_rotation(flashlight_rotation); underworld_scene.add_object(flashlight); model_instance* flashlight_light_cone = new model_instance(resource_manager->load("flashlight-light-cone.obj")); - flashlight_light_cone->set_rotation(flashlight_rotation); underworld_scene.add_object(flashlight_light_cone); control_system->set_flashlight(flashlight, flashlight_light_cone); @@ -921,7 +919,7 @@ application::application(int argc, char** argv): animator->add_animation(radial_transition_outer->get_animation()); // Setup tweens - focal_point_tween.set_interpolator(ease::linear); + focal_point_tween.set_interpolator(math::lerp); // Register CLI commands cli.register_command("echo", cc::echo); @@ -974,7 +972,7 @@ int application::execute() // Setup time tween time[0] = time[1] = 0.0; - time.set_interpolator(ease::linear); + time.set_interpolator(math::lerp); // Schedule frames until closed while (!closed) @@ -1033,19 +1031,24 @@ void application::setup_fsm() initial_state = &splash_state; } +void application::load_config() +{ + +} + void application::parse_options(int argc, char** argv) { cxxopts::Options options("Antkeeper", "Ant colony simulation game"); options.add_options() - ("q,quick-start", "Skips splash screen") - ("c,continue", "Continues from last save") + ("c,continue", "Continues from the last save") + ("d,data", "Sets the data package path", cxxopts::value()) + ("f,fullscreen", "Starts in fullscreen mode") ("n,new-game", "Starts a new game") + ("q,quick-start", "Skips to the main menu") ("r,reset", "Restores all settings to default") - ("f,fullscreen", "Starts in fullscreen mode") - ("w,windowed", "Starts in windowed mode") ("v,vsync", "Enables or disables v-sync", cxxopts::value()) - ("d,data", "Specifies the data package path", cxxopts::value()) + ("w,windowed", "Starts in windowed mode") ; logger.push_task("Parsing command line options"); @@ -1054,29 +1057,23 @@ void application::parse_options(int argc, char** argv) { auto result = options.parse(argc, argv); - // --quick-start - if (result.count("quick-start")) - { - logger.log("Skipping splash screen"); - initial_state = &play_state; - } - // --continue if (result.count("continue")) { logger.log("Continuing from last save"); } - // --new-game - if (result.count("new-game")) - { - logger.log("Starting a new game"); - } - - // --reset - if (result.count("reset")) + // --data + if (result.count("data")) { - logger.log("Restoring all settings to default"); + data_package_path = result["data"].as(); + + if (std::filesystem::path(data_package_path).is_relative()) + { + data_package_path = data_path + data_package_path; + } + + logger.log("Set alternative data package path \"" + data_package_path + "\""); } // --fullscreen @@ -1086,11 +1083,23 @@ void application::parse_options(int argc, char** argv) fullscreen = true; } - // --windowed - if (result.count("windowed")) + // --new-game + if (result.count("new-game")) { - logger.log("Starting in windowed mode"); - fullscreen = false; + logger.log("Starting a new game"); + } + + // --quick-start + if (result.count("quick-start")) + { + logger.log("Skipping splash screen"); + initial_state = &play_state; + } + + // --reset + if (result.count("reset")) + { + logger.log("Restoring all settings to default"); } // --vsync @@ -1108,17 +1117,11 @@ void application::parse_options(int argc, char** argv) } } - // --data - if (result.count("data")) + // --windowed + if (result.count("windowed")) { - data_package_path = result["data"].as(); - - if (std::filesystem::path(data_package_path).is_relative()) - { - data_package_path = data_path + data_package_path; - } - - logger.log("Set alternative data package path \"" + data_package_path + "\""); + logger.log("Starting in windowed mode"); + fullscreen = false; } } catch (const std::exception& e) diff --git a/src/application.hpp b/src/application.hpp index 085fff5..0f6e5cd 100644 --- a/src/application.hpp +++ b/src/application.hpp @@ -188,6 +188,7 @@ public: private: void setup_fsm(); + void load_config(); void parse_options(int argc, char** argv); diff --git a/src/camera-rig.cpp b/src/camera-rig.cpp index 791a284..5c3633d 100644 --- a/src/camera-rig.cpp +++ b/src/camera-rig.cpp @@ -19,16 +19,15 @@ #include "orbit-cam.hpp" #include "scene/camera.hpp" +#include "math/constants.hpp" #include "configuration.hpp" #include #include -using namespace vmq::operators; - camera_rig::camera_rig(): camera(nullptr), translation{0.0f, 0.0f, 0.0f}, - rotation(vmq::identity_quaternion), + rotation(math::identity_quaternion), forward(global_forward), right(global_right), up(global_up) @@ -53,7 +52,7 @@ void camera_rig::set_translation(const float3& translation) this->translation = translation; } -void camera_rig::set_rotation(const vmq::quaternion& rotation) +void camera_rig::set_rotation(const quaternion_type& rotation) { this->rotation = rotation; @@ -62,4 +61,3 @@ void camera_rig::set_rotation(const vmq::quaternion& rotation) up = rotation * global_up; right = rotation * global_right; } - diff --git a/src/camera-rig.hpp b/src/camera-rig.hpp index 5c355d2..830bc6a 100644 --- a/src/camera-rig.hpp +++ b/src/camera-rig.hpp @@ -20,9 +20,9 @@ #ifndef ANTKEEPER_CAMERA_RIG_HPP #define ANTKEEPER_CAMERA_RIG_HPP -#include - -using namespace vmq::types; +#include "math/quaternion-type.hpp" +#include "math/transform-type.hpp" +#include "utility/fundamental-types.hpp" class camera; @@ -32,6 +32,9 @@ class camera; class camera_rig { public: + typedef math::quaternion quaternion_type; + typedef math::transform transform_type; + camera_rig(); /** @@ -61,7 +64,7 @@ public: /** * Sets the rotation of the camera rig. */ - void set_rotation(const vmq::quaternion& rotation); + void set_rotation(const quaternion_type& rotation); /** * Returns the attached camera. @@ -72,7 +75,7 @@ public: ::camera* get_camera(); const float3& get_translation() const; - const vmq::quaternion& get_rotation() const; + const quaternion_type& get_rotation() const; const float3& get_forward() const; const float3& get_right() const; const float3& get_up() const; @@ -80,7 +83,7 @@ public: private: camera* camera; float3 translation; - vmq::quaternion rotation; + quaternion_type rotation; float3 forward; float3 right; float3 up; @@ -101,7 +104,7 @@ inline const float3& camera_rig::get_translation() const return translation; } -inline const vmq::quaternion& camera_rig::get_rotation() const +inline const typename camera_rig::quaternion_type& camera_rig::get_rotation() const { return rotation; } diff --git a/src/configuration.hpp.in b/src/configuration.hpp.in index 1b314b1..f1dda17 100644 --- a/src/configuration.hpp.in +++ b/src/configuration.hpp.in @@ -20,18 +20,16 @@ #ifndef ANTKEEPER_CONFIGURATION_HPP #define ANTKEEPER_CONFIGURATION_HPP -#include - -using namespace vmq::types; +#include "math/vector-type.hpp" #define ANTKEEPER_VERSION_MAJOR @PROJECT_VERSION_MAJOR@ #define ANTKEEPER_VERSION_MINOR @PROJECT_VERSION_MINOR@ #define ANTKEEPER_VERSION_PATCH @PROJECT_VERSION_PATCH@ #define ANTKEEPER_VERSION_STRING "@PROJECT_VERSION@" -constexpr float3 global_forward = {0.0f, 0.0f, -1.0f}; -constexpr float3 global_up = {0.0f, 1.0f, 0.0f}; -constexpr float3 global_right = {1.0f, 0.0f, 0.0f}; +constexpr math::vector global_forward = {0.0f, 0.0f, -1.0f}; +constexpr math::vector global_up = {0.0f, 1.0f, 0.0f}; +constexpr math::vector global_right = {1.0f, 0.0f, 0.0f}; #define MATERIAL_PASS_MAX_AMBIENT_LIGHT_COUNT 1 #define MATERIAL_PASS_MAX_POINT_LIGHT_COUNT 1 diff --git a/src/entity/components/cavity-component.hpp b/src/entity/components/cavity-component.hpp index bb6f655..dee3751 100644 --- a/src/entity/components/cavity-component.hpp +++ b/src/entity/components/cavity-component.hpp @@ -20,8 +20,7 @@ #ifndef ANTKEEPER_ECS_CAVITY_COMPONENT_HPP #define ANTKEEPER_ECS_CAVITY_COMPONENT_HPP -#include -using namespace vmq::types; +#include "math/math.hpp" namespace ecs { diff --git a/src/entity/components/locomotion-component.hpp b/src/entity/components/locomotion-component.hpp index ed2ec3d..783d6ac 100644 --- a/src/entity/components/locomotion-component.hpp +++ b/src/entity/components/locomotion-component.hpp @@ -21,8 +21,7 @@ #define ANTKEEPER_ECS_PLACEMENT_COMPONENT_HPP #include "geometry/mesh.hpp" -#include -using namespace vmq::types; +#include "utility/fundamental-types.hpp" namespace ecs { diff --git a/src/entity/components/samara-component.hpp b/src/entity/components/samara-component.hpp index 3c7dc31..57be90e 100644 --- a/src/entity/components/samara-component.hpp +++ b/src/entity/components/samara-component.hpp @@ -20,8 +20,7 @@ #ifndef ANTKEEPER_ECS_SAMARA_COMPONENT_HPP #define ANTKEEPER_ECS_SAMARA_COMPONENT_HPP -#include -using namespace vmq::types; +#include "utility/fundamental-types.hpp" namespace ecs { diff --git a/src/entity/components/transform-component.hpp b/src/entity/components/transform-component.hpp index 2b89e97..e475206 100644 --- a/src/entity/components/transform-component.hpp +++ b/src/entity/components/transform-component.hpp @@ -20,13 +20,13 @@ #ifndef ANTKEEPER_ECS_TRANSFORM_COMPONENT_HPP #define ANTKEEPER_ECS_TRANSFORM_COMPONENT_HPP -#include +#include "math/math.hpp" namespace ecs { struct transform_component { - vmq::transform transform; + math::transform transform; bool warp; }; diff --git a/src/entity/entity-commands.hpp b/src/entity/entity-commands.hpp index b5197fd..7240f46 100644 --- a/src/entity/entity-commands.hpp +++ b/src/entity/entity-commands.hpp @@ -20,18 +20,14 @@ #ifndef ANTKEEPER_ECS_ENTITY_COMMANDS_HPP #define ANTKEEPER_ECS_ENTITY_COMMANDS_HPP +#include "utility/fundamental-types.hpp" #include -#include - -using namespace vmq; namespace ecs { void move_to(entt::registry& registry, entt::entity entity, const float3& position); void warp_to(entt::registry& registry, entt::entity entity, const float3& position); - void assign_render_layers(entt::registry& registry, entt::entity entity, unsigned int layers); - void bind_transform(entt::registry& registry, entt::entity entity, entt::entity target); } // namespace ecs diff --git a/src/geometry/aabb.hpp b/src/geometry/aabb.hpp index 2ebc305..95ae731 100644 --- a/src/geometry/aabb.hpp +++ b/src/geometry/aabb.hpp @@ -22,20 +22,18 @@ #include "bounding-volume.hpp" #include "sphere.hpp" -#include -#include +#include "math/math.hpp" #include -using vmq::vector; -using vmq::matrix; -using vmq::transform; -using namespace vmq::operators; - template struct aabb: public bounding_volume { - vector min_point; - vector max_point; + typedef math::vector vector_type; + typedef math::matrix matrix_type; + typedef math::transform transform_type; + + vector_type min_point; + vector_type max_point; /** * Transforms an AABB. @@ -44,7 +42,7 @@ struct aabb: public bounding_volume * @param t Transform by which the AABB should be transformed. * @return Transformed AABB. */ - static aabb transform(const aabb& a, const ::transform& t); + static aabb transform(const aabb& a, const transform_type& t); /** * Transforms an AABB. @@ -53,9 +51,9 @@ struct aabb: public bounding_volume * @param m Matrix by which the AABB should be transformed. * @return Transformed AABB. */ - static aabb transform(const aabb& a, const matrix& m); + static aabb transform(const aabb& a, const matrix_type& m); - aabb(const vector& min_point, const vector& max_point); + aabb(const vector_type& min_point, const vector_type& max_point); aabb(); virtual bounding_volume_type get_bounding_volume_type() const; @@ -63,7 +61,7 @@ struct aabb: public bounding_volume virtual bool intersects(const aabb& aabb) const; virtual bool contains(const sphere& sphere) const; virtual bool contains(const aabb& aabb) const; - virtual bool contains(const vector& point) const; + virtual bool contains(const vector_type& point) const; /** * Returns the position of the specified corner. @@ -71,18 +69,18 @@ struct aabb: public bounding_volume * @param index Index of a corner. * @return Position of the specified corner. */ - vector corner(int index) const noexcept; + vector_type corner(int index) const noexcept; }; template -aabb aabb::transform(const aabb& a, const ::transform& t) +aabb aabb::transform(const aabb& a, const transform_type& t) { - vector min_point = {std::numeric_limits::infinity(), std::numeric_limits::infinity(), std::numeric_limits::infinity()}; - vector max_point = {-std::numeric_limits::infinity(), -std::numeric_limits::infinity(), -std::numeric_limits::infinity()}; + vector_type min_point = {std::numeric_limits::infinity(), std::numeric_limits::infinity(), std::numeric_limits::infinity()}; + vector_type max_point = {-std::numeric_limits::infinity(), -std::numeric_limits::infinity(), -std::numeric_limits::infinity()}; for (std::size_t i = 0; i < 8; ++i) { - vector transformed_corner = vmq::mul(t, a.corner(i)); + vector_type transformed_corner = math::mul(t, a.corner(i)); for (std::size_t j = 0; j < 3; ++j) { @@ -95,15 +93,15 @@ aabb aabb::transform(const aabb& a, const ::transform& t) } template -aabb aabb::transform(const aabb& a, const matrix& m) +aabb aabb::transform(const aabb& a, const matrix_type& m) { - vector min_point = {std::numeric_limits::infinity(), std::numeric_limits::infinity(), std::numeric_limits::infinity()}; - vector max_point = {-std::numeric_limits::infinity(), -std::numeric_limits::infinity(), -std::numeric_limits::infinity()}; + vector_type min_point = {std::numeric_limits::infinity(), std::numeric_limits::infinity(), std::numeric_limits::infinity()}; + vector_type max_point = {-std::numeric_limits::infinity(), -std::numeric_limits::infinity(), -std::numeric_limits::infinity()}; for (std::size_t i = 0; i < 8; ++i) { - vector corner = a.corner(i); - vector transformed_corner = vmq::mul(m, vector{corner.x, corner.y, corner.z, T(1)}); + vector_type corner = a.corner(i); + vector transformed_corner = math::mul(m, vector{corner.x, corner.y, corner.z, T(1)}); for (std::size_t j = 0; j < 3; ++j) { @@ -116,7 +114,7 @@ aabb aabb::transform(const aabb& a, const matrix& m) } template -aabb::aabb(const vector& min_point, const vector& max_point): +aabb::aabb(const vector_type& min_point, const vector_type& max_point): min_point(min_point), max_point(max_point) {} @@ -134,7 +132,7 @@ inline bounding_volume_type aabb::get_bounding_volume_type() const template bool aabb::intersects(const sphere& sphere) const { - const vector radius_vector = {sphere.radius, sphere.radius, sphere.radius}; + const vector_type radius_vector = {sphere.radius, sphere.radius, sphere.radius}; return aabb(min_point - radius_vector, max_point + radius_vector).contains(sphere.center); } @@ -175,7 +173,7 @@ bool aabb::contains(const aabb& aabb) const } template -bool aabb::contains(const vector& point) const +bool aabb::contains(const vector_type& point) const { if (point.x < min_point.x || point.x > max_point.x) return false; @@ -187,7 +185,7 @@ bool aabb::contains(const vector& point) const } template -vector aabb::corner(int index) const noexcept +typename aabb::vector_type aabb::corner(int index) const noexcept { return { diff --git a/src/geometry/bounding-volume.hpp b/src/geometry/bounding-volume.hpp index cb7d60d..71200ce 100644 --- a/src/geometry/bounding-volume.hpp +++ b/src/geometry/bounding-volume.hpp @@ -20,10 +20,10 @@ #ifndef ANTKEEPER_BOUNDING_VOLUME_HPP #define ANTKEEPER_BOUNDING_VOLUME_HPP +#include "math/math.hpp" #include -#include -using vmq::vector; +using math::vector; template struct sphere; @@ -91,4 +91,3 @@ bool bounding_volume::intersects(const bounding_volume& volume) const } #endif // ANTKEEPER_BOUNDING_VOLUME_HPP - diff --git a/src/geometry/convex-hull.hpp b/src/geometry/convex-hull.hpp index a9d2fd6..cfc2f91 100644 --- a/src/geometry/convex-hull.hpp +++ b/src/geometry/convex-hull.hpp @@ -20,12 +20,12 @@ #ifndef ANTKEEPER_CONVEX_HULL_HPP #define ANTKEEPER_CONVEX_HULL_HPP +#include "bounding-volume.hpp" +#include "geometry/plane.hpp" +#include "geometry/sphere.hpp" +#include "geometry/aabb.hpp" #include #include -#include "bounding-volume.hpp" -#include "plane.hpp" -#include "sphere.hpp" -#include "aabb.hpp" /** * A plane-bounded convex hull. @@ -73,7 +73,7 @@ template bool convex_hull::intersects(const sphere& sphere) const { for (const plane& plane: planes) - if (signed_distance(plane, sphere.center) < -sphere.radius) + if (plane.signed_distance(sphere.center) < -sphere.radius) return false; return true; } @@ -87,7 +87,7 @@ bool convex_hull::intersects(const aabb& aabb) const pv.x = (plane.normal.x > T(0)) ? aabb.max_point.x : aabb.min_point.x; pv.y = (plane.normal.y > T(0)) ? aabb.max_point.y : aabb.min_point.y; pv.z = (plane.normal.z > T(0)) ? aabb.max_point.z : aabb.min_point.z; - if (signed_distance(plane, pv) < T(0)) + if (plane.signed_distance(pv) < T(0)) return false; } @@ -98,7 +98,7 @@ template bool convex_hull::contains(const sphere& sphere) const { for (const plane& plane: planes) - if (signed_distance(plane, sphere.center) < sphere.radius) + if (plane.signed_distance(sphere.center) < sphere.radius) return false; return true; } @@ -118,7 +118,7 @@ bool convex_hull::contains(const aabb& aabb) const nv.y = (plane.normal.y < T(0)) ? aabb.max_point.y : aabb.min_point.y; nv.z = (plane.normal.z < T(0)) ? aabb.max_point.z : aabb.min_point.z; - if (signed_distance(plane, pv) < T(0) || signed_distance(plane, nv) < T(0)) + if (plane.signed_distance(pv) < T(0) || plane.signed_distance(nv) < T(0)) return false; } @@ -129,7 +129,7 @@ template bool convex_hull::contains(const vector& point) const { for (const plane& plane: planes) - if (signed_distance(plane, point) < T(0)) + if (plane.signed_distance(point) < T(0)) return false; return true; diff --git a/src/geometry/csg.hpp b/src/geometry/csg.hpp index 94ef6af..8237890 100644 --- a/src/geometry/csg.hpp +++ b/src/geometry/csg.hpp @@ -20,15 +20,11 @@ #ifndef ANTKEEPER_CSG_HPP #define ANTKEEPER_CSG_HPP +#include "utility/fundamental-types.hpp" #include -#include - namespace csg { -using vmq::float3; -using vmq::float4; - struct plane { float3 normal; diff --git a/src/geometry/intersection.cpp b/src/geometry/intersection.cpp index 84afa55..fd3776f 100644 --- a/src/geometry/intersection.cpp +++ b/src/geometry/intersection.cpp @@ -22,10 +22,10 @@ std::tuple ray_plane_intersection(const ray& ray, const plane& plane) { - float denom = vmq::dot(ray.direction, plane.normal); + float denom = math::dot(ray.direction, plane.normal); if (denom != 0.0f) { - float t = -(vmq::dot(ray.origin, plane.normal) + plane.distance) / denom; + float t = -(math::dot(ray.origin, plane.normal) + plane.distance) / denom; if (t >= 0.0f) { @@ -43,8 +43,8 @@ std::tuple ray_triangle_intersection(const ray float3 edge20 = c - a; // Calculate determinant - float3 pv = vmq::cross(ray.direction, edge20); - float det = vmq::dot(edge10, pv); + float3 pv = math::cross(ray.direction, edge20); + float det = math::dot(edge10, pv); if (!det) { @@ -55,7 +55,7 @@ std::tuple ray_triangle_intersection(const ray // Calculate u float3 tv = ray.origin - a; - float u = vmq::dot(tv, pv) * inverse_det; + float u = math::dot(tv, pv) * inverse_det; if (u < 0.0f || u > 1.0f) { @@ -63,8 +63,8 @@ std::tuple ray_triangle_intersection(const ray } // Calculate v - float3 qv = vmq::cross(tv, edge10); - float v = vmq::dot(ray.direction, qv) * inverse_det; + float3 qv = math::cross(tv, edge10); + float v = math::dot(ray.direction, qv) * inverse_det; if (v < 0.0f || u + v > 1.0f) { @@ -72,7 +72,7 @@ std::tuple ray_triangle_intersection(const ray } // Calculate t - float t = vmq::dot(edge20, qv) * inverse_det; + float t = math::dot(edge20, qv) * inverse_det; if (t > 0.0f) { diff --git a/src/geometry/intersection.hpp b/src/geometry/intersection.hpp index 0dfde97..4ca459f 100644 --- a/src/geometry/intersection.hpp +++ b/src/geometry/intersection.hpp @@ -20,16 +20,12 @@ #ifndef ANTKEEPER_INTERSECTION_HPP #define ANTKEEPER_INTERSECTION_HPP +#include "geometry/aabb.hpp" +#include "geometry/mesh.hpp" +#include "geometry/plane.hpp" +#include "geometry/ray.hpp" +#include "utility/fundamental-types.hpp" #include -#include -#include "aabb.hpp" -#include "mesh.hpp" -#include "plane.hpp" -#include "ray.hpp" - -using namespace vmq::types; -using namespace vmq::operators; - /** * Tests for intersection between a ray and a plane. diff --git a/src/geometry/mesh-accelerator.hpp b/src/geometry/mesh-accelerator.hpp index 097683f..5aa11e6 100644 --- a/src/geometry/mesh-accelerator.hpp +++ b/src/geometry/mesh-accelerator.hpp @@ -20,16 +20,14 @@ #ifndef ANTKEEPER_MESH_ACCELERATOR_HPP #define ANTKEEPER_MESH_ACCELERATOR_HPP -#include "mesh.hpp" +#include "geometry/mesh.hpp" #include "geometry/octree.hpp" #include "geometry/aabb.hpp" -#include "intersection.hpp" +#include "geometry/intersection.hpp" +#include "utility/fundamental-types.hpp" #include -#include #include -#include -using namespace vmq::types; -using namespace vmq::operators; +#include /** * Acceleration structure for querying mesh geometry. diff --git a/src/geometry/mesh-functions.cpp b/src/geometry/mesh-functions.cpp index 46c4a17..8f068a2 100644 --- a/src/geometry/mesh-functions.cpp +++ b/src/geometry/mesh-functions.cpp @@ -18,13 +18,8 @@ */ #include "mesh-functions.hpp" -#include -#include +#include "math/math.hpp" #include -#include -#include - -using namespace vmq::operators; struct edge_hasher { @@ -60,10 +55,6 @@ void create_triangle_mesh(mesh& mesh, const std::vector& vertices, const if (auto it = edge_map.find({start->index, end->index}); it != edge_map.end()) { - /* - if (it->second->face) - std::cout << "THIS EDGE ALREADY HAS A FACE!\n" << std::endl; - */ loop[j] = it->second; } else @@ -92,7 +83,7 @@ void calculate_face_normals(float* normals, const mesh& mesh) const float3& b = reinterpret_cast(face.edge->next->vertex->position); const float3& c = reinterpret_cast(face.edge->previous->vertex->position); - normal = vmq::normalize(vmq::cross(b - a, c - a)); + normal = math::normalize(math::cross(b - a, c - a)); } } @@ -118,5 +109,3 @@ aabb calculate_bounds(const mesh& mesh) return aabb{bounds_min, bounds_max}; } - - diff --git a/src/geometry/mesh-functions.hpp b/src/geometry/mesh-functions.hpp index b611696..410e7da 100644 --- a/src/geometry/mesh-functions.hpp +++ b/src/geometry/mesh-functions.hpp @@ -20,13 +20,11 @@ #ifndef ANTKEEPER_MESH_FUNCTIONS_HPP #define ANTKEEPER_MESH_FUNCTIONS_HPP -#include "mesh.hpp" -#include +#include "geometry/aabb.hpp" +#include "geometry/mesh.hpp" +#include "utility/fundamental-types.hpp" #include #include -#include "geometry/aabb.hpp" - -using namespace vmq::types; /** * Creates a triangle mesh from a list of vertices and indices. diff --git a/src/geometry/plane.hpp b/src/geometry/plane.hpp index b36bebb..0dd70c6 100644 --- a/src/geometry/plane.hpp +++ b/src/geometry/plane.hpp @@ -20,93 +20,97 @@ #ifndef ANTKEEPER_PLANE_HPP #define ANTKEEPER_PLANE_HPP -#include - -using vmq::vector; -using namespace vmq::operators; +#include "math/math.hpp" template struct plane { - vector normal; + typedef math::vector vector_type; + + /// Plane normal vector. + vector_type normal; + + /// Plane distance. T distance; /** * Creates a plane given a normal vector and distance. */ - plane(const vector& normal, T distance); + plane(const vector_type& normal, T distance); /** * Creates a plane given a normal vector and offset vector. */ - plane(const vector& normal, const vector& offset); + plane(const vector_type& normal, const vector_type& offset); /** * Creates a plane given three points. */ - plane(const vector& a, const vector& b, const vector& c); + plane(const vector_type& a, const vector_type& b, const vector_type& c); /** * Creates a plane given its coefficients. * * @param coefficients Vector containing the plane coefficients, A, B, C and D, as x, y, z, and w, respectively. */ - plane(const vector& coefficients); + plane(const math::vector& coefficients); /// Creates an uninitialized plane. plane() = default; + + /** + * Calculates the signed distance between a plane and a vector. + * + * @param v Vector. + * @return Signed distance between the plane and vector. + */ + T signed_distance(const vector_type& v) const; + + /** + * Calculates the point of intersection between three planes. + */ + static vector_type intersection(const plane& p0, const plane& p1, const plane& p2); }; template -inline plane::plane(const vector& normal, T distance): +inline plane::plane(const vector_type& normal, T distance): normal(normal), distance(distance) {} template -plane::plane(const vector& normal, const vector& offset): +plane::plane(const vector_type& normal, const vector_type& offset): normal(normal), - distance(-vmq::dot(normal, offset)) + distance(-math::dot(normal, offset)) {} template -plane::plane(const vector& a, const vector& b, const vector& c) +plane::plane(const vector_type& a, const vector_type& b, const vector_type& c) { - normal = vmq::normalize(vmq::cross(c - b, a - b)); - distance = -(vmq::dot(normal, b)); + normal = math::normalize(math::cross(c - b, a - b)); + distance = -(math::dot(normal, b)); } template -plane::plane(const vector& coefficients) +plane::plane(const math::vector& coefficients) { - const vector abc = vmq::resize<3>(coefficients); - const float inverse_length = T(1) / vmq::length(abc); + const vector_type abc = math::resize<3>(coefficients); + const float inverse_length = T(1) / math::length(abc); normal = abc * inverse_length; distance = coefficients[3] * inverse_length; } -/** - * Calculates the signed distance between a plane and a vector. - * - * @param p Plane. - * @param v Vector. - * @return Signed distance between the plane and a vector. - */ template -inline T signed_distance(const plane& p, const vector& v) +inline T plane::signed_distance(const vector_type& v) const { - return p.distance + vmq::dot(p.normal, v); + return distance + math::dot(normal, v); } -/** - * Calculates the point of intersection between three planes. - */ template -vector intersection(const plane& p0, const plane& p1, const plane& p2) +typename plane::vector_type plane::intersection(const plane& p0, const plane& p1, const plane& p2) { - return -(p0.distance * vmq::cross(p1.normal, p2.normal) + p1.distance * vmq::cross(p2.normal, p0.normal) + p2.distance * vmq::cross(p0.normal, p1.normal)) / vmq::dot(p0.normal, vmq::cross(p1.normal, p2.normal)); + return -(p0.distance * math::cross(p1.normal, p2.normal) + p1.distance * math::cross(p2.normal, p0.normal) + p2.distance * math::cross(p0.normal, p1.normal)) / math::dot(p0.normal, math::cross(p1.normal, p2.normal)); } #endif // ANTKEEPER_PLANE_HPP - diff --git a/src/geometry/projection.hpp b/src/geometry/projection.hpp new file mode 100644 index 0000000..d9dc9bc --- /dev/null +++ b/src/geometry/projection.hpp @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_PROJECTION_HPP +#define ANTKEEPER_PROJECTION_HPP + +#include "math/math.hpp" + +template +math::vector project_on_plane(const math::vector& v, const math::vector& p, const math::vector& n) +{ + return v - n * math::dot(v - p, n); +} + +#endif // ANTKEEPER_PROJECTION_HPP diff --git a/src/geometry/ray.hpp b/src/geometry/ray.hpp index a81c958..bfb04ef 100644 --- a/src/geometry/ray.hpp +++ b/src/geometry/ray.hpp @@ -20,22 +20,30 @@ #ifndef ANTKEEPER_RAY_HPP #define ANTKEEPER_RAY_HPP -#include - -using vmq::vector; -using namespace vmq::operators; +#include "math/math.hpp" template struct ray { - vector origin; - vector direction; - - vector extrapolate(T distance) const; + typedef math::vector vector_type; + + /// Origin of the ray. + vector_type origin; + + /// Normalized direction vector of the ray. + vector_type direction; + + /** + * Extrapolates from the ray origin along the ray direction vector. + * + * @param distance Distance to extrapolate. + * @return Extrapolated coordinates. + */ + vector_type extrapolate(T distance) const; }; template -inline vector ray::extrapolate(T distance) const +inline typename ray::vector_type ray::extrapolate(T distance) const { return origin + direction * distance; } diff --git a/src/geometry/sdf.hpp b/src/geometry/sdf.hpp index 3b1f09d..b117ec1 100644 --- a/src/geometry/sdf.hpp +++ b/src/geometry/sdf.hpp @@ -20,9 +20,8 @@ #ifndef ANTKEEPER_SDF_HPP #define ANTKEEPER_SDF_HPP -#include -using namespace vmq::types; -using namespace vmq::operators; +#include "utility/fundamental-types.hpp" +#include /** * Contains signed distance functions. @@ -36,14 +35,14 @@ inline float3 translate(const float3& sample, const float3& offset) inline float sphere(const float3& p, float r) { - return vmq::length(p) - r; + return math::length(p) - r; } inline float cylinder(const float3& p, float r, float h) { - float dx = std::abs(vmq::length(vmq::swizzle<0, 2>(p))) - r; + float dx = std::abs(math::length(math::swizzle<0, 2>(p))) - r; float dy = std::abs(p[1]) - h; - return std::min(std::max(dx, dy), 0.0f) + vmq::length(float2{std::max(dx, 0.0f), std::max(dy, 0.0f)}); + return std::min(std::max(dx, dy), 0.0f) + math::length(float2{std::max(dx, 0.0f), std::max(dy, 0.0f)}); } inline float op_union(float a, float b) diff --git a/src/geometry/sphere.hpp b/src/geometry/sphere.hpp index 2767374..0cd8427 100644 --- a/src/geometry/sphere.hpp +++ b/src/geometry/sphere.hpp @@ -20,21 +20,20 @@ #ifndef ANTKEEPER_SPHERE_HPP #define ANTKEEPER_SPHERE_HPP -#include "bounding-volume.hpp" -#include "aabb.hpp" -#include +#include "geometry/bounding-volume.hpp" +#include "geometry/aabb.hpp" +#include "math/math.hpp" #include -using vmq::vector; -using namespace vmq::operators; - template struct sphere: public bounding_volume { - vector center; + typedef math::vector vector_type; + + vector_type center; T radius; - sphere(const vector& center, T radius); + sphere(const vector_type& center, T radius); sphere(); virtual bounding_volume_type get_bounding_volume_type() const; @@ -42,11 +41,11 @@ struct sphere: public bounding_volume virtual bool intersects(const aabb& aabb) const; virtual bool contains(const sphere& sphere) const; virtual bool contains(const aabb& aabb) const; - virtual bool contains(const vector& point) const; + virtual bool contains(const vector_type& point) const; }; template -sphere::sphere(const vector& center, T radius): +sphere::sphere(const vector_type& center, T radius): center(center), radius(radius) {} @@ -64,9 +63,9 @@ inline bounding_volume_type sphere::get_bounding_volume_type() const template bool sphere::intersects(const sphere& sphere) const { - vector d = center - sphere.center; + vector_type d = center - sphere.center; float r = radius + sphere.radius; - return (vmq::dot(d, d) <= r * r); + return (math::dot(d, d) <= r * r); } template @@ -82,8 +81,8 @@ bool sphere::contains(const sphere& sphere) const if (containment_radius < T(0)) return false; - vector d = center - sphere.center; - return (vmq::dot(d, d) <= containment_radius * containment_radius); + vector_type d = center - sphere.center; + return (math::dot(d, d) <= containment_radius * containment_radius); } template @@ -91,8 +90,8 @@ bool sphere::contains(const aabb& aabb) const { T distance = T(0); - vector a = center - aabb.min_point; - vector b = center - aabb.max_point; + vector_type a = center - aabb.min_point; + vector_type b = center - aabb.max_point; distance += std::max(a.x * a.x, b.x * b.x); distance += std::max(a.y * a.y, b.y * b.y); @@ -102,10 +101,10 @@ bool sphere::contains(const aabb& aabb) const } template -bool sphere::contains(const vector& point) const +bool sphere::contains(const vector_type& point) const { - vector d = center - point; - return (vmq::dot(d, d) <= radius * radius); + vector_type d = center - point; + return (math::dot(d, d) <= radius * radius); } #endif // ANTKEEPER_SPHERE_HPP diff --git a/src/geometry/view-frustum.hpp b/src/geometry/view-frustum.hpp index 2ebae6b..a71b820 100644 --- a/src/geometry/view-frustum.hpp +++ b/src/geometry/view-frustum.hpp @@ -20,24 +20,24 @@ #ifndef ANTKEEPER_VIEW_FRUSTUM_HPP #define ANTKEEPER_VIEW_FRUSTUM_HPP -#include "convex-hull.hpp" +#include "geometry/convex-hull.hpp" +#include "math/math.hpp" #include -#include - -using vmq::vector; -using vmq::matrix; -using namespace vmq::operators; template class view_frustum { public: + typedef math::vector vector_type; + typedef math::matrix matrix_type; + typedef plane plane_type; + /** * Creates a view frustum from a view-projection matrix. * * @param view_projection View-projection matrix. */ - view_frustum(const matrix& view_projection); + view_frustum(const matrix_type& view_projection); /// Creates an uninitialized view frustum. view_frustum(); @@ -47,46 +47,46 @@ public: * * @param view_projection View-projection matrix. */ - void set_matrix(const matrix& view_projection); + void set_matrix(const matrix_type& view_projection); /// Returns a convex hull which describes the bounds of the view frustum. const convex_hull& get_bounds() const; /// Returns the left clipping plane. - const plane& get_left() const; + const plane_type& get_left() const; /// Returns the right clipping plane. - const plane& get_right() const; + const plane_type& get_right() const; /// Returns the bottom clipping plane. - const plane& get_bottom() const; + const plane_type& get_bottom() const; /// Returns the top clipping plane. - const plane& get_top() const; + const plane_type& get_top() const; /// Returns the near clipping plane. - const plane& get_near() const; + const plane_type& get_near() const; /// Returns the far clipping plane. - const plane& get_far() const; + const plane_type& get_far() const; /** * Returns an array containing the corners of the view frustum bounds. * * @return Array containing the corners of the view frustum bounds. Corners are stored in the following order: NTL, NTR, NBL, NBR, FTL, FTR, FBL, FBR; where N is near, F is far, T is top, B is bottom, L is left, and R is right, therefore NTL refers to the corner shared between the near, top, and left clipping planes. */ - const std::array, 8>& get_corners() const; + const std::array& get_corners() const; private: - void recalculate_planes(const matrix& view_projection); + void recalculate_planes(const matrix_type& view_projection); void recalculate_corners(); convex_hull bounds; - std::array, 8> corners; + std::array corners; }; template -view_frustum::view_frustum(const matrix& view_projection): +view_frustum::view_frustum(const matrix_type& view_projection): bounds(6) { set_matrix(view_projection); @@ -94,11 +94,11 @@ view_frustum::view_frustum(const matrix& view_projection): template view_frustum::view_frustum(): - view_frustum(vmq::identity4x4) + view_frustum(math::identity4x4) {} template -void view_frustum::set_matrix(const matrix& view_projection) +void view_frustum::set_matrix(const matrix_type& view_projection) { recalculate_planes(view_projection); recalculate_corners(); @@ -111,70 +111,70 @@ inline const convex_hull& view_frustum::get_bounds() const } template -inline const plane& view_frustum::get_left() const +inline const typename view_frustum::plane_type& view_frustum::get_left() const { return bounds.planes[0]; } template -inline const plane& view_frustum::get_right() const +inline const typename view_frustum::plane_type& view_frustum::get_right() const { return bounds.planes[1]; } template -inline const plane& view_frustum::get_bottom() const +inline const typename view_frustum::plane_type& view_frustum::get_bottom() const { return bounds.planes[2]; } template -inline const plane& view_frustum::get_top() const +inline const typename view_frustum::plane_type& view_frustum::get_top() const { return bounds.planes[3]; } template -inline const plane& view_frustum::get_near() const +inline const typename view_frustum::plane_type& view_frustum::get_near() const { return bounds.planes[4]; } template -inline const plane& view_frustum::get_far() const +inline const typename view_frustum::plane_type& view_frustum::get_far() const { return bounds.planes[5]; } template -inline const std::array, 8>& view_frustum::get_corners() const +inline const std::array::vector_type, 8>& view_frustum::get_corners() const { return corners; } template -void view_frustum::recalculate_planes(const matrix& view_projection) +void view_frustum::recalculate_planes(const matrix_type& view_projection) { - matrix transpose = vmq::transpose(view_projection); - bounds.planes[0] = plane(transpose[3] + transpose[0]); - bounds.planes[1] = plane(transpose[3] - transpose[0]); - bounds.planes[2] = plane(transpose[3] + transpose[1]); - bounds.planes[3] = plane(transpose[3] - transpose[1]); - bounds.planes[4] = plane(transpose[3] + transpose[2]); - bounds.planes[5] = plane(transpose[3] - transpose[2]); + matrix_type transpose = math::transpose(view_projection); + bounds.planes[0] = plane_type(transpose[3] + transpose[0]); + bounds.planes[1] = plane_type(transpose[3] - transpose[0]); + bounds.planes[2] = plane_type(transpose[3] + transpose[1]); + bounds.planes[3] = plane_type(transpose[3] - transpose[1]); + bounds.planes[4] = plane_type(transpose[3] + transpose[2]); + bounds.planes[5] = plane_type(transpose[3] - transpose[2]); } template void view_frustum::recalculate_corners() { - corners[0] = intersection(get_near(), get_top(), get_left()); - corners[1] = intersection(get_near(), get_top(), get_right()); - corners[2] = intersection(get_near(), get_bottom(), get_left()); - corners[3] = intersection(get_near(), get_bottom(), get_right()); - corners[4] = intersection(get_far(), get_top(), get_left()); - corners[5] = intersection(get_far(), get_top(), get_right()); - corners[6] = intersection(get_far(), get_bottom(), get_left()); - corners[7] = intersection(get_far(), get_bottom(), get_right()); + corners[0] = plane_type::intersection(get_near(), get_top(), get_left()); + corners[1] = plane_type::intersection(get_near(), get_top(), get_right()); + corners[2] = plane_type::intersection(get_near(), get_bottom(), get_left()); + corners[3] = plane_type::intersection(get_near(), get_bottom(), get_right()); + corners[4] = plane_type::intersection(get_far(), get_top(), get_left()); + corners[5] = plane_type::intersection(get_far(), get_top(), get_right()); + corners[6] = plane_type::intersection(get_far(), get_bottom(), get_left()); + corners[7] = plane_type::intersection(get_far(), get_bottom(), get_right()); } #endif // ANTKEEPER_VIEW_FRUSTUM_HPP diff --git a/src/math.hpp b/src/math.hpp deleted file mode 100644 index ab4559d..0000000 --- a/src/math.hpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2020 Christopher J. Howard - * - * This file is part of Antkeeper source code. - * - * Antkeeper source code is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Antkeeper source code is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Antkeeper source code. If not, see . - */ - -#ifndef ANTKEEPER_MATH_HPP -#define ANTKEEPER_MATH_HPP - -#include -#include -#include - -using namespace vmq::operators; - -inline float frand(float start, float end) -{ - float f = (float)std::rand() / RAND_MAX; - return start + f * (end - start); -} - -namespace math { - -/** - * Reinterprets data as an `N`-dimensional vector of type `T`. - * - * @tparam N Number of vector dimensions. - * @tparam T Scalar type. - * @param data Data to reinterpret. - */ -template -inline vmq::vector& as_vector(T& data) -{ - static_assert(std::is_pod>::value); - return reinterpret_cast&>(data); -} - -/** - * Reinterprets data as an `NxM` matrix of type `T`. - * - * @tparam N Number of columns. - * @tparam M Number of rows. - * @tparam T Element type. - * @param data Data to reinterpret. - */ -template -inline vmq::matrix& as_matrix(T& data) -{ - static_assert(std::is_pod>::value); - return reinterpret_cast&>(data); -} - -template -vmq::vector project_on_plane(const vmq::vector& v, const vmq::vector& p, const vmq::vector& n) -{ - return v - n * vmq::dot(v - p, n); -} - -} // namespace math - -#endif // ANTKEEPER_MATH_HPP - diff --git a/src/math/angles.hpp b/src/math/angles.hpp new file mode 100644 index 0000000..42d5953 --- /dev/null +++ b/src/math/angles.hpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_MATH_ANGLES_HPP +#define ANTKEEPER_MATH_ANGLES_HPP + +#include "math/constants.hpp" + +namespace math { + +/// @addtogroup utility +/// @{ + +/** + * Converts an angle given in radians to degrees. + * + * @param radians Angle in radians. + * @return Angle in degrees. + */ +template +T degrees(T radians); + +/** + * Converts an angle given in degrees to radians. + * + * @param radians Angle in radians. + * @return Angle in degrees. + */ +template +T radians(T degrees); + +template +inline T degrees(T radians) +{ + return radians * T(180) / pi; +} + +template +inline T radians(T degrees) +{ + return degrees * pi / T(180); +} + +/// @} + +} // namespace math + +#endif // ANTKEEPER_MATH_ANGLES_HPP diff --git a/src/math/constants.hpp b/src/math/constants.hpp new file mode 100644 index 0000000..eddade9 --- /dev/null +++ b/src/math/constants.hpp @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_MATH_CONSTANTS_HPP +#define ANTKEEPER_MATH_CONSTANTS_HPP + +#include "math/matrix-type.hpp" +#include "math/quaternion-type.hpp" +#include "math/transform-type.hpp" + +namespace math { + +/// @addtogroup utility +/// @{ + +/** + * Pi. + */ +template +constexpr T pi = T(3.14159265358979323846); + +/** + * Pi / 2. + */ +template +constexpr T half_pi = pi * T(0.5); + +/** + * Pi * 2. + */ +template +constexpr T two_pi = pi * T(2); + +/** + * 2x2 identity matrix. + */ +template +constexpr matrix identity2x2 = +{{ + {1, 0}, + {0, 1} +}}; + +/** + * 3x3 identity matrix. + */ +template +constexpr matrix identity3x3 = +{{ + {1, 0, 0}, + {0, 1, 0}, + {0, 0, 1} +}}; + +/** + * 4x4 identity matrix. + */ +template +constexpr matrix identity4x4 = +{{ + {1, 0, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 0}, + {0, 0, 0, 1} +}}; + +/** + * Unit quaternion. + */ +template +constexpr quaternion identity_quaternion = {T(1), T(0), T(0), T(0)}; + +/** + * Identity transform. + */ +template +constexpr transform identity_transform = +{ + {T(0), T(0), T(0)}, + {T(1), T(0), T(0), T(0)}, + {T(1), T(1), T(1)} +}; + +/// @} + +} // namespace math + +#endif // ANTKEEPER_MATH_CONSTANTS_HPP diff --git a/src/math/interpolation.hpp b/src/math/interpolation.hpp new file mode 100644 index 0000000..1f2e4c2 --- /dev/null +++ b/src/math/interpolation.hpp @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_MATH_INTERPOLATION_HPP +#define ANTKEEPER_MATH_INTERPOLATION_HPP + +#include "math/matrix-type.hpp" +#include "math/quaternion-type.hpp" +#include "math/transform-type.hpp" +#include +#include + +namespace math { + +/// @addtogroup utility +/// @{ + +/** + * Linearly interpolates between @p x and @p y. + * + * Requires the following operators to be defined: + * + * T operator+(const T&, const T&); + * T operator-(const T&, const T&); + * T operator*(const T&, S); + * + * @tparam T Value type. + * @tparam S Scalar type. + */ +template +T lerp(const T& x, const T& y, S a); + +/** + * Logarithmically interpolates between @p x and @p y. + * + * @warning Undefined behavior when @p x is zero. + * + * @tparam T Value type. + * @tparam S Scalar type. + */ +template +T log_lerp(const T& x, const T& y, S a); + +template +inline T lerp(const T& x, const T& y, S a) +{ + return (y - x) * a + x; +} + +template +inline T log_lerp(const T& x, const T& y, S a) +{ + //return std::exp(linear(std::log(x), std::log(y), a)); + return x * std::pow(y / x, a); +} + +/// @} + +} // namespace math + +#endif // ANTKEEPER_MATH_INTERPOLATION_HPP diff --git a/src/math/math.hpp b/src/math/math.hpp new file mode 100644 index 0000000..a8bcc1f --- /dev/null +++ b/src/math/math.hpp @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_MATH_HPP +#define ANTKEEPER_MATH_HPP + +/// Contains mathematical functions and data types. +namespace math {} + +/** + * @defgroup vector Vector + * + * Vector type, functions, and operators. + */ +#include "math/vector-type.hpp" +#include "math/vector-functions.hpp" +#include "math/vector-operators.hpp" + +/** + * @defgroup matrix Matrix + * + * Matrix type, functions, and operators. + */ +#include "math/matrix-type.hpp" +#include "math/matrix-functions.hpp" +#include "math/matrix-operators.hpp" + +/** + * @defgroup quaternion Quaternion + * + * Quaternion type, functions, and operators. + */ +#include "math/quaternion-type.hpp" +#include "math/quaternion-functions.hpp" +#include "math/quaternion-operators.hpp" + +/** + * @defgroup transform Transform + * + * TRS transform type, functions, and operators. + */ +#include "math/transform-type.hpp" +#include "math/transform-functions.hpp" +#include "math/transform-operators.hpp" + +/** + * @defgroup io I/O + * + * Functions and operators that read/write vectors, matrices, or quaternions from/to streams. + */ +#include "math/stream-operators.hpp" + +/** + * @defgroup utility Utility constants and functions + * + * Commonly used utilities. + */ +#include "math/angles.hpp" +#include "math/constants.hpp" +#include "math/interpolation.hpp" +#include "math/random.hpp" + +#endif // ANTKEEPER_MATH_HPP diff --git a/src/math/matrix-functions.hpp b/src/math/matrix-functions.hpp new file mode 100644 index 0000000..de1c265 --- /dev/null +++ b/src/math/matrix-functions.hpp @@ -0,0 +1,795 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_MATH_MATRIX_FUNCTIONS_HPP +#define ANTKEEPER_MATH_MATRIX_FUNCTIONS_HPP + +#include "math/matrix-type.hpp" +#include "math/vector-type.hpp" +#include "math/vector-functions.hpp" +#include + +namespace math { + +/// @addtogroup matrix +/// @{ + +/** + * Adds two matrices. + * + * @param x First matrix. + * @param y Second matrix. + * @return Sum of the two matrices. + */ +template +matrix add(const matrix& x, const matrix& y); + +/// @copydoc add(const matrix&, const matrix&) +template +matrix add(const matrix& x, const matrix& y); + +/// @copydoc add(const matrix&, const matrix&) +template +matrix add(const matrix& x, const matrix& y); + +/** + * Reinterprets data as an `NxM` matrix of type `T`. + * + * @tparam N Number of columns. + * @tparam M Number of rows. + * @tparam T Element type. + * @param data Data to reinterpret. + */ +template +matrix& as_matrix(T& data); + +/** + * Calculates the determinant of a matrix. + * + * @param m Matrix of which to take the determinant. + */ +template +T determinant(const matrix& m); + +/// @copydoc determinant(const matrix&) +template +T determinant(const matrix& m); + +/// @copydoc determinant(const matrix&) +template +T determinant(const matrix& m); + +/** + * Calculates the inverse of a matrix. + * + * @param m Matrix of which to take the inverse. + */ +template +matrix inverse(const matrix& m); + +/// @copydoc inverse(const matrix&) +template +matrix inverse(const matrix& m); + +/// @copydoc inverse(const matrix&) +template +matrix inverse(const matrix& m); + +/** + * Performs a component-wise multiplication of two matrices. + * + * @param x First matrix multiplicand. + * @param y Second matrix multiplicand. + */ +template +matrix componentwise_mul(const matrix& x, const matrix& y); + +/// @copydoc componentwise_mul(const matrix&, const matrix&) +template +matrix componentwise_mul(const matrix& x, const matrix& y); + +/// @copydoc componentwise_mul(const matrix&, const matrix&) +template +matrix componentwise_mul(const matrix& x, const matrix& y); + +/** + * Creates a viewing transformation matrix. + * + * @param position Position of the view point. + * @param target Position of the target. + * @param up Normalized direction of the up vector. + * @return Viewing transformation matrix. + */ +template +matrix look_at(const vector& position, const vector& target, vector up); + +/** + * Multiplies two matrices. + * + * @param x First matrix. + * @param y Second matrix. + * @return Product of the two matrices. + */ +template +matrix mul(const matrix& x, const matrix& y); + +/// @copydoc mul(const matrix&, const matrix&); +template +matrix mul(const matrix& x, const matrix& y); + +/// @copydoc mul(const matrix&, const matrix&); +template +matrix mul(const matrix& x, const matrix& y); + +/** + * Multiplies a matrix by a scalar. + * + * @param m Matrix. + * @param s Scalar. + * @return Product of the matrix and the scalar.. + */ +template +matrix mul(const matrix& m, T s); + +/** + * Transforms a vector by a matrix. + * + * @param m Matrix. + * @param v Vector. + * @return Transformed vector. + */ +template +vector mul(const matrix& m, const vector& v); + +/// @copydoc mul(const matrix&, const vector&) +template +vector mul(const matrix& m, const vector& v); + +/// @copydoc mul(const matrix&, const vector&) +template +vector mul(const matrix& m, const vector& v); + +/** + * Creates an orthographic projection matrix. + * + * @param left Signed distance to the left clipping plane. + * @param right Signed distance to the right clipping plane. + * @param bottom Signed distance to the bottom clipping plane. + * @param top Signed distance to the top clipping plane. + * @param z_near Signed distance to the near clipping plane. + * @param z_far Signed distance to the far clipping plane. + * @return Orthographic projection matrix. + */ +template +matrix ortho(T left, T right, T bottom, T top, T z_near, T z_far); + +/** + * Calculates the outer product of a pair of vectors. + * + * @param c Parameter to be treated as a column vector. + * @param r Parameter to be treated as a row vector. + */ +template +matrix outer_product(const vector& c, const vector& r); + +/// @copydoc outer_product(const vector&, const vector&) +template +matrix outer_product(const vector& c, const vector& r); + +/// @copydoc outer_product(const vector&, const vector&) +template +matrix outer_product(const vector& c, const vector r); + +/** + * Creates a perspective projection matrix. + * + * @param vertical_fov Vertical field of view angle, in radians. + * @param aspect_ratio Aspect ratio which determines the horizontal field of view. + * @param z_near Distance to the near clipping plane. + * @param z_far Distance to the far clipping plane. + * @return Perspective projection matrix. + */ +template +matrix perspective(T vertical_fov, T aspect_ratio, T z_near, T z_far); + +/** + * Resizes a matrix. Any new elements will be set to `1` if in the diagonal, and `0` otherwise. + * + * @param m Matrix to resize. + * @return Resized matrix. + */ +template +matrix resize(const matrix& m); + +/** + * Rotates a matrix. + * + * @param m Matrix to rotate. + * @param angle Angle of rotation (in radians). + * @param axis Axis of rotation + * @return Rotated matrix. + */ +template +matrix rotate(const matrix& m, T angle, const vector& axis); + +/** + * Scales a matrix. + * + * @param m Matrix to scale. + * @param v Scale vector. + * @return Scaled matrix. + */ +template +matrix scale(const matrix& m, const vector& v); + +/** + * Subtracts a matrix from another matrix. + * + * @param x First matrix. + * @param y Second matrix. + * @return Difference between the two matrices. + */ +template +matrix sub(const matrix& x, const matrix& y); + +/// @copydoc sub(const matrix&, const matrix&) +template +matrix sub(const matrix& x, const matrix& y); + +/// @copydoc sub(const matrix&, const matrix&) +template +matrix sub(const matrix& x, const matrix& y); + +/** + * Translates a matrix. + * + * @param m Matrix to translate. + * @param v Translation vector. + * @return Translated matrix. + */ +template +matrix translate(const matrix& m, const vector& v); + +/** + * Calculates the transpose of a matrix. + * + * @param m Matrix of which to take the transpose. + */ +template +matrix transpose(const matrix& m); + +/// @copydoc transpose(const matrix&) +template +matrix transpose(const matrix& m); + +/// @copydoc transpose(const matrix&) +template +matrix transpose(const matrix& m); + +template +matrix add(const matrix& x, const matrix& y) +{ + return + {{ + x[0] + y[0], + x[1] + y[1] + }}; +} + +template +matrix add(const matrix& x, const matrix& y) +{ + return + {{ + x[0] + y[0], + x[1] + y[1], + x[2] + y[2] + }}; +} + +template +matrix add(const matrix& x, const matrix& y) +{ + return + {{ + x[0] + y[0], + x[1] + y[1], + x[2] + y[2], + x[3] + y[3] + }}; +} + +template +inline matrix& as_matrix(T& data) +{ + static_assert(std::is_pod>::value); + return reinterpret_cast&>(data); +} + +template +T determinant(const matrix& m) +{ + return m[0][0] * m[1][1] - m[0][1] * m[1][0]; +} + +template +T determinant(const matrix& m) +{ + return m[0][0] * m [1][1] * m[2][2] + + m[0][1] * m[1][2] * m[2][0] + + m[0][2] * m[1][0] * m[2][1] - + m[0][0] * m[1][2] * m[2][1] - + m[0][1] * m[1][0] * m[2][2] - + m[0][2] * m[1][1] * m[2][0]; +} + +template +T determinant(const matrix& m) +{ + return m[0][3] * m[1][2] * m[2][1] * m[3][0] - m[0][2] * m[1][3] * m[2][1] * m[3][0] - + m[0][3] * m[1][1] * m[2][2] * m[3][0] + m[0][1] * m[1][3] * m[2][2] * m[3][0] + + m[0][2] * m[1][1] * m[2][3] * m[3][0] - m[0][1] * m[1][2] * m[2][3] * m[3][0] - + m[0][3] * m[1][2] * m[2][0] * m[3][1] + m[0][2] * m[1][3] * m[2][0] * m[3][1] + + m[0][3] * m[1][0] * m[2][2] * m[3][1] - m[0][0] * m[1][3] * m[2][2] * m[3][1] - + m[0][2] * m[1][0] * m[2][3] * m[3][1] + m[0][0] * m[1][2] * m[2][3] * m[3][1] + + m[0][3] * m[1][1] * m[2][0] * m[3][2] - m[0][1] * m[1][3] * m[2][0] * m[3][2] - + m[0][3] * m[1][0] * m[2][1] * m[3][2] + m[0][0] * m[1][3] * m[2][1] * m[3][2] + + m[0][1] * m[1][0] * m[2][3] * m[3][2] - m[0][0] * m[1][1] * m[2][3] * m[3][2] - + m[0][2] * m[1][1] * m[2][0] * m[3][3] + m[0][1] * m[1][2] * m[2][0] * m[3][3] + + m[0][2] * m[1][0] * m[2][1] * m[3][3] - m[0][0] * m[1][2] * m[2][1] * m[3][3] - + m[0][1] * m[1][0] * m[2][2] * m[3][3] + m[0][0] * m[1][1] * m[2][2] * m[3][3]; +} + +template +matrix inverse(const matrix& m) +{ + static_assert(std::is_floating_point::value); + + const T rd(T(1) / determinant(m)); + return + {{ + { m[1][1] * rd, -m[0][1] * rd}, + {-m[1][0] * rd, m[0][0] * rd} + }}; +} + +template +matrix inverse(const matrix& m) +{ + static_assert(std::is_floating_point::value); + + const T rd(T(1) / determinant(m)); + + return + {{ + { + (m[1][1] * m[2][2] - m[1][2] * m[2][1]) * rd, + (m[0][2] * m[2][1] - m[0][1] * m[2][2]) * rd, + (m[0][1] * m[1][2] - m[0][2] * m[1][1]) * rd + }, + + { + (m[1][2] * m[2][0] - m[1][0] * m[2][2]) * rd, + (m[0][0] * m[2][2] - m[0][2] * m[2][0]) * rd, + (m[0][2] * m[1][0] - m[0][0] * m[1][2]) * rd + }, + + { + (m[1][0] * m[2][1] - m[1][1] * m[2][0]) * rd, + (m[0][1] * m[2][0] - m[0][0] * m[2][1]) * rd, + (m[0][0] * m[1][1] - m[0][1] * m[1][0]) * rd + } + }}; +} + +template +matrix inverse(const matrix& m) +{ + static_assert(std::is_floating_point::value); + + const T rd(T(1) / determinant(m)); + + return + {{ + { + (m[1][2] * m[2][3] * m[3][1] - m[1][3] * m[2][2] * m[3][1] + m[1][3] * m[2][1] * m[3][2] - m[1][1] * m[2][3] * m[3][2] - m[1][2] * m[2][1] * m[3][3] + m[1][1] * m[2][2] * m[3][3]) * rd, + (m[0][3] * m[2][2] * m[3][1] - m[0][2] * m[2][3] * m[3][1] - m[0][3] * m[2][1] * m[3][2] + m[0][1] * m[2][3] * m[3][2] + m[0][2] * m[2][1] * m[3][3] - m[0][1] * m[2][2] * m[3][3]) * rd, + (m[0][2] * m[1][3] * m[3][1] - m[0][3] * m[1][2] * m[3][1] + m[0][3] * m[1][1] * m[3][2] - m[0][1] * m[1][3] * m[3][2] - m[0][2] * m[1][1] * m[3][3] + m[0][1] * m[1][2] * m[3][3]) * rd, + (m[0][3] * m[1][2] * m[2][1] - m[0][2] * m[1][3] * m[2][1] - m[0][3] * m[1][1] * m[2][2] + m[0][1] * m[1][3] * m[2][2] + m[0][2] * m[1][1] * m[2][3] - m[0][1] * m[1][2] * m[2][3]) * rd + }, + + { + (m[1][3] * m[2][2] * m[3][0] - m[1][2] * m[2][3] * m[3][0] - m[1][3] * m[2][0] * m[3][2] + m[1][0] * m[2][3] * m[3][2] + m[1][2] * m[2][0] * m[3][3] - m[1][0] * m[2][2] * m[3][3]) * rd, + (m[0][2] * m[2][3] * m[3][0] - m[0][3] * m[2][2] * m[3][0] + m[0][3] * m[2][0] * m[3][2] - m[0][0] * m[2][3] * m[3][2] - m[0][2] * m[2][0] * m[3][3] + m[0][0] * m[2][2] * m[3][3]) * rd, + (m[0][3] * m[1][2] * m[3][0] - m[0][2] * m[1][3] * m[3][0] - m[0][3] * m[1][0] * m[3][2] + m[0][0] * m[1][3] * m[3][2] + m[0][2] * m[1][0] * m[3][3] - m[0][0] * m[1][2] * m[3][3]) * rd, + (m[0][2] * m[1][3] * m[2][0] - m[0][3] * m[1][2] * m[2][0] + m[0][3] * m[1][0] * m[2][2] - m[0][0] * m[1][3] * m[2][2] - m[0][2] * m[1][0] * m[2][3] + m[0][0] * m[1][2] * m[2][3]) * rd + }, + + { + (m[1][1] * m[2][3] * m[3][0] - m[1][3] * m[2][1] * m[3][0] + m[1][3] * m[2][0] * m[3][1] - m[1][0] * m[2][3] * m[3][1] - m[1][1] * m[2][0] * m[3][3] + m[1][0] * m[2][1] * m[3][3]) * rd, + (m[0][3] * m[2][1] * m[3][0] - m[0][1] * m[2][3] * m[3][0] - m[0][3] * m[2][0] * m[3][1] + m[0][0] * m[2][3] * m[3][1] + m[0][1] * m[2][0] * m[3][3] - m[0][0] * m[2][1] * m[3][3]) * rd, + (m[0][1] * m[1][3] * m[3][0] - m[0][3] * m[1][1] * m[3][0] + m[0][3] * m[1][0] * m[3][1] - m[0][0] * m[1][3] * m[3][1] - m[0][1] * m[1][0] * m[3][3] + m[0][0] * m[1][1] * m[3][3]) * rd, + (m[0][3] * m[1][1] * m[2][0] - m[0][1] * m[1][3] * m[2][0] - m[0][3] * m[1][0] * m[2][1] + m[0][0] * m[1][3] * m[2][1] + m[0][1] * m[1][0] * m[2][3] - m[0][0] * m[1][1] * m[2][3]) * rd + }, + + { + (m[1][2] * m[2][1] * m[3][0] - m[1][1] * m[2][2] * m[3][0] - m[1][2] * m[2][0] * m[3][1] + m[1][0] * m[2][2] * m[3][1] + m[1][1] * m[2][0] * m[3][2] - m[1][0] * m[2][1] * m[3][2]) * rd, + (m[0][1] * m[2][2] * m[3][0] - m[0][2] * m[2][1] * m[3][0] + m[0][2] * m[2][0] * m[3][1] - m[0][0] * m[2][2] * m[3][1] - m[0][1] * m[2][0] * m[3][2] + m[0][0] * m[2][1] * m[3][2]) * rd, + (m[0][2] * m[1][1] * m[3][0] - m[0][1] * m[1][2] * m[3][0] - m[0][2] * m[1][0] * m[3][1] + m[0][0] * m[1][2] * m[3][1] + m[0][1] * m[1][0] * m[3][2] - m[0][0] * m[1][1] * m[3][2]) * rd, + (m[0][1] * m[1][2] * m[2][0] - m[0][2] * m[1][1] * m[2][0] + m[0][2] * m[1][0] * m[2][1] - m[0][0] * m[1][2] * m[2][1] - m[0][1] * m[1][0] * m[2][2] + m[0][0] * m[1][1] * m[2][2]) * rd + } + }}; +} + +template +matrix componentwise_mul(const matrix& x, const matrix& y) +{ + return + {{ + {x[0][0] * y[0][0], x[0][1] * y[0][1]}, + {x[1][0] * y[1][0], x[1][1] * y[1][1]} + }}; +} + +template +matrix componentwise_mul(const matrix& x, const matrix& y) +{ + return + {{ + {x[0][0] * y[0][0], x[0][1] * y[0][1], x[0][2] * y[0][2]}, + {x[1][0] * y[1][0], x[1][1] * y[1][1], x[1][2] * y[1][2]}, + {x[2][0] * y[2][0], x[2][1] * y[2][1], x[2][2] * y[2][2]} + }}; +} + +template +matrix componentwise_mul(const matrix& x, const matrix& y) +{ + return + {{ + {x[0][0] * y[0][0], x[0][1] * y[0][1], x[0][2] * y[0][2], x[0][3] * y[0][3]}, + {x[1][0] * y[1][0], x[1][1] * y[1][1], x[1][2] * y[1][2], x[1][3] * y[1][3]}, + {x[2][0] * y[2][0], x[2][1] * y[2][1], x[2][2] * y[2][2], x[2][3] * y[2][3]}, + {x[3][0] * y[3][0], x[3][1] * y[3][1], x[3][2] * y[3][2], x[3][3] * y[3][3]} + }}; +} + +template +matrix look_at(const vector& position, const vector& target, vector up) +{ + vector forward = normalize(sub(target, position)); + vector right = normalize(cross(forward, up)); + up = cross(right, forward); + + matrix m = + {{ + {right[0], up[0], -forward[0], T(0)}, + {right[1], up[1], -forward[1], T(0)}, + {right[2], up[2], -forward[2], T(0)}, + {T(0), T(0), T(0), T(1)} + }}; + + return translate(m, negate(position)); +} + +template +matrix mul(const matrix& x, const matrix& y) +{ + return + {{ + x[0] * y[0][0] + x[1] * y[0][1], + x[0] * y[1][0] + x[1] * y[1][1] + }}; +} + +template +matrix mul(const matrix& x, const matrix& y) +{ + return + {{ + x[0] * y[0][0] + x[1] * y[0][1] + x[2] * y[0][2], + x[0] * y[1][0] + x[1] * y[1][1] + x[2] * y[1][2], + x[0] * y[2][0] + x[1] * y[2][1] + x[2] * y[2][2] + }}; +} + +template +matrix mul(const matrix& x, const matrix& y) +{ + return + {{ + x[0] * y[0][0] + x[1] * y[0][1] + x[2] * y[0][2] + x[3] * y[0][3], + x[0] * y[1][0] + x[1] * y[1][1] + x[2] * y[1][2] + x[3] * y[1][3], + x[0] * y[2][0] + x[1] * y[2][1] + x[2] * y[2][2] + x[3] * y[2][3], + x[0] * y[3][0] + x[1] * y[3][1] + x[2] * y[3][2] + x[3] * y[3][3] + }}; +} + +/// @private +template +inline matrix mul(const matrix& m, T s, std::index_sequence) +{ + return {{(m[I] * s)...}}; +} + +template +inline matrix mul(const matrix& m, T s) +{ + return mul(m, s, std::make_index_sequence{}); +} + +template +vector mul(const matrix& m, const vector& v) +{ + return + { + m[0][0] * v[0] + m[1][0] * v[1], + m[0][1] * v[0] + m[1][1] * v[1] + }; +} + +template +vector mul(const matrix& m, const vector& v) +{ + return + { + m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2], + m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2], + m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + }; +} + +template +vector mul(const matrix& m, const vector& v) +{ + return + { + m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2] + m[3][0] * v[3], + m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2] + m[3][1] * v[3], + m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2] * v[3], + m[0][3] * v[0] + m[1][3] * v[1] + m[2][3] * v[2] + m[3][3] * v[3] + }; +} + +template +matrix ortho(T left, T right, T bottom, T top, T z_near, T z_far) +{ + return + {{ + {T(2) / (right - left), T(0), T(0), T(0)}, + {T(0), T(2) / (top - bottom), T(0), T(0)}, + {T(0), T(0), T(-2) / (z_far - z_near), T(0)}, + {-((right + left) / (right - left)), -((top + bottom) / (top - bottom)), -((z_far + z_near) / (z_far - z_near)), T(1)} + }}; +} + +template +matrix outer_product(const vector& c, const vector& r) +{ + return + {{ + {c[0] * r[0], c[1] * r[0]}, + {c[0] * r[1], c[1] * r[1]} + }}; +} + +template +matrix outer_product(const vector& c, const vector& r) +{ + return + {{ + {c[0] * r[0], c[1] * r[0], c[2] * r[0]}, + {c[0] * r[1], c[1] * r[1], c[2] * r[1]}, + {c[0] * r[2], c[1] * r[2], c[2] * r[2]} + }}; +} + +template +matrix outer_product(const vector& c, const vector r) +{ + return + {{ + {c[0] * r[0], c[1] * r[0], c[2] * r[0], c[3] * r[0]}, + {c[0] * r[1], c[1] * r[1], c[2] * r[1], c[3] * r[1]}, + {c[0] * r[2], c[1] * r[2], c[2] * r[2], c[3] * r[2]}, + {c[0] * r[3], c[1] * r[3], c[2] * r[3], c[3] * r[3]} + }}; +} + +template +matrix perspective(T vertical_fov, T aspect_ratio, T z_near, T z_far) +{ + T half_fov = vertical_fov * T(0.5); + T f = std::cos(half_fov) / std::sin(half_fov); + + return + {{ + {f / aspect_ratio, T(0), T(0), T(0)}, + {T(0), f, T(0), T(0)}, + {T(0), T(0), (z_far + z_near) / (z_near - z_far), T(-1)}, + {T(0), T(0), (T(2) * z_near * z_far) / (z_near - z_far), T(0)} + }}; +} + +template +matrix resize(const matrix& m) +{ + matrix resized; + + for (std::size_t i = 0; i < N1; ++i) + { + for (std::size_t j = 0; j < M1; ++j) + { + resized[i][j] = (i < N0 && j < M0) ? m[i][j] : ((i == j) ? T(1) : T(0)); + } + } + + return resized; +} + +template +matrix rotate(const matrix& m, T angle, const vector& axis) +{ + const T c = std::cos(angle); + const T s = std::sin(angle); + const vector temp = mul(axis, T(1) - c); + + matrix rotation; + rotation[0][0] = axis[0] * temp[0] + c + rotation[0][1] = axis[1] * temp[0] + axis[2] * s; + rotation[0][2] = axis[2] * temp[0] - axis[1] * s; + rotation[0][3] = T(0); + rotation[1][0] = axis[0] * temp[1] - axis[2] * s + rotation[1][1] = axis[1] * temp[1] + c; + rotation[1][2] = axis[2] * temp[1] + axis[0] * s; + rotation[1][3] = T(0); + rotation[2][0] = axis[0] * temp[2] + axis[1] * s; + rotation[2][1] = axis[1] * temp[2] - axis[0] * s; + rotation[2][2] = axis[2] * temp[2] + c + rotation[2][3] = T(0); + rotation[3][0] = T(0); + rotation[3][1] = T(0); + rotation[3][2] = T(0); + rotation[3][3] = T(1); + + return mul(m, rotation); +} + +template +matrix scale(const matrix& m, const vector& v) +{ + return mul(m, matrix + {{ + {v[0], T(0), T(0), T(0)}, + {T(0), v[1], T(0), T(0)}, + {T(0), T(0), v[2], T(0)}, + {T(0), T(0), T(0), T(1)} + }}); +} + +template +matrix sub(const matrix& x, const matrix& y) +{ + return + {{ + x[0] - y[0], + x[1] - y[1] + }}; +} + +template +matrix sub(const matrix& x, const matrix& y) +{ + return + {{ + x[0] - y[0], + x[1] - y[1], + x[2] - y[2] + }}; +} + +template +matrix sub(const matrix& x, const matrix& y) +{ + return + {{ + x[0] - y[0], + x[1] - y[1], + x[2] - y[2], + x[3] - y[3] + }}; +} + +template +matrix translate(const matrix& m, const vector& v) +{ + return mul(m, matrix + {{ + {T(1), T(0), T(0), T(0)}, + {T(0), T(1), T(0), T(0)}, + {T(0), T(0), T(1), T(0)}, + {v[0], v[1], v[2], T(1)} + }}); +} + +template +matrix transpose(const matrix& m) +{ + + return + {{ + { + m[0][0], m[1][0] + }, + + { + m[0][1], m[1][1] + } + }}; +} + +template +matrix transpose(const matrix& m) +{ + + return + {{ + { + m[0][0], m[1][0], m[2][0] + }, + + { + m[0][1], m[1][1], m[2][1] + }, + + { + m[0][2], m[1][2], m[2][2] + } + }}; +} + +template +matrix transpose(const matrix& m) +{ + + return + {{ + { + m[0][0], m[1][0], m[2][0], m[3][0] + }, + + { + m[0][1], m[1][1], m[2][1], m[3][1] + }, + + { + m[0][2], m[1][2], m[2][2], m[3][2] + }, + + { + m[0][3], m[1][3], m[2][3], m[3][3] + } + }}; +} + +/// @} + +} // namespace math + +#endif // ANTKEEPER_MATH_MATRIX_FUNCTIONS_HPP diff --git a/src/math/matrix-operators.hpp b/src/math/matrix-operators.hpp new file mode 100644 index 0000000..78b2467 --- /dev/null +++ b/src/math/matrix-operators.hpp @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_MATH_MATRIX_OPERATORS_HPP +#define ANTKEEPER_MATH_MATRIX_OPERATORS_HPP + +#include "math/matrix-type.hpp" +#include "math/matrix-functions.hpp" + +namespace math { +namespace matrix_operators { + +/// @addtogroup matrix +/// @{ + +/// @copydoc add(const matrix&, const matrix&) +template +matrix operator+(const matrix& x, const matrix& y); + +/// @copydoc mul(const matrix&, const matrix&) +template +matrix operator*(const matrix& x, const matrix& y); + +/// @copydoc mul(const matrix&, T) +template +matrix operator*(const matrix& m, T s); + +/// @copydoc mul(const matrix&, T) +template +matrix operator*(T s, const matrix& m); + +/// @copydoc mul(const matrix&, const vector&) +template +vector operator*(const matrix& m, const vector& v); + +/// @copydoc sub(const matrix&, const matrix&) +template +matrix operator-(const matrix& x, const matrix& y); + +template +inline matrix operator+(const matrix& x, const matrix& y) +{ + return add(x, y); +} + +template +inline matrix operator*(const matrix& x, const matrix& y) +{ + return mul(x, y); +} + +template +inline matrix operator*(const matrix& m, T s) +{ + return mul(m, s); +} + +template +inline matrix operator*(T s, const matrix& m) +{ + return mul(m, s); +} + +template +inline vector operator*(const matrix& m, const vector& v) +{ + return mul(m, v); +} + +template +inline matrix operator-(const matrix& x, const matrix& y) +{ + return sub(x, y); +} + +/// @} + +} // namespace matrix_operators +} // namespace math + +// Bring matrix operators into global namespace +using namespace math::matrix_operators; + +#endif // ANTKEEPER_MATH_MATRIX_OPERATORS_HPP diff --git a/src/math/matrix-type.hpp b/src/math/matrix-type.hpp new file mode 100644 index 0000000..1de3af2 --- /dev/null +++ b/src/math/matrix-type.hpp @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_MATH_MATRIX_TYPE_HPP +#define ANTKEEPER_MATH_MATRIX_TYPE_HPP + +#include "math/vector-type.hpp" +#include + +namespace math { + +/// @addtogroup matrix +/// @{ + +/** + * An NxM matrix. + * + * @tparam T Matrix element type. + * @tparam N Number of columns. + * @tparam M Number of rows. + */ +template +struct matrix +{ + typedef T element_type; + typedef vector row_type; + row_type columns[N]; + + inline constexpr row_type& operator[](std::size_t i) noexcept { return columns[i]; } + inline constexpr const row_type& operator[](std::size_t i) const noexcept { return columns[i]; } +}; + +/// @} + +} // namespace math + +#endif // ANTKEEPER_MATH_MATRIX_TYPE_HPP + diff --git a/src/math/operators.hpp b/src/math/operators.hpp new file mode 100644 index 0000000..b943bee --- /dev/null +++ b/src/math/operators.hpp @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_MATH_OPERATORS_HPP +#define ANTKEEPER_MATH_OPERATORS_HPP + +#include "math/vector-operators.hpp" +#include "math/matrix-operators.hpp" +#include "math/quaternion-operators.hpp" +#include "math/transform-operators.hpp" +#include "math/stream-operators.hpp" + +#endif // ANTKEEPER_MATH_OPERATORS_HPP diff --git a/src/math/quaternion-functions.hpp b/src/math/quaternion-functions.hpp new file mode 100644 index 0000000..8b96f3f --- /dev/null +++ b/src/math/quaternion-functions.hpp @@ -0,0 +1,443 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_MATH_QUATERNION_FUNCTIONS_HPP +#define ANTKEEPER_MATH_QUATERNION_FUNCTIONS_HPP + +#include "math/matrix-type.hpp" +#include "math/quaternion-type.hpp" +#include "math/vector-type.hpp" +#include "math/vector-functions.hpp" +#include + +namespace math { + +/// @addtogroup quaternion +/// @{ + +/** + * Adds two quaternions. + * + * @param x First quaternion. + * @param y Second quaternion. + * @return Sum of the two quaternions. + */ +template +quaternion add(const quaternion& x, const quaternion& y); + +/** + * Calculates the conjugate of a quaternion. + * + * @param x Quaternion from which the conjugate will be calculated. + * @return Conjugate of the quaternion. + */ +template +quaternion conjugate(const quaternion& x); + +/** + * Calculates the dot product of two quaternions. + * + * @param x First quaternion. + * @param y Second quaternion. + * @return Dot product of the two quaternions. + */ +template +T dot(const quaternion& x, const quaternion& y); + +/** + * Divides a quaternion by a scalar. + * + * @param q Quaternion. + * @param s Scalar. + * @return Result of the division. + */ +template +quaternion div(const quaternion& q, T s); + +/** + * Calculates the length of a quaternion. + * + * @param x Quaternion to calculate the length of. + * @return Length of the quaternion. + */ +template +T length(const quaternion& x); + +/** + * Calculates the squared length of a quaternion. The squared length can be calculated faster than the length because a call to `std::sqrt` is saved. + * + * @param x Quaternion to calculate the squared length of. + * @return Squared length of the quaternion. + */ +template +T length_squared(const quaternion& x); + +/** + * Performs linear interpolation between two quaternions. + * + * @param x First quaternion. + * @param y Second quaternion. + * @param a Interpolation factor. + * @return Interpolated quaternion. + */ +template +quaternion lerp(const quaternion& x, const quaternion& y, T a); + +/** + * Creates a unit quaternion rotation using forward and up vectors. + * + * @param forward Unit forward vector. + * @param up Unit up vector. + * @return Unit rotation quaternion. + */ +template +quaternion look_rotation(const vector& forward, vector up); + +/** + * Converts a quaternion to a rotation matrix. + * + * @param q Unit quaternion. + * @return Matrix representing the rotation described by `q`. + */ +template +matrix matrix_cast(const quaternion& q); + +/** + * Multiplies two quaternions. + * + * @param x First quaternion. + * @param y Second quaternion. + * @return Product of the two quaternions. + */ +template +quaternion mul(const quaternion& x, const quaternion& y); + +/** + * Multiplies a quaternion by a scalar. + * + * @param q Quaternion. + * @param s Scalar. + * @return Product of the quaternion and scalar. + */ +template +quaternion mul(const quaternion& q, T s); + +/** + * Rotates a 3-dimensional vector by a quaternion. + * + * @param q Unit quaternion. + * @param v Vector. + * @return Rotated vector. + */ +template +vector mul(const quaternion& q, const vector& v); + +/** + * Negates a quaternion. + */ +template +quaternion negate(const quaternion& x); + +/** + * Normalizes a quaternion. + */ +template +quaternion normalize(const quaternion& x); + +/** + * Creates a rotation from an angle and axis. + * + * @param angle Angle of rotation (in radians). + * @param axis Axis of rotation + * @return Quaternion representing the rotation. + */ +template +quaternion angle_axis(T angle, const vector& axis); + +/** + * Calculates the minimum rotation between two normalized direction vectors. + * + * @param source Normalized source direction. + * @param destination Normalized destination direction. + * @return Quaternion representing the minimum rotation between the source and destination vectors. + */ +template +quaternion rotation(const vector& source, const vector& destination); + +/** + * Performs spherical linear interpolation between two quaternions. + * + * @param x First quaternion. + * @param y Second quaternion. + * @param a Interpolation factor. + * @return Interpolated quaternion. + */ +template +quaternion slerp(const quaternion& x, const quaternion& y, T a); + +/** + * Subtracts a quaternion from another quaternion. + * + * @param x First quaternion. + * @param y Second quaternion. + * @return Difference between the quaternions. + */ +template +quaternion sub(const quaternion& x, const quaternion& y); + +/** + * Converts a 3x3 rotation matrix to a quaternion. + * + * @param m Rotation matrix. + * @return Unit quaternion representing the rotation described by `m`. + */ +template +quaternion quaternion_cast(const matrix& m); + +template +inline quaternion add(const quaternion& x, const quaternion& y) +{ + return {x.w + y.w, x.x + y.x, x.y + y.y, x.z + y.z}; +} + +template +inline quaternion conjugate(const quaternion& x) +{ + return {x.w, -x.x, -x.y, -x.z}; +} + +template +inline T dot(const quaternion& x, const quaternion& y) +{ + return {x.w * y.w + x.x * y.x + x.y * y.y + x.z * y.z}; +} + +template +inline quaternion div(const quaternion& q, T s) +{ + return {q.w / s, q.x / s, q.y / s, q.z / s} +} + +template +inline T length(const quaternion& x) +{ + return std::sqrt(x.w * x.w + x.x * x.x + x.y * x.y + x.z * x.z); +} + +template +inline T length_squared(const quaternion& x) +{ + return x.w * x.w + x.x * x.x + x.y * x.y + x.z * x.z; +} + +template +inline quaternion lerp(const quaternion& x, const quaternion& y, T a) +{ + return + { + x.w * (T(1) - a) + y.w * a, + x.x * (T(1) - a) + y.x * a, + x.y * (T(1) - a) + y.y * a, + x.z * (T(1) - a) + y.z * a + }; +} + +template +quaternion look_rotation(const vector& forward, vector up) +{ + vector right = normalize(cross(forward, up)); + up = cross(right, forward); + + matrix m = + {{ + {right[0], up[0], -forward[0]}, + {right[1], up[1], -forward[1]}, + {right[2], up[2], -forward[2]} + }}; + + // Convert to quaternion + return normalize(quaternion_cast(m)); +} + +template +matrix matrix_cast(const quaternion& q) +{ + T wx = q.w * q.x; + T wy = q.w * q.y; + T wz = q.w * q.z; + T xx = q.x * q.x; + T xy = q.x * q.y; + T xz = q.x * q.z; + T yy = q.y * q.y; + T yz = q.y * q.z; + T zz = q.z * q.z; + + return + {{ + {T(1) - (yy + zz) * T(2), (xy + wz) * T(2), (xz - wy) * T(2)}, + {(xy - wz) * T(2), T(1) - (xx + zz) * T(2), (yz + wx) * T(2)}, + {(xz + wy) * T(2), (yz - wx) * T(2), T(1) - (xx + yy) * T(2)} + }}; +} + +template +quaternion mul(const quaternion& x, const quaternion& y) +{ + return + { + -x.x * y.x - x.y * y.y - x.z * y.z + x.w * y.w, + x.x * y.w + x.y * y.z - x.z * y.y + x.w * y.x, + -x.x * y.z + x.y * y.w + x.z * y.x + x.w * y.y, + x.x * y.y - x.y * y.x + x.z * y.w + x.w * y.z + }; +} + +template +inline quaternion mul(const quaternion& q, T s) +{ + return {q.w * s, q.x * s, q.y * s, q.z * s}; +} + +template +vector mul(const quaternion& q, const vector& v) +{ + const T r = q.w; // Real part + const vector& i = reinterpret_cast&>(q.x); // Imaginary part + return i * dot(i, v) * T(2) + v * (r * r - dot(i, i)) + cross(i, v) * r * T(2); +} + +template +inline quaternion negate(const quaternion& x) +{ + return {-x.w, -x.x, -x.y, -x.z}; +} + +template +inline quaternion normalize(const quaternion& x) +{ + return mul(x, T(1) / length(x)); +} + +template +quaternion angle_axis(T angle, const vector& axis) +{ + T s = std::sin(angle * T(0.5)); + return {static_cast(std::cos(angle * T(0.5))), axis.x * s, axis.y * s, axis.z * s}; +} + +template +quaternion rotation(const vector& source, const vector& destination) +{ + quaternion q; + q.w = dot(source, destination); + reinterpret_cast&>(q.x) = cross(source, destination); + + q.w += length(q); + return normalize(q); +} + +template +quaternion slerp(const quaternion& x, const quaternion& y, T a) +{ + T cos_theta = dot(x, y); + + constexpr T epsilon = T(0.0005); + if (cos_theta > T(1) - epsilon) + { + return normalize(lerp(x, y, a)); + } + + cos_theta = std::max(T(-1), std::min(T(1), cos_theta)); + T theta = static_cast(std::acos(cos_theta)) * a; + + quaternion z = normalize(sub(y, mul(x, cos_theta))); + + return add(mul(x, static_cast(std::cos(theta))), mul(z, static_cast(std::sin(theta)))); +} + +template +inline quaternion sub(const quaternion& x, const quaternion& y) +{ + return {x.w - y.w, x.x - y.x, x.y - y.y, x.z - y.z}; +} + +template +quaternion quaternion_cast(const matrix& m) +{ + T r; + vector i; + + T trace = m[0][0] + m[1][1] + m[2][2]; + if (trace > T(0)) + { + T s = T(0.5) / std::sqrt(trace + T(1)); + r = T(0.25) / s; + i = + { + (m[2][1] - m[1][2]) * s, + (m[0][2] - m[2][0]) * s, + (m[1][0] - m[0][1]) * s + }; + } + else + { + if (m[0][0] > m[1][1] && m[0][0] > m[2][2]) + { + T s = T(2) * std::sqrt(T(1) + m[0][0] - m[1][1] - m[2][2]); + r = (m[2][1] - m[1][2]) / s; + i = + { + T(0.25) * s, + (m[0][1] + m[1][0]) / s, + (m[0][2] + m[2][0]) / s + }; + } + else if (m[1][1] > m[2][2]) + { + T s = T(2) * std::sqrt(T(1) + m[1][1] - m[0][0] - m[2][2]); + r = (m[0][2] - m[2][0]) / s; + i = + { + (m[0][1] + m[1][0]) / s, + T(0.25) * s, + (m[1][2] + m[2][1]) / s + }; + } + else + { + T s = T(2) * std::sqrt(T(1) + m[2][2] - m[0][0] - m[1][1]); + r = (m[1][0] - m[0][1]) / s; + i = + { + (m[0][2] + m[2][0]) / s, + (m[1][2] + m[2][1]) / s, + T(0.25) * s + }; + } + } + + return {r, i.x, i.y, i.z}; +} + +/// @} + +} // namespace math + +#endif // ANTKEEPER_MATH_QUATERNION_FUNCTIONS_HPP + diff --git a/src/math/quaternion-operators.hpp b/src/math/quaternion-operators.hpp new file mode 100644 index 0000000..1b32ec5 --- /dev/null +++ b/src/math/quaternion-operators.hpp @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_MATH_QUATERNION_OPERATORS_HPP +#define ANTKEEPER_MATH_QUATERNION_OPERATORS_HPP + +#include "math/quaternion-type.hpp" +#include "math/quaternion-functions.hpp" + +namespace math { +namespace quaternion_operators { + +/// @addtogroup quaternion +/// @{ + +/// @copydoc add(const quaternion&, const quaternion&) +template +quaternion operator+(const quaternion& x, const quaternion& y); + +/// @copydoc div(const quaternion&, T) +template +quaternion operator/(const quaternion& q, T s); + +/// @copydoc mul(const quaternion&, const quaternion&) +template +quaternion operator*(const quaternion& x, const quaternion& y); + +/// @copydoc mul(const quaternion&, T) +template +quaternion operator*(const quaternion& q, T s); + +/// @copydoc mul(const quaternion&, const vector&) +template +vector operator*(const quaternion& q, const vector& v); + +/// @copydoc sub(const quaternion&, const quaternion&) +template +quaternion operator-(const quaternion& x, const quaternion& y); + +/// @copydoc negate(const quaternion&) +template +quaternion operator-(const quaternion& x); + +template +inline quaternion operator+(const quaternion& x, const quaternion& y) +{ + return add(x, y); +} + +template +inline quaternion operator/(const quaternion& q, T s) +{ + return div(q, s); +} + +template +inline quaternion operator*(const quaternion& x, const quaternion& y) +{ + return mul(x, y); +} + +template +inline quaternion operator*(const quaternion& q, T s) +{ + return mul(q, s); +} + +template +inline vector operator*(const quaternion& q, const vector& v) +{ + return mul(q, v); +} + +template +inline quaternion operator-(const quaternion& x, const quaternion& y) +{ + return sub(x, y); +} + +template +inline quaternion operator-(const quaternion& x) +{ + return negate(x); +} + +/// @} + +} // namespace quaternion_operators +} // namespace math + +/// Bring quaternion operators into global namespace +using namespace math::quaternion_operators; + +#endif // ANTKEEPER_MATH_QUATERNION_OPERATORS_HPP + diff --git a/src/math/quaternion-type.hpp b/src/math/quaternion-type.hpp new file mode 100644 index 0000000..0cf2445 --- /dev/null +++ b/src/math/quaternion-type.hpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_MATH_QUATERNION_TYPE_HPP +#define ANTKEEPER_MATH_QUATERNION_TYPE_HPP + +namespace math { + +/// @addtogroup quaternion +/// @{ + +/** + * A quaternion type is a tuple made of a scalar (real) part and vector (imaginary) part. + * + * @tparam T Scalar type. + */ +template +struct quaternion +{ + typedef T scalar_type; + scalar_type w; + scalar_type x; + scalar_type y; + scalar_type z; +}; + +/// @} + +} // namespace math + +#endif // ANTKEEPER_MATH_QUATERNION_TYPE_HPP + diff --git a/src/math/random.hpp b/src/math/random.hpp new file mode 100644 index 0000000..8cd3e23 --- /dev/null +++ b/src/math/random.hpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_MATH_RANDOM_HPP +#define ANTKEEPER_MATH_RANDOM_HPP + +#include +#include + +namespace math { + +/// @addtogroup utility +/// @{ + +/** + * Generates a pseudo-random floating point number on `[start, end)` using std::rand(). + * + * @warning Don't forget to seed with std::srand() before using! + * + * @param start Start of the range (inclusive). + * @param end End of the range (exclusive). + * @return Pseudo-random floating point number. + */ +template +T random(T start, T end); + +template +inline T random(T start, T end) +{ + static_assert(std::is_floating_point::value); + constexpr T rand_max_inverse = T(1) / static_cast(RAND_MAX); + return static_cast(std::rand()) * rand_max_inverse * (end - start) + start; +} + +/// @} + +} // namespace math + +#endif // ANTKEEPER_MATH_RANDOM_HPP diff --git a/src/math/stream-operators.hpp b/src/math/stream-operators.hpp new file mode 100644 index 0000000..91737a2 --- /dev/null +++ b/src/math/stream-operators.hpp @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_MATH_STREAM_OPERATORS_HPP +#define ANTKEEPER_MATH_STREAM_OPERATORS_HPP + +#include "math/vector-type.hpp" +#include "math/matrix-type.hpp" +#include "math/quaternion-type.hpp" +#include + +namespace math { +namespace stream_operators { + +/// @addtogroup io +/// @{ + +/** + * Writes the elements of a vector to an output stream, with each element delimeted by a space. + * + * @param os Output stream. + * @param v Vector. + * @return Output stream. + */ +template +std::ostream& operator<<(std::ostream& os, const vector& v); + +/** + * Writes the elements of a matrix to an output stream, with each element delimeted by a space. + * + * @param os Output stream. + * @param m Matrix. + * @return Output stream. + */ +template +std::ostream& operator<<(std::ostream& os, const matrix& m); + +/** + * Writes the real and imaginary parts of a quaternion to an output stream, with each number delimeted by a space. + * + * @param os Output stream. + * @param q Quaternion. + * @return Output stream. + */ +template +std::ostream& operator<<(std::ostream& os, const quaternion& q); + +template +std::ostream& operator<<(std::ostream& os, const vector& v) +{ + for (std::size_t i = 0; i < N; ++i) + { + os << v[i]; + + if (i < N - 1) + { + os << ' '; + } + } + + return os; +} + +template +std::ostream& operator<<(std::ostream& os, const matrix& m) +{ + for (std::size_t i = 0; i < N; ++i) + { + for (std::size_t j = 0; j < M; ++j) + { + os << m[i][j]; + + if (i < N - 1 || j < M - 1) + { + os << ' '; + } + } + } + + return os; +} + +template +std::ostream& operator<<(std::ostream& os, const quaternion& q) +{ + os << std::get<0>(q) << ' ' << std::get<1>(q)[0] << ' ' << std::get<1>(q)[1] << ' ' << std::get<1>(q)[2]; + return os; +} + +/// @} + +} // namespace stream_operators +} // namespace math + +// Bring stream operators into global namespace +using namespace math::stream_operators; + +#endif // ANTKEEPER_MATH_STREAM_OPERATORS_HPP diff --git a/src/math/transform-functions.hpp b/src/math/transform-functions.hpp new file mode 100644 index 0000000..a937f64 --- /dev/null +++ b/src/math/transform-functions.hpp @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_MATH_TRANSFORM_FUNCTIONS_HPP +#define ANTKEEPER_MATH_TRANSFORM_FUNCTIONS_HPP + +#include "math/transform-type.hpp" +#include "math/vector-functions.hpp" +#include "math/matrix-functions.hpp" +#include "math/quaternion-functions.hpp" + +namespace math { + +/// @addtogroup transform +/// @{ + +/** + * Calculates the inverse of a transform. + * + * @param t Transform of which to take the inverse. + */ +template +transform inverse(const transform& t); + +/** + * Converts a transform to a transformation matrix. + * + * @param t Transform. + * @return Matrix representing the transformation described by `t`. + */ +template +matrix matrix_cast(const transform& t); + +/** + * Multiplies two transforms. + * + * @param x First transform. + * @param y Second transform. + * @return Product of the two transforms. + */ +template +transform mul(const transform& x, const transform& y); + +/** + * Multiplies a vector by a transform. + * + * @param t Transform. + * @param v Vector. + * @return Product of the transform and vector. + */ +template +vector mul(const transform& t, const vector& v); + +template +transform inverse(const transform& t) +{ + transform inverse_t; + inverse_t.scale = {T(1) / t.scale.x, T(1) / t.scale.y, T(1) / t.scale.z}; + inverse_t.rotation = conjugate(t.rotation); + inverse_t.translation = negate(mul(inverse_t.rotation, t.translation)); + return inverse_t; +} + +template +matrix matrix_cast(const transform& t) +{ + matrix transformation = resize<4, 4>(matrix_cast(t.rotation)); + transformation[3] = {t.translation[0], t.translation[1], t.translation[2], T(1)}; + return scale(transformation, t.scale); +} + +template +transform mul(const transform& x, const transform& y) +{ + return + { + mul(x, y.translation), + normalize(mul(x.rotation, y.rotation)), + x.scale * y.scale + }; +} + +template +vector mul(const transform& t, const vector& v) +{ + return t.translation + (t.rotation * (v * t.scale)); +} + +/// @} + +} // namespace math + +#endif // ANTKEEPER_MATH_TRANSFORM_FUNCTIONS_HPP + diff --git a/src/math/transform-operators.hpp b/src/math/transform-operators.hpp new file mode 100644 index 0000000..fbf4e72 --- /dev/null +++ b/src/math/transform-operators.hpp @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_MATH_TRANSFORM_OPERATORS_HPP +#define ANTKEEPER_MATH_TRANSFORM_OPERATORS_HPP + +#include "math/transform-type.hpp" +#include "math/transform-functions.hpp" + +namespace math { +namespace transform_operators { + +/// @addtogroup transform +/// @{ + +/// @copydoc mul(const transform&, const transform&) +template +transform operator*(const transform& x, const transform& y); + +/// @copydoc mul(const transform&, const vector&) +template +vector operator*(const transform& t, const vector& v); + +/** + * Multiplies two transforms and stores the result in the first transform. + * + * @param x First transform. + * @param y Second transform. + * @return Reference to the first transform. + */ +template +transform& operator*=(transform& x, const transform& y); + +template +inline transform operator*(const transform& x, const transform& y) +{ + return mul(x, y); +} + +template +inline vector operator*(const transform& t, const vector& v) +{ + return mul(t, v); +} + +template +inline transform& operator*=(transform& x, const vector& y) +{ + return (x = x * y); +} + +/// @} + +} // namespace transform_operators +} // namespace math + +// Bring transform operators into global namespace +using namespace math::transform_operators; + +#endif // ANTKEEPER_MATH_TRANSFORM_OPERATORS_HPP + diff --git a/src/math/transform-type.hpp b/src/math/transform-type.hpp new file mode 100644 index 0000000..5637a19 --- /dev/null +++ b/src/math/transform-type.hpp @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_MATH_TRANSFORM_TYPE_HPP +#define ANTKEEPER_MATH_TRANSFORM_TYPE_HPP + +#include "math/vector-type.hpp" +#include "math/quaternion-type.hpp" + +namespace math { + +/// @addtogroup transform +/// @{ + +/** + * Represents 3D TRS transformation. + * + * @tparam T Scalar type. + */ +template +struct transform +{ + /// Translation vector + vector translation; + + /// Rotation quaternion + quaternion rotation; + + /// Scale vector + vector scale; +}; + +/// @} + +} // namespace math + +#endif // ANTKEEPER_MATH_TRANSFORM_TYPE_HPP + diff --git a/src/math/vector-functions.hpp b/src/math/vector-functions.hpp new file mode 100644 index 0000000..c939fa9 --- /dev/null +++ b/src/math/vector-functions.hpp @@ -0,0 +1,627 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_MATH_VECTOR_FUNCTIONS_HPP +#define ANTKEEPER_MATH_VECTOR_FUNCTIONS_HPP + +#include "math/vector-type.hpp" +#include +#include +#include +#include + +namespace math { + +/// @addtogroup vector +/// @{ + +/** + * Adds two vectors. + * + * @param x First vector. + * @param y Second vector. + * @return Sum of the two vectors. + */ +template +vector add(const vector& x, const vector& y); + +/** + * Checks if all elements of a boolean vector are `true`. + * + * @param x Vector to be tested for truth. + * @return `true` if all elements are `true`, `false` otherwise. + */ +template +bool all(const vector& x); + +/** + * Checks if any elements of a boolean vector are `true`. + * + * @param x Vector to be tested for truth. + * @return `true` if any elements are `true`, `false` otherwise. + */ +template +bool any(const vector& x); + +/** + * Reinterprets data as an `N`-dimensional vector of type `T`. + * + * @tparam N Number of vector dimensions. + * @tparam T Scalar type. + * @param data Data to reinterpret. + */ +template +vector& as_vector(T& data); + +/** + * Clamps the values of a vector's elements. + * + * @param x Vector to clamp. + * @param min_value Minimum element value. + * @param max_value Maximum element value. + * @return Clamped vector. + */ +template +vector clamp(const vector& x, T min_value, T max_value); + +/** + * Clamps the length of a vector. + * + * @param x Vector to clamp. + * @param max_length Maximum length. + * @return Length-clamped vector. + */ +template +vector clamp_length(const vector& x, T max_length); + +/** + * Calculate the cross product of two vectors. + * + * @param x First vector. + * @param y Second vector. + * @return Cross product of the two vectors. + */ +template +vector cross(const vector& x, const vector& y); + +/** + * Calculates the distance between two points. + * + * @param p0 First of two points. + * @param p1 Second of two points. + * @return Distance between the two points. + */ +template +vector distance(const vector& p0, const vector& p1); + +/** + * Calculates the squared distance between two points. The squared distance can be calculated faster than the distance because a call to `std::sqrt` is saved. + * + * @param p0 First of two points. + * @param p1 Second of two points. + * @return Squared distance between the two points. + */ +template +vector distance_squared(const vector& p0, const vector& p1); + +/** + * Divides a vector by another vector. + * + * @param x First vector. + * @param y Second vector. + * @return Result of the division. + */ +template +vector div(const vector& x, const vector& y); + +/** + * Divides a vector by a scalar. + * + * @param v Vector. + * @param s Scalar. + * @return Result of the division. + */ +template +vector div(const vector& v, T s); + +/** + * Calculates the dot product of two vectors. + * + * @param x First vector. + * @param y Second vector. + * @return Dot product of the two vectors. + */ +template +T dot(const vector& x, const vector& y); + +/** + * Compares two vectors for equality + * + * @param x First vector. + * @param y Second vector. + * @return Boolean vector containing the result of the element comparisons. + */ +template +vector equal(const vector& x, const vector& y); + +/** + * Performs a component-wise greater-than comparison of two vectors. + * + * @param x First vector. + * @param y Second vector. + * @return Boolean vector containing the result of the element comparisons. + */ +template +vector greater_than(const vector& x, const vector& y); + +/** + * Performs a component-wise greater-than or equal-to comparison of two vectors. + * + * @param x First vector. + * @param y Second vector. + * @return Boolean vector containing the result of the element comparisons. + */ +template +vector greater_than_equal(const vector& x, const vector& y); + +/** + * Calculates the length of a vector. + * + * @param x Vector of which to calculate the length. + * @return Length of the vector. + */ +template +T length(const vector& x); + +/** + * Calculates the squared length of a vector. The squared length can be calculated faster than the length because a call to `std::sqrt` is saved. + * + * @param x Vector of which to calculate the squared length. + * @return Squared length of the vector. + */ +template +T length_squared(const vector& x); + +/** + * Performs a component-wise less-than comparison of two vectors. + * + * @param x First vector. + * @param y Second vector. + * @return Boolean vector containing the result of the element comparisons. + */ +template +vector less_than(const vector& x, const vector& y); + +/** + * Performs a component-wise less-than or equal-to comparison of two vectors. + * + * @param x First vector. + * @param y Second vector. + * @return Boolean vector containing the result of the element comparisons. + */ +template +vector less_than_equal(const vector& x, const vector& y); + +/** + * Multiplies two vectors. + * + * @param x First vector. + * @param y Second vector. + * @return Product of the two vectors. + */ +template +vector mul(const vector& x, const vector& y); + +/** + * Multiplies a vector by a scalar. + * + * @param v Vector. + * @param s Scalar. + * @return Product of the vector and scalar. + */ +template +vector mul(const vector& v, T s); + +/** + * Negates a vector. + * + * @param x Vector to negate. + * @return Negated vector. + */ +template +vector negate(const vector& x); + +/** + * Calculates the unit vector in the same direction as the original vector. + * + * @param x Vector to normalize. + * @return Normalized vector. + */ +template +vector normalize(const vector& x); + +/** + * Logically inverts a boolean vector. + * + * @param x Vector to be inverted. + * @return Logically inverted vector. + */ +template +vector not(const vector& x); + +/** + * Compares two vectors for inequality + * + * @param x First vector. + * @param y Second vector. + * @return Boolean vector containing the result of the element comparisons. + */ +template +vector not_equal(const vector& x, const vector& y); + +/** + * Resizes a vector. Any new elements will be set to `0`. + * + * @param v Vector to resize. + * @return Resized vector. + */ +template +vector resize(const vector& v); + +/** + * Subtracts a vector from another vector. + * + * @param x First vector. + * @param y Second vector. + * @return Difference between the two vectors. + */ +template +vector sub(const vector& x, const vector& y); + +/** + * Makes an m-dimensional vector by rearranging and/or duplicating elements of an n-dimensional vector. + * + * @tparam Indices List of indices of elements in the vector `v`. + * @tparam T Vector component type. + * @tparam N Number of dimensions in vector `v`. + * @return Vector containing elements from vector `v` in the order specified by `Indices`. The size of the returned vector is equivalent to the number of indices in `Indices`. + */ +template +vector swizzle(const vector& v); + +/// @private +template +inline vector add(const vector& x, const vector& y, std::index_sequence) +{ + return {(x[I] + y[I])...}; +} + +template +inline vector add(const vector& x, const vector& y) +{ + return add(x, y, std::make_index_sequence{}); +} + +/// @private +template +inline bool all(const vector& x, std::index_sequence) +{ + return (x[I] && ...); +} + +template +inline bool all(const vector& x) +{ + return all(x, std::make_index_sequence{}); +} + +/// @private +template +inline bool any(const vector& x, std::index_sequence) +{ + return (x[I] || ...); +} + +template +inline bool any(const vector& x) +{ + return any(x, std::make_index_sequence{}); +} + +template +inline vector& as_vector(T& data) +{ + static_assert(std::is_pod>::value); + return reinterpret_cast&>(data); +} + +/// @private +template +inline vector clamp(const vector& x, T min_value, T max_value, std::index_sequence) +{ + return {std::min(max_value, std::max(min_value, x[I]))...}; +} + +template +inline vector clamp(const vector& x, T min_value, T max_value) +{ + return clamp(x, min_value, max_value, std::make_index_sequence{}); +} + +template +vector clamp_length(const vector& x, T max_length) +{ + T length2 = length_squared(x); + return (length2 > max_length * max_length) ? (x * max_length / std::sqrt(length2)) : x; +} + +template +inline vector cross(const vector& x, const vector& y) +{ + return + { + x[1] * y[2] - y[1] * x[2], + x[2] * y[0] - y[2] * x[0], + x[0] * y[1] - y[0] * x[1] + }; +} + +template +inline vector distance(const vector& p0, const vector& p1) +{ + static_assert(std::is_floating_point::value); + return length(sub(p0, p1)); +} + +template +inline vector distance_squared(const vector& p0, const vector& p1) +{ + static_assert(std::is_floating_point::value); + return length_squared(sub(p0, p1)); +} + +/// @private +template +inline vector div(const vector& x, const vector& y, std::index_sequence) +{ + return {(x[I] / y[I])...}; +} + +template +inline vector div(const vector& x, const vector& y) +{ + return div(x, y, std::make_index_sequence{}); +} + +/// @private +template +inline vector div(const vector& v, T s, std::index_sequence) +{ + return {(v[I] / s)...}; +} + +template +inline vector div(const vector& v, T s) +{ + return div(v, s, std::make_index_sequence{}); +} + +/// @private +template +inline T dot(const vector& x, const vector& y, std::index_sequence) +{ + return ((x[I] * y[I]) + ...); +} + +template +inline T dot(const vector& x, const vector& y) +{ + return dot(x, y, std::make_index_sequence{}); +} + +/// @private +template +inline vector equal(const vector& x, const vector& y, std::index_sequence) +{ + return {(x[I] == y[I])...}; +} + +template +inline vector equal(const vector& x, const vector& y) +{ + return equal(x, y, std::make_index_sequence{}); +} + +/// @private +template +inline vector greater_than(const vector& x, const vector& y, std::index_sequence) +{ + return {(x[I] > y[I])...}; +} + +template +inline vector greater_than(const vector& x, const vector& y) +{ + return greater_than(x, y, std::make_index_sequence{}); +} + +/// @private +template +inline vector greater_than_equal(const vector& x, const vector& y, std::index_sequence) +{ + return {(x[I] >= y[I])...}; +} + +template +inline vector greater_than_equal(const vector& x, const vector& y) +{ + return greater_than_equal(x, y, std::make_index_sequence{}); +} + +template +inline T length(const vector& x) +{ + static_assert(std::is_floating_point::value); + return std::sqrt(dot(x, x)); +} + +template +inline T length_squared(const vector& x) +{ + static_assert(std::is_floating_point::value); + return dot(x, x); +} + +/// @private +template +inline vector less_than(const vector& x, const vector& y, std::index_sequence) +{ + return {(x[I] < y[I])...}; +} + +template +inline vector less_than(const vector& x, const vector& y) +{ + return less_than(x, y, std::make_index_sequence{}); +} + +/// @private +template +inline vector less_than_equal(const vector& x, const vector& y, std::index_sequence) +{ + return {(x[I] <= y[I])...}; +} + +template +inline vector less_than_equal(const vector& x, const vector& y) +{ + return less_than_equal(x, y, std::make_index_sequence{}); +} + +/// @private +template +inline vector mul(const vector& x, const vector& y, std::index_sequence) +{ + return {(x[I] * y[I])...}; +} + +template +inline vector mul(const vector& x, const vector& y) +{ + return mul(x, y, std::make_index_sequence{}); +} + +/// @private +template +inline vector mul(const vector& v, T s, std::index_sequence) +{ + return {(v[I] * s)...}; +} + +template +inline vector mul(const vector& v, T s) +{ + return mul(v, s, std::make_index_sequence{}); +} + +/// @private +template +inline vector negate(const vector& x, std::index_sequence) +{ + return {(-x[I])...}; +} + +template +inline vector negate(const vector& x) +{ + return negate(x, std::make_index_sequence{}); +} + +template +inline vector normalize(const vector& x) +{ + static_assert(std::is_floating_point::value); + return mul(x, T(1) / length(x)); +} + +/// @private +template +inline vector not(const vector& x, std::index_sequence) +{ + return {!x[I]...}; +} + +template +inline vector not(const vector& x) +{ + return not(x, std::make_index_sequence{}); +} + +/// @private +template +inline vector not_equal(const vector& x, const vector& y, std::index_sequence) +{ + return {(x[I] != y[I])...}; +} + +template +inline vector not_equal(const vector& x, const vector& y) +{ + return not_equal(x, y, std::make_index_sequence{}); +} + +template +vector resize(const vector& v) +{ + vector resized; + + for (std::size_t i = 0; i < N1; ++i) + { + resized[i] = (i < N0) ? v[i] : T(0); + } + + return resized; +} + + +/// @private +template +inline vector sub(const vector& x, const vector& y, std::index_sequence) +{ + return {(x[I] - y[I])...}; +} + +template +inline vector sub(const vector& x, const vector& y) +{ + return sub(x, y, std::make_index_sequence{}); +} + +template +inline vector swizzle(const vector& v) +{ + return { v[Indices]... }; +} + +/// @} + +} // namespace math + +#endif // ANTKEEPER_MATH_VECTOR_FUNCTIONS_HPP + diff --git a/src/math/vector-operators.hpp b/src/math/vector-operators.hpp new file mode 100644 index 0000000..dc5424e --- /dev/null +++ b/src/math/vector-operators.hpp @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_MATH_VECTOR_OPERATORS_HPP +#define ANTKEEPER_MATH_VECTOR_OPERATORS_HPP + +#include "math/vector-type.hpp" +#include "math/vector-functions.hpp" + +namespace math { +namespace vector_operators { + +/// @addtogroup vector +/// @{ + +/// @copydoc add(const vector&, const vector&) +template +vector operator+(const vector& x, const vector& y); + +/// @copydoc div(const vector&, const vector&) +template +vector operator/(const vector& x, const vector& y); + +/// @copydoc div(const vector&, T) +template +vector operator/(const vector& v, T s); + +/// @copydoc mul(const vector&, const vector&) +template +vector operator*(const vector& x, const vector& y); + +/// @copydoc mul(const vector&, T) +template +vector operator*(const vector& v, T s); + +/// @copydoc mul(const vector&, T) +template +vector operator*(T s, const vector& v); + +/// @copydoc negate(const vector&) +template +vector operator-(const vector& x); + +/// @copydoc sub(const vector&, const vector&) +template +vector operator-(const vector& x, const vector& y); + +/** + * Adds two vectors and stores the result in the first vector. + * + * @param x First vector. + * @param y Second vector. + * @return Reference to the first vector. + */ +template +vector& operator+=(vector& x, const vector& y); + +/** + * Subtracts two vectors and stores the result in the first vector. + * + * @param x First vector. + * @param y Second vector. + * @return Reference to the first vector. + */ +template +vector& operator-=(vector& x, const vector& y); + +/** + * Multiplies two vectors and stores the result in the first vector. + * + * @param x First vector. + * @param y Second vector. + * @return Reference to the first vector. + */ +template +vector& operator*=(vector& x, const vector& y); + +/** + * Multiplies a vector and a scalar and stores the result in the vector. + * + * @param v Vector. + * @param s Scalar. + * @return Reference to the vector. + */ +template +vector& operator*=(vector& v, T s); + +/** + * Divides the first vector by the second vector the result in the first vector. + * + * @param x First vector. + * @param y Second vector. + * @return Reference to the first vector. + */ +template +vector& operator/=(vector& x, const vector& y); + +/** + * Divides a vector by a scalar and stores the result in the vector. + * + * @param v Vector. + * @param s Scalar. + * @return Reference to the vector. + */ +template +vector& operator/=(vector& v, T s); + +template +inline vector operator+(const vector& x, const vector& y) +{ + return add(x, y); +} + +template +inline vector operator-(const vector& x) +{ + return negate(x); +} + +template +inline vector operator-(const vector& x, const vector& y) +{ + return sub(x, y); +} + +template +inline vector operator*(const vector& x, const vector& y) +{ + return mul(x, y); +} + +template +inline vector operator*(const vector& v, T s) +{ + return mul(v, s); +} + +template +inline vector operator*(T s, const vector& v) +{ + return mul(v, s); +} + +template +inline vector operator/(const vector& x, const vector& y) +{ + return div(x, y); +} + +template +inline vector operator/(const vector& v, T s) +{ + return div(v, s); +} + +template +inline vector& operator+=(vector& x, const vector& y) +{ + return (x = x + y); +} + +template +inline vector& operator-=(vector& x, const vector& y) +{ + return (x = x - y); +} + +template +inline vector& operator*=(vector& x, const vector& y) +{ + return (x = x * y); +} + +template +inline vector& operator*=(vector& v, T s) +{ + return (v = v * s); +} + +template +inline vector& operator/=(vector& x, const vector& y) +{ + return (x = x * y); +} + +template +inline vector& operator/=(vector& v, T s) +{ + return (v = v / s); +} + +/// @} + +} // namespace vector_operators +} // namespace math + +// Bring vector operators into global namespace +using namespace math::vector_operators; + +#endif // ANTKEEPER_MATH_VECTOR_OPERATORS_HPP + diff --git a/src/math/vector-type.hpp b/src/math/vector-type.hpp new file mode 100644 index 0000000..3d2eebd --- /dev/null +++ b/src/math/vector-type.hpp @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_MATH_VECTOR_TYPE_HPP +#define ANTKEEPER_MATH_VECTOR_TYPE_HPP + +#include +#include + +namespace math { + +/// @addtogroup vector +/// @{ + +/** + * An `N`-dimensional Euclidean vector. + * + * @tparam T Vector component type. + * @tparam N Number of dimensions. + */ +template +struct vector +{ + typedef T scalar_type; + typedef std::array array_type; + scalar_type components[N]; + + inline constexpr scalar_type& operator[](std::size_t i) noexcept { return components[i]; } + inline constexpr const scalar_type& operator[](std::size_t i) const noexcept { return components[i]; } + inline constexpr operator array_type&() noexcept { return reinterpret_cast(components[0]); } + inline constexpr operator const array_type&() const noexcept { return reinterpret_cast(components[0]); } + inline constexpr const scalar_type* data() const noexcept { return components; }; + inline constexpr scalar_type* data() noexcept { return components; }; + inline constexpr std::size_t size() const noexcept { return N; }; +}; + +template +struct vector +{ + typedef T scalar_type; + typedef std::array array_type; + scalar_type x; + + inline constexpr scalar_type& operator[](std::size_t i) noexcept { return *((&x) + i); } + inline constexpr const scalar_type& operator[](std::size_t i) const noexcept { return *((&x) + i); } + inline constexpr operator array_type&() noexcept { return reinterpret_cast(x); } + inline constexpr operator const array_type&() const noexcept { return reinterpret_cast(x); } + inline constexpr const scalar_type* data() const noexcept { return &x; }; + inline constexpr scalar_type* data() noexcept { return &x; }; + inline constexpr std::size_t size() const noexcept { return 1; }; +}; + +template +struct vector +{ + typedef T scalar_type; + typedef std::array array_type; + scalar_type x; + scalar_type y; + + inline constexpr scalar_type& operator[](std::size_t i) noexcept { return *((&x) + i); } + inline constexpr const scalar_type& operator[](std::size_t i) const noexcept { return *((&x) + i); } + inline constexpr operator array_type&() noexcept { return reinterpret_cast(x); } + inline constexpr operator const array_type&() const noexcept { return reinterpret_cast(x); } + inline constexpr const scalar_type* data() const noexcept { return &x; }; + inline constexpr scalar_type* data() noexcept { return &x; }; + inline constexpr std::size_t size() const noexcept { return 2; }; +}; + +template +struct vector +{ + typedef T scalar_type; + typedef std::array array_type; + scalar_type x; + scalar_type y; + scalar_type z; + + inline constexpr scalar_type& operator[](std::size_t i) noexcept { return *((&x) + i); } + inline constexpr const scalar_type& operator[](std::size_t i) const noexcept { return *((&x) + i); } + inline constexpr operator array_type&() noexcept { return reinterpret_cast(x); } + inline constexpr operator const array_type&() const noexcept { return reinterpret_cast(x); } + inline constexpr const scalar_type* data() const noexcept { return &x; }; + inline constexpr scalar_type* data() noexcept { return &x; }; + inline constexpr std::size_t size() const noexcept { return 3; }; + +}; + +template +struct vector +{ + typedef T scalar_type; + typedef std::array array_type; + scalar_type x; + scalar_type y; + scalar_type z; + scalar_type w; + + inline constexpr scalar_type& operator[](std::size_t i) noexcept { return *((&x) + i); } + inline constexpr const scalar_type& operator[](std::size_t i) const noexcept { return *((&x) + i); } + inline constexpr operator array_type&() noexcept { return reinterpret_cast(x); } + inline constexpr operator const array_type&() const noexcept { return reinterpret_cast(x); } + inline constexpr const scalar_type* data() const noexcept { return &x; }; + inline constexpr scalar_type* data() noexcept { return &x; }; + inline constexpr std::size_t size() const noexcept { return 4; }; +}; + +static_assert(std::is_trivial>::value); + +/// @} + +} // namespace math + +#endif // ANTKEEPER_MATH_VECTOR_TYPE_HPP + diff --git a/src/nest.cpp b/src/nest.cpp index fbacac1..c87351f 100644 --- a/src/nest.cpp +++ b/src/nest.cpp @@ -18,8 +18,7 @@ */ #include "nest.hpp" -#include "animation/ease.hpp" -#include "math.hpp" +#include "math/math.hpp" nest::nest() { @@ -30,7 +29,7 @@ float3 nest::extend_shaft(shaft& shaft) { float3 dig_position = get_shaft_position(shaft, shaft.current_depth); - float dr = frand(dig_radius * 0.75f, dig_radius * 1.25f); + float dr = math::random(dig_radius * 0.75f, dig_radius * 1.25f); shaft.current_depth += dr * 0.1f; @@ -39,15 +38,15 @@ float3 nest::extend_shaft(shaft& shaft) float3 nest::expand_chamber(chamber& chamber) { - float dig_angle = frand(0.0f, vmq::two_pi); - float2 dig_direction = vmq::normalize(float2{std::cos(dig_angle), std::sin(dig_angle)}); + float dig_angle = math::random(0.0f, math::two_pi); + float2 dig_direction = math::normalize(float2{std::cos(dig_angle), std::sin(dig_angle)}); float3 chamber_center = get_shaft_position(*chamber.shaft, chamber.depth); float3 dig_position = chamber_center; - float dr = frand(dig_radius * 0.75f, dig_radius * 1.25f); + float dr = math::random(dig_radius * 0.75f, dig_radius * 1.25f); - float t = frand(0.0f, 1.0f); + float t = math::random(0.0f, 1.0f); dig_position.x += dig_direction.x * (chamber.outer_radius - dr) * t; dig_position.z += dig_direction.y * (chamber.outer_radius - dr) * t; @@ -63,8 +62,8 @@ float nest::get_shaft_angle(const shaft& shaft, float depth) const { float shaft_length = shaft.depth[1] - shaft.depth[0]; float depth_factor = (depth - shaft.depth[0]) / shaft_length; - float pitch = ease::linear(shaft.pitch[0], shaft.pitch[1], depth_factor); - return shaft.rotation + (depth / pitch) * shaft.chirality * vmq::two_pi; + float pitch = math::lerp(shaft.pitch[0], shaft.pitch[1], depth_factor); + return shaft.rotation + (depth / pitch) * shaft.chirality * math::two_pi; } float nest::get_shaft_depth(const shaft& shaft, float turns) const @@ -77,11 +76,11 @@ float3 nest::get_shaft_position(const shaft& shaft, float depth) const float shaft_length = shaft.depth[1] - shaft.depth[0]; float depth_factor = (depth - shaft.depth[0]) / shaft_length; - float pitch = ease::linear(shaft.pitch[0], shaft.pitch[1], depth_factor); - float radius = ease::out_expo(shaft.radius[0], shaft.radius[1], depth_factor); - float translation_x = ease::linear(shaft.translation[0][0], shaft.translation[1][0], depth_factor); - float translation_z = ease::linear(shaft.translation[0][1], shaft.translation[1][1], depth_factor); - float angle = shaft.rotation + (depth / pitch) * shaft.chirality * vmq::two_pi; + float pitch = math::lerp(shaft.pitch[0], shaft.pitch[1], depth_factor); + float radius = math::lerp(shaft.radius[0], shaft.radius[1], depth_factor); + float translation_x = math::lerp(shaft.translation[0][0], shaft.translation[1][0], depth_factor); + float translation_z = math::lerp(shaft.translation[0][1], shaft.translation[1][1], depth_factor); + float angle = shaft.rotation + (depth / pitch) * shaft.chirality * math::two_pi; float3 position; position[0] = std::cos(angle) * radius + translation_x; diff --git a/src/nest.hpp b/src/nest.hpp index 50286b1..a19b1c6 100644 --- a/src/nest.hpp +++ b/src/nest.hpp @@ -21,13 +21,10 @@ #define ANTKEEPER_NEST_HPP #include "geometry/mesh.hpp" -#include +#include "utility/fundamental-types.hpp" #include #include -using namespace vmq::types; -using namespace vmq::operators; - class nest { public: diff --git a/src/orbit-cam.cpp b/src/orbit-cam.cpp index 1a88da2..5666b81 100644 --- a/src/orbit-cam.cpp +++ b/src/orbit-cam.cpp @@ -19,23 +19,16 @@ #include "orbit-cam.hpp" #include "scene/camera.hpp" +#include "math/math.hpp" #include #include -using namespace vmq::operators; - -template -static inline T lerp(const T& x, const T& y, float a) -{ - return x * (1.0f - a) + y * a; -} - orbit_cam::orbit_cam(): - elevation_rotation(vmq::identity_quaternion), - azimuth_rotation(vmq::identity_quaternion), - target_elevation_rotation(vmq::identity_quaternion), - target_azimuth_rotation(vmq::identity_quaternion), - target_rotation(vmq::identity_quaternion) + elevation_rotation(math::identity_quaternion), + azimuth_rotation(math::identity_quaternion), + target_elevation_rotation(math::identity_quaternion), + target_azimuth_rotation(math::identity_quaternion), + target_rotation(math::identity_quaternion) {} orbit_cam::~orbit_cam() @@ -47,7 +40,7 @@ void orbit_cam::update(float dt) // Calculate rotation and target rotation quaternions //rotation = azimuth_rotation * elevation_rotation; - target_rotation = vmq::normalize(target_azimuth_rotation * target_elevation_rotation); + target_rotation = math::normalize(target_azimuth_rotation * target_elevation_rotation); // Calculate target translation target_translation = target_focal_point + target_rotation * float3{0.0f, 0.0f, target_focal_distance}; @@ -56,15 +49,15 @@ void orbit_cam::update(float dt) //rotation = glm::mix(rotation, target_rotation, interpolation_factor); // Interpolate angles - set_elevation(lerp(elevation, target_elevation, interpolation_factor)); - set_azimuth(lerp(azimuth, target_azimuth, interpolation_factor)); + set_elevation(math::lerp(elevation, target_elevation, interpolation_factor)); + set_azimuth(math::lerp(azimuth, target_azimuth, interpolation_factor)); // Calculate rotation - set_rotation(vmq::normalize(azimuth_rotation * elevation_rotation)); + set_rotation(math::normalize(azimuth_rotation * elevation_rotation)); // Interpolate focal point and focal distance - focal_point = vmq::lerp(focal_point, target_focal_point, interpolation_factor); - focal_distance = lerp(focal_distance, target_focal_distance, interpolation_factor); + focal_point = math::lerp(focal_point, target_focal_point, interpolation_factor); + focal_distance = math::lerp(focal_distance, target_focal_distance, interpolation_factor); // Caluclate translation set_translation(focal_point + get_rotation() * float3{0.0f, 0.0f, focal_distance}); @@ -87,7 +80,7 @@ void orbit_cam::update(float dt) // Update camera if (get_camera() != nullptr) { - transform transform = vmq::identity_transform; + transform_type transform = math::identity_transform; transform.translation = get_translation(); transform.rotation = get_rotation(); get_camera()->set_transform(transform); @@ -128,13 +121,13 @@ void orbit_cam::set_focal_distance(float distance) void orbit_cam::set_elevation(float angle) { elevation = angle; - elevation_rotation = vmq::angle_axis(elevation, float3{-1.0f, 0.0f, 0.0f}); + elevation_rotation = math::angle_axis(elevation, float3{-1.0f, 0.0f, 0.0f}); } void orbit_cam::set_azimuth(float angle) { azimuth = angle; - azimuth_rotation = vmq::angle_axis(azimuth, float3{0.0f, 1.0f, 0.0f}); + azimuth_rotation = math::angle_axis(azimuth, float3{0.0f, 1.0f, 0.0f}); } void orbit_cam::set_target_focal_point(const float3& point) @@ -150,12 +143,12 @@ void orbit_cam::set_target_focal_distance(float distance) void orbit_cam::set_target_elevation(float angle) { target_elevation = angle; - target_elevation_rotation = vmq::angle_axis(target_elevation, float3{-1.0f, 0.0f, 0.0f}); + target_elevation_rotation = math::angle_axis(target_elevation, float3{-1.0f, 0.0f, 0.0f}); } void orbit_cam::set_target_azimuth(float angle) { target_azimuth = angle; - target_azimuth_rotation = vmq::angle_axis(target_azimuth, float3{0.0f, 1.0f, 0.0f}); + target_azimuth_rotation = math::angle_axis(target_azimuth, float3{0.0f, 1.0f, 0.0f}); } diff --git a/src/orbit-cam.hpp b/src/orbit-cam.hpp index 9bcbc52..f68d945 100644 --- a/src/orbit-cam.hpp +++ b/src/orbit-cam.hpp @@ -56,7 +56,7 @@ public: float get_target_elevation() const; float get_target_azimuth() const; const float3& get_target_translation() const; - const vmq::quaternion& get_target_rotation() const; + const quaternion_type& get_target_rotation() const; private: float3 focal_point; @@ -69,11 +69,11 @@ private: float target_elevation; float target_azimuth; - vmq::quaternion elevation_rotation; - vmq::quaternion azimuth_rotation; - vmq::quaternion target_elevation_rotation; - vmq::quaternion target_azimuth_rotation; - vmq::quaternion target_rotation; + quaternion_type elevation_rotation; + quaternion_type azimuth_rotation; + quaternion_type target_elevation_rotation; + quaternion_type target_azimuth_rotation; + quaternion_type target_rotation; float3 target_translation; }; @@ -122,7 +122,7 @@ inline const float3& orbit_cam::get_target_translation() const return target_translation; } -inline const vmq::quaternion& orbit_cam::get_target_rotation() const +inline const typename camera_rig::quaternion_type& orbit_cam::get_target_rotation() const { return target_rotation; } diff --git a/src/pheromone-matrix.cpp b/src/pheromone-matrix.cpp index b1031b3..aec6395 100644 --- a/src/pheromone-matrix.cpp +++ b/src/pheromone-matrix.cpp @@ -18,7 +18,7 @@ */ #include "pheromone-matrix.hpp" -#include +#include "math/math.hpp" void convolve(pheromone_matrix* matrix, const float* kernel, int kernel_size) { @@ -75,9 +75,9 @@ void evaporate(pheromone_matrix* matrix, float factor) void diffuse(pheromone_matrix* matrix) { - const vmq::matrix diffusion_kernel = - vmq::mul( - vmq::matrix + const math::matrix diffusion_kernel = + math::mul( + math::matrix {{ {1, 2, 1}, {2, 4, 2}, diff --git a/src/rasterizer/shader-input.hpp b/src/rasterizer/shader-input.hpp index 5d455af..82956d0 100644 --- a/src/rasterizer/shader-input.hpp +++ b/src/rasterizer/shader-input.hpp @@ -20,14 +20,13 @@ #ifndef ANTKEEPER_SHADER_INPUT_HPP #define ANTKEEPER_SHADER_INPUT_HPP -#include +#include "utility/fundamental-types.hpp" #include class shader_program; class texture_2d; class texture_cube; enum class shader_variable_type; -using namespace vmq::types; /** * Port through which data can be uploaded to shader variables. diff --git a/src/renderer/material-property.hpp b/src/renderer/material-property.hpp index 355b799..a16dfce 100644 --- a/src/renderer/material-property.hpp +++ b/src/renderer/material-property.hpp @@ -23,13 +23,10 @@ #include "animation/tween.hpp" #include "rasterizer/shader-variable-type.hpp" #include "rasterizer/shader-input.hpp" -#include "animation/ease.hpp" -#include +#include "math/interpolation.hpp" +#include "utility/fundamental-types.hpp" #include -using namespace vmq::types; -using namespace vmq::operators; - class material; class shader_program; class texture_2d; @@ -191,25 +188,25 @@ inline T material_property::default_interpolator(const T& x, const T& y, doub template <> inline float material_property::default_interpolator(const float& x, const float& y, double a) { - return ease::linear(x, y, static_cast(a)); + return math::lerp(x, y, static_cast(a)); } template <> inline float2 material_property::default_interpolator(const float2& x, const float2& y, double a) { - return ease::linear(x, y, static_cast(a)); + return math::lerp(x, y, static_cast(a)); } template <> inline float3 material_property::default_interpolator(const float3& x, const float3& y, double a) { - return ease::linear(x, y, static_cast(a)); + return math::lerp(x, y, static_cast(a)); } template <> inline float4 material_property::default_interpolator(const float4& x, const float4& y, double a) { - return ease::linear(x, y, static_cast(a)); + return math::lerp(x, y, static_cast(a)); } template diff --git a/src/renderer/passes/bloom-pass.cpp b/src/renderer/passes/bloom-pass.cpp index 630f99a..6005e2b 100644 --- a/src/renderer/passes/bloom-pass.cpp +++ b/src/renderer/passes/bloom-pass.cpp @@ -32,12 +32,10 @@ #include "rasterizer/texture-filter.hpp" #include "renderer/vertex-attributes.hpp" #include "renderer/render-context.hpp" -#include +#include "math/math.hpp" #include #include -using namespace vmq; - bloom_pass::bloom_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, resource_manager* resource_manager): render_pass(rasterizer, framebuffer), source_texture(nullptr), diff --git a/src/renderer/passes/bloom-pass.hpp b/src/renderer/passes/bloom-pass.hpp index 46d9034..30c1019 100644 --- a/src/renderer/passes/bloom-pass.hpp +++ b/src/renderer/passes/bloom-pass.hpp @@ -21,9 +21,7 @@ #define ANTKEEPER_BLOOM_PASS_HPP #include "renderer/render-pass.hpp" -#include - -using namespace vmq::types; +#include "math/math.hpp" class shader_program; class shader_input; diff --git a/src/renderer/passes/clear-pass.hpp b/src/renderer/passes/clear-pass.hpp index fa8d496..257e234 100644 --- a/src/renderer/passes/clear-pass.hpp +++ b/src/renderer/passes/clear-pass.hpp @@ -21,9 +21,7 @@ #define ANTKEEPER_CLEAR_PASS_HPP #include "renderer/render-pass.hpp" -#include - -using namespace vmq::types; +#include "utility/fundamental-types.hpp" /** * Clears the color, depth, or stencil buffer of a render target. diff --git a/src/renderer/passes/final-pass.cpp b/src/renderer/passes/final-pass.cpp index 65a409d..fcbafa1 100644 --- a/src/renderer/passes/final-pass.cpp +++ b/src/renderer/passes/final-pass.cpp @@ -32,12 +32,10 @@ #include "rasterizer/texture-filter.hpp" #include "renderer/vertex-attributes.hpp" #include "renderer/render-context.hpp" -#include +#include "math/math.hpp" #include #include -using namespace vmq; - final_pass::final_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, resource_manager* resource_manager): render_pass(rasterizer, framebuffer), color_texture(nullptr), diff --git a/src/renderer/passes/final-pass.hpp b/src/renderer/passes/final-pass.hpp index 2bdefd5..61ae249 100644 --- a/src/renderer/passes/final-pass.hpp +++ b/src/renderer/passes/final-pass.hpp @@ -21,9 +21,7 @@ #define ANTKEEPER_FINAL_PASS_HPP #include "renderer/render-pass.hpp" -#include - -using namespace vmq::types; +#include "math/math.hpp" class shader_program; class shader_input; diff --git a/src/renderer/passes/material-pass.cpp b/src/renderer/passes/material-pass.cpp index 3fe41ca..b493eb8 100644 --- a/src/renderer/passes/material-pass.cpp +++ b/src/renderer/passes/material-pass.cpp @@ -45,15 +45,13 @@ #include "scene/spotlight.hpp" #include "scene/scene.hpp" #include "configuration.hpp" -#include +#include "math/math.hpp" #include #include #include #include "shadow-map-pass.hpp" -using namespace vmq; - static bool operation_compare(const render_operation& a, const render_operation& b); material_pass::material_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, resource_manager* resource_manager): @@ -174,7 +172,7 @@ void material_pass::render(render_context* context) const // Transform position into view-space float3 position = light->get_transform_tween().interpolate(context->alpha).translation; - float3 view_space_position = vmq::resize<3>(view * float4{position.x, position.y, position.z, 1.0f}); + float3 view_space_position = math::resize<3>(view * float4{position.x, position.y, position.z, 1.0f}); point_light_positions[point_light_count] = view_space_position; point_light_attenuations[point_light_count] = static_cast(light)->get_attenuation_tween().interpolate(context->alpha); @@ -192,7 +190,7 @@ void material_pass::render(render_context* context) const // Transform direction into view-space float3 direction = static_cast(light)->get_direction_tween().interpolate(context->alpha); - float3 view_space_direction = vmq::normalize(vmq::resize<3>(view * vmq::resize<4>(-direction))); + float3 view_space_direction = math::normalize(math::resize<3>(view * math::resize<4>(-direction))); directional_light_directions[directional_light_count] = view_space_direction; ++directional_light_count; @@ -209,14 +207,14 @@ void material_pass::render(render_context* context) const // Transform position into view-space float3 position = light->get_transform_tween().interpolate(context->alpha).translation; - float3 view_space_position = vmq::resize<3>(view * float4{position.x, position.y, position.z, 1.0f}); + float3 view_space_position = math::resize<3>(view * float4{position.x, position.y, position.z, 1.0f}); spotlight_positions[spotlight_count] = view_space_position; const ::spotlight* spotlight = static_cast(light); // Transform direction into view-space float3 direction = spotlight->get_direction_tween().interpolate(context->alpha); - float3 view_space_direction = vmq::normalize(vmq::resize<3>(view * vmq::resize<4>(-direction))); + float3 view_space_direction = math::normalize(math::resize<3>(view * math::resize<4>(-direction))); spotlight_directions[spotlight_count] = view_space_direction; spotlight_attenuations[spotlight_count] = spotlight->get_attenuation_tween().interpolate(context->alpha); @@ -414,7 +412,7 @@ void material_pass::render(render_context* context) const model = operation.transform; model_view_projection = view_projection * model; model_view = view * model; - normal_model_view = vmq::transpose(vmq::inverse(vmq::resize<3, 3>(model_view))); + normal_model_view = math::transpose(math::inverse(math::resize<3, 3>(model_view))); // Upload operation-dependent parameters if (parameters->model) diff --git a/src/renderer/passes/material-pass.hpp b/src/renderer/passes/material-pass.hpp index 1cc5636..f91dde3 100644 --- a/src/renderer/passes/material-pass.hpp +++ b/src/renderer/passes/material-pass.hpp @@ -23,6 +23,7 @@ #include "renderer/render-pass.hpp" #include "renderer/material.hpp" #include "animation/tween.hpp" +#include "utility/fundamental-types.hpp" #include class camera; diff --git a/src/renderer/passes/shadow-map-pass.cpp b/src/renderer/passes/shadow-map-pass.cpp index acb5108..16ef536 100644 --- a/src/renderer/passes/shadow-map-pass.cpp +++ b/src/renderer/passes/shadow-map-pass.cpp @@ -34,12 +34,9 @@ #include "geometry/view-frustum.hpp" #include "geometry/aabb.hpp" #include "configuration.hpp" -#include +#include "math/math.hpp" #include #include -#include - -using namespace vmq; static bool operation_compare(const render_operation& a, const render_operation& b); @@ -74,13 +71,13 @@ shadow_map_pass::shadow_map_pass(::rasterizer* rasterizer, const ::framebuffer* skinned_model_view_projection_input = skinned_shader_program->get_input("model_view_projection"); // Calculate bias-tile matrices - float4x4 bias_matrix = vmq::translate(vmq::identity4x4, float3{0.5f, 0.5f, 0.5f}) * vmq::scale(vmq::identity4x4, float3{0.5f, 0.5f, 0.5f}); - float4x4 tile_scale = vmq::scale(vmq::identity4x4, float3{0.5f, 0.5f, 1.0f}); + float4x4 bias_matrix = math::translate(math::identity4x4, float3{0.5f, 0.5f, 0.5f}) * math::scale(math::identity4x4, float3{0.5f, 0.5f, 0.5f}); + float4x4 tile_scale = math::scale(math::identity4x4, float3{0.5f, 0.5f, 1.0f}); for (int i = 0; i < 4; ++i) { float x = static_cast(i % 2) * 0.5f; float y = static_cast(i / 2) * 0.5f; - float4x4 tile_matrix = vmq::translate(vmq::identity4x4, float3{x, y, 0.0f}) * tile_scale; + float4x4 tile_matrix = math::translate(math::identity4x4, float3{x, y, 0.0f}) * tile_scale; bias_tile_matrices[i] = tile_matrix * bias_matrix; } } @@ -151,11 +148,11 @@ void shadow_map_pass::render(render_context* context) const } // Calculate a view-projection matrix from the directional light's transform - transform light_transform = light->get_transform_tween().interpolate(context->alpha); + math::transform light_transform = light->get_transform_tween().interpolate(context->alpha); float3 forward = light_transform.rotation * global_forward; float3 up = light_transform.rotation * global_up; - float4x4 light_view = vmq::look_at(light_transform.translation, light_transform.translation + forward, up); - float4x4 light_projection = vmq::ortho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f); + float4x4 light_view = math::look_at(light_transform.translation, light_transform.translation + forward, up); + float4x4 light_projection = math::ortho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f); float4x4 light_view_projection = light_projection * light_view; // Get the camera's view matrix @@ -179,7 +176,7 @@ void shadow_map_pass::render(render_context* context) const // Calculate projection matrix for view camera subfrustum const float subfrustum_near = split_distances[i]; const float subfrustum_far = split_distances[i + 1]; - float4x4 subfrustum_projection = vmq::perspective(camera.get_fov(), camera.get_aspect_ratio(), subfrustum_near, subfrustum_far); + float4x4 subfrustum_projection = math::perspective(camera.get_fov(), camera.get_aspect_ratio(), subfrustum_near, subfrustum_far); // Calculate view camera subfrustum view_frustum subfrustum(subfrustum_projection * camera_view); @@ -222,7 +219,7 @@ void shadow_map_pass::render(render_context* context) const offset.y = std::ceil(offset.y * half_shadow_map_resolution) / half_shadow_map_resolution; // Crop the light view-projection matrix - crop_matrix = vmq::translate(vmq::identity4x4, offset) * vmq::scale(vmq::identity4x4, scale); + crop_matrix = math::translate(math::identity4x4, offset) * math::scale(math::identity4x4, scale); cropped_view_projection = crop_matrix * light_view_projection; // Calculate shadow matrix diff --git a/src/renderer/passes/shadow-map-pass.hpp b/src/renderer/passes/shadow-map-pass.hpp index 5b03379..db6326e 100644 --- a/src/renderer/passes/shadow-map-pass.hpp +++ b/src/renderer/passes/shadow-map-pass.hpp @@ -21,10 +21,7 @@ #define ANTKEEPER_SHADOW_MAP_PASS_HPP #include "renderer/render-pass.hpp" - -#include - -using namespace vmq::types; +#include "utility/fundamental-types.hpp" class shader_program; class shader_input; @@ -86,4 +83,3 @@ inline const float* shadow_map_pass::get_split_distances() const } #endif // ANTKEEPER_SHADOW_MAP_PASS_HPP - diff --git a/src/renderer/passes/sky-pass.cpp b/src/renderer/passes/sky-pass.cpp index eae7838..46e126a 100644 --- a/src/renderer/passes/sky-pass.cpp +++ b/src/renderer/passes/sky-pass.cpp @@ -37,12 +37,10 @@ #include "scene/ambient-light.hpp" #include "scene/directional-light.hpp" #include "scene/scene.hpp" -#include +#include "utility/fundamental-types.hpp" #include #include -using namespace vmq; - sky_pass::sky_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, resource_manager* resource_manager): render_pass(rasterizer, framebuffer) { @@ -113,7 +111,7 @@ void sky_pass::render(render_context* context) const rasterizer->set_viewport(0, 0, std::get<0>(viewport), std::get<1>(viewport)); float3 sun_direction = {0, 0, -1}; - float sun_angular_radius = 3.0f * vmq::pi / 180.0f; + float sun_angular_radius = math::radians(3.0f); // Find sun direction const std::list* lights = context->scene->get_objects(light::object_type_id); @@ -129,9 +127,9 @@ void sky_pass::render(render_context* context) const } // Calculate matrix - float4x4 model_view = vmq::resize<4, 4>(vmq::resize<3, 3>(context->camera->get_view_tween().interpolate(context->alpha))); - float4x4 inverse_projection = vmq::inverse(context->camera->get_projection_tween().interpolate(context->alpha)); - float4x4 matrix = vmq::inverse(model_view) * inverse_projection; + float4x4 model_view = math::resize<4, 4>(math::resize<3, 3>(context->camera->get_view_tween().interpolate(context->alpha))); + float4x4 inverse_projection = math::inverse(context->camera->get_projection_tween().interpolate(context->alpha)); + float4x4 matrix = math::inverse(model_view) * inverse_projection; // Change shader program rasterizer->use_program(*shader_program); diff --git a/src/renderer/passes/ui-pass.cpp b/src/renderer/passes/ui-pass.cpp index 79c26b5..a008da0 100644 --- a/src/renderer/passes/ui-pass.cpp +++ b/src/renderer/passes/ui-pass.cpp @@ -41,12 +41,10 @@ #include "scene/directional-light.hpp" #include "scene/scene.hpp" #include "scene/billboard.hpp" -#include +#include "math/math.hpp" #include #include -using namespace vmq; - ui_pass::ui_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, resource_manager* resource_manager): render_pass(rasterizer, framebuffer), time(0.0f) diff --git a/src/renderer/render-context.hpp b/src/renderer/render-context.hpp index 418aa60..fcd4bb5 100644 --- a/src/renderer/render-context.hpp +++ b/src/renderer/render-context.hpp @@ -23,19 +23,16 @@ #include "renderer/render-operation.hpp" #include "geometry/plane.hpp" #include "geometry/bounding-volume.hpp" -#include +#include "utility/fundamental-types.hpp" #include class camera; class scene; -using namespace vmq::types; -using vmq::transform; - struct render_context { const camera* camera; - transform camera_transform; + math::transform camera_transform; float3 camera_forward; float3 camera_up; const bounding_volume* camera_culling_volume; diff --git a/src/renderer/render-operation.hpp b/src/renderer/render-operation.hpp index 83592e0..cb139b2 100644 --- a/src/renderer/render-operation.hpp +++ b/src/renderer/render-operation.hpp @@ -20,14 +20,13 @@ #ifndef ANTKEEPER_RENDER_OPERATION_HPP #define ANTKEEPER_RENDER_OPERATION_HPP +#include "utility/fundamental-types.hpp" #include -#include class pose; class material; class vertex_array; enum class drawing_mode; -using namespace vmq::types; /** * Describes a render operation with a single mesh and single material. diff --git a/src/renderer/renderer.cpp b/src/renderer/renderer.cpp index 69fff3f..04ed5eb 100644 --- a/src/renderer/renderer.cpp +++ b/src/renderer/renderer.cpp @@ -27,13 +27,12 @@ #include "scene/lod-group.hpp" #include "renderer/model.hpp" #include "rasterizer/drawing-mode.hpp" +#include "math/math.hpp" +#include "geometry/projection.hpp" #include "configuration.hpp" -#include "math.hpp" #include #include -using namespace vmq::operators; - renderer::renderer() { // Setup billboard render operation @@ -166,8 +165,8 @@ void renderer::process_model_instance(render_context& context, const ::model_ins operation.drawing_mode = group->get_drawing_mode(); operation.start_index = group->get_start_index(); operation.index_count = group->get_index_count(); - operation.transform = vmq::matrix_cast(model_instance->get_transform_tween().interpolate(context.alpha)); - operation.depth = signed_distance(context.clip_near, vmq::resize<3>(operation.transform[3])); + operation.transform = math::matrix_cast(model_instance->get_transform_tween().interpolate(context.alpha)); + operation.depth = context.clip_near.signed_distance(math::resize<3>(operation.transform[3])); operation.instance_count = model_instance->get_instance_count(); context.operations.push_back(operation); @@ -185,26 +184,26 @@ void renderer::process_billboard(render_context& context, const ::billboard* bil if (!context.camera_culling_volume->intersects(*object_culling_volume)) return; - transform billboard_transform = billboard->get_transform_tween().interpolate(context.alpha); + math::transform billboard_transform = billboard->get_transform_tween().interpolate(context.alpha); billboard_op.material = billboard->get_material(); - billboard_op.depth = signed_distance(context.clip_near, vmq::resize<3>(billboard_transform.translation)); + billboard_op.depth = context.clip_near.signed_distance(math::resize<3>(billboard_transform.translation)); // Align billboard if (billboard->get_billboard_type() == billboard_type::spherical) { - billboard_transform.rotation = vmq::normalize(vmq::look_rotation(context.camera_forward, context.camera_up) * billboard_transform.rotation); + billboard_transform.rotation = math::normalize(math::look_rotation(context.camera_forward, context.camera_up) * billboard_transform.rotation); } else if (billboard->get_billboard_type() == billboard_type::cylindrical) { const float3& alignment_axis = billboard->get_alignment_axis(); - float3 look = vmq::normalize(math::project_on_plane(billboard_transform.translation - context.camera_transform.translation, {0.0f, 0.0f, 0.0f}, alignment_axis)); - float3 right = vmq::normalize(vmq::cross(alignment_axis, look)); - look = vmq::cross(right, alignment_axis); - float3 up = vmq::cross(look, right); - billboard_transform.rotation = vmq::normalize(vmq::look_rotation(look, up) * billboard_transform.rotation); + float3 look = math::normalize(project_on_plane(billboard_transform.translation - context.camera_transform.translation, {0.0f, 0.0f, 0.0f}, alignment_axis)); + float3 right = math::normalize(math::cross(alignment_axis, look)); + look = math::cross(right, alignment_axis); + float3 up = math::cross(look, right); + billboard_transform.rotation = math::normalize(math::look_rotation(look, up) * billboard_transform.rotation); } - billboard_op.transform = vmq::matrix_cast(billboard_transform); + billboard_op.transform = math::matrix_cast(billboard_transform); context.operations.push_back(billboard_op); } diff --git a/src/renderer/simple-render-pass.cpp b/src/renderer/simple-render-pass.cpp index 1e8f97b..d479ea8 100644 --- a/src/renderer/simple-render-pass.cpp +++ b/src/renderer/simple-render-pass.cpp @@ -33,11 +33,9 @@ #include "renderer/render-context.hpp" #include "renderer/material.hpp" #include "renderer/material-property.hpp" -#include +#include "math/math.hpp" #include -using namespace vmq; - simple_render_pass::simple_render_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, ::shader_program* shader_program): render_pass(rasterizer, framebuffer), shader_program(shader_program), diff --git a/src/renderer/simple-render-pass.hpp b/src/renderer/simple-render-pass.hpp index 0cd5595..6e22314 100644 --- a/src/renderer/simple-render-pass.hpp +++ b/src/renderer/simple-render-pass.hpp @@ -22,9 +22,7 @@ #include "renderer/render-pass.hpp" #include "animation/tween.hpp" -#include - -using namespace vmq::types; +#include "utility/fundamental-types.hpp" class shader_program; class shader_input; diff --git a/src/resources/material-loader.cpp b/src/resources/material-loader.cpp index 206eb0a..b1ed21b 100644 --- a/src/resources/material-loader.cpp +++ b/src/resources/material-loader.cpp @@ -24,6 +24,7 @@ #include "rasterizer/texture-wrapping.hpp" #include "rasterizer/texture-filter.hpp" #include "rasterizer/texture-2d.hpp" +#include "utility/fundamental-types.hpp" #include "string-table.hpp" #include #include diff --git a/src/resources/mesh-loader.cpp b/src/resources/mesh-loader.cpp index 4786338..10e395c 100644 --- a/src/resources/mesh-loader.cpp +++ b/src/resources/mesh-loader.cpp @@ -20,6 +20,7 @@ #include "resources/resource-loader.hpp" #include "geometry/mesh.hpp" #include "geometry/mesh-functions.hpp" +#include "utility/fundamental-types.hpp" #include #include #include diff --git a/src/resources/model-loader.cpp b/src/resources/model-loader.cpp index c56f360..b4a1fa2 100644 --- a/src/resources/model-loader.cpp +++ b/src/resources/model-loader.cpp @@ -23,13 +23,11 @@ #include "renderer/vertex-attributes.hpp" #include "rasterizer/vertex-attribute-type.hpp" #include "rasterizer/drawing-mode.hpp" +#include "utility/fundamental-types.hpp" #include #include #include #include -#include - -using namespace vmq::types; struct material_group { diff --git a/src/scene/billboard.hpp b/src/scene/billboard.hpp index 54d9147..fba38dc 100644 --- a/src/scene/billboard.hpp +++ b/src/scene/billboard.hpp @@ -22,6 +22,7 @@ #include "scene/scene-object.hpp" #include "geometry/aabb.hpp" +#include "utility/fundamental-types.hpp" class material; diff --git a/src/scene/camera.cpp b/src/scene/camera.cpp index 2896f1f..8c6daf0 100644 --- a/src/scene/camera.cpp +++ b/src/scene/camera.cpp @@ -20,22 +20,22 @@ #include "scene/camera.hpp" #include "configuration.hpp" #include "animation/ease.hpp" - -using namespace vmq::operators; +#include "math/constants.hpp" +#include "math/interpolation.hpp" static float4x4 interpolate_view(const camera* camera, const float4x4& x, const float4x4& y, float a) { - transform transform = camera->get_transform_tween().interpolate(a); + math::transform transform = camera->get_transform_tween().interpolate(a); float3 forward = transform.rotation * global_forward; float3 up = transform.rotation * global_up; - return vmq::look_at(transform.translation, transform.translation + forward, up); + return math::look_at(transform.translation, transform.translation + forward, up); } static float4x4 interpolate_projection(const camera* camera, const float4x4& x, const float4x4& y, float a) { if (camera->is_orthographic()) { - return vmq::ortho( + return math::ortho( camera->get_clip_left_tween().interpolate(a), camera->get_clip_right_tween().interpolate(a), camera->get_clip_bottom_tween().interpolate(a), @@ -45,7 +45,7 @@ static float4x4 interpolate_projection(const camera* camera, const float4x4& x, } else { - return vmq::perspective( + return math::perspective( camera->get_fov_tween().interpolate(a), camera->get_aspect_ratio_tween().interpolate(a), camera->get_clip_near_tween().interpolate(a), @@ -62,17 +62,17 @@ camera::camera(): compositor(nullptr), composite_index(0), orthographic(true), - clip_left(-1.0f, ease::linear), - clip_right(1.0f, ease::linear), - clip_bottom(-1.0f, ease::linear), - clip_top(1.0f, ease::linear), - clip_near(-1.0f, ease::linear), - clip_far(1.0f, ease::linear), - fov(vmq::half_pi, ease::linear), - aspect_ratio(1.0f, ease::linear), - view(vmq::identity4x4, std::bind(&interpolate_view, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)), - projection(vmq::identity4x4, std::bind(&interpolate_projection, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)), - view_projection(vmq::identity4x4, std::bind(&interpolate_view_projection, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)) + clip_left(-1.0f, math::lerp), + clip_right(1.0f, math::lerp), + clip_bottom(-1.0f, math::lerp), + clip_top(1.0f, math::lerp), + clip_near(-1.0f, math::lerp), + clip_far(1.0f, math::lerp), + fov(math::half_pi, math::lerp), + aspect_ratio(1.0f, math::lerp), + view(math::identity4x4, std::bind(&interpolate_view, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)), + projection(math::identity4x4, std::bind(&interpolate_projection, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)), + view_projection(math::identity4x4, std::bind(&interpolate_view_projection, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)) {} float3 camera::project(const float3& object, const float4& viewport) const @@ -85,7 +85,7 @@ float3 camera::project(const float3& object, const float4& viewport) const result[0] = result[0] * viewport[2] + viewport[0]; result[1] = result[1] * viewport[3] + viewport[1]; - return vmq::resize<3>(result); + return math::resize<3>(result); } float3 camera::unproject(const float3& window, const float4& viewport) const @@ -96,9 +96,9 @@ float3 camera::unproject(const float3& window, const float4& viewport) const result[2] = window[2] * 2.0f - 1.0f; result[3] = 1.0f; - result = vmq::inverse(view_projection[1]) * result; + result = math::inverse(view_projection[1]) * result; - return vmq::resize<3>(result) * (1.0f / result[3]); + return math::resize<3>(result) * (1.0f / result[3]); } void camera::set_perspective(float fov, float aspect_ratio, float clip_near, float clip_far) @@ -110,7 +110,7 @@ void camera::set_perspective(float fov, float aspect_ratio, float clip_near, flo this->clip_near[1] = clip_near; this->clip_far[1] = clip_far; - projection[1] = vmq::perspective(fov, aspect_ratio, clip_near, clip_far); + projection[1] = math::perspective(fov, aspect_ratio, clip_near, clip_far); // Recalculate view-projection matrix view_projection[1] = projection[1] * view[1]; @@ -130,7 +130,7 @@ void camera::set_orthographic(float clip_left, float clip_right, float clip_bott this->clip_near[1] = clip_near; this->clip_far[1] = clip_far; - projection[1] = vmq::ortho(clip_left, clip_right, clip_bottom, clip_top, clip_near, clip_far); + projection[1] = math::ortho(clip_left, clip_right, clip_bottom, clip_top, clip_near, clip_far); // Recalculate view-projection matrix view_projection[1] = projection[1] * view[1]; @@ -170,7 +170,7 @@ void camera::transformed() // Recalculate view and view-projection matrices float3 forward = get_rotation() * global_forward; float3 up = get_rotation() * global_up; - view[1] = vmq::look_at(get_translation(), get_translation() + forward, up); + view[1] = math::look_at(get_translation(), get_translation() + forward, up); view_projection[1] = projection[1] * view[1]; // Recalculate view frustum diff --git a/src/scene/camera.hpp b/src/scene/camera.hpp index 11173f4..168316b 100644 --- a/src/scene/camera.hpp +++ b/src/scene/camera.hpp @@ -22,6 +22,7 @@ #include "scene/scene-object.hpp" #include "geometry/view-frustum.hpp" +#include "utility/fundamental-types.hpp" class compositor; diff --git a/src/scene/directional-light.cpp b/src/scene/directional-light.cpp index 4123888..79801e9 100644 --- a/src/scene/directional-light.cpp +++ b/src/scene/directional-light.cpp @@ -19,14 +19,13 @@ #include "directional-light.hpp" #include "configuration.hpp" - -using namespace vmq::operators; +#include "math/math.hpp" static float3 interpolate_direction(const float3& x, const float3& y, float a) { - quaternion q0 = vmq::rotation(global_forward, x); - quaternion q1 = vmq::rotation(global_forward, y); - return vmq::normalize(vmq::slerp(q0, q1, a) * global_forward); + math::quaternion q0 = math::rotation(global_forward, x); + math::quaternion q1 = math::rotation(global_forward, y); + return math::normalize(math::slerp(q0, q1, a) * global_forward); } directional_light::directional_light(): @@ -41,6 +40,6 @@ void directional_light::update_tweens() void directional_light::transformed() { - direction[1] = vmq::normalize(get_transform().rotation * global_forward); + direction[1] = math::normalize(get_transform().rotation * global_forward); } diff --git a/src/scene/directional-light.hpp b/src/scene/directional-light.hpp index c7cddaf..e014d80 100644 --- a/src/scene/directional-light.hpp +++ b/src/scene/directional-light.hpp @@ -21,9 +21,7 @@ #define ANTKEEPER_DIRECTIONAL_LIGHT_HPP #include "scene/light.hpp" -#include - -using namespace vmq::types; +#include "utility/fundamental-types.hpp" class directional_light: public light { diff --git a/src/scene/light.cpp b/src/scene/light.cpp index 23d291e..8402373 100644 --- a/src/scene/light.cpp +++ b/src/scene/light.cpp @@ -19,14 +19,13 @@ #include "scene/light.hpp" #include "animation/ease.hpp" - -using namespace vmq::operators; +#include "math/interpolation.hpp" light::light(): bounds(get_translation(), 0.0f), - color(float3{1.0f, 1.0f, 1.0f}, ease::linear), - intensity(1.0f, ease::linear), - scaled_color(float3{1.0f, 1.0f, 1.0f}, ease::linear) + color(float3{1.0f, 1.0f, 1.0f}, math::lerp), + intensity(1.0f, math::lerp), + scaled_color(float3{1.0f, 1.0f, 1.0f}, math::lerp) {} void light::set_color(const float3& color) diff --git a/src/scene/light.hpp b/src/scene/light.hpp index 06a71ca..c729fb5 100644 --- a/src/scene/light.hpp +++ b/src/scene/light.hpp @@ -22,6 +22,7 @@ #include "scene/scene-object.hpp" #include "geometry/sphere.hpp" +#include "utility/fundamental-types.hpp" enum class light_type { diff --git a/src/scene/lod-group.cpp b/src/scene/lod-group.cpp index cc3e584..465bd53 100644 --- a/src/scene/lod-group.cpp +++ b/src/scene/lod-group.cpp @@ -37,7 +37,7 @@ void lod_group::resize(std::size_t level_count) std::size_t lod_group::select_lod(const ::camera& camera) const { - float distance = signed_distance(camera.get_view_frustum().get_near(), get_translation()); + float distance = camera.get_view_frustum().get_near().signed_distance(get_translation()); if (distance < 300.0f) return 0; diff --git a/src/scene/point-light.cpp b/src/scene/point-light.cpp index f171f34..ff17f42 100644 --- a/src/scene/point-light.cpp +++ b/src/scene/point-light.cpp @@ -18,12 +18,10 @@ */ #include "point-light.hpp" -#include "animation/ease.hpp" - -using namespace vmq::operators; +#include "math/interpolation.hpp" point_light::point_light(): - attenuation(float3{1, 0, 0}, ease::linear) + attenuation(float3{1, 0, 0}, math::lerp) {} void point_light::set_attenuation(const float3& attenuation) @@ -36,4 +34,3 @@ void point_light::update_tweens() light::update_tweens(); attenuation.update(); } - diff --git a/src/scene/point-light.hpp b/src/scene/point-light.hpp index daec171..b64639e 100644 --- a/src/scene/point-light.hpp +++ b/src/scene/point-light.hpp @@ -21,6 +21,7 @@ #define ANTKEEPER_POINT_LIGHT_HPP #include "scene/light.hpp" +#include "utility/fundamental-types.hpp" class point_light: public light { diff --git a/src/scene/scene-object.cpp b/src/scene/scene-object.cpp index acbc9d4..f596350 100644 --- a/src/scene/scene-object.cpp +++ b/src/scene/scene-object.cpp @@ -18,24 +18,25 @@ */ #include "scene/scene-object.hpp" +#include "math/math.hpp" -static transform transform_interpolate(const transform& x, const transform& y, float a) +typename scene_object_base::transform_type scene_object_base::interpolate_transforms(const transform_type& x, const transform_type& y, float a) { return { - vmq::lerp(x.translation, y.translation, a), - vmq::slerp(x.rotation, y.rotation, a), - vmq::lerp(x.scale, y.scale, a), + math::lerp(x.translation, y.translation, a), + math::slerp(x.rotation, y.rotation, a), + math::lerp(x.scale, y.scale, a), }; } scene_object_base::scene_object_base(): active(true), - transform(vmq::identity_transform, transform_interpolate), + transform(math::identity_transform, interpolate_transforms), culling_mask(nullptr) {} -void scene_object_base::set_culling_mask(const bounding_volume* culling_mask) +void scene_object_base::set_culling_mask(const bounding_volume_type* culling_mask) { this->culling_mask = culling_mask; } @@ -51,10 +52,10 @@ void scene_object_base::update_tweens() transform.update(); } -void scene_object_base::look_at(const float3& position, const float3& target, const float3& up) +void scene_object_base::look_at(const vector_type& position, const vector_type& target, const vector_type& up) { transform[1].translation = position; - transform[1].rotation = vmq::look_rotation(vmq::normalize(vmq::sub(target, position)), up); + transform[1].rotation = math::look_rotation(math::normalize(math::sub(target, position)), up); transformed(); } diff --git a/src/scene/scene-object.hpp b/src/scene/scene-object.hpp index 4ee883e..805797c 100644 --- a/src/scene/scene-object.hpp +++ b/src/scene/scene-object.hpp @@ -20,15 +20,13 @@ #ifndef ANTKEEPER_SCENE_OBJECT_HPP #define ANTKEEPER_SCENE_OBJECT_HPP -#include -#include -#include #include "animation/tween.hpp" #include "geometry/bounding-volume.hpp" - -using namespace vmq::types; -using vmq::quaternion; -using vmq::transform; +#include "math/vector-type.hpp" +#include "math/quaternion-type.hpp" +#include "math/transform-type.hpp" +#include +#include /** * Internal base class for scene objects. @@ -36,6 +34,11 @@ using vmq::transform; class scene_object_base { public: + typedef math::vector vector_type; + typedef math::quaternion quaternion_type; + typedef math::transform transform_type; + typedef bounding_volume bounding_volume_type; + /// Returns the type ID for this scene object type. virtual const std::size_t get_object_type_id() const = 0; @@ -62,32 +65,32 @@ public: /** * */ - void look_at(const float3& position, const float3& target, const float3& up); + void look_at(const vector_type& position, const vector_type& target, const vector_type& up); /** * Sets the scene object's transform. */ - void set_transform(const transform& transform); + void set_transform(const transform_type& transform); /** * Sets the scene object's translation. */ - void set_translation(const float3& translation); + void set_translation(const vector_type& translation); /** * Sets the scene object's rotation. */ - void set_rotation(const quaternion& rotation); + void set_rotation(const quaternion_type& rotation); /** * Sets the scene object's scale. */ - void set_scale(const float3& scale); + void set_scale(const vector_type& scale); /** * Sets a culling mask for the object, which will be used for view-frustum culling instead of the object's bounds. */ - void set_culling_mask(const bounding_volume* culling_mask); + void set_culling_mask(const bounding_volume_type* culling_mask); /// Returns whether the scene object is active. bool is_active() const; @@ -95,51 +98,54 @@ public: /** * Returns the transform. */ - const transform& get_transform() const; + const transform_type& get_transform() const; /** * Returns the transform's translation vector. */ - const float3& get_translation() const; + const vector_type& get_translation() const; /** * Returns the transform's rotation quaternion. */ - const quaternion& get_rotation() const; + const quaternion_type& get_rotation() const; /** * Returns the transform's scale vector. */ - const float3& get_scale() const; + const vector_type& get_scale() const; /** * Returns the transform tween. */ - const tween>& get_transform_tween() const; - tween>& get_transform_tween(); + const tween& get_transform_tween() const; + tween& get_transform_tween(); /** * Returns the bounds of the object. */ - virtual const bounding_volume& get_bounds() const = 0; + virtual const bounding_volume_type& get_bounds() const = 0; /** * Returns the culling mask of the object. */ - const bounding_volume* get_culling_mask() const; + const bounding_volume_type* get_culling_mask() const; protected: static std::size_t next_object_type_id(); private: + /// Interpolates between two transforms. + static transform_type interpolate_transforms(const transform_type& x, const transform_type& y, float a); + /** * Called every time the scene object's tranform is changed. */ virtual void transformed(); bool active; - tween> transform; - const bounding_volume* culling_mask; + tween transform; + const bounding_volume_type* culling_mask; }; inline void scene_object_base::set_active(bool active) @@ -147,25 +153,25 @@ inline void scene_object_base::set_active(bool active) this->active = active; } -inline void scene_object_base::set_transform(const ::transform& transform) +inline void scene_object_base::set_transform(const transform_type& transform) { this->transform[1] = transform; transformed(); } -inline void scene_object_base::set_translation(const float3& translation) +inline void scene_object_base::set_translation(const vector_type& translation) { transform[1].translation = translation; transformed(); } -inline void scene_object_base::set_rotation(const quaternion& rotation) +inline void scene_object_base::set_rotation(const quaternion_type& rotation) { transform[1].rotation = rotation; transformed(); } -inline void scene_object_base::set_scale(const float3& scale) +inline void scene_object_base::set_scale(const vector_type& scale) { transform[1].scale = scale; transformed(); @@ -176,37 +182,37 @@ inline bool scene_object_base::is_active() const return active; } -inline const transform& scene_object_base::get_transform() const +inline const typename scene_object_base::transform_type& scene_object_base::get_transform() const { return transform[1]; } -inline const float3& scene_object_base::get_translation() const +inline const typename scene_object_base::vector_type& scene_object_base::get_translation() const { return get_transform().translation; } -inline const quaternion& scene_object_base::get_rotation() const +inline const typename scene_object_base::quaternion_type& scene_object_base::get_rotation() const { return get_transform().rotation; } -inline const float3& scene_object_base::get_scale() const +inline const typename scene_object_base::vector_type& scene_object_base::get_scale() const { return get_transform().scale; } -inline const tween>& scene_object_base::get_transform_tween() const +inline const tween& scene_object_base::get_transform_tween() const { return transform; } -inline tween>& scene_object_base::get_transform_tween() +inline tween& scene_object_base::get_transform_tween() { return transform; } -inline const bounding_volume* scene_object_base::get_culling_mask() const +inline const typename scene_object_base::bounding_volume_type* scene_object_base::get_culling_mask() const { return culling_mask; } diff --git a/src/scene/spotlight.cpp b/src/scene/spotlight.cpp index 62d2f93..8ff4c4f 100644 --- a/src/scene/spotlight.cpp +++ b/src/scene/spotlight.cpp @@ -19,23 +19,21 @@ #include "spotlight.hpp" #include "configuration.hpp" -#include "animation/ease.hpp" +#include "math/math.hpp" #include -using namespace vmq::operators; - static float3 interpolate_direction(const float3& x, const float3& y, float a) { - quaternion q0 = vmq::rotation(global_forward, x); - quaternion q1 = vmq::rotation(global_forward, y); - return vmq::normalize(vmq::slerp(q0, q1, a) * global_forward); + math::quaternion q0 = math::rotation(global_forward, x); + math::quaternion q1 = math::rotation(global_forward, y); + return math::normalize(math::slerp(q0, q1, a) * global_forward); } spotlight::spotlight(): direction(global_forward, interpolate_direction), - attenuation(float3{1, 0, 0}, ease::linear), - cutoff(float2{vmq::pi, vmq::pi}, ease::linear), - cosine_cutoff(float2{std::cos(vmq::pi), std::cos(vmq::pi)}, ease::linear) + attenuation(float3{1, 0, 0}, math::lerp), + cutoff(float2{math::pi, math::pi}, math::lerp), + cosine_cutoff(float2{std::cos(math::pi), std::cos(math::pi)}, math::lerp) {} void spotlight::set_attenuation(const float3& attenuation) @@ -60,6 +58,6 @@ void spotlight::update_tweens() void spotlight::transformed() { - direction[1] = vmq::normalize(get_transform().rotation * global_forward); + direction[1] = math::normalize(get_transform().rotation * global_forward); } diff --git a/src/scene/spotlight.hpp b/src/scene/spotlight.hpp index 38b1a0b..e812037 100644 --- a/src/scene/spotlight.hpp +++ b/src/scene/spotlight.hpp @@ -21,9 +21,7 @@ #define ANTKEEPER_SPOTLIGHT_HPP #include "scene/light.hpp" -#include - -using namespace vmq::types; +#include "utility/fundamental-types.hpp" class spotlight: public light { diff --git a/src/state/play-state.cpp b/src/state/play-state.cpp index 19a9027..da4062a 100644 --- a/src/state/play-state.cpp +++ b/src/state/play-state.cpp @@ -39,13 +39,11 @@ #include "entity/archetype.hpp" #include "entity/entity-commands.hpp" #include "nest.hpp" -#include "math.hpp" +#include "math/math.hpp" +#include "utility/fundamental-types.hpp" #include "geometry/mesh-accelerator.hpp" #include "behavior/ebt.hpp" #include "animation/ease.hpp" -#include - -using namespace vmq::operators; void enter_play_state(application* app) { @@ -92,15 +90,15 @@ void enter_play_state(application* app) for (int i = 0; i < pebble_count; ++i) { - float x = frand(-pebble_radius, pebble_radius); - float z = frand(-pebble_radius, pebble_radius); + float x = math::random(-pebble_radius, pebble_radius); + float z = math::random(-pebble_radius, pebble_radius); auto pebble_entity = pebble_archetype->create(ecs_registry); auto& transform = ecs_registry.get(pebble_entity); - transform.transform = vmq::identity_transform; - transform.transform.rotation = vmq::angle_axis(frand(0.0f, vmq::two_pi), {0, 1, 0}); - transform.transform.scale = float3{1, 1, 1} * frand(0.75f, 1.25f); + transform.transform = math::identity_transform; + transform.transform.rotation = math::angle_axis(math::random(0.0f, math::two_pi), {0, 1, 0}); + transform.transform.scale = float3{1, 1, 1} * math::random(0.75f, 1.25f); placement.ray.origin = {x, 10000, z}; ecs_registry.assign(pebble_entity, placement); @@ -133,15 +131,15 @@ void enter_play_state(application* app) auto& transform = ecs_registry.get(samara_entity); float zone = 200.0f; - transform.transform = vmq::identity_transform; - transform.transform.translation.x = frand(-zone, zone); - transform.transform.translation.y = frand(50.0f, 150.0f); - transform.transform.translation.z = frand(-zone, zone); + transform.transform = math::identity_transform; + transform.transform.translation.x = math::random(-zone, zone); + transform.transform.translation.y = math::random(50.0f, 150.0f); + transform.transform.translation.z = math::random(-zone, zone); ecs::samara_component samara_component; - samara_component.angle = frand(0.0f, vmq::radians(360.0f)); - samara_component.direction = vmq::normalize(float3{frand(-1, 1), frand(-1, -5), frand(-1, 1)}); - samara_component.chirality = (frand(0, 1) < 0.5f) ? -1.0f : 1.0f; + samara_component.angle = math::random(0.0f, math::radians(360.0f)); + samara_component.direction = math::normalize(float3{math::random(-1.0f, 1.0f), math::random(-1.0f, -5.0f), math::random(-1.0f, 1.0f)}); + samara_component.chirality = (math::random(0.0f, 1.0f) < 0.5f) ? -1.0f : 1.0f; ecs_registry.assign_or_replace(samara_entity, samara_component); } @@ -150,7 +148,7 @@ void enter_play_state(application* app) ecs::archetype* grass_archetype = resource_manager->load("grassland-grass.ent"); auto grass_entity_1 = grass_archetype->create(ecs_registry); auto grass_entity_2 = grass_archetype->create(ecs_registry); - ecs_registry.get(grass_entity_2).transform.rotation = vmq::angle_axis(vmq::radians(120.0f), float3{0, 1, 0}); + ecs_registry.get(grass_entity_2).transform.rotation = math::angle_axis(math::radians(120.0f), float3{0, 1, 0}); */ // Setup overworld camera @@ -159,7 +157,7 @@ void enter_play_state(application* app) orbit_cam->attach(camera); orbit_cam->set_target_focal_point({0, 0, 0}); orbit_cam->set_target_focal_distance(15.0f); - orbit_cam->set_target_elevation(vmq::radians(25.0f)); + orbit_cam->set_target_elevation(math::radians(25.0f)); orbit_cam->set_target_azimuth(0.0f); orbit_cam->set_focal_point(orbit_cam->get_target_focal_point()); orbit_cam->set_focal_distance(orbit_cam->get_target_focal_distance()); @@ -185,7 +183,7 @@ void enter_play_state(application* app) nest->set_tunnel_radius(tunnel_radius); nest::shaft* central_shaft = nest->get_central_shaft(); central_shaft->chirality = 1.0f; - central_shaft->rotation = vmq::radians(0.0f); + central_shaft->rotation = math::radians(0.0f); central_shaft->depth = {0.0f, 200.0f}; central_shaft->radius = {15.0f, 15.0f}; central_shaft->pitch = {40.0f, 40.0f}; @@ -196,7 +194,7 @@ void enter_play_state(application* app) nest::chamber chamber; chamber.shaft = central_shaft; chamber.depth = (i + 1) * 50.0f; - chamber.rotation = vmq::radians(0.0f); + chamber.rotation = math::radians(0.0f); chamber.inner_radius = 4.0f; chamber.outer_radius = 10.0f; central_shaft->chambers.push_back(chamber); @@ -208,8 +206,8 @@ void enter_play_state(application* app) { ecs::cavity_component cavity; cavity.position = nest->extend_shaft(*nest->get_central_shaft()); - cavity.position += float3{frand(-shift, shift), frand(-shift, shift), frand(-shift, shift)}; - cavity.radius = tunnel_radius * frand(1.0f, 1.1f); + cavity.position += float3{math::random(-shift, shift), math::random(-shift, shift), math::random(-shift, shift)}; + cavity.radius = tunnel_radius * math::random(1.0f, 1.1f); ecs_registry.assign(ecs_registry.create(), cavity); } @@ -222,8 +220,8 @@ void enter_play_state(application* app) { ecs::cavity_component cavity; cavity.position = nest->expand_chamber(central_shaft->chambers[i]); - cavity.position += float3{frand(-shift, shift), frand(-shift, shift), frand(-shift, shift)}; - cavity.radius = tunnel_radius * frand(1.0f, 1.1f); + cavity.position += float3{math::random(-shift, shift), math::random(-shift, shift), math::random(-shift, shift)}; + cavity.radius = tunnel_radius * math::random(1.0f, 1.1f); ecs_registry.assign(ecs_registry.create(), cavity); } @@ -236,7 +234,7 @@ void enter_play_state(application* app) ecs::assign_render_layers(ecs_registry, larva, 1); //ecs::warp_to(ecs_registry, larva, {0, -20, 0}); //auto& transform = ecs_registry.get(larva_entity); - //transform.transform = vmq::identity_transform; + //transform.transform = math::identity_transform; //transform.transform.translation = nest->get_shaft_position(*central_shaft, central_shaft->depth[1]); //transform.transform.translation.y -= 1.0f; } diff --git a/src/systems/camera-system.cpp b/src/systems/camera-system.cpp index 403f3ee..dbc188b 100644 --- a/src/systems/camera-system.cpp +++ b/src/systems/camera-system.cpp @@ -25,9 +25,8 @@ #include "orbit-cam.hpp" #include "geometry/mesh.hpp" #include "geometry/intersection.hpp" -#include +#include "math/math.hpp" -using namespace vmq::operators; using namespace ecs; camera_system::camera_system(entt::registry& registry): @@ -74,9 +73,9 @@ void camera_system::update(double t, double dt) registry.view().each( [&](auto entity, auto& transform, auto& collision) { - vmq::transform inverse_transform = vmq::inverse(transform.transform); + math::transform inverse_transform = math::inverse(transform.transform); float3 origin = inverse_transform * pick_origin; - float3 direction = vmq::normalize(vmq::conjugate(transform.transform.rotation) * pick_direction); + float3 direction = math::normalize(math::conjugate(transform.transform.rotation) * pick_direction); ray transformed_ray = {origin, direction}; // Broad phase AABB test diff --git a/src/systems/camera-system.hpp b/src/systems/camera-system.hpp index 261a6f0..3a13da2 100644 --- a/src/systems/camera-system.hpp +++ b/src/systems/camera-system.hpp @@ -23,8 +23,7 @@ #include "entity-system.hpp" #include "event/event-handler.hpp" #include "input/input-events.hpp" -#include -using namespace vmq::types; +#include "utility/fundamental-types.hpp" class camera; class orbit_cam; diff --git a/src/systems/constraint-system.cpp b/src/systems/constraint-system.cpp index 09d0367..0166287 100644 --- a/src/systems/constraint-system.cpp +++ b/src/systems/constraint-system.cpp @@ -23,9 +23,9 @@ #include "entity/components/copy-scale-component.hpp" #include "entity/components/copy-transform-component.hpp" #include "entity/components/transform-component.hpp" +#include "utility/fundamental-types.hpp" using namespace ecs; -using namespace vmq; constraint_system::constraint_system(entt::registry& registry): entity_system(registry) diff --git a/src/systems/control-system.cpp b/src/systems/control-system.cpp index 939f0f0..196623e 100644 --- a/src/systems/control-system.cpp +++ b/src/systems/control-system.cpp @@ -24,9 +24,7 @@ #include "geometry/intersection.hpp" #include "animation/ease.hpp" #include "nest.hpp" -#include - -using namespace vmq::operators; +#include "math/math.hpp" control_system::control_system(): timestep(0.0f), @@ -60,14 +58,14 @@ control_system::control_system(): } zoom_speed = 4.0f; //1 - min_elevation = vmq::radians(-85.0f); - max_elevation = vmq::radians(85.0f); + min_elevation = math::radians(-85.0f); + max_elevation = math::radians(85.0f); near_focal_distance = 2.0f; far_focal_distance = 200.0f; near_movement_speed = 10.0f; far_movement_speed = 80.0f; - near_fov = vmq::radians(80.0f); - far_fov = vmq::radians(35.0f); + near_fov = math::radians(80.0f); + far_fov = math::radians(35.0f); near_clip_near = 0.1f; far_clip_near = 5.0f; near_clip_far = 100.0f; @@ -98,15 +96,15 @@ void control_system::update(float dt) zoom -= zoom_speed * dt * zoom_out_control.get_current_value(); zoom = std::max(0.0f, std::min(1.0f, zoom)); - float focal_distance = ease::log(near_focal_distance, far_focal_distance, 1.0f - zoom); + float focal_distance = math::log_lerp(near_focal_distance, far_focal_distance, 1.0f - zoom); - float fov = ease::log(near_fov, far_fov, 1.0f - zoom); + float fov = math::log_lerp(near_fov, far_fov, 1.0f - zoom); //float elevation_factor = (orbit_cam->get_target_elevation() - min_elevation) / max_elevation; - //fov = ease::log(near_fov, far_fov, elevation_factor); - float clip_near = ease::log(near_clip_near, far_clip_near, 1.0f - zoom); - float clip_far = ease::log(near_clip_far, far_clip_far, 1.0f - zoom); - float movement_speed = ease::log(near_movement_speed * dt, far_movement_speed * dt, 1.0f - zoom); + //fov = math::log_lerp(near_fov, far_fov, elevation_factor); + float clip_near = math::log_lerp(near_clip_near, far_clip_near, 1.0f - zoom); + float clip_far = math::log_lerp(near_clip_far, far_clip_far, 1.0f - zoom); + float movement_speed = math::log_lerp(near_movement_speed * dt, far_movement_speed * dt, 1.0f - zoom); orbit_cam->set_target_focal_distance(focal_distance); orbit_cam->get_camera()->set_perspective(fov, orbit_cam->get_camera()->get_aspect_ratio(), clip_near, clip_far); @@ -147,13 +145,13 @@ void control_system::update(float dt) movement[1] += move_back_control.get_current_value(); const float deadzone = 0.01f; - float magnitude_squared = vmq::length_squared(movement); + float magnitude_squared = math::length_squared(movement); if (magnitude_squared > deadzone) { if (magnitude_squared > 1.0f) { - movement = vmq::normalize(movement); + movement = math::normalize(movement); } orbit_cam->move(movement * movement_speed); @@ -189,7 +187,7 @@ void control_system::update(float dt) float3 pick_near = camera->unproject({mouse_position[0], viewport[3] - mouse_position[1], 0.0f}, viewport); float3 pick_far = camera->unproject({mouse_position[0], viewport[3] - mouse_position[1], 1.0f}, viewport); - float3 pick_direction = vmq::normalize(pick_far - pick_near); + float3 pick_direction = math::normalize(pick_far - pick_near); ray picking_ray = {pick_near, pick_direction}; plane ground_plane = {float3{0, 1, 0}, 0.0f}; @@ -210,7 +208,7 @@ void control_system::update(float dt) float2 viewport_center = {(viewport[0] + viewport[2]) * 0.5f, (viewport[1] + viewport[3]) * 0.5f}; - float2 mouse_direction = vmq::normalize(mouse_position - viewport_center); + float2 mouse_direction = math::normalize(mouse_position - viewport_center); old_mouse_angle = mouse_angle; mouse_angle = std::atan2(-mouse_direction.y, mouse_direction.x); @@ -218,22 +216,22 @@ void control_system::update(float dt) { - if (mouse_angle - old_mouse_angle <= -vmq::pi) + if (mouse_angle - old_mouse_angle <= -math::pi) flashlight_turns_i -= 1; - else if (mouse_angle - old_mouse_angle >= vmq::pi) + else if (mouse_angle - old_mouse_angle >= math::pi) flashlight_turns_i += 1; - flashlight_turns_f = (mouse_angle) / vmq::two_pi; + flashlight_turns_f = (mouse_angle) / math::two_pi; flashlight_turns = flashlight_turns_i - flashlight_turns_f; if (flashlight && nest) { - transform flashlight_transform = vmq::identity_transform; + math::transform flashlight_transform = math::identity_transform; float flashlight_depth = nest->get_shaft_depth(*nest->get_central_shaft(), flashlight_turns); flashlight_transform.translation = {0.0f, -flashlight_depth, 0.0f}; - flashlight_transform.rotation = vmq::angle_axis(-flashlight_turns * vmq::two_pi + vmq::half_pi, {0, 1, 0}); + flashlight_transform.rotation = math::angle_axis(-flashlight_turns * math::two_pi + math::half_pi, {0, 1, 0}); flashlight->set_transform(flashlight_transform); flashlight_light_cone->set_transform(flashlight_transform); @@ -298,7 +296,7 @@ void control_system::handle_event(const mouse_moved_event& event) elevation_factor *= -1.0f; } - float rotation = vmq::radians(22.5f) * rotation_factor * timestep; + float rotation = math::radians(22.5f) * rotation_factor * timestep; float elevation = orbit_cam->get_target_elevation() + elevation_factor * 0.25f * timestep; elevation = std::min(max_elevation, std::max(min_elevation, elevation)); diff --git a/src/systems/control-system.hpp b/src/systems/control-system.hpp index 2d3de9c..bb54d11 100644 --- a/src/systems/control-system.hpp +++ b/src/systems/control-system.hpp @@ -25,6 +25,7 @@ #include "input/control.hpp" #include "input/control-set.hpp" #include "scene/model-instance.hpp" +#include "utility/fundamental-types.hpp" class orbit_cam; class nest; diff --git a/src/systems/nest-system.cpp b/src/systems/nest-system.cpp index eb24827..5ab5c95 100644 --- a/src/systems/nest-system.cpp +++ b/src/systems/nest-system.cpp @@ -19,6 +19,7 @@ #include "nest-system.hpp" #include "nest.hpp" +#include "math/math.hpp" using namespace ecs; @@ -45,7 +46,7 @@ void nest_system::on_nest_construct(entt::registry& registry, entt::entity entit nest->set_tunnel_radius(1.15f); nest::shaft* central_shaft = nest->get_central_shaft(); central_shaft->chirality = -1.0f; - central_shaft->rotation = vmq::radians(0.0f); + central_shaft->rotation = math::radians(0.0f); central_shaft->depth = {0.0f, 100.0f}; central_shaft->current_depth = 0.0f; central_shaft->radius = {0.0f, 5.0f}; @@ -56,7 +57,7 @@ void nest_system::on_nest_construct(entt::registry& registry, entt::entity entit nest::chamber chamber; chamber.shaft = central_shaft; chamber.depth = (i + 1) * 23.0f; - chamber.rotation = vmq::radians(0.0f); + chamber.rotation = math::radians(0.0f); chamber.inner_radius = 4.0f; chamber.outer_radius = 10.0f; central_shaft->chambers.push_back(chamber); diff --git a/src/systems/placement-system.cpp b/src/systems/placement-system.cpp index b6130c6..721f446 100644 --- a/src/systems/placement-system.cpp +++ b/src/systems/placement-system.cpp @@ -22,6 +22,7 @@ #include "entity/components/placement-component.hpp" #include "entity/components/transform-component.hpp" #include "entity/components/terrain-component.hpp" +#include "utility/fundamental-types.hpp" using namespace ecs; @@ -42,9 +43,9 @@ void placement_system::update(double t, double dt) [&](auto entity, auto& transform, auto& collision) { // Transform ray into local space of collision component - vmq::transform inverse_transform = vmq::inverse(transform.transform); + math::transform inverse_transform = math::inverse(transform.transform); float3 origin = inverse_transform * placement.ray.origin; - float3 direction = vmq::normalize(vmq::conjugate(transform.transform.rotation) * placement.ray.direction); + float3 direction = math::normalize(math::conjugate(transform.transform.rotation) * placement.ray.direction); ray transformed_ray = {origin, direction}; // Broad phase AABB test diff --git a/src/systems/samara-system.cpp b/src/systems/samara-system.cpp index 40c2ed6..4b0770e 100644 --- a/src/systems/samara-system.cpp +++ b/src/systems/samara-system.cpp @@ -20,9 +20,9 @@ #include "samara-system.hpp" #include "entity/components/transform-component.hpp" #include "entity/components/samara-component.hpp" -#include "math.hpp" +#include "math/math.hpp" +#include "utility/fundamental-types.hpp" -using namespace vmq::operators; using namespace ecs; samara_system::samara_system(entt::registry& registry): @@ -34,23 +34,23 @@ void samara_system::update(double t, double dt) registry.view().each( [&](auto entity, auto& samara, auto& transform) { - samara.angle += samara.chirality * vmq::radians(360.0f * 6.0f) * dt; + samara.angle += samara.chirality * math::radians(360.0f * 6.0f) * dt; transform.transform.translation += samara.direction * 20.0f * (float)dt; transform.transform.rotation = - vmq::angle_axis(samara.angle, float3{0, 1, 0}) * - vmq::angle_axis(vmq::radians(20.0f), float3{1, 0, 0}) * - ((samara.chirality < 0.0f) ? vmq::angle_axis(vmq::radians(180.0f), float3{0, 0, -1}) : vmq::quaternion{1, 0, 0, 0}); + math::angle_axis(samara.angle, float3{0, 1, 0}) * + math::angle_axis(math::radians(20.0f), float3{1, 0, 0}) * + ((samara.chirality < 0.0f) ? math::angle_axis(math::radians(180.0f), float3{0, 0, -1}) : math::quaternion{1, 0, 0, 0}); if (transform.transform.translation.y < 0.0f) { const float zone = 200.0f; - transform.transform.translation.x = frand(-zone, zone); - transform.transform.translation.y = frand(100.0f, 150.0f); - transform.transform.translation.z = frand(-zone, zone); + transform.transform.translation.x = math::random(-zone, zone); + transform.transform.translation.y = math::random(100.0f, 150.0f); + transform.transform.translation.z = math::random(-zone, zone); transform.warp = true; - samara.chirality = (frand(0, 1) < 0.5f) ? -1.0f : 1.0f; + samara.chirality = (math::random(0.0f, 1.0f) < 0.5f) ? -1.0f : 1.0f; } }); } diff --git a/src/systems/subterrain-system.cpp b/src/systems/subterrain-system.cpp index 8963cd8..a73cf22 100644 --- a/src/systems/subterrain-system.cpp +++ b/src/systems/subterrain-system.cpp @@ -32,15 +32,13 @@ #include "geometry/intersection.hpp" #include "scene/scene.hpp" #include "scene/model-instance.hpp" -#include "math.hpp" - -using namespace vmq::operators; -using namespace ecs; - +#include "utility/fundamental-types.hpp" #include #include #include +using namespace ecs; + /** * An octree containing cubes for the marching cubes algorithm. */ @@ -422,7 +420,7 @@ void subterrain_system::regenerate_subterrain_model() edge = edge->previous->symmetric; } while (edge != start); - n = vmq::normalize(n); + n = math::normalize(n); //float3 n = reinterpret_cast(face_normals[i * 3]); @@ -474,10 +472,10 @@ void subterrain_system::dig(const float3& position, float radius) for (int i = 0; i < 8; ++i) { // For outside normals (also set node initial distance to +infinity) - //float distance = vmq::length(node->corners[i] - position) - radius; + //float distance = math::length(node->corners[i] - position) - radius; // if (distance < node->distances[i]) - float distance = radius - vmq::length(node.corners[i] - position); + float distance = radius - math::length(node.corners[i] - position); if (distance > node.distances[i]) node.distances[i] = distance; } diff --git a/src/systems/subterrain-system.hpp b/src/systems/subterrain-system.hpp index 6aade28..7b9d42b 100644 --- a/src/systems/subterrain-system.hpp +++ b/src/systems/subterrain-system.hpp @@ -23,6 +23,7 @@ #include "entity-system.hpp" #include "geometry/mesh.hpp" #include "geometry/aabb.hpp" +#include "utility/fundamental-types.hpp" #include class resource_manager; @@ -33,8 +34,6 @@ struct cube_tree; class scene; class model_instance; -using namespace vmq::types; - template struct epsilon { @@ -49,7 +48,7 @@ typedef epsilon<1, -5> epsilon_1en5; template struct vector_hasher { - typedef vmq::vector vector_type; + typedef math::vector vector_type; std::size_t operator()(const vector_type& v) const noexcept { @@ -69,7 +68,7 @@ struct vector_hasher template struct vector_equals { - typedef vmq::vector vector_type; + typedef math::vector vector_type; bool operator()(const vector_type& a, const vector_type& b) const noexcept { diff --git a/src/systems/terrain-system.cpp b/src/systems/terrain-system.cpp index 4612dd8..cc66ce7 100644 --- a/src/systems/terrain-system.cpp +++ b/src/systems/terrain-system.cpp @@ -30,9 +30,9 @@ #include "rasterizer/vertex-buffer.hpp" #include "resources/resource-manager.hpp" #include "resources/image.hpp" +#include "utility/fundamental-types.hpp" #include -using namespace vmq::operators; using namespace ecs; terrain_system::terrain_system(entt::registry& registry, ::resource_manager* resource_manager): @@ -275,7 +275,7 @@ void terrain_system::update_terrain_model(model* terrain_model, mesh* terrain_me edge = edge->previous->symmetric; } while (edge != start); - n = vmq::normalize(n); + n = math::normalize(n); *(v++) = vertex->position[0]; *(v++) = vertex->position[1]; @@ -330,7 +330,7 @@ void terrain_system::on_terrain_construct(entt::registry& registry, entt::entity // Assign the entity a transform component transform_component transform; - transform.transform = vmq::identity_transform; + transform.transform = math::identity_transform; transform.transform.translation = float3{(float)component.x * patch_size, 0.0f, (float)component.z * patch_size}; transform.warp = true; registry.assign_or_replace(entity, transform); diff --git a/src/systems/tool-system.cpp b/src/systems/tool-system.cpp index b6709c8..4f4af6f 100644 --- a/src/systems/tool-system.cpp +++ b/src/systems/tool-system.cpp @@ -25,9 +25,8 @@ #include "orbit-cam.hpp" #include "geometry/mesh.hpp" #include "geometry/intersection.hpp" -#include +#include "math/math.hpp" -using namespace vmq::operators; using namespace ecs; tool_system::tool_system(entt::registry& registry): @@ -47,7 +46,7 @@ void tool_system::update(double t, double dt) float3 pick_near = camera->unproject({mouse_position[0], viewport[3] - mouse_position[1], 0.0f}, viewport); float3 pick_far = camera->unproject({mouse_position[0], viewport[3] - mouse_position[1], 1.0f}, viewport); float3 pick_origin = pick_near; - float3 pick_direction = vmq::normalize(pick_far - pick_near); + float3 pick_direction = math::normalize(pick_far - pick_near); ray picking_ray = {pick_near, pick_direction}; float a = std::numeric_limits::infinity(); @@ -58,9 +57,9 @@ void tool_system::update(double t, double dt) registry.view().each( [&](auto entity, auto& transform, auto& collision) { - vmq::transform inverse_transform = vmq::inverse(transform.transform); + math::transform inverse_transform = math::inverse(transform.transform); float3 origin = inverse_transform * pick_origin; - float3 direction = vmq::normalize(vmq::conjugate(transform.transform.rotation) * pick_direction); + float3 direction = math::normalize(math::conjugate(transform.transform.rotation) * pick_direction); ray transformed_ray = {origin, direction}; // Broad phase AABB test @@ -88,13 +87,13 @@ void tool_system::update(double t, double dt) float3 camera_planar_position = float3{camera_position.x, 0, camera_position.z}; float pick_angle = 0.0f; - float3 pick_planar_direction = vmq::normalize(pick_planar_position - camera_planar_position); + float3 pick_planar_direction = math::normalize(pick_planar_position - camera_planar_position); float3 camera_planar_focal_point = float3{orbit_cam->get_focal_point().x, 0, orbit_cam->get_focal_point().z}; - float3 camera_planar_direction = vmq::normalize(camera_planar_focal_point - camera_planar_position); - if (std::fabs(vmq::length_squared(camera_planar_direction - pick_planar_direction) > 0.0001f)) + float3 camera_planar_direction = math::normalize(camera_planar_focal_point - camera_planar_position); + if (std::fabs(math::length_squared(camera_planar_direction - pick_planar_direction) > 0.0001f)) { - pick_angle = std::acos(vmq::dot(camera_planar_direction, pick_planar_direction)); - if (vmq::dot(vmq::cross(camera_planar_direction, pick_planar_direction), float3{0, 1, 0}) < 0.0f) + pick_angle = std::acos(math::dot(camera_planar_direction, pick_planar_direction)); + if (math::dot(math::cross(camera_planar_direction, pick_planar_direction), float3{0, 1, 0}) < 0.0f) pick_angle = -pick_angle; } @@ -110,7 +109,7 @@ void tool_system::update(double t, double dt) transform.transform.translation = pick; } - vmq::quaternion rotation = vmq::angle_axis(orbit_cam->get_azimuth() + pick_angle, float3{0, 1, 0}); + math::quaternion rotation = math::angle_axis(orbit_cam->get_azimuth() + pick_angle, float3{0, 1, 0}); transform.transform.rotation = rotation; }); } @@ -143,4 +142,3 @@ void tool_system::handle_event(const mouse_moved_event& event) mouse_position[1] = event.y; } } - diff --git a/src/systems/tool-system.hpp b/src/systems/tool-system.hpp index 74526ce..8e69c57 100644 --- a/src/systems/tool-system.hpp +++ b/src/systems/tool-system.hpp @@ -23,8 +23,7 @@ #include "entity-system.hpp" #include "event/event-handler.hpp" #include "input/input-events.hpp" -#include -using namespace vmq::types; +#include "utility/fundamental-types.hpp" class camera; class orbit_cam; diff --git a/src/systems/ui-system.cpp b/src/systems/ui-system.cpp index 9a5d5e7..bbf4266 100644 --- a/src/systems/ui-system.cpp +++ b/src/systems/ui-system.cpp @@ -21,8 +21,6 @@ #include "input/control.hpp" #include "resources/resource-manager.hpp" -using namespace vmq::operators; - ui_system::ui_system(::resource_manager* resource_manager): resource_manager(resource_manager), tool_menu_control(nullptr) @@ -52,7 +50,7 @@ ui_system::ui_system(::resource_manager* resource_manager): // Setup tool selector ant tool_selector_ant.set_model(resource_manager->load("worker-ant.obj")); tool_selector_ant.set_scale({350, 350, 350}); - tool_selector_ant.set_rotation(vmq::angle_axis(vmq::radians(180.0f), {0, 0, 1}) * vmq::angle_axis(vmq::radians(90.0f), {1, 0, 0})); + tool_selector_ant.set_rotation(math::angle_axis(math::radians(180.0f), {0, 0, 1}) * math::angle_axis(math::radians(90.0f), {1, 0, 0})); tool_selector_ant.update_tweens(); // Setup energy symbol @@ -113,9 +111,9 @@ void ui_system::handle_event(const mouse_moved_event& event) float max_length = 200.0f; float selection_threshold = 20.0f; int sector_count = 6; - float sector_angle = vmq::two_pi / static_cast(sector_count); + float sector_angle = math::two_pi / static_cast(sector_count); - float length_squared = vmq::length_squared(tool_selection_vector); + float length_squared = math::length_squared(tool_selection_vector); // Select tool if length of selection vector within threshold if (length_squared >= selection_threshold * selection_threshold) @@ -127,16 +125,16 @@ void ui_system::handle_event(const mouse_moved_event& event) } float2 selection_direction = tool_selection_vector / std::sqrt(length_squared); - float selection_angle = std::atan2(-selection_direction.y, selection_direction.x) - vmq::radians(90.0f); - selection_angle = (selection_angle >= 0.0f ? selection_angle : (vmq::two_pi + selection_angle)); + float selection_angle = std::atan2(-selection_direction.y, selection_direction.x) - math::radians(90.0f); + selection_angle = (selection_angle >= 0.0f ? selection_angle : (math::two_pi + selection_angle)); int sector = static_cast((selection_angle + sector_angle * 0.5f) / sector_angle) % sector_count; - + float rotation_angle = static_cast(sector) * sector_angle; - tool_selector_bg.set_rotation(vmq::angle_axis(rotation_angle, {0, 0, 1})); + tool_selector_bg.set_rotation(math::angle_axis(rotation_angle, {0, 0, 1})); tool_selector_bg.update_tweens(); - tool_selector_ant.set_rotation(vmq::angle_axis(rotation_angle + vmq::radians(180.0f), {0, 0, 1}) * vmq::angle_axis(vmq::radians(90.0f), {1, 0, 0})); + tool_selector_ant.set_rotation(math::angle_axis(rotation_angle + math::radians(180.0f), {0, 0, 1}) * math::angle_axis(math::radians(90.0f), {1, 0, 0})); } } diff --git a/src/systems/ui-system.hpp b/src/systems/ui-system.hpp index 1a53752..46d4123 100644 --- a/src/systems/ui-system.hpp +++ b/src/systems/ui-system.hpp @@ -29,9 +29,7 @@ #include "scene/model-instance.hpp" #include "scene/billboard.hpp" #include "renderer/material.hpp" -#include - -using namespace vmq::types; +#include "math/math.hpp" class control; class scene; diff --git a/src/systems/vegetation-system.cpp b/src/systems/vegetation-system.cpp index 7f89155..772ba2f 100644 --- a/src/systems/vegetation-system.cpp +++ b/src/systems/vegetation-system.cpp @@ -25,10 +25,9 @@ #include "scene/scene.hpp" #include "renderer/material.hpp" #include "geometry/aabb.hpp" +#include "utility/fundamental-types.hpp" #include -using namespace vmq::types; -using namespace vmq::operators; using namespace ecs; vegetation_system::vegetation_system(entt::registry& registry): @@ -99,7 +98,7 @@ void vegetation_system::on_terrain_construct(entt::registry& registry, entt::ent // Assign a transform component transform_component transform; - transform.transform = vmq::identity_transform; + transform.transform = math::identity_transform; transform.transform.translation = float3{vegetation_patch_x, 0.0f, vegetation_patch_z}; transform.warp = true; registry.assign_or_replace(vegetation_patch_entity, transform); @@ -170,7 +169,7 @@ void vegetation_system::on_terrain_construct(entt::registry& registry, entt::ent lod_group->update_tweens(); // Add LOD group to scene - scene->add_object(lod_group); + //scene->add_object(lod_group); } } } diff --git a/src/utility/fundamental-types.hpp b/src/utility/fundamental-types.hpp new file mode 100644 index 0000000..24ae3ed --- /dev/null +++ b/src/utility/fundamental-types.hpp @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_FUNDAMENTAL_TYPES_HPP +#define ANTKEEPER_FUNDAMENTAL_TYPES_HPP + +#include "math/vector-type.hpp" +#include "math/vector-operators.hpp" +#include "math/matrix-type.hpp" +#include "math/matrix-operators.hpp" + +/// 2D vector of bools +using bool2 = math::vector; + +/// 3D vector of bools +using bool3 = math::vector; + +/// 4D vector of bools +using bool4 = math::vector; + +/// 2D vector of chars +using char2 = math::vector; + +/// 3D vector of chars +using char3 = math::vector; + +/// 4D vector of chars +using char4 = math::vector; + +/// 2D vector of unsigned chars +using uchar2 = math::vector; + +/// 3D vector of unsigned chars +using uchar3 = math::vector; + +/// 4D vector of unsigned chars +using uchar4 = math::vector; + +/// 2D vector of shorts +using short2 = math::vector; + +/// 3D vector of shorts +using short3 = math::vector; + +/// 4D vector of shorts +using short4 = math::vector; + +/// 2D vector of unsigned shorts +using ushort2 = math::vector; + +/// 3D vector of unsigned shorts +using ushort3 = math::vector; + +/// 4D vector of unsigned shorts +using ushort4 = math::vector; + +/// 2D vector of ints +using int2 = math::vector; + +/// 3D vector of ints +using int3 = math::vector; + +/// 4D vector of ints +using int4 = math::vector; + +/// 2D vector of unsigned ints +using uint2 = math::vector; + +/// 3D vector of unsigned ints +using uint3 = math::vector; + +/// 4D vector of unsigned ints +using uint4 = math::vector; + +/// 2D vector of longs +using long2 = math::vector; + +/// 3D vector of longs +using long3 = math::vector; + +/// 4D vector of longs +using long4 = math::vector; + +/// 2D vector of unsigned longs +using ulong2 = math::vector; + +/// 3D vector of unsigned longs +using ulong3 = math::vector; + +/// 4D vector of unsigned longs +using ulong4 = math::vector; + +/// 2D vector of floats +using float2 = math::vector; + +/// 3D vector of floats +using float3 = math::vector; + +/// 4D vector of floats +using float4 = math::vector; + +/// 2D vector of doubles +using double2 = math::vector; + +/// 3D vector of doubles +using double3 = math::vector; + +/// 4D vector of doubles +using double4 = math::vector; + +/// 2x2 matrix of bools +using bool2x2 = math::matrix; + +/// 3x3 matrix of bools +using bool3x3 = math::matrix; + +/// 4x4 matrix of bools +using bool4x4 = math::matrix; + +/// 2x2 matrix of chars +using char2x2 = math::matrix; + +/// 3x3 matrix of chars +using char3x3 = math::matrix; + +/// 4x4 matrix of chars +using char4x4 = math::matrix; + +/// 2x2 matrix of unsigned chars +using uchar2x2 = math::matrix; + +/// 3x3 matrix of unsigned chars +using uchar3x3 = math::matrix; + +/// 4x4 matrix of unsigned chars +using uchar4x4 = math::matrix; + +/// 2x2 matrix of shorts +using short2x2 = math::matrix; + +/// 3x3 matrix of shorts +using short3x3 = math::matrix; + +/// 4x4 matrix of shorts +using short4x4 = math::matrix; + +/// 2x2 matrix of unsigned shorts +using ushort2x2 = math::matrix; + +/// 3x3 matrix of unsigned shorts +using ushort3x3 = math::matrix; + +/// 4x4 matrix of unsigned shorts +using ushort4x4 = math::matrix; + +/// 2x2 matrix of ints +using int2x2 = math::matrix; + +/// 3x3 matrix of ints +using int3x3 = math::matrix; + +/// 4x4 matrix of ints +using int4x4 = math::matrix; + +/// 2x2 matrix of unsigned ints +using uint2x2 = math::matrix; + +/// 3x3 matrix of unsigned ints +using uint3x3 = math::matrix; + +/// 4x4 matrix of unsigned ints +using uint4x4 = math::matrix; + +/// 2x2 matrix of longs +using long2x2 = math::matrix; + +/// 3x3 matrix of longs +using long3x3 = math::matrix; + +/// 4x4 matrix of longs +using long4x4 = math::matrix; + +/// 2x2 matrix of unsigned longs +using ulong2x2 = math::matrix; + +/// 3x3 matrix of unsigned longs +using ulong3x3 = math::matrix; + +/// 4x4 matrix of unsigned longs +using ulong4x4 = math::matrix; + +/// 2x2 matrix of floats +using float2x2 = math::matrix; + +/// 3x3 matrix of floats +using float3x3 = math::matrix; + +/// 4x4 matrix of floats +using float4x4 = math::matrix; + +/// 2x2 matrix of doubles +using double2x2 = math::matrix; + +/// 3x3 matrix of doubles +using double3x3 = math::matrix; + +/// 4x4 matrix of doubles +using double4x4 = math::matrix; + +#endif // ANTKEEPER_FUNDAMENTAL_TYPES_HPP