Browse Source

Integrate previously separate unpublished VMQ math library directly into Antkeeper source

master
C. J. Howard 3 years ago
parent
commit
0a5a7035d8
105 changed files with 4137 additions and 769 deletions
  1. +0
    -3
      CMakeLists.txt
  2. +37
    -57
      src/animation/ease.hpp
  3. +54
    -51
      src/application.cpp
  4. +1
    -0
      src/application.hpp
  5. +3
    -5
      src/camera-rig.cpp
  6. +10
    -7
      src/camera-rig.hpp
  7. +4
    -6
      src/configuration.hpp.in
  8. +1
    -2
      src/entity/components/cavity-component.hpp
  9. +1
    -2
      src/entity/components/locomotion-component.hpp
  10. +1
    -2
      src/entity/components/samara-component.hpp
  11. +2
    -2
      src/entity/components/transform-component.hpp
  12. +1
    -5
      src/entity/entity-commands.hpp
  13. +25
    -27
      src/geometry/aabb.hpp
  14. +2
    -3
      src/geometry/bounding-volume.hpp
  15. +9
    -9
      src/geometry/convex-hull.hpp
  16. +1
    -5
      src/geometry/csg.hpp
  17. +8
    -8
      src/geometry/intersection.cpp
  18. +5
    -9
      src/geometry/intersection.hpp
  19. +4
    -6
      src/geometry/mesh-accelerator.hpp
  20. +2
    -13
      src/geometry/mesh-functions.cpp
  21. +3
    -5
      src/geometry/mesh-functions.hpp
  22. +37
    -33
      src/geometry/plane.hpp
  23. +31
    -0
      src/geometry/projection.hpp
  24. +17
    -9
      src/geometry/ray.hpp
  25. +5
    -6
      src/geometry/sdf.hpp
  26. +18
    -19
      src/geometry/sphere.hpp
  27. +43
    -43
      src/geometry/view-frustum.hpp
  28. +0
    -75
      src/math.hpp
  29. +64
    -0
      src/math/angles.hpp
  30. +104
    -0
      src/math/constants.hpp
  31. +77
    -0
      src/math/interpolation.hpp
  32. +79
    -0
      src/math/math.hpp
  33. +795
    -0
      src/math/matrix-functions.hpp
  34. +100
    -0
      src/math/matrix-operators.hpp
  35. +54
    -0
      src/math/matrix-type.hpp
  36. +29
    -0
      src/math/operators.hpp
  37. +443
    -0
      src/math/quaternion-functions.hpp
  38. +111
    -0
      src/math/quaternion-operators.hpp
  39. +48
    -0
      src/math/quaternion-type.hpp
  40. +55
    -0
      src/math/random.hpp
  41. +114
    -0
      src/math/stream-operators.hpp
  42. +110
    -0
      src/math/transform-functions.hpp
  43. +77
    -0
      src/math/transform-operators.hpp
  44. +54
    -0
      src/math/transform-type.hpp
  45. +627
    -0
      src/math/vector-functions.hpp
  46. +217
    -0
      src/math/vector-operators.hpp
  47. +131
    -0
      src/math/vector-type.hpp
  48. +13
    -14
      src/nest.cpp
  49. +1
    -4
      src/nest.hpp
  50. +17
    -24
      src/orbit-cam.cpp
  51. +7
    -7
      src/orbit-cam.hpp
  52. +4
    -4
      src/pheromone-matrix.cpp
  53. +1
    -2
      src/rasterizer/shader-input.hpp
  54. +6
    -9
      src/renderer/material-property.hpp
  55. +1
    -3
      src/renderer/passes/bloom-pass.cpp
  56. +1
    -3
      src/renderer/passes/bloom-pass.hpp
  57. +1
    -3
      src/renderer/passes/clear-pass.hpp
  58. +1
    -3
      src/renderer/passes/final-pass.cpp
  59. +1
    -3
      src/renderer/passes/final-pass.hpp
  60. +6
    -8
      src/renderer/passes/material-pass.cpp
  61. +1
    -0
      src/renderer/passes/material-pass.hpp
  62. +9
    -12
      src/renderer/passes/shadow-map-pass.cpp
  63. +1
    -5
      src/renderer/passes/shadow-map-pass.hpp
  64. +5
    -7
      src/renderer/passes/sky-pass.cpp
  65. +1
    -3
      src/renderer/passes/ui-pass.cpp
  66. +2
    -5
      src/renderer/render-context.hpp
  67. +1
    -2
      src/renderer/render-operation.hpp
  68. +13
    -14
      src/renderer/renderer.cpp
  69. +1
    -3
      src/renderer/simple-render-pass.cpp
  70. +1
    -3
      src/renderer/simple-render-pass.hpp
  71. +1
    -0
      src/resources/material-loader.cpp
  72. +1
    -0
      src/resources/mesh-loader.cpp
  73. +1
    -3
      src/resources/model-loader.cpp
  74. +1
    -0
      src/scene/billboard.hpp
  75. +23
    -23
      src/scene/camera.cpp
  76. +1
    -0
      src/scene/camera.hpp
  77. +5
    -6
      src/scene/directional-light.cpp
  78. +1
    -3
      src/scene/directional-light.hpp
  79. +4
    -5
      src/scene/light.cpp
  80. +1
    -0
      src/scene/light.hpp
  81. +1
    -1
      src/scene/lod-group.cpp
  82. +2
    -5
      src/scene/point-light.cpp
  83. +1
    -0
      src/scene/point-light.hpp
  84. +9
    -8
      src/scene/scene-object.cpp
  85. +40
    -34
      src/scene/scene-object.hpp
  86. +8
    -10
      src/scene/spotlight.cpp
  87. +1
    -3
      src/scene/spotlight.hpp
  88. +23
    -25
      src/state/play-state.cpp
  89. +3
    -4
      src/systems/camera-system.cpp
  90. +1
    -2
      src/systems/camera-system.hpp
  91. +1
    -1
      src/systems/constraint-system.cpp
  92. +21
    -23
      src/systems/control-system.cpp
  93. +1
    -0
      src/systems/control-system.hpp
  94. +3
    -2
      src/systems/nest-system.cpp
  95. +3
    -2
      src/systems/placement-system.cpp
  96. +10
    -10
      src/systems/samara-system.cpp
  97. +6
    -8
      src/systems/subterrain-system.cpp
  98. +3
    -4
      src/systems/subterrain-system.hpp
  99. +3
    -3
      src/systems/terrain-system.cpp
  100. +10
    -12
      src/systems/tool-system.cpp

+ 0
- 3
CMakeLists.txt View File

@ -5,7 +5,6 @@ option(VERSION_STRING "Project version string" "0.0.0")
project(antkeeper VERSION ${VERSION_STRING} LANGUAGES CXX) project(antkeeper VERSION ${VERSION_STRING} LANGUAGES CXX)
# Find dependency packages # Find dependency packages
find_package(vmq REQUIRED CONFIG)
find_package(dr_wav REQUIRED CONFIG) find_package(dr_wav REQUIRED CONFIG)
find_package(stb REQUIRED CONFIG) find_package(stb REQUIRED CONFIG)
find_package(glad 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_package(OpenAL REQUIRED CONFIG)
find_library(physfs REQUIRED NAMES physfs-static PATHS "${CMAKE_PREFIX_PATH}/lib") find_library(physfs REQUIRED NAMES physfs-static PATHS "${CMAKE_PREFIX_PATH}/lib")
# Determine dependencies # Determine dependencies
set(STATIC_LIBS set(STATIC_LIBS
vmq
dr_wav dr_wav
stb stb
glad glad

+ 37
- 57
src/animation/ease.hpp View File

@ -51,9 +51,8 @@
#ifndef ANTKEEPER_EASE_HPP #ifndef ANTKEEPER_EASE_HPP
#define ANTKEEPER_EASE_HPP #define ANTKEEPER_EASE_HPP
#include <vmq/vmq.hpp>
#include "math/math.hpp"
#include <cmath> #include <cmath>
#include <type_traits>
/** /**
* Container for templated easing functions. * 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&, 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 T Value type.
* @tparam S Scalar type. * @tparam S Scalar type.
@ -72,12 +71,6 @@ struct ease
{ {
typedef T value_type; typedef T value_type;
typedef S scalar_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 in_sine(const T& x, const T& y, S a);
static T out_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); static T in_out_bounce(const T& x, const T& y, S a);
}; };
template <typename T, typename S>
inline T ease<T, S>::linear(const T& x, const T& y, S a)
{
return (y - x) * a + x;
}
template <typename T, typename S>
inline T ease<T, S>::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 <typename T, typename S> template <typename T, typename S>
T ease<T, S>::in_sine(const T& x, const T& y, S a) T ease<T, S>::in_sine(const T& x, const T& y, S a)
{ {
return linear(y, x, std::cos(a * vmq::half_pi<S>));
return math::lerp(y, x, std::cos(a * math::half_pi<S>));
} }
template <typename T, typename S> template <typename T, typename S>
T ease<T, S>::out_sine(const T& x, const T& y, S a) T ease<T, S>::out_sine(const T& x, const T& y, S a)
{ {
return linear(x, y, std::sin(a * vmq::half_pi<S>));
return math::lerp(x, y, std::sin(a * math::half_pi<S>));
} }
template <typename T, typename S> template <typename T, typename S>
T ease<T, S>::in_out_sine(const T& x, const T& y, S a) T ease<T, S>::in_out_sine(const T& x, const T& y, S a)
{ {
return linear(x, y, -(std::cos(a * vmq::pi<S>) - S(1)) * S(0.5));
return math::lerp(x, y, -(std::cos(a * math::pi<S>) - S(1)) * S(0.5));
} }
template <typename T, typename S> template <typename T, typename S>
T ease<T, S>::in_quad(const T& x, const T& y, S a) T ease<T, S>::in_quad(const T& x, const T& y, S a)
{ {
return linear(x, y, a * a);
return math::lerp(x, y, a * a);
} }
template <typename T, typename S> template <typename T, typename S>
T ease<T, S>::out_quad(const T& x, const T& y, S a) T ease<T, S>::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 <typename T, typename S> template <typename T, typename S>
T ease<T, S>::in_out_quad(const T& x, const T& y, S a) T ease<T, S>::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 <typename T, typename S> template <typename T, typename S>
T ease<T, S>::in_cubic(const T& x, const T& y, S a) T ease<T, S>::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 <typename T, typename S> template <typename T, typename S>
T ease<T, S>::out_cubic(const T& x, const T& y, S a) T ease<T, S>::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 <typename T, typename S> template <typename T, typename S>
T ease<T, S>::in_out_cubic(const T& x, const T& y, S a) T ease<T, S>::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 <typename T, typename S> template <typename T, typename S>
T ease<T, S>::in_quart(const T& x, const T& y, S a) T ease<T, S>::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 <typename T, typename S> template <typename T, typename S>
T ease<T, S>::out_quart(const T& x, const T& y, S a) T ease<T, S>::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 <typename T, typename S> template <typename T, typename S>
T ease<T, S>::in_out_quart(const T& x, const T& y, S a) T ease<T, S>::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 <typename T, typename S> template <typename T, typename S>
T ease<T, S>::in_quint(const T& x, const T& y, S a) T ease<T, S>::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 <typename T, typename S> template <typename T, typename S>
T ease<T, S>::out_quint(const T& x, const T& y, S a) T ease<T, S>::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 <typename T, typename S> template <typename T, typename S>
@ -222,25 +202,25 @@ T ease::in_out_quint(const T& x, const T& y, S a)
{ {
if (a < S(0.5)) 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 else
{ {
a = S(2) * (S(1) - a); 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 <typename T, typename S> template <typename T, typename S>
T ease<T, S>::in_expo(const T& x, const T& y, S a) T ease<T, S>::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 <typename T, typename S> template <typename T, typename S>
T ease<T, S>::out_expo(const T& x, const T& y, S a) T ease<T, S>::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 <typename T, typename S> template <typename T, typename S>
@ -255,19 +235,19 @@ T ease::in_out_expo(const T& x, const T& y, S a)
return y; 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 <typename T, typename S> template <typename T, typename S>
T ease<T, S>::in_circ(const T& x, const T& y, S a) T ease<T, S>::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 <typename T, typename S> template <typename T, typename S>
T ease<T, S>::out_circ(const T& x, const T& y, S a) T ease<T, S>::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 <typename T, typename S> template <typename T, typename S>
@ -275,11 +255,11 @@ T ease::in_out_circ(const T& x, const T& y, S a)
{ {
if (a < S(0.5)) 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 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<T, S>::in_back(const T& x, const T& y, S a) T ease<T, S>::in_back(const T& x, const T& y, S a)
{ {
const S c = S(1.70158); 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 <typename T, typename S> template <typename T, typename S>
@ -295,7 +275,7 @@ T ease::out_back(const T& x, const T& y, S a)
{ {
const S c = S(1.70158); const S c = S(1.70158);
a -= S(1); 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 <typename T, typename S> template <typename T, typename S>
@ -305,12 +285,12 @@ T ease::in_out_back(const T& x, const T& y, S a)
if (a < S(0.5)) 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 else
{ {
S b = S(1) - S(2) * a; 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 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 <typename T, typename S> template <typename T, typename S>
@ -341,7 +321,7 @@ T ease::out_elastic(const T& x, const T& y, S a)
return y; 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 <typename T, typename S> template <typename T, typename S>
@ -358,19 +338,19 @@ T ease::in_out_elastic(const T& x, const T& y, S a)
if (a < S(0.5)) 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 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 <typename T, typename S> template <typename T, typename S>
T ease<T, S>::in_bounce(const T& x, const T& y, S a) T ease<T, S>::in_bounce(const T& x, const T& y, S a)
{ {
return linear(x, y, S(1) - ease<S, S>::out_bounce(S(0), S(1), S(1) - a));
return math::lerp(x, y, S(1) - ease<S, S>::out_bounce(S(0), S(1), S(1) - a));
} }
template <typename T, typename S> template <typename T, typename S>
@ -399,7 +379,7 @@ T ease::out_bounce(const T& x, const T& y, S a)
a = n * a * a + S(0.984375); a = n * a * a + S(0.984375);
} }
return linear(x, y, a);
return math::lerp(x, y, a);
} }
template <typename T, typename S> template <typename T, typename S>
@ -407,11 +387,11 @@ T ease::in_out_bounce(const T& x, const T& y, S a)
{ {
if (a < S(0.5)) if (a < S(0.5))
{ {
return linear(x, y, (S(1) - ease<S, S>::out_bounce(S(0), S(1), S(1) - S(2) * a)) * S(0.5));
return math::lerp(x, y, (S(1) - ease<S, S>::out_bounce(S(0), S(1), S(1) - S(2) * a)) * S(0.5));
} }
else else
{ {
return linear(x, y, (S(1) + ease<S, S>::out_bounce(S(0), S(1), S(2) * a - S(1))) * S(0.5));
return math::lerp(x, y, (S(1) + ease<S, S>::out_bounce(S(0), S(1), S(2) * a - S(1))) * S(0.5));
} }
} }

+ 54
- 51
src/application.cpp View File

@ -20,7 +20,6 @@
#include "application.hpp" #include "application.hpp"
#include "configuration.hpp" #include "configuration.hpp"
#include "state/application-states.hpp" #include "state/application-states.hpp"
#include "math.hpp"
// STL // STL
#include <cstdlib> #include <cstdlib>
@ -42,6 +41,9 @@
#include "debug/ansi-codes.hpp" #include "debug/ansi-codes.hpp"
#include "debug/console-commands.hpp" #include "debug/console-commands.hpp"
// Math
#include "math/math.hpp"
// Resources // Resources
#include "resources/resource-manager.hpp" #include "resources/resource-manager.hpp"
@ -109,8 +111,7 @@
// Utilities // Utilities
#include "utility/paths.hpp" #include "utility/paths.hpp"
#include "utility/timestamp.hpp" #include "utility/timestamp.hpp"
using namespace vmq::operators;
#include "utility/fundamental-types.hpp"
application::application(int argc, char** argv): application::application(int argc, char** argv):
closed(false), closed(false),
@ -177,7 +178,7 @@ application::application(int argc, char** argv):
// Load configuration // Load configuration
//load_config(); //load_config();
fullscreen = true; fullscreen = true;
vsync = false;
vsync = true;
// Parse command line options // Parse command line options
parse_options(argc, argv); parse_options(argc, argv);
@ -518,7 +519,7 @@ application::application(int argc, char** argv):
overworld_compositor.add_pass(final_pass); overworld_compositor.add_pass(final_pass);
// Setup overworld camera // Setup overworld camera
overworld_camera.set_perspective(45.0f * vmq::pi<float> / 180.0f, (float)window_width / (float)window_height, 0.1f, 1000.0f);
overworld_camera.set_perspective(math::radians<float>(45.0f), (float)window_width / (float)window_height, 0.1f, 1000.0f);
overworld_camera.set_compositor(&overworld_compositor); overworld_camera.set_compositor(&overworld_compositor);
overworld_camera.set_composite_index(0); overworld_camera.set_composite_index(0);
overworld_camera.set_active(true); overworld_camera.set_active(true);
@ -548,7 +549,7 @@ application::application(int argc, char** argv):
underworld_compositor.add_pass(underworld_final_pass); underworld_compositor.add_pass(underworld_final_pass);
// Setup underworld camera // Setup underworld camera
underworld_camera.set_perspective(45.0f * vmq::pi<float> / 180.0f, (float)window_width / (float)window_height, 0.1f, 1000.0f);
underworld_camera.set_perspective(math::radians<float>(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.look_at({0, 50, 0}, {0, 0, 0}, {0, 0, -1});
underworld_camera.set_compositor(&underworld_compositor); underworld_camera.set_compositor(&underworld_compositor);
underworld_camera.set_composite_index(0); underworld_camera.set_composite_index(0);
@ -751,11 +752,11 @@ application::application(int argc, char** argv):
ecs::cavity_component cavity; ecs::cavity_component cavity;
cavity.position = 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::cavity_component>(ecs_registry.create(), cavity); ecs_registry.assign<ecs::cavity_component>(ecs_registry.create(), cavity);
}); });
@ -800,7 +801,7 @@ application::application(int argc, char** argv):
spotlight.set_color({1, 1, 1}); spotlight.set_color({1, 1, 1});
spotlight.set_intensity(1.0f); spotlight.set_intensity(1.0f);
spotlight.set_attenuation({1.0f, 0.09f, 0.032f}); 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.update_tweens();
spotlight.set_active(false); spotlight.set_active(false);
@ -875,12 +876,9 @@ application::application(int argc, char** argv):
//model_instance* larva = new model_instance(resource_manager->load<model>("larva.obj")); //model_instance* larva = new model_instance(resource_manager->load<model>("larva.obj"));
//underworld_scene.add_object(larva); //underworld_scene.add_object(larva);
quaternion<float> flashlight_rotation = vmq::angle_axis(vmq::half_pi<float>, {0.0f, 1.0f, 0.0f});
model_instance* flashlight = new model_instance(resource_manager->load<model>("flashlight.obj")); model_instance* flashlight = new model_instance(resource_manager->load<model>("flashlight.obj"));
flashlight->set_rotation(flashlight_rotation);
underworld_scene.add_object(flashlight); underworld_scene.add_object(flashlight);
model_instance* flashlight_light_cone = new model_instance(resource_manager->load<model>("flashlight-light-cone.obj")); model_instance* flashlight_light_cone = new model_instance(resource_manager->load<model>("flashlight-light-cone.obj"));
flashlight_light_cone->set_rotation(flashlight_rotation);
underworld_scene.add_object(flashlight_light_cone); underworld_scene.add_object(flashlight_light_cone);
control_system->set_flashlight(flashlight, 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()); animator->add_animation(radial_transition_outer->get_animation());
// Setup tweens // Setup tweens
focal_point_tween.set_interpolator(ease<float3>::linear);
focal_point_tween.set_interpolator(math::lerp<float3, float>);
// Register CLI commands // Register CLI commands
cli.register_command("echo", cc::echo); cli.register_command("echo", cc::echo);
@ -974,7 +972,7 @@ int application::execute()
// Setup time tween // Setup time tween
time[0] = time[1] = 0.0; time[0] = time[1] = 0.0;
time.set_interpolator(ease<double>::linear);
time.set_interpolator(math::lerp<double, double>);
// Schedule frames until closed // Schedule frames until closed
while (!closed) while (!closed)
@ -1033,19 +1031,24 @@ void application::setup_fsm()
initial_state = &splash_state; initial_state = &splash_state;
} }
void application::load_config()
{
}
void application::parse_options(int argc, char** argv) void application::parse_options(int argc, char** argv)
{ {
cxxopts::Options options("Antkeeper", "Ant colony simulation game"); cxxopts::Options options("Antkeeper", "Ant colony simulation game");
options.add_options() 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<std::string>())
("f,fullscreen", "Starts in fullscreen mode")
("n,new-game", "Starts a new game") ("n,new-game", "Starts a new game")
("q,quick-start", "Skips to the main menu")
("r,reset", "Restores all settings to default") ("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<int>()) ("v,vsync", "Enables or disables v-sync", cxxopts::value<int>())
("d,data", "Specifies the data package path", cxxopts::value<std::string>())
("w,windowed", "Starts in windowed mode")
; ;
logger.push_task("Parsing command line options"); 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); auto result = options.parse(argc, argv);
// --quick-start
if (result.count("quick-start"))
{
logger.log("Skipping splash screen");
initial_state = &play_state;
}
// --continue // --continue
if (result.count("continue")) if (result.count("continue"))
{ {
logger.log("Continuing from last save"); 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<std::string>();
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 // --fullscreen
@ -1086,11 +1083,23 @@ void application::parse_options(int argc, char** argv)
fullscreen = true; 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 // --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<std::string>();
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) catch (const std::exception& e)

+ 1
- 0
src/application.hpp View File

@ -188,6 +188,7 @@ public:
private: private:
void setup_fsm(); void setup_fsm();
void load_config();
void parse_options(int argc, char** argv); void parse_options(int argc, char** argv);

+ 3
- 5
src/camera-rig.cpp View File

@ -19,16 +19,15 @@
#include "orbit-cam.hpp" #include "orbit-cam.hpp"
#include "scene/camera.hpp" #include "scene/camera.hpp"
#include "math/constants.hpp"
#include "configuration.hpp" #include "configuration.hpp"
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
using namespace vmq::operators;
camera_rig::camera_rig(): camera_rig::camera_rig():
camera(nullptr), camera(nullptr),
translation{0.0f, 0.0f, 0.0f}, translation{0.0f, 0.0f, 0.0f},
rotation(vmq::identity_quaternion<float>),
rotation(math::identity_quaternion<float>),
forward(global_forward), forward(global_forward),
right(global_right), right(global_right),
up(global_up) up(global_up)
@ -53,7 +52,7 @@ void camera_rig::set_translation(const float3& translation)
this->translation = translation; this->translation = translation;
} }
void camera_rig::set_rotation(const vmq::quaternion<float>& rotation)
void camera_rig::set_rotation(const quaternion_type& rotation)
{ {
this->rotation = rotation; this->rotation = rotation;
@ -62,4 +61,3 @@ void camera_rig::set_rotation(const vmq::quaternion& rotation)
up = rotation * global_up; up = rotation * global_up;
right = rotation * global_right; right = rotation * global_right;
} }

+ 10
- 7
src/camera-rig.hpp View File

@ -20,9 +20,9 @@
#ifndef ANTKEEPER_CAMERA_RIG_HPP #ifndef ANTKEEPER_CAMERA_RIG_HPP
#define ANTKEEPER_CAMERA_RIG_HPP #define ANTKEEPER_CAMERA_RIG_HPP
#include <vmq/vmq.hpp>
using namespace vmq::types;
#include "math/quaternion-type.hpp"
#include "math/transform-type.hpp"
#include "utility/fundamental-types.hpp"
class camera; class camera;
@ -32,6 +32,9 @@ class camera;
class camera_rig class camera_rig
{ {
public: public:
typedef math::quaternion<float> quaternion_type;
typedef math::transform<float> transform_type;
camera_rig(); camera_rig();
/** /**
@ -61,7 +64,7 @@ public:
/** /**
* Sets the rotation of the camera rig. * Sets the rotation of the camera rig.
*/ */
void set_rotation(const vmq::quaternion<float>& rotation);
void set_rotation(const quaternion_type& rotation);
/** /**
* Returns the attached camera. * Returns the attached camera.
@ -72,7 +75,7 @@ public:
::camera* get_camera(); ::camera* get_camera();
const float3& get_translation() const; const float3& get_translation() const;
const vmq::quaternion<float>& get_rotation() const;
const quaternion_type& get_rotation() const;
const float3& get_forward() const; const float3& get_forward() const;
const float3& get_right() const; const float3& get_right() const;
const float3& get_up() const; const float3& get_up() const;
@ -80,7 +83,7 @@ public:
private: private:
camera* camera; camera* camera;
float3 translation; float3 translation;
vmq::quaternion<float> rotation;
quaternion_type rotation;
float3 forward; float3 forward;
float3 right; float3 right;
float3 up; float3 up;
@ -101,7 +104,7 @@ inline const float3& camera_rig::get_translation() const
return translation; return translation;
} }
inline const vmq::quaternion<float>& camera_rig::get_rotation() const
inline const typename camera_rig::quaternion_type& camera_rig::get_rotation() const
{ {
return rotation; return rotation;
} }

+ 4
- 6
src/configuration.hpp.in View File

@ -20,18 +20,16 @@
#ifndef ANTKEEPER_CONFIGURATION_HPP #ifndef ANTKEEPER_CONFIGURATION_HPP
#define ANTKEEPER_CONFIGURATION_HPP #define ANTKEEPER_CONFIGURATION_HPP
#include <vmq/vmq.hpp>
using namespace vmq::types;
#include "math/vector-type.hpp"
#define ANTKEEPER_VERSION_MAJOR @PROJECT_VERSION_MAJOR@ #define ANTKEEPER_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
#define ANTKEEPER_VERSION_MINOR @PROJECT_VERSION_MINOR@ #define ANTKEEPER_VERSION_MINOR @PROJECT_VERSION_MINOR@
#define ANTKEEPER_VERSION_PATCH @PROJECT_VERSION_PATCH@ #define ANTKEEPER_VERSION_PATCH @PROJECT_VERSION_PATCH@
#define ANTKEEPER_VERSION_STRING "@PROJECT_VERSION@" #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<float, 3> global_forward = {0.0f, 0.0f, -1.0f};
constexpr math::vector<float, 3> global_up = {0.0f, 1.0f, 0.0f};
constexpr math::vector<float, 3> global_right = {1.0f, 0.0f, 0.0f};
#define MATERIAL_PASS_MAX_AMBIENT_LIGHT_COUNT 1 #define MATERIAL_PASS_MAX_AMBIENT_LIGHT_COUNT 1
#define MATERIAL_PASS_MAX_POINT_LIGHT_COUNT 1 #define MATERIAL_PASS_MAX_POINT_LIGHT_COUNT 1

+ 1
- 2
src/entity/components/cavity-component.hpp View File

@ -20,8 +20,7 @@
#ifndef ANTKEEPER_ECS_CAVITY_COMPONENT_HPP #ifndef ANTKEEPER_ECS_CAVITY_COMPONENT_HPP
#define ANTKEEPER_ECS_CAVITY_COMPONENT_HPP #define ANTKEEPER_ECS_CAVITY_COMPONENT_HPP
#include <vmq/vmq.hpp>
using namespace vmq::types;
#include "math/math.hpp"
namespace ecs { namespace ecs {

+ 1
- 2
src/entity/components/locomotion-component.hpp View File

@ -21,8 +21,7 @@
#define ANTKEEPER_ECS_PLACEMENT_COMPONENT_HPP #define ANTKEEPER_ECS_PLACEMENT_COMPONENT_HPP
#include "geometry/mesh.hpp" #include "geometry/mesh.hpp"
#include <vmq/vmq.hpp>
using namespace vmq::types;
#include "utility/fundamental-types.hpp"
namespace ecs { namespace ecs {

+ 1
- 2
src/entity/components/samara-component.hpp View File

@ -20,8 +20,7 @@
#ifndef ANTKEEPER_ECS_SAMARA_COMPONENT_HPP #ifndef ANTKEEPER_ECS_SAMARA_COMPONENT_HPP
#define ANTKEEPER_ECS_SAMARA_COMPONENT_HPP #define ANTKEEPER_ECS_SAMARA_COMPONENT_HPP
#include <vmq/vmq.hpp>
using namespace vmq::types;
#include "utility/fundamental-types.hpp"
namespace ecs { namespace ecs {

+ 2
- 2
src/entity/components/transform-component.hpp View File

@ -20,13 +20,13 @@
#ifndef ANTKEEPER_ECS_TRANSFORM_COMPONENT_HPP #ifndef ANTKEEPER_ECS_TRANSFORM_COMPONENT_HPP
#define ANTKEEPER_ECS_TRANSFORM_COMPONENT_HPP #define ANTKEEPER_ECS_TRANSFORM_COMPONENT_HPP
#include <vmq/vmq.hpp>
#include "math/math.hpp"
namespace ecs { namespace ecs {
struct transform_component struct transform_component
{ {
vmq::transform<float> transform;
math::transform<float> transform;
bool warp; bool warp;
}; };

+ 1
- 5
src/entity/entity-commands.hpp View File

@ -20,18 +20,14 @@
#ifndef ANTKEEPER_ECS_ENTITY_COMMANDS_HPP #ifndef ANTKEEPER_ECS_ENTITY_COMMANDS_HPP
#define ANTKEEPER_ECS_ENTITY_COMMANDS_HPP #define ANTKEEPER_ECS_ENTITY_COMMANDS_HPP
#include "utility/fundamental-types.hpp"
#include <entt/entt.hpp> #include <entt/entt.hpp>
#include <vmq/vmq.hpp>
using namespace vmq;
namespace ecs { namespace ecs {
void move_to(entt::registry& registry, entt::entity entity, const float3& position); 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 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 assign_render_layers(entt::registry& registry, entt::entity entity, unsigned int layers);
void bind_transform(entt::registry& registry, entt::entity entity, entt::entity target); void bind_transform(entt::registry& registry, entt::entity entity, entt::entity target);
} // namespace ecs } // namespace ecs

+ 25
- 27
src/geometry/aabb.hpp View File

@ -22,20 +22,18 @@
#include "bounding-volume.hpp" #include "bounding-volume.hpp"
#include "sphere.hpp" #include "sphere.hpp"
#include <vmq/vmq.hpp>
#include <array>
#include "math/math.hpp"
#include <limits> #include <limits>
using vmq::vector;
using vmq::matrix;
using vmq::transform;
using namespace vmq::operators;
template <class T> template <class T>
struct aabb: public bounding_volume<T> struct aabb: public bounding_volume<T>
{ {
vector<T, 3> min_point;
vector<T, 3> max_point;
typedef math::vector<T, 3> vector_type;
typedef math::matrix<T, 4, 4> matrix_type;
typedef math::transform<T> transform_type;
vector_type min_point;
vector_type max_point;
/** /**
* Transforms an AABB. * Transforms an AABB.
@ -44,7 +42,7 @@ struct aabb: public bounding_volume
* @param t Transform by which the AABB should be transformed. * @param t Transform by which the AABB should be transformed.
* @return Transformed AABB. * @return Transformed AABB.
*/ */
static aabb transform(const aabb& a, const ::transform<T>& t);
static aabb transform(const aabb& a, const transform_type& t);
/** /**
* Transforms an AABB. * Transforms an AABB.
@ -53,9 +51,9 @@ struct aabb: public bounding_volume
* @param m Matrix by which the AABB should be transformed. * @param m Matrix by which the AABB should be transformed.
* @return Transformed AABB. * @return Transformed AABB.
*/ */
static aabb transform(const aabb& a, const matrix<T, 4, 4>& m);
static aabb transform(const aabb& a, const matrix_type& m);
aabb(const vector<T, 3>& min_point, const vector<T, 3>& max_point);
aabb(const vector_type& min_point, const vector_type& max_point);
aabb(); aabb();
virtual bounding_volume_type get_bounding_volume_type() const; virtual bounding_volume_type get_bounding_volume_type() const;
@ -63,7 +61,7 @@ struct aabb: public bounding_volume
virtual bool intersects(const aabb<T>& aabb) const; virtual bool intersects(const aabb<T>& aabb) const;
virtual bool contains(const sphere<T>& sphere) const; virtual bool contains(const sphere<T>& sphere) const;
virtual bool contains(const aabb<T>& aabb) const; virtual bool contains(const aabb<T>& aabb) const;
virtual bool contains(const vector<T, 3>& point) const;
virtual bool contains(const vector_type& point) const;
/** /**
* Returns the position of the specified corner. * Returns the position of the specified corner.
@ -71,18 +69,18 @@ struct aabb: public bounding_volume
* @param index Index of a corner. * @param index Index of a corner.
* @return Position of the specified corner. * @return Position of the specified corner.
*/ */
vector<T, 3> corner(int index) const noexcept;
vector_type corner(int index) const noexcept;
}; };
template <class T> template <class T>
aabb<T> aabb<T>::transform(const aabb& a, const ::transform<T>& t)
aabb<T> aabb<T>::transform(const aabb& a, const transform_type& t)
{ {
vector<T, 3> min_point = {std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity()};
vector<T, 3> max_point = {-std::numeric_limits<T>::infinity(), -std::numeric_limits<T>::infinity(), -std::numeric_limits<T>::infinity()};
vector_type min_point = {std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity()};
vector_type max_point = {-std::numeric_limits<T>::infinity(), -std::numeric_limits<T>::infinity(), -std::numeric_limits<T>::infinity()};
for (std::size_t i = 0; i < 8; ++i) for (std::size_t i = 0; i < 8; ++i)
{ {
vector<T, 3> 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) for (std::size_t j = 0; j < 3; ++j)
{ {
@ -95,15 +93,15 @@ aabb aabb::transform(const aabb& a, const ::transform& t)
} }
template <class T> template <class T>
aabb<T> aabb<T>::transform(const aabb& a, const matrix<T, 4, 4>& m)
aabb<T> aabb<T>::transform(const aabb& a, const matrix_type& m)
{ {
vector<T, 3> min_point = {std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity()};
vector<T, 3> max_point = {-std::numeric_limits<T>::infinity(), -std::numeric_limits<T>::infinity(), -std::numeric_limits<T>::infinity()};
vector_type min_point = {std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity()};
vector_type max_point = {-std::numeric_limits<T>::infinity(), -std::numeric_limits<T>::infinity(), -std::numeric_limits<T>::infinity()};
for (std::size_t i = 0; i < 8; ++i) for (std::size_t i = 0; i < 8; ++i)
{ {
vector<T, 3> corner = a.corner(i);
vector<T, 4> transformed_corner = vmq::mul(m, vector<T, 4>{corner.x, corner.y, corner.z, T(1)});
vector_type corner = a.corner(i);
vector<T, 4> transformed_corner = math::mul(m, vector<T, 4>{corner.x, corner.y, corner.z, T(1)});
for (std::size_t j = 0; j < 3; ++j) for (std::size_t j = 0; j < 3; ++j)
{ {
@ -116,7 +114,7 @@ aabb aabb::transform(const aabb& a, const matrix& m)
} }
template <class T> template <class T>
aabb<T>::aabb(const vector<T, 3>& min_point, const vector<T, 3>& max_point):
aabb<T>::aabb(const vector_type& min_point, const vector_type& max_point):
min_point(min_point), min_point(min_point),
max_point(max_point) max_point(max_point)
{} {}
@ -134,7 +132,7 @@ inline bounding_volume_type aabb::get_bounding_volume_type() const
template <class T> template <class T>
bool aabb<T>::intersects(const sphere<T>& sphere) const bool aabb<T>::intersects(const sphere<T>& sphere) const
{ {
const vector<T, 3> radius_vector = {sphere.radius, sphere.radius, sphere.radius};
const vector_type radius_vector = {sphere.radius, sphere.radius, sphere.radius};
return aabb<T>(min_point - radius_vector, max_point + radius_vector).contains(sphere.center); return aabb<T>(min_point - radius_vector, max_point + radius_vector).contains(sphere.center);
} }
@ -175,7 +173,7 @@ bool aabb::contains(const aabb& aabb) const
} }
template <class T> template <class T>
bool aabb<T>::contains(const vector<T, 3>& point) const
bool aabb<T>::contains(const vector_type& point) const
{ {
if (point.x < min_point.x || point.x > max_point.x) if (point.x < min_point.x || point.x > max_point.x)
return false; return false;
@ -187,7 +185,7 @@ bool aabb::contains(const vector& point) const
} }
template <class T> template <class T>
vector<T, 3> aabb<T>::corner(int index) const noexcept
typename aabb<T>::vector_type aabb<T>::corner(int index) const noexcept
{ {
return return
{ {

+ 2
- 3
src/geometry/bounding-volume.hpp View File

@ -20,10 +20,10 @@
#ifndef ANTKEEPER_BOUNDING_VOLUME_HPP #ifndef ANTKEEPER_BOUNDING_VOLUME_HPP
#define ANTKEEPER_BOUNDING_VOLUME_HPP #define ANTKEEPER_BOUNDING_VOLUME_HPP
#include "math/math.hpp"
#include <stdexcept> #include <stdexcept>
#include <vmq/vmq.hpp>
using vmq::vector;
using math::vector;
template <class T> template <class T>
struct sphere; struct sphere;
@ -91,4 +91,3 @@ bool bounding_volume::intersects(const bounding_volume& volume) const
} }
#endif // ANTKEEPER_BOUNDING_VOLUME_HPP #endif // ANTKEEPER_BOUNDING_VOLUME_HPP

+ 9
- 9
src/geometry/convex-hull.hpp View File

@ -20,12 +20,12 @@
#ifndef ANTKEEPER_CONVEX_HULL_HPP #ifndef ANTKEEPER_CONVEX_HULL_HPP
#define 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 <cstdlib> #include <cstdlib>
#include <vector> #include <vector>
#include "bounding-volume.hpp"
#include "plane.hpp"
#include "sphere.hpp"
#include "aabb.hpp"
/** /**
* A plane-bounded convex hull. * A plane-bounded convex hull.
@ -73,7 +73,7 @@ template
bool convex_hull<T>::intersects(const sphere<T>& sphere) const bool convex_hull<T>::intersects(const sphere<T>& sphere) const
{ {
for (const plane<T>& plane: planes) for (const plane<T>& plane: planes)
if (signed_distance(plane, sphere.center) < -sphere.radius)
if (plane.signed_distance(sphere.center) < -sphere.radius)
return false; return false;
return true; 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.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.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; 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; return false;
} }
@ -98,7 +98,7 @@ template
bool convex_hull<T>::contains(const sphere<T>& sphere) const bool convex_hull<T>::contains(const sphere<T>& sphere) const
{ {
for (const plane<T>& plane: planes) for (const plane<T>& plane: planes)
if (signed_distance(plane, sphere.center) < sphere.radius)
if (plane.signed_distance(sphere.center) < sphere.radius)
return false; return false;
return true; 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.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; 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; return false;
} }
@ -129,7 +129,7 @@ template
bool convex_hull<T>::contains(const vector<T, 3>& point) const bool convex_hull<T>::contains(const vector<T, 3>& point) const
{ {
for (const plane<T>& plane: planes) for (const plane<T>& plane: planes)
if (signed_distance(plane, point) < T(0))
if (plane.signed_distance(point) < T(0))
return false; return false;
return true; return true;

+ 1
- 5
src/geometry/csg.hpp View File

@ -20,15 +20,11 @@
#ifndef ANTKEEPER_CSG_HPP #ifndef ANTKEEPER_CSG_HPP
#define ANTKEEPER_CSG_HPP #define ANTKEEPER_CSG_HPP
#include "utility/fundamental-types.hpp"
#include <list> #include <list>
#include <vmq/vmq.hpp>
namespace csg { namespace csg {
using vmq::float3;
using vmq::float4;
struct plane struct plane
{ {
float3 normal; float3 normal;

+ 8
- 8
src/geometry/intersection.cpp View File

@ -22,10 +22,10 @@
std::tuple<bool, float> ray_plane_intersection(const ray<float>& ray, const plane<float>& plane) std::tuple<bool, float> ray_plane_intersection(const ray<float>& ray, const plane<float>& plane)
{ {
float denom = vmq::dot(ray.direction, plane.normal);
float denom = math::dot(ray.direction, plane.normal);
if (denom != 0.0f) 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) if (t >= 0.0f)
{ {
@ -43,8 +43,8 @@ std::tuple ray_triangle_intersection(const ray
float3 edge20 = c - a; float3 edge20 = c - a;
// Calculate determinant // 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) if (!det)
{ {
@ -55,7 +55,7 @@ std::tuple ray_triangle_intersection(const ray
// Calculate u // Calculate u
float3 tv = ray.origin - a; 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) if (u < 0.0f || u > 1.0f)
{ {
@ -63,8 +63,8 @@ std::tuple ray_triangle_intersection(const ray
} }
// Calculate v // 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) if (v < 0.0f || u + v > 1.0f)
{ {
@ -72,7 +72,7 @@ std::tuple ray_triangle_intersection(const ray
} }
// Calculate t // Calculate t
float t = vmq::dot(edge20, qv) * inverse_det;
float t = math::dot(edge20, qv) * inverse_det;
if (t > 0.0f) if (t > 0.0f)
{ {

+ 5
- 9
src/geometry/intersection.hpp View File

@ -20,16 +20,12 @@
#ifndef ANTKEEPER_INTERSECTION_HPP #ifndef ANTKEEPER_INTERSECTION_HPP
#define 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 <tuple> #include <tuple>
#include <vmq/vmq.hpp>
#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. * Tests for intersection between a ray and a plane.

+ 4
- 6
src/geometry/mesh-accelerator.hpp View File

@ -20,16 +20,14 @@
#ifndef ANTKEEPER_MESH_ACCELERATOR_HPP #ifndef ANTKEEPER_MESH_ACCELERATOR_HPP
#define ANTKEEPER_MESH_ACCELERATOR_HPP #define ANTKEEPER_MESH_ACCELERATOR_HPP
#include "mesh.hpp"
#include "geometry/mesh.hpp"
#include "geometry/octree.hpp" #include "geometry/octree.hpp"
#include "geometry/aabb.hpp" #include "geometry/aabb.hpp"
#include "intersection.hpp"
#include "geometry/intersection.hpp"
#include "utility/fundamental-types.hpp"
#include <list> #include <list>
#include <unordered_map>
#include <optional> #include <optional>
#include <vmq/vmq.hpp>
using namespace vmq::types;
using namespace vmq::operators;
#include <unordered_map>
/** /**
* Acceleration structure for querying mesh geometry. * Acceleration structure for querying mesh geometry.

+ 2
- 13
src/geometry/mesh-functions.cpp View File

@ -18,13 +18,8 @@
*/ */
#include "mesh-functions.hpp" #include "mesh-functions.hpp"
#include <vmq/vmq.hpp>
#include <stdexcept>
#include "math/math.hpp"
#include <unordered_map> #include <unordered_map>
#include <map>
#include <iostream>
using namespace vmq::operators;
struct edge_hasher 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 (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; loop[j] = it->second;
} }
else else
@ -92,7 +83,7 @@ void calculate_face_normals(float* normals, const mesh& mesh)
const float3& b = reinterpret_cast<const float3&>(face.edge->next->vertex->position); const float3& b = reinterpret_cast<const float3&>(face.edge->next->vertex->position);
const float3& c = reinterpret_cast<const float3&>(face.edge->previous->vertex->position); const float3& c = reinterpret_cast<const float3&>(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<float>{bounds_min, bounds_max}; return aabb<float>{bounds_min, bounds_max};
} }

+ 3
- 5
src/geometry/mesh-functions.hpp View File

@ -20,13 +20,11 @@
#ifndef ANTKEEPER_MESH_FUNCTIONS_HPP #ifndef ANTKEEPER_MESH_FUNCTIONS_HPP
#define ANTKEEPER_MESH_FUNCTIONS_HPP #define ANTKEEPER_MESH_FUNCTIONS_HPP
#include "mesh.hpp"
#include <vmq/vmq.hpp>
#include "geometry/aabb.hpp"
#include "geometry/mesh.hpp"
#include "utility/fundamental-types.hpp"
#include <array> #include <array>
#include <vector> #include <vector>
#include "geometry/aabb.hpp"
using namespace vmq::types;
/** /**
* Creates a triangle mesh from a list of vertices and indices. * Creates a triangle mesh from a list of vertices and indices.

+ 37
- 33
src/geometry/plane.hpp View File

@ -20,93 +20,97 @@
#ifndef ANTKEEPER_PLANE_HPP #ifndef ANTKEEPER_PLANE_HPP
#define ANTKEEPER_PLANE_HPP #define ANTKEEPER_PLANE_HPP
#include <vmq/vmq.hpp>
using vmq::vector;
using namespace vmq::operators;
#include "math/math.hpp"
template <class T> template <class T>
struct plane struct plane
{ {
vector<T, 3> normal;
typedef math::vector<T, 3> vector_type;
/// Plane normal vector.
vector_type normal;
/// Plane distance.
T distance; T distance;
/** /**
* Creates a plane given a normal vector and distance. * Creates a plane given a normal vector and distance.
*/ */
plane(const vector<T, 3>& normal, T distance);
plane(const vector_type& normal, T distance);
/** /**
* Creates a plane given a normal vector and offset vector. * Creates a plane given a normal vector and offset vector.
*/ */
plane(const vector<T, 3>& normal, const vector<T, 3>& offset);
plane(const vector_type& normal, const vector_type& offset);
/** /**
* Creates a plane given three points. * Creates a plane given three points.
*/ */
plane(const vector<T, 3>& a, const vector<T, 3>& b, const vector<T, 3>& c);
plane(const vector_type& a, const vector_type& b, const vector_type& c);
/** /**
* Creates a plane given its coefficients. * 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. * @param coefficients Vector containing the plane coefficients, A, B, C and D, as x, y, z, and w, respectively.
*/ */
plane(const vector<T, 4>& coefficients);
plane(const math::vector<T, 4>& coefficients);
/// Creates an uninitialized plane. /// Creates an uninitialized plane.
plane() = default; 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 <class T> template <class T>
inline plane<T>::plane(const vector<T, 3>& normal, T distance):
inline plane<T>::plane(const vector_type& normal, T distance):
normal(normal), normal(normal),
distance(distance) distance(distance)
{} {}
template <class T> template <class T>
plane<T>::plane(const vector<T, 3>& normal, const vector<T, 3>& offset):
plane<T>::plane(const vector_type& normal, const vector_type& offset):
normal(normal), normal(normal),
distance(-vmq::dot(normal, offset))
distance(-math::dot(normal, offset))
{} {}
template <class T> template <class T>
plane<T>::plane(const vector<T, 3>& a, const vector<T, 3>& b, const vector<T, 3>& c)
plane<T>::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 <class T> template <class T>
plane<T>::plane(const vector<T, 4>& coefficients)
plane<T>::plane(const math::vector<T, 4>& coefficients)
{ {
const vector<T, 3> 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; normal = abc * inverse_length;
distance = coefficients[3] * 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 <class T> template <class T>
inline T signed_distance(const plane<T>& p, const vector<T, 3>& v)
inline T plane<T>::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 <class T> template <class T>
vector<T, 3> intersection(const plane<T>& p0, const plane<T>& p1, const plane<T>& p2)
typename plane<T>::vector_type plane<T>::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 #endif // ANTKEEPER_PLANE_HPP

+ 31
- 0
src/geometry/projection.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_PROJECTION_HPP
#define ANTKEEPER_PROJECTION_HPP
#include "math/math.hpp"
template <class T>
math::vector<T, 3> project_on_plane(const math::vector<T, 3>& v, const math::vector<T, 3>& p, const math::vector<T, 3>& n)
{
return v - n * math::dot(v - p, n);
}
#endif // ANTKEEPER_PROJECTION_HPP

+ 17
- 9
src/geometry/ray.hpp View File

@ -20,22 +20,30 @@
#ifndef ANTKEEPER_RAY_HPP #ifndef ANTKEEPER_RAY_HPP
#define ANTKEEPER_RAY_HPP #define ANTKEEPER_RAY_HPP
#include <vmq/vmq.hpp>
using vmq::vector;
using namespace vmq::operators;
#include "math/math.hpp"
template <class T> template <class T>
struct ray struct ray
{ {
vector<T, 3> origin;
vector<T, 3> direction;
vector<T, 3> extrapolate(T distance) const;
typedef math::vector<T, 3> 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 <class T> template <class T>
inline vector<T, 3> ray<T>::extrapolate(T distance) const
inline typename ray<T>::vector_type ray<T>::extrapolate(T distance) const
{ {
return origin + direction * distance; return origin + direction * distance;
} }

+ 5
- 6
src/geometry/sdf.hpp View File

@ -20,9 +20,8 @@
#ifndef ANTKEEPER_SDF_HPP #ifndef ANTKEEPER_SDF_HPP
#define ANTKEEPER_SDF_HPP #define ANTKEEPER_SDF_HPP
#include <vmq/vmq.hpp>
using namespace vmq::types;
using namespace vmq::operators;
#include "utility/fundamental-types.hpp"
#include <algorithm>
/** /**
* Contains signed distance functions. * 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) 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) 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; float dy = std::abs(p[1]) - h;
return std::min<float>(std::max<float>(dx, dy), 0.0f) + vmq::length(float2{std::max<float>(dx, 0.0f), std::max<float>(dy, 0.0f)});
return std::min<float>(std::max<float>(dx, dy), 0.0f) + math::length(float2{std::max<float>(dx, 0.0f), std::max<float>(dy, 0.0f)});
} }
inline float op_union(float a, float b) inline float op_union(float a, float b)

+ 18
- 19
src/geometry/sphere.hpp View File

@ -20,21 +20,20 @@
#ifndef ANTKEEPER_SPHERE_HPP #ifndef ANTKEEPER_SPHERE_HPP
#define ANTKEEPER_SPHERE_HPP #define ANTKEEPER_SPHERE_HPP
#include "bounding-volume.hpp"
#include "aabb.hpp"
#include <vmq/vmq.hpp>
#include "geometry/bounding-volume.hpp"
#include "geometry/aabb.hpp"
#include "math/math.hpp"
#include <algorithm> #include <algorithm>
using vmq::vector;
using namespace vmq::operators;
template <class T> template <class T>
struct sphere: public bounding_volume<T> struct sphere: public bounding_volume<T>
{ {
vector<T, 3> center;
typedef math::vector<T, 3> vector_type;
vector_type center;
T radius; T radius;
sphere(const vector<T, 3>& center, T radius);
sphere(const vector_type& center, T radius);
sphere(); sphere();
virtual bounding_volume_type get_bounding_volume_type() const; virtual bounding_volume_type get_bounding_volume_type() const;
@ -42,11 +41,11 @@ struct sphere: public bounding_volume
virtual bool intersects(const aabb<T>& aabb) const; virtual bool intersects(const aabb<T>& aabb) const;
virtual bool contains(const sphere<T>& sphere) const; virtual bool contains(const sphere<T>& sphere) const;
virtual bool contains(const aabb<T>& aabb) const; virtual bool contains(const aabb<T>& aabb) const;
virtual bool contains(const vector<T, 3>& point) const;
virtual bool contains(const vector_type& point) const;
}; };
template <class T> template <class T>
sphere<T>::sphere(const vector<T, 3>& center, T radius):
sphere<T>::sphere(const vector_type& center, T radius):
center(center), center(center),
radius(radius) radius(radius)
{} {}
@ -64,9 +63,9 @@ inline bounding_volume_type sphere::get_bounding_volume_type() const
template <class T> template <class T>
bool sphere<T>::intersects(const sphere<T>& sphere) const bool sphere<T>::intersects(const sphere<T>& sphere) const
{ {
vector<T, 3> d = center - sphere.center;
vector_type d = center - sphere.center;
float r = radius + sphere.radius; float r = radius + sphere.radius;
return (vmq::dot(d, d) <= r * r);
return (math::dot(d, d) <= r * r);
} }
template <class T> template <class T>
@ -82,8 +81,8 @@ bool sphere::contains(const sphere& sphere) const
if (containment_radius < T(0)) if (containment_radius < T(0))
return false; return false;
vector<T, 3> 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 <class T> template <class T>
@ -91,8 +90,8 @@ bool sphere::contains(const aabb& aabb) const
{ {
T distance = T(0); T distance = T(0);
vector<T, 3> a = center - aabb.min_point;
vector<T, 3> 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.x * a.x, b.x * b.x);
distance += std::max(a.y * a.y, b.y * b.y); distance += std::max(a.y * a.y, b.y * b.y);
@ -102,10 +101,10 @@ bool sphere::contains(const aabb& aabb) const
} }
template <class T> template <class T>
bool sphere<T>::contains(const vector<T, 3>& point) const
bool sphere<T>::contains(const vector_type& point) const
{ {
vector<T, 3> 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 #endif // ANTKEEPER_SPHERE_HPP

+ 43
- 43
src/geometry/view-frustum.hpp View File

@ -20,24 +20,24 @@
#ifndef ANTKEEPER_VIEW_FRUSTUM_HPP #ifndef ANTKEEPER_VIEW_FRUSTUM_HPP
#define ANTKEEPER_VIEW_FRUSTUM_HPP #define ANTKEEPER_VIEW_FRUSTUM_HPP
#include "convex-hull.hpp"
#include "geometry/convex-hull.hpp"
#include "math/math.hpp"
#include <array> #include <array>
#include <vmq/vmq.hpp>
using vmq::vector;
using vmq::matrix;
using namespace vmq::operators;
template <class T> template <class T>
class view_frustum class view_frustum
{ {
public: public:
typedef math::vector<T, 3> vector_type;
typedef math::matrix<T, 4, 4> matrix_type;
typedef plane<T> plane_type;
/** /**
* Creates a view frustum from a view-projection matrix. * Creates a view frustum from a view-projection matrix.
* *
* @param view_projection View-projection matrix. * @param view_projection View-projection matrix.
*/ */
view_frustum(const matrix<T, 4, 4>& view_projection);
view_frustum(const matrix_type& view_projection);
/// Creates an uninitialized view frustum. /// Creates an uninitialized view frustum.
view_frustum(); view_frustum();
@ -47,46 +47,46 @@ public:
* *
* @param view_projection View-projection matrix. * @param view_projection View-projection matrix.
*/ */
void set_matrix(const matrix<T, 4, 4>& view_projection);
void set_matrix(const matrix_type& view_projection);
/// Returns a convex hull which describes the bounds of the view frustum. /// Returns a convex hull which describes the bounds of the view frustum.
const convex_hull<T>& get_bounds() const; const convex_hull<T>& get_bounds() const;
/// Returns the left clipping plane. /// Returns the left clipping plane.
const plane<T>& get_left() const;
const plane_type& get_left() const;
/// Returns the right clipping plane. /// Returns the right clipping plane.
const plane<T>& get_right() const;
const plane_type& get_right() const;
/// Returns the bottom clipping plane. /// Returns the bottom clipping plane.
const plane<T>& get_bottom() const;
const plane_type& get_bottom() const;
/// Returns the top clipping plane. /// Returns the top clipping plane.
const plane<T>& get_top() const;
const plane_type& get_top() const;
/// Returns the near clipping plane. /// Returns the near clipping plane.
const plane<T>& get_near() const;
const plane_type& get_near() const;
/// Returns the far clipping plane. /// Returns the far clipping plane.
const plane<T>& get_far() const;
const plane_type& get_far() const;
/** /**
* Returns an array containing the corners of the view frustum bounds. * 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. * @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<vector<T, 3>, 8>& get_corners() const;
const std::array<vector_type, 8>& get_corners() const;
private: private:
void recalculate_planes(const matrix<T, 4, 4>& view_projection);
void recalculate_planes(const matrix_type& view_projection);
void recalculate_corners(); void recalculate_corners();
convex_hull<T> bounds; convex_hull<T> bounds;
std::array<vector<T, 3>, 8> corners;
std::array<vector_type, 8> corners;
}; };
template <class T> template <class T>
view_frustum<T>::view_frustum(const matrix<T, 4, 4>& view_projection):
view_frustum<T>::view_frustum(const matrix_type& view_projection):
bounds(6) bounds(6)
{ {
set_matrix(view_projection); set_matrix(view_projection);
@ -94,11 +94,11 @@ view_frustum::view_frustum(const matrix& view_projection):
template <class T> template <class T>
view_frustum<T>::view_frustum(): view_frustum<T>::view_frustum():
view_frustum(vmq::identity4x4<T>)
view_frustum(math::identity4x4<T>)
{} {}
template <class T> template <class T>
void view_frustum<T>::set_matrix(const matrix<T, 4, 4>& view_projection)
void view_frustum<T>::set_matrix(const matrix_type& view_projection)
{ {
recalculate_planes(view_projection); recalculate_planes(view_projection);
recalculate_corners(); recalculate_corners();
@ -111,70 +111,70 @@ inline const convex_hull& view_frustum::get_bounds() const
} }
template <class T> template <class T>
inline const plane<T>& view_frustum<T>::get_left() const
inline const typename view_frustum<T>::plane_type& view_frustum<T>::get_left() const
{ {
return bounds.planes[0]; return bounds.planes[0];
} }
template <class T> template <class T>
inline const plane<T>& view_frustum<T>::get_right() const
inline const typename view_frustum<T>::plane_type& view_frustum<T>::get_right() const
{ {
return bounds.planes[1]; return bounds.planes[1];
} }
template <class T> template <class T>
inline const plane<T>& view_frustum<T>::get_bottom() const
inline const typename view_frustum<T>::plane_type& view_frustum<T>::get_bottom() const
{ {
return bounds.planes[2]; return bounds.planes[2];
} }
template <class T> template <class T>
inline const plane<T>& view_frustum<T>::get_top() const
inline const typename view_frustum<T>::plane_type& view_frustum<T>::get_top() const
{ {
return bounds.planes[3]; return bounds.planes[3];
} }
template <class T> template <class T>
inline const plane<T>& view_frustum<T>::get_near() const
inline const typename view_frustum<T>::plane_type& view_frustum<T>::get_near() const
{ {
return bounds.planes[4]; return bounds.planes[4];
} }
template <class T> template <class T>
inline const plane<T>& view_frustum<T>::get_far() const
inline const typename view_frustum<T>::plane_type& view_frustum<T>::get_far() const
{ {
return bounds.planes[5]; return bounds.planes[5];
} }
template <class T> template <class T>
inline const std::array<vector<T, 3>, 8>& view_frustum<T>::get_corners() const
inline const std::array<typename view_frustum<T>::vector_type, 8>& view_frustum<T>::get_corners() const
{ {
return corners; return corners;
} }
template <class T> template <class T>
void view_frustum<T>::recalculate_planes(const matrix<T, 4, 4>& view_projection)
void view_frustum<T>::recalculate_planes(const matrix_type& view_projection)
{ {
matrix<T, 4, 4> transpose = vmq::transpose(view_projection);
bounds.planes[0] = plane<T>(transpose[3] + transpose[0]);
bounds.planes[1] = plane<T>(transpose[3] - transpose[0]);
bounds.planes[2] = plane<T>(transpose[3] + transpose[1]);
bounds.planes[3] = plane<T>(transpose[3] - transpose[1]);
bounds.planes[4] = plane<T>(transpose[3] + transpose[2]);
bounds.planes[5] = plane<T>(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 <class T> template <class T>
void view_frustum<T>::recalculate_corners() void view_frustum<T>::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 #endif // ANTKEEPER_VIEW_FRUSTUM_HPP

+ 0
- 75
src/math.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_MATH_HPP
#define ANTKEEPER_MATH_HPP
#include <cstdlib>
#include <type_traits>
#include <vmq/vmq.hpp>
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 <std::size_t N, typename T>
inline vmq::vector<T, N>& as_vector(T& data)
{
static_assert(std::is_pod<vmq::vector<T, N>>::value);
return reinterpret_cast<vmq::vector<T, N>&>(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 <std::size_t N, std::size_t M, typename T>
inline vmq::matrix<T, N, M>& as_matrix(T& data)
{
static_assert(std::is_pod<vmq::matrix<T, N, M>>::value);
return reinterpret_cast<vmq::matrix<T, N, M>&>(data);
}
template <class T>
vmq::vector<T, 3> project_on_plane(const vmq::vector<T, 3>& v, const vmq::vector<T, 3>& p, const vmq::vector<T, 3>& n)
{
return v - n * vmq::dot(v - p, n);
}
} // namespace math
#endif // ANTKEEPER_MATH_HPP

+ 64
- 0
src/math/angles.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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 <class T>
T degrees(T radians);
/**
* Converts an angle given in degrees to radians.
*
* @param radians Angle in radians.
* @return Angle in degrees.
*/
template <class T>
T radians(T degrees);
template <class T>
inline T degrees(T radians)
{
return radians * T(180) / pi<T>;
}
template <class T>
inline T radians(T degrees)
{
return degrees * pi<T> / T(180);
}
/// @}
} // namespace math
#endif // ANTKEEPER_MATH_ANGLES_HPP

+ 104
- 0
src/math/constants.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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 <class T>
constexpr T pi = T(3.14159265358979323846);
/**
* Pi / 2.
*/
template <class T>
constexpr T half_pi = pi<T> * T(0.5);
/**
* Pi * 2.
*/
template <class T>
constexpr T two_pi = pi<T> * T(2);
/**
* 2x2 identity matrix.
*/
template <class T>
constexpr matrix<T, 2, 2> identity2x2 =
{{
{1, 0},
{0, 1}
}};
/**
* 3x3 identity matrix.
*/
template <class T>
constexpr matrix<T, 3, 3> identity3x3 =
{{
{1, 0, 0},
{0, 1, 0},
{0, 0, 1}
}};
/**
* 4x4 identity matrix.
*/
template <class T>
constexpr matrix<T, 4, 4> identity4x4 =
{{
{1, 0, 0, 0},
{0, 1, 0, 0},
{0, 0, 1, 0},
{0, 0, 0, 1}
}};
/**
* Unit quaternion.
*/
template <class T>
constexpr quaternion<T> identity_quaternion = {T(1), T(0), T(0), T(0)};
/**
* Identity transform.
*/
template <class T>
constexpr transform<T> 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

+ 77
- 0
src/math/interpolation.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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 <cmath>
#include <type_traits>
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 <typename T, typename S = float>
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 <typename T, typename S = float>
T log_lerp(const T& x, const T& y, S a);
template <typename T, typename S>
inline T lerp(const T& x, const T& y, S a)
{
return (y - x) * a + x;
}
template <typename T, typename S>
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

+ 79
- 0
src/math/math.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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

+ 795
- 0
src/math/matrix-functions.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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 <type_traits>
namespace math {
/// @addtogroup matrix
/// @{
/**
* Adds two matrices.
*
* @param x First matrix.
* @param y Second matrix.
* @return Sum of the two matrices.
*/
template <class T>
matrix<T, 2, 2> add(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y);
/// @copydoc add(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&)
template <class T>
matrix<T, 3, 3> add(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y);
/// @copydoc add(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&)
template <class T>
matrix<T, 4, 4> add(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& 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 <std::size_t N, std::size_t M, typename T>
matrix<T, N, M>& as_matrix(T& data);
/**
* Calculates the determinant of a matrix.
*
* @param m Matrix of which to take the determinant.
*/
template <class T>
T determinant(const matrix<T, 2, 2>& m);
/// @copydoc determinant(const matrix<T, 2, 2>&)
template <class T>
T determinant(const matrix<T, 3, 3>& m);
/// @copydoc determinant(const matrix<T, 2, 2>&)
template <class T>
T determinant(const matrix<T, 4, 4>& m);
/**
* Calculates the inverse of a matrix.
*
* @param m Matrix of which to take the inverse.
*/
template <class T>
matrix<T, 2, 2> inverse(const matrix<T, 2, 2>& m);
/// @copydoc inverse(const matrix<T, 2, 2>&)
template <class T>
matrix<T, 3, 3> inverse(const matrix<T, 3, 3>& m);
/// @copydoc inverse(const matrix<T, 2, 2>&)
template <class T>
matrix<T, 4, 4> inverse(const matrix<T, 4, 4>& m);
/**
* Performs a component-wise multiplication of two matrices.
*
* @param x First matrix multiplicand.
* @param y Second matrix multiplicand.
*/
template <class T>
matrix<T, 2, 2> componentwise_mul(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y);
/// @copydoc componentwise_mul(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&)
template <class T>
matrix<T, 3, 3> componentwise_mul(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y);
/// @copydoc componentwise_mul(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&)
template <class T>
matrix<T, 4, 4> componentwise_mul(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& 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 <class T>
matrix<T, 4, 4> look_at(const vector<T, 3>& position, const vector<T, 3>& target, vector<T, 3> up);
/**
* Multiplies two matrices.
*
* @param x First matrix.
* @param y Second matrix.
* @return Product of the two matrices.
*/
template <class T>
matrix<T, 2, 2> mul(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y);
/// @copydoc mul(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&);
template <class T>
matrix<T, 3, 3> mul(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y);
/// @copydoc mul(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&);
template <class T>
matrix<T, 4, 4> mul(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y);
/**
* Multiplies a matrix by a scalar.
*
* @param m Matrix.
* @param s Scalar.
* @return Product of the matrix and the scalar..
*/
template <class T, std::size_t N, std::size_t M>
matrix<T, N, M> mul(const matrix<T, N, M>& m, T s);
/**
* Transforms a vector by a matrix.
*
* @param m Matrix.
* @param v Vector.
* @return Transformed vector.
*/
template <class T>
vector<T, 2> mul(const matrix<T, 2, 2>& m, const vector<T, 2>& v);
/// @copydoc mul(const matrix<T, 2, 2>&, const vector<T, 2>&)
template <class T>
vector<T, 3> mul(const matrix<T, 3, 3>& m, const vector<T, 3>& v);
/// @copydoc mul(const matrix<T, 2, 2>&, const vector<T, 2>&)
template <class T>
vector<T, 4> mul(const matrix<T, 4, 4>& m, const vector<T, 4>& 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 <class T>
matrix<T, 4, 4> 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 <class T>
matrix<T, 2, 2> outer_product(const vector<T, 2>& c, const vector<T, 2>& r);
/// @copydoc outer_product(const vector<T, 2>&, const vector<T, 2>&)
template <class T>
matrix<T, 3, 3> outer_product(const vector<T, 3>& c, const vector<T, 3>& r);
/// @copydoc outer_product(const vector<T, 2>&, const vector<T, 2>&)
template <class T>
matrix<T, 4, 4> outer_product(const vector<T, 4>& c, const vector<T, 4> 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 <class T>
matrix<T, 4, 4> 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 <std::size_t N1, std::size_t M1, class T, std::size_t N0, std::size_t M0>
matrix<T, N1, M1> resize(const matrix<T, N0, M0>& 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 <class T>
matrix<T, 4, 4> rotate(const matrix<T, 4, 4>& m, T angle, const vector<T, 3>& axis);
/**
* Scales a matrix.
*
* @param m Matrix to scale.
* @param v Scale vector.
* @return Scaled matrix.
*/
template <class T>
matrix<T, 4, 4> scale(const matrix<T, 4, 4>& m, const vector<T, 3>& v);
/**
* Subtracts a matrix from another matrix.
*
* @param x First matrix.
* @param y Second matrix.
* @return Difference between the two matrices.
*/
template <class T>
matrix<T, 2, 2> sub(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y);
/// @copydoc sub(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&)
template <class T>
matrix<T, 3, 3> sub(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y);
/// @copydoc sub(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&)
template <class T>
matrix<T, 4, 4> sub(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y);
/**
* Translates a matrix.
*
* @param m Matrix to translate.
* @param v Translation vector.
* @return Translated matrix.
*/
template <class T>
matrix<T, 4, 4> translate(const matrix<T, 4, 4>& m, const vector<T, 3>& v);
/**
* Calculates the transpose of a matrix.
*
* @param m Matrix of which to take the transpose.
*/
template <class T>
matrix<T, 2, 2> transpose(const matrix<T, 2, 2>& m);
/// @copydoc transpose(const matrix<T, 2, 2>&)
template <class T>
matrix<T, 3, 3> transpose(const matrix<T, 3, 3>& m);
/// @copydoc transpose(const matrix<T, 2, 2>&)
template <class T>
matrix<T, 4, 4> transpose(const matrix<T, 4, 4>& m);
template <class T>
matrix<T, 2, 2> add(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y)
{
return
{{
x[0] + y[0],
x[1] + y[1]
}};
}
template <class T>
matrix<T, 3, 3> add(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y)
{
return
{{
x[0] + y[0],
x[1] + y[1],
x[2] + y[2]
}};
}
template <class T>
matrix<T, 4, 4> add(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y)
{
return
{{
x[0] + y[0],
x[1] + y[1],
x[2] + y[2],
x[3] + y[3]
}};
}
template <std::size_t N, std::size_t M, typename T>
inline matrix<T, N, M>& as_matrix(T& data)
{
static_assert(std::is_pod<matrix<T, N, M>>::value);
return reinterpret_cast<matrix<T, N, M>&>(data);
}
template <class T>
T determinant(const matrix<T, 2, 2>& m)
{
return m[0][0] * m[1][1] - m[0][1] * m[1][0];
}
template <class T>
T determinant(const matrix<T, 3, 3>& 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 <class T>
T determinant(const matrix<T, 4, 4>& 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 <class T>
matrix<T, 2, 2> inverse(const matrix<T, 2, 2>& m)
{
static_assert(std::is_floating_point<T>::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 <class T>
matrix<T, 3, 3> inverse(const matrix<T, 3, 3>& m)
{
static_assert(std::is_floating_point<T>::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 <class T>
matrix<T, 4, 4> inverse(const matrix<T, 4, 4>& m)
{
static_assert(std::is_floating_point<T>::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 <class T>
matrix<T, 2, 2> componentwise_mul(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& 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 <class T>
matrix<T, 3, 3> componentwise_mul(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& 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 <class T>
matrix<T, 4, 4> componentwise_mul(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& 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 <class T>
matrix<T, 4, 4> look_at(const vector<T, 3>& position, const vector<T, 3>& target, vector<T, 3> up)
{
vector<T, 3> forward = normalize(sub(target, position));
vector<T, 3> right = normalize(cross(forward, up));
up = cross(right, forward);
matrix<T, 4, 4> 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 <class T>
matrix<T, 2, 2> mul(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y)
{
return
{{
x[0] * y[0][0] + x[1] * y[0][1],
x[0] * y[1][0] + x[1] * y[1][1]
}};
}
template <class T>
matrix<T, 3, 3> mul(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& 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 <class T>
matrix<T, 4, 4> mul(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& 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 <class T, std::size_t N, std::size_t M, std::size_t... I>
inline matrix<T, N, M> mul(const matrix<T, N, M>& m, T s, std::index_sequence<I...>)
{
return {{(m[I] * s)...}};
}
template <class T, std::size_t N, std::size_t M>
inline matrix<T, N, M> mul(const matrix<T, N, M>& m, T s)
{
return mul(m, s, std::make_index_sequence<N>{});
}
template <class T>
vector<T, 2> mul(const matrix<T, 2, 2>& m, const vector<T, 2>& v)
{
return
{
m[0][0] * v[0] + m[1][0] * v[1],
m[0][1] * v[0] + m[1][1] * v[1]
};
}
template <class T>
vector<T, 3> mul(const matrix<T, 3, 3>& m, const vector<T, 3>& 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 <class T>
vector<T, 4> mul(const matrix<T, 4, 4>& m, const vector<T, 4>& 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 <class T>
matrix<T, 4, 4> 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 <class T>
matrix<T, 2, 2> outer_product(const vector<T, 2>& c, const vector<T, 2>& r)
{
return
{{
{c[0] * r[0], c[1] * r[0]},
{c[0] * r[1], c[1] * r[1]}
}};
}
template <class T>
matrix<T, 3, 3> outer_product(const vector<T, 3>& c, const vector<T, 3>& 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 <class T>
matrix<T, 4, 4> outer_product(const vector<T, 4>& c, const vector<T, 4> 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 <class T>
matrix<T, 4, 4> 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 <std::size_t N1, std::size_t M1, class T, std::size_t N0, std::size_t M0>
matrix<T, N1, M1> resize(const matrix<T, N0, M0>& m)
{
matrix<T, N1, M1> 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 <class T>
matrix<T, 4, 4> rotate(const matrix<T, 4, 4>& m, T angle, const vector<T, 3>& axis)
{
const T c = std::cos(angle);
const T s = std::sin(angle);
const vector<T, 3> temp = mul(axis, T(1) - c);
matrix<T, 4, 4> 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 <class T>
matrix<T, 4, 4> scale(const matrix<T, 4, 4>& m, const vector<T, 3>& v)
{
return mul(m, matrix<T, 4, 4>
{{
{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 <class T>
matrix<T, 2, 2> sub(const matrix<T, 2, 2>& x, const matrix<T, 2, 2>& y)
{
return
{{
x[0] - y[0],
x[1] - y[1]
}};
}
template <class T>
matrix<T, 3, 3> sub(const matrix<T, 3, 3>& x, const matrix<T, 3, 3>& y)
{
return
{{
x[0] - y[0],
x[1] - y[1],
x[2] - y[2]
}};
}
template <class T>
matrix<T, 4, 4> sub(const matrix<T, 4, 4>& x, const matrix<T, 4, 4>& y)
{
return
{{
x[0] - y[0],
x[1] - y[1],
x[2] - y[2],
x[3] - y[3]
}};
}
template <class T>
matrix<T, 4, 4> translate(const matrix<T, 4, 4>& m, const vector<T, 3>& v)
{
return mul(m, matrix<T, 4, 4>
{{
{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 <class T>
matrix<T, 2, 2> transpose(const matrix<T, 2, 2>& m)
{
return
{{
{
m[0][0], m[1][0]
},
{
m[0][1], m[1][1]
}
}};
}
template <class T>
matrix<T, 3, 3> transpose(const matrix<T, 3, 3>& 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 <class T>
matrix<T, 4, 4> transpose(const matrix<T, 4, 4>& 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

+ 100
- 0
src/math/matrix-operators.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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<T, 2, 2>&, const matrix<T, 2, 2>&)
template <class T, std::size_t N, std::size_t M>
matrix<T, N, M> operator+(const matrix<T, N, M>& x, const matrix<T, N, M>& y);
/// @copydoc mul(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&)
template <class T, std::size_t N, std::size_t M>
matrix<T, N, M> operator*(const matrix<T, N, M>& x, const matrix<T, N, M>& y);
/// @copydoc mul(const matrix<T, N, M>&, T)
template <class T, std::size_t N, std::size_t M>
matrix<T, N, M> operator*(const matrix<T, N, M>& m, T s);
/// @copydoc mul(const matrix<T, N, M>&, T)
template <class T, std::size_t N, std::size_t M>
matrix<T, N, M> operator*(T s, const matrix<T, N, M>& m);
/// @copydoc mul(const matrix<T, 2, 2>&, const vector<T, 2>&)
template <class T, std::size_t N>
vector<T, N> operator*(const matrix<T, N, N>& m, const vector<T, N>& v);
/// @copydoc sub(const matrix<T, 2, 2>&, const matrix<T, 2, 2>&)
template <class T, std::size_t N, std::size_t M>
matrix<T, N, M> operator-(const matrix<T, N, M>& x, const matrix<T, N, M>& y);
template <class T, std::size_t N, std::size_t M>
inline matrix<T, N, M> operator+(const matrix<T, N, M>& x, const matrix<T, N, M>& y)
{
return add(x, y);
}
template <class T, std::size_t N, std::size_t M>
inline matrix<T, N, M> operator*(const matrix<T, N, M>& x, const matrix<T, N, M>& y)
{
return mul(x, y);
}
template <class T, std::size_t N, std::size_t M>
inline matrix<T, N, M> operator*(const matrix<T, N, M>& m, T s)
{
return mul(m, s);
}
template <class T, std::size_t N, std::size_t M>
inline matrix<T, N, M> operator*(T s, const matrix<T, N, M>& m)
{
return mul(m, s);
}
template <class T, std::size_t N>
inline vector<T, N> operator*(const matrix<T, N, N>& m, const vector<T, N>& v)
{
return mul(m, v);
}
template <class T, std::size_t N, std::size_t M>
inline matrix<T, N, M> operator-(const matrix<T, N, M>& x, const matrix<T, N, M>& 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

+ 54
- 0
src/math/matrix-type.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_MATH_MATRIX_TYPE_HPP
#define ANTKEEPER_MATH_MATRIX_TYPE_HPP
#include "math/vector-type.hpp"
#include <cstddef>
namespace math {
/// @addtogroup matrix
/// @{
/**
* An NxM matrix.
*
* @tparam T Matrix element type.
* @tparam N Number of columns.
* @tparam M Number of rows.
*/
template <typename T, std::size_t N, std::size_t M>
struct matrix
{
typedef T element_type;
typedef vector<element_type, M> 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

+ 29
- 0
src/math/operators.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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

+ 443
- 0
src/math/quaternion-functions.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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 <cmath>
namespace math {
/// @addtogroup quaternion
/// @{
/**
* Adds two quaternions.
*
* @param x First quaternion.
* @param y Second quaternion.
* @return Sum of the two quaternions.
*/
template <class T>
quaternion<T> add(const quaternion<T>& x, const quaternion<T>& y);
/**
* Calculates the conjugate of a quaternion.
*
* @param x Quaternion from which the conjugate will be calculated.
* @return Conjugate of the quaternion.
*/
template <class T>
quaternion<T> conjugate(const quaternion<T>& x);
/**
* Calculates the dot product of two quaternions.
*
* @param x First quaternion.
* @param y Second quaternion.
* @return Dot product of the two quaternions.
*/
template <class T>
T dot(const quaternion<T>& x, const quaternion<T>& y);
/**
* Divides a quaternion by a scalar.
*
* @param q Quaternion.
* @param s Scalar.
* @return Result of the division.
*/
template <class T>
quaternion<T> div(const quaternion<T>& q, T s);
/**
* Calculates the length of a quaternion.
*
* @param x Quaternion to calculate the length of.
* @return Length of the quaternion.
*/
template <class T>
T length(const quaternion<T>& 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 <class T>
T length_squared(const quaternion<T>& x);
/**
* Performs linear interpolation between two quaternions.
*
* @param x First quaternion.
* @param y Second quaternion.
* @param a Interpolation factor.
* @return Interpolated quaternion.
*/
template <class T>
quaternion<T> lerp(const quaternion<T>& x, const quaternion<T>& 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 <class T>
quaternion<T> look_rotation(const vector<T, 3>& forward, vector<T, 3> up);
/**
* Converts a quaternion to a rotation matrix.
*
* @param q Unit quaternion.
* @return Matrix representing the rotation described by `q`.
*/
template <class T>
matrix<T, 3, 3> matrix_cast(const quaternion<T>& q);
/**
* Multiplies two quaternions.
*
* @param x First quaternion.
* @param y Second quaternion.
* @return Product of the two quaternions.
*/
template <class T>
quaternion<T> mul(const quaternion<T>& x, const quaternion<T>& y);
/**
* Multiplies a quaternion by a scalar.
*
* @param q Quaternion.
* @param s Scalar.
* @return Product of the quaternion and scalar.
*/
template <class T>
quaternion<T> mul(const quaternion<T>& q, T s);
/**
* Rotates a 3-dimensional vector by a quaternion.
*
* @param q Unit quaternion.
* @param v Vector.
* @return Rotated vector.
*/
template <class T>
vector<T, 3> mul(const quaternion<T>& q, const vector<T, 3>& v);
/**
* Negates a quaternion.
*/
template <class T>
quaternion<T> negate(const quaternion<T>& x);
/**
* Normalizes a quaternion.
*/
template <class T>
quaternion<T> normalize(const quaternion<T>& 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 <class T>
quaternion<T> angle_axis(T angle, const vector<T, 3>& 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 <class T>
quaternion<T> rotation(const vector<T, 3>& source, const vector<T, 3>& destination);
/**
* Performs spherical linear interpolation between two quaternions.
*
* @param x First quaternion.
* @param y Second quaternion.
* @param a Interpolation factor.
* @return Interpolated quaternion.
*/
template <class T>
quaternion<T> slerp(const quaternion<T>& x, const quaternion<T>& y, T a);
/**
* Subtracts a quaternion from another quaternion.
*
* @param x First quaternion.
* @param y Second quaternion.
* @return Difference between the quaternions.
*/
template <class T>
quaternion<T> sub(const quaternion<T>& x, const quaternion<T>& y);
/**
* Converts a 3x3 rotation matrix to a quaternion.
*
* @param m Rotation matrix.
* @return Unit quaternion representing the rotation described by `m`.
*/
template <class T>
quaternion<T> quaternion_cast(const matrix<T, 3, 3>& m);
template <class T>
inline quaternion<T> add(const quaternion<T>& x, const quaternion<T>& y)
{
return {x.w + y.w, x.x + y.x, x.y + y.y, x.z + y.z};
}
template <class T>
inline quaternion<T> conjugate(const quaternion<T>& x)
{
return {x.w, -x.x, -x.y, -x.z};
}
template <class T>
inline T dot(const quaternion<T>& x, const quaternion<T>& y)
{
return {x.w * y.w + x.x * y.x + x.y * y.y + x.z * y.z};
}
template <class T>
inline quaternion<T> div(const quaternion<T>& q, T s)
{
return {q.w / s, q.x / s, q.y / s, q.z / s}
}
template <class T>
inline T length(const quaternion<T>& x)
{
return std::sqrt(x.w * x.w + x.x * x.x + x.y * x.y + x.z * x.z);
}
template <class T>
inline T length_squared(const quaternion<T>& x)
{
return x.w * x.w + x.x * x.x + x.y * x.y + x.z * x.z;
}
template <class T>
inline quaternion<T> lerp(const quaternion<T>& x, const quaternion<T>& 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 <class T>
quaternion<T> look_rotation(const vector<T, 3>& forward, vector<T, 3> up)
{
vector<T, 3> right = normalize(cross(forward, up));
up = cross(right, forward);
matrix<T, 3, 3> 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 <class T>
matrix<T, 3, 3> matrix_cast(const quaternion<T>& 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 <class T>
quaternion<T> mul(const quaternion<T>& x, const quaternion<T>& 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 <class T>
inline quaternion<T> mul(const quaternion<T>& q, T s)
{
return {q.w * s, q.x * s, q.y * s, q.z * s};
}
template <class T>
vector<T, 3> mul(const quaternion<T>& q, const vector<T, 3>& v)
{
const T r = q.w; // Real part
const vector<T, 3>& i = reinterpret_cast<const vector<T, 3>&>(q.x); // Imaginary part
return i * dot(i, v) * T(2) + v * (r * r - dot(i, i)) + cross(i, v) * r * T(2);
}
template <class T>
inline quaternion<T> negate(const quaternion<T>& x)
{
return {-x.w, -x.x, -x.y, -x.z};
}
template <class T>
inline quaternion<T> normalize(const quaternion<T>& x)
{
return mul(x, T(1) / length(x));
}
template <class T>
quaternion<T> angle_axis(T angle, const vector<T, 3>& axis)
{
T s = std::sin(angle * T(0.5));
return {static_cast<T>(std::cos(angle * T(0.5))), axis.x * s, axis.y * s, axis.z * s};
}
template <class T>
quaternion<T> rotation(const vector<T, 3>& source, const vector<T, 3>& destination)
{
quaternion<T> q;
q.w = dot(source, destination);
reinterpret_cast<vector<T, 3>&>(q.x) = cross(source, destination);
q.w += length(q);
return normalize(q);
}
template <class T>
quaternion<T> slerp(const quaternion<T>& x, const quaternion<T>& 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>(T(-1), std::min<T>(T(1), cos_theta));
T theta = static_cast<T>(std::acos(cos_theta)) * a;
quaternion<T> z = normalize(sub(y, mul(x, cos_theta)));
return add(mul(x, static_cast<T>(std::cos(theta))), mul(z, static_cast<T>(std::sin(theta))));
}
template <class T>
inline quaternion<T> sub(const quaternion<T>& x, const quaternion<T>& y)
{
return {x.w - y.w, x.x - y.x, x.y - y.y, x.z - y.z};
}
template <class T>
quaternion<T> quaternion_cast(const matrix<T, 3, 3>& m)
{
T r;
vector<T, 3> 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

+ 111
- 0
src/math/quaternion-operators.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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<T>&, const quaternion<T>&)
template <class T>
quaternion<T> operator+(const quaternion<T>& x, const quaternion<T>& y);
/// @copydoc div(const quaternion<T>&, T)
template <class T>
quaternion<T> operator/(const quaternion<T>& q, T s);
/// @copydoc mul(const quaternion<T>&, const quaternion<T>&)
template <class T>
quaternion<T> operator*(const quaternion<T>& x, const quaternion<T>& y);
/// @copydoc mul(const quaternion<T>&, T)
template <class T>
quaternion<T> operator*(const quaternion<T>& q, T s);
/// @copydoc mul(const quaternion<T>&, const vector<T, 3>&)
template <class T>
vector<T, 3> operator*(const quaternion<T>& q, const vector<T, 3>& v);
/// @copydoc sub(const quaternion<T>&, const quaternion<T>&)
template <class T>
quaternion<T> operator-(const quaternion<T>& x, const quaternion<T>& y);
/// @copydoc negate(const quaternion<T>&)
template <class T, std::size_t N>
quaternion<T> operator-(const quaternion<T>& x);
template <class T>
inline quaternion<T> operator+(const quaternion<T>& x, const quaternion<T>& y)
{
return add(x, y);
}
template <class T>
inline quaternion<T> operator/(const quaternion<T>& q, T s)
{
return div(q, s);
}
template <class T>
inline quaternion<T> operator*(const quaternion<T>& x, const quaternion<T>& y)
{
return mul(x, y);
}
template <class T>
inline quaternion<T> operator*(const quaternion<T>& q, T s)
{
return mul(q, s);
}
template <class T>
inline vector<T, 3> operator*(const quaternion<T>& q, const vector<T, 3>& v)
{
return mul(q, v);
}
template <class T>
inline quaternion<T> operator-(const quaternion<T>& x, const quaternion<T>& y)
{
return sub(x, y);
}
template <class T, std::size_t N>
inline quaternion<T> operator-(const quaternion<T>& 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

+ 48
- 0
src/math/quaternion-type.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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 <class T>
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

+ 55
- 0
src/math/random.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_MATH_RANDOM_HPP
#define ANTKEEPER_MATH_RANDOM_HPP
#include <cstdlib>
#include <type_traits>
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 <typename T = float>
T random(T start, T end);
template <typename T>
inline T random(T start, T end)
{
static_assert(std::is_floating_point<T>::value);
constexpr T rand_max_inverse = T(1) / static_cast<T>(RAND_MAX);
return static_cast<T>(std::rand()) * rand_max_inverse * (end - start) + start;
}
/// @}
} // namespace math
#endif // ANTKEEPER_MATH_RANDOM_HPP

+ 114
- 0
src/math/stream-operators.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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 <ostream>
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 <class T, std::size_t N>
std::ostream& operator<<(std::ostream& os, const vector<T, N>& 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 <class T, std::size_t N, std::size_t M>
std::ostream& operator<<(std::ostream& os, const matrix<T, N, M>& 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 <class T>
std::ostream& operator<<(std::ostream& os, const quaternion<T>& q);
template <class T, std::size_t N>
std::ostream& operator<<(std::ostream& os, const vector<T, N>& v)
{
for (std::size_t i = 0; i < N; ++i)
{
os << v[i];
if (i < N - 1)
{
os << ' ';
}
}
return os;
}
template <class T, std::size_t N, std::size_t M>
std::ostream& operator<<(std::ostream& os, const matrix<T, N, M>& 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 <class T>
std::ostream& operator<<(std::ostream& os, const quaternion<T>& 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

+ 110
- 0
src/math/transform-functions.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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 <class T>
transform<T> inverse(const transform<T>& t);
/**
* Converts a transform to a transformation matrix.
*
* @param t Transform.
* @return Matrix representing the transformation described by `t`.
*/
template <class T>
matrix<T, 4, 4> matrix_cast(const transform<T>& t);
/**
* Multiplies two transforms.
*
* @param x First transform.
* @param y Second transform.
* @return Product of the two transforms.
*/
template <class T>
transform<T> mul(const transform<T>& x, const transform<T>& y);
/**
* Multiplies a vector by a transform.
*
* @param t Transform.
* @param v Vector.
* @return Product of the transform and vector.
*/
template <class T>
vector<T, 3> mul(const transform<T>& t, const vector<T, 3>& v);
template <class T>
transform<T> inverse(const transform<T>& t)
{
transform<T> 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 <class T>
matrix<T, 4, 4> matrix_cast(const transform<T>& t)
{
matrix<T, 4, 4> 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 <class T>
transform<T> mul(const transform<T>& x, const transform<T>& y)
{
return
{
mul(x, y.translation),
normalize(mul(x.rotation, y.rotation)),
x.scale * y.scale
};
}
template <class T>
vector<T, 3> mul(const transform<T>& t, const vector<T, 3>& v)
{
return t.translation + (t.rotation * (v * t.scale));
}
/// @}
} // namespace math
#endif // ANTKEEPER_MATH_TRANSFORM_FUNCTIONS_HPP

+ 77
- 0
src/math/transform-operators.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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<T>&, const transform<T>&)
template <class T>
transform<T> operator*(const transform<T>& x, const transform<T>& y);
/// @copydoc mul(const transform<T>&, const vector<T, 3>&)
template <class T>
vector<T, 3> operator*(const transform<T>& t, const vector<T, 3>& 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 <class T>
transform<T>& operator*=(transform<T>& x, const transform<T>& y);
template <class T>
inline transform<T> operator*(const transform<T>& x, const transform<T>& y)
{
return mul(x, y);
}
template <class T>
inline vector<T, 3> operator*(const transform<T>& t, const vector<T, 3>& v)
{
return mul(t, v);
}
template <class T>
inline transform<T>& operator*=(transform<T>& x, const vector<T, 3>& 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

+ 54
- 0
src/math/transform-type.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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 <class T>
struct transform
{
/// Translation vector
vector<T, 3> translation;
/// Rotation quaternion
quaternion<T> rotation;
/// Scale vector
vector<T, 3> scale;
};
/// @}
} // namespace math
#endif // ANTKEEPER_MATH_TRANSFORM_TYPE_HPP

+ 627
- 0
src/math/vector-functions.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_MATH_VECTOR_FUNCTIONS_HPP
#define ANTKEEPER_MATH_VECTOR_FUNCTIONS_HPP
#include "math/vector-type.hpp"
#include <algorithm>
#include <cmath>
#include <type_traits>
#include <utility>
namespace math {
/// @addtogroup vector
/// @{
/**
* Adds two vectors.
*
* @param x First vector.
* @param y Second vector.
* @return Sum of the two vectors.
*/
template <class T, std::size_t N>
vector<T, N> add(const vector<T, N>& x, const vector<T, N>& 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 <std::size_t N>
bool all(const vector<bool, N>& 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 <std::size_t N>
bool any(const vector<bool, N>& 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 <std::size_t N, typename T>
vector<T, N>& 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 <class T, std::size_t N>
vector<T, N> clamp(const vector<T, N>& 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 <class T, std::size_t N>
vector<T, N> clamp_length(const vector<T, N>& 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 <class T>
vector<T, 3> cross(const vector<T, 3>& x, const vector<T, 3>& 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 <class T, std::size_t N>
vector<T, N> distance(const vector<T, N>& p0, const vector<T, N>& 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 <class T, std::size_t N>
vector<T, N> distance_squared(const vector<T, N>& p0, const vector<T, N>& p1);
/**
* Divides a vector by another vector.
*
* @param x First vector.
* @param y Second vector.
* @return Result of the division.
*/
template <class T, std::size_t N>
vector<T, N> div(const vector<T, N>& x, const vector<T, N>& y);
/**
* Divides a vector by a scalar.
*
* @param v Vector.
* @param s Scalar.
* @return Result of the division.
*/
template <class T, std::size_t N>
vector<T, N> div(const vector<T, N>& 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 <class T, std::size_t N>
T dot(const vector<T, N>& x, const vector<T, N>& 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 <class T, std::size_t N>
vector<bool, N> equal(const vector<T, N>& x, const vector<T, N>& 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 <class T, std::size_t N>
vector<bool, N> greater_than(const vector<T, N>& x, const vector<T, N>& 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 <class T, std::size_t N>
vector<bool, N> greater_than_equal(const vector<T, N>& x, const vector<T, N>& y);
/**
* Calculates the length of a vector.
*
* @param x Vector of which to calculate the length.
* @return Length of the vector.
*/
template <class T, std::size_t N>
T length(const vector<T, N>& 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 <class T, std::size_t N>
T length_squared(const vector<T, N>& 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 <class T, std::size_t N>
vector<bool, N> less_than(const vector<T, N>& x, const vector<T, N>& 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 <class T, std::size_t N>
vector<bool, N> less_than_equal(const vector<T, N>& x, const vector<T, N>& y);
/**
* Multiplies two vectors.
*
* @param x First vector.
* @param y Second vector.
* @return Product of the two vectors.
*/
template <class T, std::size_t N>
vector<T, N> mul(const vector<T, N>& x, const vector<T, N>& y);
/**
* Multiplies a vector by a scalar.
*
* @param v Vector.
* @param s Scalar.
* @return Product of the vector and scalar.
*/
template <class T, std::size_t N>
vector<T, N> mul(const vector<T, N>& v, T s);
/**
* Negates a vector.
*
* @param x Vector to negate.
* @return Negated vector.
*/
template <class T, std::size_t N>
vector<T, N> negate(const vector<T, N>& x);
/**
* Calculates the unit vector in the same direction as the original vector.
*
* @param x Vector to normalize.
* @return Normalized vector.
*/
template <class T, std::size_t N>
vector<T, N> normalize(const vector<T, N>& x);
/**
* Logically inverts a boolean vector.
*
* @param x Vector to be inverted.
* @return Logically inverted vector.
*/
template <class T, std::size_t N>
vector<bool, N> not(const vector<T, N>& 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 <class T, std::size_t N>
vector<bool, N> not_equal(const vector<T, N>& x, const vector<T, N>& y);
/**
* Resizes a vector. Any new elements will be set to `0`.
*
* @param v Vector to resize.
* @return Resized vector.
*/
template <std::size_t N1, class T, std::size_t N0>
vector<T, N1> resize(const vector<T, N0>& v);
/**
* Subtracts a vector from another vector.
*
* @param x First vector.
* @param y Second vector.
* @return Difference between the two vectors.
*/
template <class T, std::size_t N>
vector<T, N> sub(const vector<T, N>& x, const vector<T, N>& 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 <std::size_t... Indices, class T, std::size_t N>
vector<T, sizeof...(Indices)> swizzle(const vector<T, N>& v);
/// @private
template <class T, std::size_t N, std::size_t... I>
inline vector<T, N> add(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
{
return {(x[I] + y[I])...};
}
template <class T, std::size_t N>
inline vector<T, N> add(const vector<T, N>& x, const vector<T, N>& y)
{
return add(x, y, std::make_index_sequence<N>{});
}
/// @private
template <std::size_t N, std::size_t... I>
inline bool all(const vector<bool, N>& x, std::index_sequence<I...>)
{
return (x[I] && ...);
}
template <std::size_t N>
inline bool all(const vector<bool, N>& x)
{
return all(x, std::make_index_sequence<N>{});
}
/// @private
template <std::size_t N, std::size_t... I>
inline bool any(const vector<bool, N>& x, std::index_sequence<I...>)
{
return (x[I] || ...);
}
template <std::size_t N>
inline bool any(const vector<bool, N>& x)
{
return any(x, std::make_index_sequence<N>{});
}
template <std::size_t N, typename T>
inline vector<T, N>& as_vector(T& data)
{
static_assert(std::is_pod<vector<T, N>>::value);
return reinterpret_cast<vector<T, N>&>(data);
}
/// @private
template <class T, std::size_t N, std::size_t... I>
inline vector<T, N> clamp(const vector<T, N>& x, T min_value, T max_value, std::index_sequence<I...>)
{
return {std::min<T>(max_value, std::max<T>(min_value, x[I]))...};
}
template <class T, std::size_t N>
inline vector<T, N> clamp(const vector<T, N>& x, T min_value, T max_value)
{
return clamp(x, min_value, max_value, std::make_index_sequence<N>{});
}
template <class T, std::size_t N>
vector<T, N> clamp_length(const vector<T, N>& x, T max_length)
{
T length2 = length_squared(x);
return (length2 > max_length * max_length) ? (x * max_length / std::sqrt(length2)) : x;
}
template <class T>
inline vector<T, 3> cross(const vector<T, 3>& x, const vector<T, 3>& 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 <class T, std::size_t N>
inline vector<T, N> distance(const vector<T, N>& p0, const vector<T, N>& p1)
{
static_assert(std::is_floating_point<T>::value);
return length(sub(p0, p1));
}
template <class T, std::size_t N>
inline vector<T, N> distance_squared(const vector<T, N>& p0, const vector<T, N>& p1)
{
static_assert(std::is_floating_point<T>::value);
return length_squared(sub(p0, p1));
}
/// @private
template <class T, std::size_t N, std::size_t... I>
inline vector<T, N> div(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
{
return {(x[I] / y[I])...};
}
template <class T, std::size_t N>
inline vector<T, N> div(const vector<T, N>& x, const vector<T, N>& y)
{
return div(x, y, std::make_index_sequence<N>{});
}
/// @private
template <class T, std::size_t N, std::size_t... I>
inline vector<T, N> div(const vector<T, N>& v, T s, std::index_sequence<I...>)
{
return {(v[I] / s)...};
}
template <class T, std::size_t N>
inline vector<T, N> div(const vector<T, N>& v, T s)
{
return div(v, s, std::make_index_sequence<N>{});
}
/// @private
template <class T, std::size_t N, std::size_t... I>
inline T dot(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
{
return ((x[I] * y[I]) + ...);
}
template <class T, std::size_t N>
inline T dot(const vector<T, N>& x, const vector<T, N>& y)
{
return dot(x, y, std::make_index_sequence<N>{});
}
/// @private
template <class T, std::size_t N, std::size_t... I>
inline vector<bool, N> equal(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
{
return {(x[I] == y[I])...};
}
template <class T, std::size_t N>
inline vector<bool, N> equal(const vector<T, N>& x, const vector<T, N>& y)
{
return equal(x, y, std::make_index_sequence<N>{});
}
/// @private
template <class T, std::size_t N, std::size_t... I>
inline vector<bool, N> greater_than(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
{
return {(x[I] > y[I])...};
}
template <class T, std::size_t N>
inline vector<bool, N> greater_than(const vector<T, N>& x, const vector<T, N>& y)
{
return greater_than(x, y, std::make_index_sequence<N>{});
}
/// @private
template <class T, std::size_t N, std::size_t... I>
inline vector<bool, N> greater_than_equal(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
{
return {(x[I] >= y[I])...};
}
template <class T, std::size_t N>
inline vector<bool, N> greater_than_equal(const vector<T, N>& x, const vector<T, N>& y)
{
return greater_than_equal(x, y, std::make_index_sequence<N>{});
}
template <class T, std::size_t N>
inline T length(const vector<T, N>& x)
{
static_assert(std::is_floating_point<T>::value);
return std::sqrt(dot(x, x));
}
template <class T, std::size_t N>
inline T length_squared(const vector<T, N>& x)
{
static_assert(std::is_floating_point<T>::value);
return dot(x, x);
}
/// @private
template <class T, std::size_t N, std::size_t... I>
inline vector<bool, N> less_than(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
{
return {(x[I] < y[I])...};
}
template <class T, std::size_t N>
inline vector<bool, N> less_than(const vector<T, N>& x, const vector<T, N>& y)
{
return less_than(x, y, std::make_index_sequence<N>{});
}
/// @private
template <class T, std::size_t N, std::size_t... I>
inline vector<bool, N> less_than_equal(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
{
return {(x[I] <= y[I])...};
}
template <class T, std::size_t N>
inline vector<bool, N> less_than_equal(const vector<T, N>& x, const vector<T, N>& y)
{
return less_than_equal(x, y, std::make_index_sequence<N>{});
}
/// @private
template <class T, std::size_t N, std::size_t... I>
inline vector<T, N> mul(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
{
return {(x[I] * y[I])...};
}
template <class T, std::size_t N>
inline vector<T, N> mul(const vector<T, N>& x, const vector<T, N>& y)
{
return mul(x, y, std::make_index_sequence<N>{});
}
/// @private
template <class T, std::size_t N, std::size_t... I>
inline vector<T, N> mul(const vector<T, N>& v, T s, std::index_sequence<I...>)
{
return {(v[I] * s)...};
}
template <class T, std::size_t N>
inline vector<T, N> mul(const vector<T, N>& v, T s)
{
return mul(v, s, std::make_index_sequence<N>{});
}
/// @private
template <class T, std::size_t N, std::size_t... I>
inline vector<T, N> negate(const vector<T, N>& x, std::index_sequence<I...>)
{
return {(-x[I])...};
}
template <class T, std::size_t N>
inline vector<T, N> negate(const vector<T, N>& x)
{
return negate(x, std::make_index_sequence<N>{});
}
template <class T, std::size_t N>
inline vector<T, N> normalize(const vector<T, N>& x)
{
static_assert(std::is_floating_point<T>::value);
return mul(x, T(1) / length(x));
}
/// @private
template <class T, std::size_t N, std::size_t... I>
inline vector<bool, N> not(const vector<T, N>& x, std::index_sequence<I...>)
{
return {!x[I]...};
}
template <class T, std::size_t N>
inline vector<bool, N> not(const vector<T, N>& x)
{
return not(x, std::make_index_sequence<N>{});
}
/// @private
template <class T, std::size_t N, std::size_t... I>
inline vector<bool, N> not_equal(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
{
return {(x[I] != y[I])...};
}
template <class T, std::size_t N>
inline vector<bool, N> not_equal(const vector<T, N>& x, const vector<T, N>& y)
{
return not_equal(x, y, std::make_index_sequence<N>{});
}
template <std::size_t N1, class T, std::size_t N0>
vector<T, N1> resize(const vector<T, N0>& v)
{
vector<T, N1> resized;
for (std::size_t i = 0; i < N1; ++i)
{
resized[i] = (i < N0) ? v[i] : T(0);
}
return resized;
}
/// @private
template <class T, std::size_t N, std::size_t... I>
inline vector<T, N> sub(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
{
return {(x[I] - y[I])...};
}
template <class T, std::size_t N>
inline vector<T, N> sub(const vector<T, N>& x, const vector<T, N>& y)
{
return sub(x, y, std::make_index_sequence<N>{});
}
template <std::size_t... Indices, class T, std::size_t N>
inline vector<T, sizeof...(Indices)> swizzle(const vector<T, N>& v)
{
return { v[Indices]... };
}
/// @}
} // namespace math
#endif // ANTKEEPER_MATH_VECTOR_FUNCTIONS_HPP

+ 217
- 0
src/math/vector-operators.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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<T, N>&, const vector<T, N>&)
template <class T, std::size_t N>
vector<T, N> operator+(const vector<T, N>& x, const vector<T, N>& y);
/// @copydoc div(const vector<T, N>&, const vector<T, N>&)
template <class T, std::size_t N>
vector<T, N> operator/(const vector<T, N>& x, const vector<T, N>& y);
/// @copydoc div(const vector<T, N>&, T)
template <class T, std::size_t N>
vector<T, N> operator/(const vector<T, N>& v, T s);
/// @copydoc mul(const vector<T, N>&, const vector<T, N>&)
template <class T, std::size_t N>
vector<T, N> operator*(const vector<T, N>& x, const vector<T, N>& y);
/// @copydoc mul(const vector<T, N>&, T)
template <class T, std::size_t N>
vector<T, N> operator*(const vector<T, N>& v, T s);
/// @copydoc mul(const vector<T, N>&, T)
template <class T, std::size_t N>
vector<T, N> operator*(T s, const vector<T, N>& v);
/// @copydoc negate(const vector<T, N>&)
template <class T, std::size_t N>
vector<T, N> operator-(const vector<T, N>& x);
/// @copydoc sub(const vector<T, N>&, const vector<T, N>&)
template <class T, std::size_t N>
vector<T, N> operator-(const vector<T, N>& x, const vector<T, N>& 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 <class T, std::size_t N>
vector<T, N>& operator+=(vector<T, N>& x, const vector<T, N>& 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 <class T, std::size_t N>
vector<T, N>& operator-=(vector<T, N>& x, const vector<T, N>& 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 <class T, std::size_t N>
vector<T, N>& operator*=(vector<T, N>& x, const vector<T, N>& 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 <class T, std::size_t N>
vector<T, N>& operator*=(vector<T, N>& 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 <class T, std::size_t N>
vector<T, N>& operator/=(vector<T, N>& x, const vector<T, N>& 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 <class T, std::size_t N>
vector<T, N>& operator/=(vector<T, N>& v, T s);
template <class T, std::size_t N>
inline vector<T, N> operator+(const vector<T, N>& x, const vector<T, N>& y)
{
return add(x, y);
}
template <class T, std::size_t N>
inline vector<T, N> operator-(const vector<T, N>& x)
{
return negate(x);
}
template <class T, std::size_t N>
inline vector<T, N> operator-(const vector<T, N>& x, const vector<T, N>& y)
{
return sub(x, y);
}
template <class T, std::size_t N>
inline vector<T, N> operator*(const vector<T, N>& x, const vector<T, N>& y)
{
return mul(x, y);
}
template <class T, std::size_t N>
inline vector<T, N> operator*(const vector<T, N>& v, T s)
{
return mul(v, s);
}
template <class T, std::size_t N>
inline vector<T, N> operator*(T s, const vector<T, N>& v)
{
return mul(v, s);
}
template <class T, std::size_t N>
inline vector<T, N> operator/(const vector<T, N>& x, const vector<T, N>& y)
{
return div(x, y);
}
template <class T, std::size_t N>
inline vector<T, N> operator/(const vector<T, N>& v, T s)
{
return div(v, s);
}
template <class T, std::size_t N>
inline vector<T, N>& operator+=(vector<T, N>& x, const vector<T, N>& y)
{
return (x = x + y);
}
template <class T, std::size_t N>
inline vector<T, N>& operator-=(vector<T, N>& x, const vector<T, N>& y)
{
return (x = x - y);
}
template <class T, std::size_t N>
inline vector<T, N>& operator*=(vector<T, N>& x, const vector<T, N>& y)
{
return (x = x * y);
}
template <class T, std::size_t N>
inline vector<T, N>& operator*=(vector<T, N>& v, T s)
{
return (v = v * s);
}
template <class T, std::size_t N>
inline vector<T, N>& operator/=(vector<T, N>& x, const vector<T, N>& y)
{
return (x = x * y);
}
template <class T, std::size_t N>
inline vector<T, N>& operator/=(vector<T, N>& 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

+ 131
- 0
src/math/vector-type.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_MATH_VECTOR_TYPE_HPP
#define ANTKEEPER_MATH_VECTOR_TYPE_HPP
#include <array>
#include <cstddef>
namespace math {
/// @addtogroup vector
/// @{
/**
* An `N`-dimensional Euclidean vector.
*
* @tparam T Vector component type.
* @tparam N Number of dimensions.
*/
template <typename T, std::size_t N>
struct vector
{
typedef T scalar_type;
typedef std::array<T, N> 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<array_type&>(components[0]); }
inline constexpr operator const array_type&() const noexcept { return reinterpret_cast<const array_type&>(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 <typename T>
struct vector<T, 1>
{
typedef T scalar_type;
typedef std::array<T, 1> 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<array_type&>(x); }
inline constexpr operator const array_type&() const noexcept { return reinterpret_cast<const array_type&>(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 <typename T>
struct vector<T, 2>
{
typedef T scalar_type;
typedef std::array<T, 2> 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<array_type&>(x); }
inline constexpr operator const array_type&() const noexcept { return reinterpret_cast<const array_type&>(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 <typename T>
struct vector<T, 3>
{
typedef T scalar_type;
typedef std::array<T, 3> 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<array_type&>(x); }
inline constexpr operator const array_type&() const noexcept { return reinterpret_cast<const array_type&>(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 <typename T>
struct vector<T, 4>
{
typedef T scalar_type;
typedef std::array<T, 4> 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<array_type&>(x); }
inline constexpr operator const array_type&() const noexcept { return reinterpret_cast<const array_type&>(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<vector<float, 4>>::value);
/// @}
} // namespace math
#endif // ANTKEEPER_MATH_VECTOR_TYPE_HPP

+ 13
- 14
src/nest.cpp View File

@ -18,8 +18,7 @@
*/ */
#include "nest.hpp" #include "nest.hpp"
#include "animation/ease.hpp"
#include "math.hpp"
#include "math/math.hpp"
nest::nest() nest::nest()
{ {
@ -30,7 +29,7 @@ float3 nest::extend_shaft(shaft& shaft)
{ {
float3 dig_position = get_shaft_position(shaft, shaft.current_depth); 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; shaft.current_depth += dr * 0.1f;
@ -39,15 +38,15 @@ float3 nest::extend_shaft(shaft& shaft)
float3 nest::expand_chamber(chamber& chamber) float3 nest::expand_chamber(chamber& chamber)
{ {
float dig_angle = frand(0.0f, vmq::two_pi<float>);
float2 dig_direction = vmq::normalize(float2{std::cos(dig_angle), std::sin(dig_angle)});
float dig_angle = math::random(0.0f, math::two_pi<float>);
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 chamber_center = get_shaft_position(*chamber.shaft, chamber.depth);
float3 dig_position = chamber_center; 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.x += dig_direction.x * (chamber.outer_radius - dr) * t;
dig_position.z += dig_direction.y * (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 shaft_length = shaft.depth[1] - shaft.depth[0];
float depth_factor = (depth - shaft.depth[0]) / shaft_length; float depth_factor = (depth - shaft.depth[0]) / shaft_length;
float pitch = ease<float>::linear(shaft.pitch[0], shaft.pitch[1], depth_factor);
return shaft.rotation + (depth / pitch) * shaft.chirality * vmq::two_pi<float>;
float pitch = math::lerp<float>(shaft.pitch[0], shaft.pitch[1], depth_factor);
return shaft.rotation + (depth / pitch) * shaft.chirality * math::two_pi<float>;
} }
float nest::get_shaft_depth(const shaft& shaft, float turns) const 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 shaft_length = shaft.depth[1] - shaft.depth[0];
float depth_factor = (depth - shaft.depth[0]) / shaft_length; float depth_factor = (depth - shaft.depth[0]) / shaft_length;
float pitch = ease<float>::linear(shaft.pitch[0], shaft.pitch[1], depth_factor);
float radius = ease<float>::out_expo(shaft.radius[0], shaft.radius[1], depth_factor);
float translation_x = ease<float>::linear(shaft.translation[0][0], shaft.translation[1][0], depth_factor);
float translation_z = ease<float>::linear(shaft.translation[0][1], shaft.translation[1][1], depth_factor);
float angle = shaft.rotation + (depth / pitch) * shaft.chirality * vmq::two_pi<float>;
float pitch = math::lerp<float>(shaft.pitch[0], shaft.pitch[1], depth_factor);
float radius = math::lerp<float>(shaft.radius[0], shaft.radius[1], depth_factor);
float translation_x = math::lerp<float>(shaft.translation[0][0], shaft.translation[1][0], depth_factor);
float translation_z = math::lerp<float>(shaft.translation[0][1], shaft.translation[1][1], depth_factor);
float angle = shaft.rotation + (depth / pitch) * shaft.chirality * math::two_pi<float>;
float3 position; float3 position;
position[0] = std::cos(angle) * radius + translation_x; position[0] = std::cos(angle) * radius + translation_x;

+ 1
- 4
src/nest.hpp View File

@ -21,13 +21,10 @@
#define ANTKEEPER_NEST_HPP #define ANTKEEPER_NEST_HPP
#include "geometry/mesh.hpp" #include "geometry/mesh.hpp"
#include <vmq/vmq.hpp>
#include "utility/fundamental-types.hpp"
#include <array> #include <array>
#include <vector> #include <vector>
using namespace vmq::types;
using namespace vmq::operators;
class nest class nest
{ {
public: public:

+ 17
- 24
src/orbit-cam.cpp View File

@ -19,23 +19,16 @@
#include "orbit-cam.hpp" #include "orbit-cam.hpp"
#include "scene/camera.hpp" #include "scene/camera.hpp"
#include "math/math.hpp"
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
using namespace vmq::operators;
template <class T>
static inline T lerp(const T& x, const T& y, float a)
{
return x * (1.0f - a) + y * a;
}
orbit_cam::orbit_cam(): orbit_cam::orbit_cam():
elevation_rotation(vmq::identity_quaternion<float>),
azimuth_rotation(vmq::identity_quaternion<float>),
target_elevation_rotation(vmq::identity_quaternion<float>),
target_azimuth_rotation(vmq::identity_quaternion<float>),
target_rotation(vmq::identity_quaternion<float>)
elevation_rotation(math::identity_quaternion<float>),
azimuth_rotation(math::identity_quaternion<float>),
target_elevation_rotation(math::identity_quaternion<float>),
target_azimuth_rotation(math::identity_quaternion<float>),
target_rotation(math::identity_quaternion<float>)
{} {}
orbit_cam::~orbit_cam() orbit_cam::~orbit_cam()
@ -47,7 +40,7 @@ void orbit_cam::update(float dt)
// Calculate rotation and target rotation quaternions // Calculate rotation and target rotation quaternions
//rotation = azimuth_rotation * elevation_rotation; //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 // Calculate target translation
target_translation = target_focal_point + target_rotation * float3{0.0f, 0.0f, target_focal_distance}; 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); //rotation = glm::mix(rotation, target_rotation, interpolation_factor);
// Interpolate angles // 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 // Calculate rotation
set_rotation(vmq::normalize(azimuth_rotation * elevation_rotation));
set_rotation(math::normalize(azimuth_rotation * elevation_rotation));
// Interpolate focal point and focal distance // 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 // Caluclate translation
set_translation(focal_point + get_rotation() * float3{0.0f, 0.0f, focal_distance}); 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 // Update camera
if (get_camera() != nullptr) if (get_camera() != nullptr)
{ {
transform<float> transform = vmq::identity_transform<float>;
transform_type transform = math::identity_transform<float>;
transform.translation = get_translation(); transform.translation = get_translation();
transform.rotation = get_rotation(); transform.rotation = get_rotation();
get_camera()->set_transform(transform); get_camera()->set_transform(transform);
@ -128,13 +121,13 @@ void orbit_cam::set_focal_distance(float distance)
void orbit_cam::set_elevation(float angle) void orbit_cam::set_elevation(float angle)
{ {
elevation = 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) void orbit_cam::set_azimuth(float angle)
{ {
azimuth = 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) 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) void orbit_cam::set_target_elevation(float angle)
{ {
target_elevation = 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) void orbit_cam::set_target_azimuth(float angle)
{ {
target_azimuth = 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});
} }

+ 7
- 7
src/orbit-cam.hpp View File

@ -56,7 +56,7 @@ public:
float get_target_elevation() const; float get_target_elevation() const;
float get_target_azimuth() const; float get_target_azimuth() const;
const float3& get_target_translation() const; const float3& get_target_translation() const;
const vmq::quaternion<float>& get_target_rotation() const;
const quaternion_type& get_target_rotation() const;
private: private:
float3 focal_point; float3 focal_point;
@ -69,11 +69,11 @@ private:
float target_elevation; float target_elevation;
float target_azimuth; float target_azimuth;
vmq::quaternion<float> elevation_rotation;
vmq::quaternion<float> azimuth_rotation;
vmq::quaternion<float> target_elevation_rotation;
vmq::quaternion<float> target_azimuth_rotation;
vmq::quaternion<float> 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; float3 target_translation;
}; };
@ -122,7 +122,7 @@ inline const float3& orbit_cam::get_target_translation() const
return target_translation; return target_translation;
} }
inline const vmq::quaternion<float>& orbit_cam::get_target_rotation() const
inline const typename camera_rig::quaternion_type& orbit_cam::get_target_rotation() const
{ {
return target_rotation; return target_rotation;
} }

+ 4
- 4
src/pheromone-matrix.cpp View File

@ -18,7 +18,7 @@
*/ */
#include "pheromone-matrix.hpp" #include "pheromone-matrix.hpp"
#include <vmq/vmq.hpp>
#include "math/math.hpp"
void convolve(pheromone_matrix* matrix, const float* kernel, int kernel_size) 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) void diffuse(pheromone_matrix* matrix)
{ {
const vmq::matrix<float, 3, 3> diffusion_kernel =
vmq::mul(
vmq::matrix<float, 3, 3>
const math::matrix<float, 3, 3> diffusion_kernel =
math::mul(
math::matrix<float, 3, 3>
{{ {{
{1, 2, 1}, {1, 2, 1},
{2, 4, 2}, {2, 4, 2},

+ 1
- 2
src/rasterizer/shader-input.hpp View File

@ -20,14 +20,13 @@
#ifndef ANTKEEPER_SHADER_INPUT_HPP #ifndef ANTKEEPER_SHADER_INPUT_HPP
#define ANTKEEPER_SHADER_INPUT_HPP #define ANTKEEPER_SHADER_INPUT_HPP
#include <vmq/vmq.hpp>
#include "utility/fundamental-types.hpp"
#include <string> #include <string>
class shader_program; class shader_program;
class texture_2d; class texture_2d;
class texture_cube; class texture_cube;
enum class shader_variable_type; enum class shader_variable_type;
using namespace vmq::types;
/** /**
* Port through which data can be uploaded to shader variables. * Port through which data can be uploaded to shader variables.

+ 6
- 9
src/renderer/material-property.hpp View File

@ -23,13 +23,10 @@
#include "animation/tween.hpp" #include "animation/tween.hpp"
#include "rasterizer/shader-variable-type.hpp" #include "rasterizer/shader-variable-type.hpp"
#include "rasterizer/shader-input.hpp" #include "rasterizer/shader-input.hpp"
#include "animation/ease.hpp"
#include <vmq/vmq.hpp>
#include "math/interpolation.hpp"
#include "utility/fundamental-types.hpp"
#include <cstdlib> #include <cstdlib>
using namespace vmq::types;
using namespace vmq::operators;
class material; class material;
class shader_program; class shader_program;
class texture_2d; class texture_2d;
@ -191,25 +188,25 @@ inline T material_property::default_interpolator(const T& x, const T& y, doub
template <> template <>
inline float material_property<float>::default_interpolator(const float& x, const float& y, double a) inline float material_property<float>::default_interpolator(const float& x, const float& y, double a)
{ {
return ease<float, float>::linear(x, y, static_cast<float>(a));
return math::lerp<float, float>(x, y, static_cast<float>(a));
} }
template <> template <>
inline float2 material_property<float2>::default_interpolator(const float2& x, const float2& y, double a) inline float2 material_property<float2>::default_interpolator(const float2& x, const float2& y, double a)
{ {
return ease<float2, float>::linear(x, y, static_cast<float>(a));
return math::lerp<float2, float>(x, y, static_cast<float>(a));
} }
template <> template <>
inline float3 material_property<float3>::default_interpolator(const float3& x, const float3& y, double a) inline float3 material_property<float3>::default_interpolator(const float3& x, const float3& y, double a)
{ {
return ease<float3, float>::linear(x, y, static_cast<float>(a));
return math::lerp<float3, float>(x, y, static_cast<float>(a));
} }
template <> template <>
inline float4 material_property<float4>::default_interpolator(const float4& x, const float4& y, double a) inline float4 material_property<float4>::default_interpolator(const float4& x, const float4& y, double a)
{ {
return ease<float4, float>::linear(x, y, static_cast<float>(a));
return math::lerp<float4, float>(x, y, static_cast<float>(a));
} }
template <class T> template <class T>

+ 1
- 3
src/renderer/passes/bloom-pass.cpp View File

@ -32,12 +32,10 @@
#include "rasterizer/texture-filter.hpp" #include "rasterizer/texture-filter.hpp"
#include "renderer/vertex-attributes.hpp" #include "renderer/vertex-attributes.hpp"
#include "renderer/render-context.hpp" #include "renderer/render-context.hpp"
#include <vmq/vmq.hpp>
#include "math/math.hpp"
#include <cmath> #include <cmath>
#include <glad/glad.h> #include <glad/glad.h>
using namespace vmq;
bloom_pass::bloom_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, resource_manager* resource_manager): bloom_pass::bloom_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, resource_manager* resource_manager):
render_pass(rasterizer, framebuffer), render_pass(rasterizer, framebuffer),
source_texture(nullptr), source_texture(nullptr),

+ 1
- 3
src/renderer/passes/bloom-pass.hpp View File

@ -21,9 +21,7 @@
#define ANTKEEPER_BLOOM_PASS_HPP #define ANTKEEPER_BLOOM_PASS_HPP
#include "renderer/render-pass.hpp" #include "renderer/render-pass.hpp"
#include <vmq/vmq.hpp>
using namespace vmq::types;
#include "math/math.hpp"
class shader_program; class shader_program;
class shader_input; class shader_input;

+ 1
- 3
src/renderer/passes/clear-pass.hpp View File

@ -21,9 +21,7 @@
#define ANTKEEPER_CLEAR_PASS_HPP #define ANTKEEPER_CLEAR_PASS_HPP
#include "renderer/render-pass.hpp" #include "renderer/render-pass.hpp"
#include <vmq/vmq.hpp>
using namespace vmq::types;
#include "utility/fundamental-types.hpp"
/** /**
* Clears the color, depth, or stencil buffer of a render target. * Clears the color, depth, or stencil buffer of a render target.

+ 1
- 3
src/renderer/passes/final-pass.cpp View File

@ -32,12 +32,10 @@
#include "rasterizer/texture-filter.hpp" #include "rasterizer/texture-filter.hpp"
#include "renderer/vertex-attributes.hpp" #include "renderer/vertex-attributes.hpp"
#include "renderer/render-context.hpp" #include "renderer/render-context.hpp"
#include <vmq/vmq.hpp>
#include "math/math.hpp"
#include <cmath> #include <cmath>
#include <glad/glad.h> #include <glad/glad.h>
using namespace vmq;
final_pass::final_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, resource_manager* resource_manager): final_pass::final_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, resource_manager* resource_manager):
render_pass(rasterizer, framebuffer), render_pass(rasterizer, framebuffer),
color_texture(nullptr), color_texture(nullptr),

+ 1
- 3
src/renderer/passes/final-pass.hpp View File

@ -21,9 +21,7 @@
#define ANTKEEPER_FINAL_PASS_HPP #define ANTKEEPER_FINAL_PASS_HPP
#include "renderer/render-pass.hpp" #include "renderer/render-pass.hpp"
#include <vmq/vmq.hpp>
using namespace vmq::types;
#include "math/math.hpp"
class shader_program; class shader_program;
class shader_input; class shader_input;

+ 6
- 8
src/renderer/passes/material-pass.cpp View File

@ -45,15 +45,13 @@
#include "scene/spotlight.hpp" #include "scene/spotlight.hpp"
#include "scene/scene.hpp" #include "scene/scene.hpp"
#include "configuration.hpp" #include "configuration.hpp"
#include <vmq/vmq.hpp>
#include "math/math.hpp"
#include <cmath> #include <cmath>
#include <glad/glad.h> #include <glad/glad.h>
#include <iostream> #include <iostream>
#include "shadow-map-pass.hpp" #include "shadow-map-pass.hpp"
using namespace vmq;
static bool operation_compare(const render_operation& a, const render_operation& b); 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): 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 // Transform position into view-space
float3 position = light->get_transform_tween().interpolate(context->alpha).translation; 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_positions[point_light_count] = view_space_position;
point_light_attenuations[point_light_count] = static_cast<const point_light*>(light)->get_attenuation_tween().interpolate(context->alpha); point_light_attenuations[point_light_count] = static_cast<const point_light*>(light)->get_attenuation_tween().interpolate(context->alpha);
@ -192,7 +190,7 @@ void material_pass::render(render_context* context) const
// Transform direction into view-space // Transform direction into view-space
float3 direction = static_cast<const directional_light*>(light)->get_direction_tween().interpolate(context->alpha); float3 direction = static_cast<const directional_light*>(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_directions[directional_light_count] = view_space_direction;
++directional_light_count; ++directional_light_count;
@ -209,14 +207,14 @@ void material_pass::render(render_context* context) const
// Transform position into view-space // Transform position into view-space
float3 position = light->get_transform_tween().interpolate(context->alpha).translation; 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; spotlight_positions[spotlight_count] = view_space_position;
const ::spotlight* spotlight = static_cast<const ::spotlight*>(light); const ::spotlight* spotlight = static_cast<const ::spotlight*>(light);
// Transform direction into view-space // Transform direction into view-space
float3 direction = spotlight->get_direction_tween().interpolate(context->alpha); 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_directions[spotlight_count] = view_space_direction;
spotlight_attenuations[spotlight_count] = spotlight->get_attenuation_tween().interpolate(context->alpha); 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 = operation.transform;
model_view_projection = view_projection * model; model_view_projection = view_projection * model;
model_view = view * 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 // Upload operation-dependent parameters
if (parameters->model) if (parameters->model)

+ 1
- 0
src/renderer/passes/material-pass.hpp View File

@ -23,6 +23,7 @@
#include "renderer/render-pass.hpp" #include "renderer/render-pass.hpp"
#include "renderer/material.hpp" #include "renderer/material.hpp"
#include "animation/tween.hpp" #include "animation/tween.hpp"
#include "utility/fundamental-types.hpp"
#include <unordered_map> #include <unordered_map>
class camera; class camera;

+ 9
- 12
src/renderer/passes/shadow-map-pass.cpp View File

@ -34,12 +34,9 @@
#include "geometry/view-frustum.hpp" #include "geometry/view-frustum.hpp"
#include "geometry/aabb.hpp" #include "geometry/aabb.hpp"
#include "configuration.hpp" #include "configuration.hpp"
#include <vmq/vmq.hpp>
#include "math/math.hpp"
#include <cmath> #include <cmath>
#include <glad/glad.h> #include <glad/glad.h>
#include <iostream>
using namespace vmq;
static bool operation_compare(const render_operation& a, const render_operation& b); 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"); skinned_model_view_projection_input = skinned_shader_program->get_input("model_view_projection");
// Calculate bias-tile matrices // Calculate bias-tile matrices
float4x4 bias_matrix = vmq::translate(vmq::identity4x4<float>, float3{0.5f, 0.5f, 0.5f}) * vmq::scale(vmq::identity4x4<float>, float3{0.5f, 0.5f, 0.5f});
float4x4 tile_scale = vmq::scale(vmq::identity4x4<float>, float3{0.5f, 0.5f, 1.0f});
float4x4 bias_matrix = math::translate(math::identity4x4<float>, float3{0.5f, 0.5f, 0.5f}) * math::scale(math::identity4x4<float>, float3{0.5f, 0.5f, 0.5f});
float4x4 tile_scale = math::scale(math::identity4x4<float>, float3{0.5f, 0.5f, 1.0f});
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
{ {
float x = static_cast<float>(i % 2) * 0.5f; float x = static_cast<float>(i % 2) * 0.5f;
float y = static_cast<float>(i / 2) * 0.5f; float y = static_cast<float>(i / 2) * 0.5f;
float4x4 tile_matrix = vmq::translate(vmq::identity4x4<float>, float3{x, y, 0.0f}) * tile_scale;
float4x4 tile_matrix = math::translate(math::identity4x4<float>, float3{x, y, 0.0f}) * tile_scale;
bias_tile_matrices[i] = tile_matrix * bias_matrix; 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 // Calculate a view-projection matrix from the directional light's transform
transform<float> light_transform = light->get_transform_tween().interpolate(context->alpha);
math::transform<float> light_transform = light->get_transform_tween().interpolate(context->alpha);
float3 forward = light_transform.rotation * global_forward; float3 forward = light_transform.rotation * global_forward;
float3 up = light_transform.rotation * global_up; 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; float4x4 light_view_projection = light_projection * light_view;
// Get the camera's view matrix // 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 // Calculate projection matrix for view camera subfrustum
const float subfrustum_near = split_distances[i]; const float subfrustum_near = split_distances[i];
const float subfrustum_far = split_distances[i + 1]; 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 // Calculate view camera subfrustum
view_frustum<float> subfrustum(subfrustum_projection * camera_view); view_frustum<float> 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; offset.y = std::ceil(offset.y * half_shadow_map_resolution) / half_shadow_map_resolution;
// Crop the light view-projection matrix // Crop the light view-projection matrix
crop_matrix = vmq::translate(vmq::identity4x4<float>, offset) * vmq::scale(vmq::identity4x4<float>, scale);
crop_matrix = math::translate(math::identity4x4<float>, offset) * math::scale(math::identity4x4<float>, scale);
cropped_view_projection = crop_matrix * light_view_projection; cropped_view_projection = crop_matrix * light_view_projection;
// Calculate shadow matrix // Calculate shadow matrix

+ 1
- 5
src/renderer/passes/shadow-map-pass.hpp View File

@ -21,10 +21,7 @@
#define ANTKEEPER_SHADOW_MAP_PASS_HPP #define ANTKEEPER_SHADOW_MAP_PASS_HPP
#include "renderer/render-pass.hpp" #include "renderer/render-pass.hpp"
#include <vmq/vmq.hpp>
using namespace vmq::types;
#include "utility/fundamental-types.hpp"
class shader_program; class shader_program;
class shader_input; class shader_input;
@ -86,4 +83,3 @@ inline const float* shadow_map_pass::get_split_distances() const
} }
#endif // ANTKEEPER_SHADOW_MAP_PASS_HPP #endif // ANTKEEPER_SHADOW_MAP_PASS_HPP

+ 5
- 7
src/renderer/passes/sky-pass.cpp View File

@ -37,12 +37,10 @@
#include "scene/ambient-light.hpp" #include "scene/ambient-light.hpp"
#include "scene/directional-light.hpp" #include "scene/directional-light.hpp"
#include "scene/scene.hpp" #include "scene/scene.hpp"
#include <vmq/vmq.hpp>
#include "utility/fundamental-types.hpp"
#include <cmath> #include <cmath>
#include <glad/glad.h> #include <glad/glad.h>
using namespace vmq;
sky_pass::sky_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, resource_manager* resource_manager): sky_pass::sky_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, resource_manager* resource_manager):
render_pass(rasterizer, framebuffer) 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)); rasterizer->set_viewport(0, 0, std::get<0>(viewport), std::get<1>(viewport));
float3 sun_direction = {0, 0, -1}; float3 sun_direction = {0, 0, -1};
float sun_angular_radius = 3.0f * vmq::pi<float> / 180.0f;
float sun_angular_radius = math::radians<float>(3.0f);
// Find sun direction // Find sun direction
const std::list<scene_object_base*>* lights = context->scene->get_objects(light::object_type_id); const std::list<scene_object_base*>* lights = context->scene->get_objects(light::object_type_id);
@ -129,9 +127,9 @@ void sky_pass::render(render_context* context) const
} }
// Calculate matrix // 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 // Change shader program
rasterizer->use_program(*shader_program); rasterizer->use_program(*shader_program);

+ 1
- 3
src/renderer/passes/ui-pass.cpp View File

@ -41,12 +41,10 @@
#include "scene/directional-light.hpp" #include "scene/directional-light.hpp"
#include "scene/scene.hpp" #include "scene/scene.hpp"
#include "scene/billboard.hpp" #include "scene/billboard.hpp"
#include <vmq/vmq.hpp>
#include "math/math.hpp"
#include <cmath> #include <cmath>
#include <glad/glad.h> #include <glad/glad.h>
using namespace vmq;
ui_pass::ui_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, resource_manager* resource_manager): ui_pass::ui_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, resource_manager* resource_manager):
render_pass(rasterizer, framebuffer), render_pass(rasterizer, framebuffer),
time(0.0f) time(0.0f)

+ 2
- 5
src/renderer/render-context.hpp View File

@ -23,19 +23,16 @@
#include "renderer/render-operation.hpp" #include "renderer/render-operation.hpp"
#include "geometry/plane.hpp" #include "geometry/plane.hpp"
#include "geometry/bounding-volume.hpp" #include "geometry/bounding-volume.hpp"
#include <vmq/vmq.hpp>
#include "utility/fundamental-types.hpp"
#include <list> #include <list>
class camera; class camera;
class scene; class scene;
using namespace vmq::types;
using vmq::transform;
struct render_context struct render_context
{ {
const camera* camera; const camera* camera;
transform<float> camera_transform;
math::transform<float> camera_transform;
float3 camera_forward; float3 camera_forward;
float3 camera_up; float3 camera_up;
const bounding_volume<float>* camera_culling_volume; const bounding_volume<float>* camera_culling_volume;

+ 1
- 2
src/renderer/render-operation.hpp View File

@ -20,14 +20,13 @@
#ifndef ANTKEEPER_RENDER_OPERATION_HPP #ifndef ANTKEEPER_RENDER_OPERATION_HPP
#define ANTKEEPER_RENDER_OPERATION_HPP #define ANTKEEPER_RENDER_OPERATION_HPP
#include "utility/fundamental-types.hpp"
#include <cstdlib> #include <cstdlib>
#include <vmq/vmq.hpp>
class pose; class pose;
class material; class material;
class vertex_array; class vertex_array;
enum class drawing_mode; enum class drawing_mode;
using namespace vmq::types;
/** /**
* Describes a render operation with a single mesh and single material. * Describes a render operation with a single mesh and single material.

+ 13
- 14
src/renderer/renderer.cpp View File

@ -27,13 +27,12 @@
#include "scene/lod-group.hpp" #include "scene/lod-group.hpp"
#include "renderer/model.hpp" #include "renderer/model.hpp"
#include "rasterizer/drawing-mode.hpp" #include "rasterizer/drawing-mode.hpp"
#include "math/math.hpp"
#include "geometry/projection.hpp"
#include "configuration.hpp" #include "configuration.hpp"
#include "math.hpp"
#include <functional> #include <functional>
#include <set> #include <set>
using namespace vmq::operators;
renderer::renderer() renderer::renderer()
{ {
// Setup billboard render operation // 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.drawing_mode = group->get_drawing_mode();
operation.start_index = group->get_start_index(); operation.start_index = group->get_start_index();
operation.index_count = group->get_index_count(); 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(); operation.instance_count = model_instance->get_instance_count();
context.operations.push_back(operation); 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)) if (!context.camera_culling_volume->intersects(*object_culling_volume))
return; return;
transform<float> billboard_transform = billboard->get_transform_tween().interpolate(context.alpha);
math::transform<float> billboard_transform = billboard->get_transform_tween().interpolate(context.alpha);
billboard_op.material = billboard->get_material(); 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 // Align billboard
if (billboard->get_billboard_type() == billboard_type::spherical) 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) else if (billboard->get_billboard_type() == billboard_type::cylindrical)
{ {
const float3& alignment_axis = billboard->get_alignment_axis(); 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); context.operations.push_back(billboard_op);
} }

+ 1
- 3
src/renderer/simple-render-pass.cpp View File

@ -33,11 +33,9 @@
#include "renderer/render-context.hpp" #include "renderer/render-context.hpp"
#include "renderer/material.hpp" #include "renderer/material.hpp"
#include "renderer/material-property.hpp" #include "renderer/material-property.hpp"
#include <vmq/vmq.hpp>
#include "math/math.hpp"
#include <glad/glad.h> #include <glad/glad.h>
using namespace vmq;
simple_render_pass::simple_render_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, ::shader_program* shader_program): simple_render_pass::simple_render_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, ::shader_program* shader_program):
render_pass(rasterizer, framebuffer), render_pass(rasterizer, framebuffer),
shader_program(shader_program), shader_program(shader_program),

+ 1
- 3
src/renderer/simple-render-pass.hpp View File

@ -22,9 +22,7 @@
#include "renderer/render-pass.hpp" #include "renderer/render-pass.hpp"
#include "animation/tween.hpp" #include "animation/tween.hpp"
#include <vmq/vmq.hpp>
using namespace vmq::types;
#include "utility/fundamental-types.hpp"
class shader_program; class shader_program;
class shader_input; class shader_input;

+ 1
- 0
src/resources/material-loader.cpp View File

@ -24,6 +24,7 @@
#include "rasterizer/texture-wrapping.hpp" #include "rasterizer/texture-wrapping.hpp"
#include "rasterizer/texture-filter.hpp" #include "rasterizer/texture-filter.hpp"
#include "rasterizer/texture-2d.hpp" #include "rasterizer/texture-2d.hpp"
#include "utility/fundamental-types.hpp"
#include "string-table.hpp" #include "string-table.hpp"
#include <cctype> #include <cctype>
#include <vector> #include <vector>

+ 1
- 0
src/resources/mesh-loader.cpp View File

@ -20,6 +20,7 @@
#include "resources/resource-loader.hpp" #include "resources/resource-loader.hpp"
#include "geometry/mesh.hpp" #include "geometry/mesh.hpp"
#include "geometry/mesh-functions.hpp" #include "geometry/mesh-functions.hpp"
#include "utility/fundamental-types.hpp"
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
#include <physfs.h> #include <physfs.h>

+ 1
- 3
src/resources/model-loader.cpp View File

@ -23,13 +23,11 @@
#include "renderer/vertex-attributes.hpp" #include "renderer/vertex-attributes.hpp"
#include "rasterizer/vertex-attribute-type.hpp" #include "rasterizer/vertex-attribute-type.hpp"
#include "rasterizer/drawing-mode.hpp" #include "rasterizer/drawing-mode.hpp"
#include "utility/fundamental-types.hpp"
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
#include <limits> #include <limits>
#include <physfs.h> #include <physfs.h>
#include <vmq/vmq.hpp>
using namespace vmq::types;
struct material_group struct material_group
{ {

+ 1
- 0
src/scene/billboard.hpp View File

@ -22,6 +22,7 @@
#include "scene/scene-object.hpp" #include "scene/scene-object.hpp"
#include "geometry/aabb.hpp" #include "geometry/aabb.hpp"
#include "utility/fundamental-types.hpp"
class material; class material;

+ 23
- 23
src/scene/camera.cpp View File

@ -20,22 +20,22 @@
#include "scene/camera.hpp" #include "scene/camera.hpp"
#include "configuration.hpp" #include "configuration.hpp"
#include "animation/ease.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) static float4x4 interpolate_view(const camera* camera, const float4x4& x, const float4x4& y, float a)
{ {
transform<float> transform = camera->get_transform_tween().interpolate(a);
math::transform<float> transform = camera->get_transform_tween().interpolate(a);
float3 forward = transform.rotation * global_forward; float3 forward = transform.rotation * global_forward;
float3 up = transform.rotation * global_up; 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) static float4x4 interpolate_projection(const camera* camera, const float4x4& x, const float4x4& y, float a)
{ {
if (camera->is_orthographic()) if (camera->is_orthographic())
{ {
return vmq::ortho(
return math::ortho(
camera->get_clip_left_tween().interpolate(a), camera->get_clip_left_tween().interpolate(a),
camera->get_clip_right_tween().interpolate(a), camera->get_clip_right_tween().interpolate(a),
camera->get_clip_bottom_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 else
{ {
return vmq::perspective(
return math::perspective(
camera->get_fov_tween().interpolate(a), camera->get_fov_tween().interpolate(a),
camera->get_aspect_ratio_tween().interpolate(a), camera->get_aspect_ratio_tween().interpolate(a),
camera->get_clip_near_tween().interpolate(a), camera->get_clip_near_tween().interpolate(a),
@ -62,17 +62,17 @@ camera::camera():
compositor(nullptr), compositor(nullptr),
composite_index(0), composite_index(0),
orthographic(true), orthographic(true),
clip_left(-1.0f, ease<float>::linear),
clip_right(1.0f, ease<float>::linear),
clip_bottom(-1.0f, ease<float>::linear),
clip_top(1.0f, ease<float>::linear),
clip_near(-1.0f, ease<float>::linear),
clip_far(1.0f, ease<float>::linear),
fov(vmq::half_pi<float>, ease<float>::linear),
aspect_ratio(1.0f, ease<float>::linear),
view(vmq::identity4x4<float>, std::bind(&interpolate_view, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)),
projection(vmq::identity4x4<float>, std::bind(&interpolate_projection, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)),
view_projection(vmq::identity4x4<float>, std::bind(&interpolate_view_projection, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3))
clip_left(-1.0f, math::lerp<float, float>),
clip_right(1.0f, math::lerp<float, float>),
clip_bottom(-1.0f, math::lerp<float, float>),
clip_top(1.0f, math::lerp<float, float>),
clip_near(-1.0f, math::lerp<float, float>),
clip_far(1.0f, math::lerp<float, float>),
fov(math::half_pi<float>, math::lerp<float, float>),
aspect_ratio(1.0f, math::lerp<float, float>),
view(math::identity4x4<float>, std::bind(&interpolate_view, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)),
projection(math::identity4x4<float>, std::bind(&interpolate_projection, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)),
view_projection(math::identity4x4<float>, 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 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[0] = result[0] * viewport[2] + viewport[0];
result[1] = result[1] * viewport[3] + viewport[1]; 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 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[2] = window[2] * 2.0f - 1.0f;
result[3] = 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) 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_near[1] = clip_near;
this->clip_far[1] = clip_far; 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 // Recalculate view-projection matrix
view_projection[1] = projection[1] * view[1]; 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_near[1] = clip_near;
this->clip_far[1] = clip_far; 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 // Recalculate view-projection matrix
view_projection[1] = projection[1] * view[1]; view_projection[1] = projection[1] * view[1];
@ -170,7 +170,7 @@ void camera::transformed()
// Recalculate view and view-projection matrices // Recalculate view and view-projection matrices
float3 forward = get_rotation() * global_forward; float3 forward = get_rotation() * global_forward;
float3 up = get_rotation() * global_up; 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]; view_projection[1] = projection[1] * view[1];
// Recalculate view frustum // Recalculate view frustum

+ 1
- 0
src/scene/camera.hpp View File

@ -22,6 +22,7 @@
#include "scene/scene-object.hpp" #include "scene/scene-object.hpp"
#include "geometry/view-frustum.hpp" #include "geometry/view-frustum.hpp"
#include "utility/fundamental-types.hpp"
class compositor; class compositor;

+ 5
- 6
src/scene/directional-light.cpp View File

@ -19,14 +19,13 @@
#include "directional-light.hpp" #include "directional-light.hpp"
#include "configuration.hpp" #include "configuration.hpp"
using namespace vmq::operators;
#include "math/math.hpp"
static float3 interpolate_direction(const float3& x, const float3& y, float a) static float3 interpolate_direction(const float3& x, const float3& y, float a)
{ {
quaternion<float> q0 = vmq::rotation(global_forward, x);
quaternion<float> q1 = vmq::rotation(global_forward, y);
return vmq::normalize(vmq::slerp(q0, q1, a) * global_forward);
math::quaternion<float> q0 = math::rotation(global_forward, x);
math::quaternion<float> q1 = math::rotation(global_forward, y);
return math::normalize(math::slerp(q0, q1, a) * global_forward);
} }
directional_light::directional_light(): directional_light::directional_light():
@ -41,6 +40,6 @@ void directional_light::update_tweens()
void directional_light::transformed() void directional_light::transformed()
{ {
direction[1] = vmq::normalize(get_transform().rotation * global_forward);
direction[1] = math::normalize(get_transform().rotation * global_forward);
} }

+ 1
- 3
src/scene/directional-light.hpp View File

@ -21,9 +21,7 @@
#define ANTKEEPER_DIRECTIONAL_LIGHT_HPP #define ANTKEEPER_DIRECTIONAL_LIGHT_HPP
#include "scene/light.hpp" #include "scene/light.hpp"
#include <vmq/vmq.hpp>
using namespace vmq::types;
#include "utility/fundamental-types.hpp"
class directional_light: public light class directional_light: public light
{ {

+ 4
- 5
src/scene/light.cpp View File

@ -19,14 +19,13 @@
#include "scene/light.hpp" #include "scene/light.hpp"
#include "animation/ease.hpp" #include "animation/ease.hpp"
using namespace vmq::operators;
#include "math/interpolation.hpp"
light::light(): light::light():
bounds(get_translation(), 0.0f), bounds(get_translation(), 0.0f),
color(float3{1.0f, 1.0f, 1.0f}, ease<float3>::linear),
intensity(1.0f, ease<float>::linear),
scaled_color(float3{1.0f, 1.0f, 1.0f}, ease<float3>::linear)
color(float3{1.0f, 1.0f, 1.0f}, math::lerp<float3, float>),
intensity(1.0f, math::lerp<float, float>),
scaled_color(float3{1.0f, 1.0f, 1.0f}, math::lerp<float3, float>)
{} {}
void light::set_color(const float3& color) void light::set_color(const float3& color)

+ 1
- 0
src/scene/light.hpp View File

@ -22,6 +22,7 @@
#include "scene/scene-object.hpp" #include "scene/scene-object.hpp"
#include "geometry/sphere.hpp" #include "geometry/sphere.hpp"
#include "utility/fundamental-types.hpp"
enum class light_type enum class light_type
{ {

+ 1
- 1
src/scene/lod-group.cpp View File

@ -37,7 +37,7 @@ void lod_group::resize(std::size_t level_count)
std::size_t lod_group::select_lod(const ::camera& camera) const 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) if (distance < 300.0f)
return 0; return 0;

+ 2
- 5
src/scene/point-light.cpp View File

@ -18,12 +18,10 @@
*/ */
#include "point-light.hpp" #include "point-light.hpp"
#include "animation/ease.hpp"
using namespace vmq::operators;
#include "math/interpolation.hpp"
point_light::point_light(): point_light::point_light():
attenuation(float3{1, 0, 0}, ease<float3>::linear)
attenuation(float3{1, 0, 0}, math::lerp<float3, float>)
{} {}
void point_light::set_attenuation(const float3& attenuation) void point_light::set_attenuation(const float3& attenuation)
@ -36,4 +34,3 @@ void point_light::update_tweens()
light::update_tweens(); light::update_tweens();
attenuation.update(); attenuation.update();
} }

+ 1
- 0
src/scene/point-light.hpp View File

@ -21,6 +21,7 @@
#define ANTKEEPER_POINT_LIGHT_HPP #define ANTKEEPER_POINT_LIGHT_HPP
#include "scene/light.hpp" #include "scene/light.hpp"
#include "utility/fundamental-types.hpp"
class point_light: public light class point_light: public light
{ {

+ 9
- 8
src/scene/scene-object.cpp View File

@ -18,24 +18,25 @@
*/ */
#include "scene/scene-object.hpp" #include "scene/scene-object.hpp"
#include "math/math.hpp"
static transform<float> transform_interpolate(const transform<float>& x, const transform<float>& 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 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(): scene_object_base::scene_object_base():
active(true), active(true),
transform(vmq::identity_transform<float>, transform_interpolate),
transform(math::identity_transform<float>, interpolate_transforms),
culling_mask(nullptr) culling_mask(nullptr)
{} {}
void scene_object_base::set_culling_mask(const bounding_volume<float>* culling_mask)
void scene_object_base::set_culling_mask(const bounding_volume_type* culling_mask)
{ {
this->culling_mask = culling_mask; this->culling_mask = culling_mask;
} }
@ -51,10 +52,10 @@ void scene_object_base::update_tweens()
transform.update(); 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].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(); transformed();
} }

+ 40
- 34
src/scene/scene-object.hpp View File

@ -20,15 +20,13 @@
#ifndef ANTKEEPER_SCENE_OBJECT_HPP #ifndef ANTKEEPER_SCENE_OBJECT_HPP
#define ANTKEEPER_SCENE_OBJECT_HPP #define ANTKEEPER_SCENE_OBJECT_HPP
#include <atomic>
#include <cstdlib>
#include <vmq/vmq.hpp>
#include "animation/tween.hpp" #include "animation/tween.hpp"
#include "geometry/bounding-volume.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 <atomic>
#include <cstdlib>
/** /**
* Internal base class for scene objects. * Internal base class for scene objects.
@ -36,6 +34,11 @@ using vmq::transform;
class scene_object_base class scene_object_base
{ {
public: public:
typedef math::vector<float, 3> vector_type;
typedef math::quaternion<float> quaternion_type;
typedef math::transform<float> transform_type;
typedef bounding_volume<float> bounding_volume_type;
/// Returns the type ID for this scene object type. /// Returns the type ID for this scene object type.
virtual const std::size_t get_object_type_id() const = 0; 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. * Sets the scene object's transform.
*/ */
void set_transform(const transform<float>& transform);
void set_transform(const transform_type& transform);
/** /**
* Sets the scene object's translation. * 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. * Sets the scene object's rotation.
*/ */
void set_rotation(const quaternion<float>& rotation);
void set_rotation(const quaternion_type& rotation);
/** /**
* Sets the scene object's scale. * 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. * 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<float>* culling_mask);
void set_culling_mask(const bounding_volume_type* culling_mask);
/// Returns whether the scene object is active. /// Returns whether the scene object is active.
bool is_active() const; bool is_active() const;
@ -95,51 +98,54 @@ public:
/** /**
* Returns the transform. * Returns the transform.
*/ */
const transform<float>& get_transform() const;
const transform_type& get_transform() const;
/** /**
* Returns the transform's translation vector. * Returns the transform's translation vector.
*/ */
const float3& get_translation() const;
const vector_type& get_translation() const;
/** /**
* Returns the transform's rotation quaternion. * Returns the transform's rotation quaternion.
*/ */
const quaternion<float>& get_rotation() const;
const quaternion_type& get_rotation() const;
/** /**
* Returns the transform's scale vector. * Returns the transform's scale vector.
*/ */
const float3& get_scale() const;
const vector_type& get_scale() const;
/** /**
* Returns the transform tween. * Returns the transform tween.
*/ */
const tween<transform<float>>& get_transform_tween() const;
tween<transform<float>>& get_transform_tween();
const tween<transform_type>& get_transform_tween() const;
tween<transform_type>& get_transform_tween();
/** /**
* Returns the bounds of the object. * Returns the bounds of the object.
*/ */
virtual const bounding_volume<float>& get_bounds() const = 0;
virtual const bounding_volume_type& get_bounds() const = 0;
/** /**
* Returns the culling mask of the object. * Returns the culling mask of the object.
*/ */
const bounding_volume<float>* get_culling_mask() const;
const bounding_volume_type* get_culling_mask() const;
protected: protected:
static std::size_t next_object_type_id(); static std::size_t next_object_type_id();
private: 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. * Called every time the scene object's tranform is changed.
*/ */
virtual void transformed(); virtual void transformed();
bool active; bool active;
tween<transform<float>> transform;
const bounding_volume<float>* culling_mask;
tween<transform_type> transform;
const bounding_volume_type* culling_mask;
}; };
inline void scene_object_base::set_active(bool active) 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; this->active = active;
} }
inline void scene_object_base::set_transform(const ::transform<float>& transform)
inline void scene_object_base::set_transform(const transform_type& transform)
{ {
this->transform[1] = transform; this->transform[1] = transform;
transformed(); 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; transform[1].translation = translation;
transformed(); transformed();
} }
inline void scene_object_base::set_rotation(const quaternion<float>& rotation)
inline void scene_object_base::set_rotation(const quaternion_type& rotation)
{ {
transform[1].rotation = rotation; transform[1].rotation = rotation;
transformed(); 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; transform[1].scale = scale;
transformed(); transformed();
@ -176,37 +182,37 @@ inline bool scene_object_base::is_active() const
return active; return active;
} }
inline const transform<float>& scene_object_base::get_transform() const
inline const typename scene_object_base::transform_type& scene_object_base::get_transform() const
{ {
return transform[1]; 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; return get_transform().translation;
} }
inline const quaternion<float>& scene_object_base::get_rotation() const
inline const typename scene_object_base::quaternion_type& scene_object_base::get_rotation() const
{ {
return get_transform().rotation; 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; return get_transform().scale;
} }
inline const tween<transform<float>>& scene_object_base::get_transform_tween() const
inline const tween<typename scene_object_base::transform_type>& scene_object_base::get_transform_tween() const
{ {
return transform; return transform;
} }
inline tween<transform<float>>& scene_object_base::get_transform_tween()
inline tween<typename scene_object_base::transform_type>& scene_object_base::get_transform_tween()
{ {
return transform; return transform;
} }
inline const bounding_volume<float>* 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; return culling_mask;
} }

+ 8
- 10
src/scene/spotlight.cpp View File

@ -19,23 +19,21 @@
#include "spotlight.hpp" #include "spotlight.hpp"
#include "configuration.hpp" #include "configuration.hpp"
#include "animation/ease.hpp"
#include "math/math.hpp"
#include <cmath> #include <cmath>
using namespace vmq::operators;
static float3 interpolate_direction(const float3& x, const float3& y, float a) static float3 interpolate_direction(const float3& x, const float3& y, float a)
{ {
quaternion<float> q0 = vmq::rotation(global_forward, x);
quaternion<float> q1 = vmq::rotation(global_forward, y);
return vmq::normalize(vmq::slerp(q0, q1, a) * global_forward);
math::quaternion<float> q0 = math::rotation(global_forward, x);
math::quaternion<float> q1 = math::rotation(global_forward, y);
return math::normalize(math::slerp(q0, q1, a) * global_forward);
} }
spotlight::spotlight(): spotlight::spotlight():
direction(global_forward, interpolate_direction), direction(global_forward, interpolate_direction),
attenuation(float3{1, 0, 0}, ease<float3>::linear),
cutoff(float2{vmq::pi<float>, vmq::pi<float>}, ease<float2>::linear),
cosine_cutoff(float2{std::cos(vmq::pi<float>), std::cos(vmq::pi<float>)}, ease<float2>::linear)
attenuation(float3{1, 0, 0}, math::lerp<float3, float>),
cutoff(float2{math::pi<float>, math::pi<float>}, math::lerp<float2, float>),
cosine_cutoff(float2{std::cos(math::pi<float>), std::cos(math::pi<float>)}, math::lerp<float2, float>)
{} {}
void spotlight::set_attenuation(const float3& attenuation) void spotlight::set_attenuation(const float3& attenuation)
@ -60,6 +58,6 @@ void spotlight::update_tweens()
void spotlight::transformed() void spotlight::transformed()
{ {
direction[1] = vmq::normalize(get_transform().rotation * global_forward);
direction[1] = math::normalize(get_transform().rotation * global_forward);
} }

+ 1
- 3
src/scene/spotlight.hpp View File

@ -21,9 +21,7 @@
#define ANTKEEPER_SPOTLIGHT_HPP #define ANTKEEPER_SPOTLIGHT_HPP
#include "scene/light.hpp" #include "scene/light.hpp"
#include <vmq/vmq.hpp>
using namespace vmq::types;
#include "utility/fundamental-types.hpp"
class spotlight: public light class spotlight: public light
{ {

+ 23
- 25
src/state/play-state.cpp View File

@ -39,13 +39,11 @@
#include "entity/archetype.hpp" #include "entity/archetype.hpp"
#include "entity/entity-commands.hpp" #include "entity/entity-commands.hpp"
#include "nest.hpp" #include "nest.hpp"
#include "math.hpp"
#include "math/math.hpp"
#include "utility/fundamental-types.hpp"
#include "geometry/mesh-accelerator.hpp" #include "geometry/mesh-accelerator.hpp"
#include "behavior/ebt.hpp" #include "behavior/ebt.hpp"
#include "animation/ease.hpp" #include "animation/ease.hpp"
#include <iostream>
using namespace vmq::operators;
void enter_play_state(application* app) void enter_play_state(application* app)
{ {
@ -92,15 +90,15 @@ void enter_play_state(application* app)
for (int i = 0; i < pebble_count; ++i) 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 pebble_entity = pebble_archetype->create(ecs_registry);
auto& transform = ecs_registry.get<ecs::transform_component>(pebble_entity); auto& transform = ecs_registry.get<ecs::transform_component>(pebble_entity);
transform.transform = vmq::identity_transform<float>;
transform.transform.rotation = vmq::angle_axis(frand(0.0f, vmq::two_pi<float>), {0, 1, 0});
transform.transform.scale = float3{1, 1, 1} * frand(0.75f, 1.25f);
transform.transform = math::identity_transform<float>;
transform.transform.rotation = math::angle_axis(math::random(0.0f, math::two_pi<float>), {0, 1, 0});
transform.transform.scale = float3{1, 1, 1} * math::random(0.75f, 1.25f);
placement.ray.origin = {x, 10000, z}; placement.ray.origin = {x, 10000, z};
ecs_registry.assign<ecs::placement_component>(pebble_entity, placement); ecs_registry.assign<ecs::placement_component>(pebble_entity, placement);
@ -133,15 +131,15 @@ void enter_play_state(application* app)
auto& transform = ecs_registry.get<ecs::transform_component>(samara_entity); auto& transform = ecs_registry.get<ecs::transform_component>(samara_entity);
float zone = 200.0f; float zone = 200.0f;
transform.transform = vmq::identity_transform<float>;
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<float>;
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; 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<ecs::samara_component>(samara_entity, samara_component); ecs_registry.assign_or_replace<ecs::samara_component>(samara_entity, samara_component);
} }
@ -150,7 +148,7 @@ void enter_play_state(application* app)
ecs::archetype* grass_archetype = resource_manager->load<ecs::archetype>("grassland-grass.ent"); ecs::archetype* grass_archetype = resource_manager->load<ecs::archetype>("grassland-grass.ent");
auto grass_entity_1 = grass_archetype->create(ecs_registry); auto grass_entity_1 = grass_archetype->create(ecs_registry);
auto grass_entity_2 = grass_archetype->create(ecs_registry); auto grass_entity_2 = grass_archetype->create(ecs_registry);
ecs_registry.get<ecs::transform_component>(grass_entity_2).transform.rotation = vmq::angle_axis(vmq::radians(120.0f), float3{0, 1, 0});
ecs_registry.get<ecs::transform_component>(grass_entity_2).transform.rotation = math::angle_axis(math::radians(120.0f), float3{0, 1, 0});
*/ */
// Setup overworld camera // Setup overworld camera
@ -159,7 +157,7 @@ void enter_play_state(application* app)
orbit_cam->attach(camera); orbit_cam->attach(camera);
orbit_cam->set_target_focal_point({0, 0, 0}); orbit_cam->set_target_focal_point({0, 0, 0});
orbit_cam->set_target_focal_distance(15.0f); 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_target_azimuth(0.0f);
orbit_cam->set_focal_point(orbit_cam->get_target_focal_point()); orbit_cam->set_focal_point(orbit_cam->get_target_focal_point());
orbit_cam->set_focal_distance(orbit_cam->get_target_focal_distance()); 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->set_tunnel_radius(tunnel_radius);
nest::shaft* central_shaft = nest->get_central_shaft(); nest::shaft* central_shaft = nest->get_central_shaft();
central_shaft->chirality = 1.0f; 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->depth = {0.0f, 200.0f};
central_shaft->radius = {15.0f, 15.0f}; central_shaft->radius = {15.0f, 15.0f};
central_shaft->pitch = {40.0f, 40.0f}; central_shaft->pitch = {40.0f, 40.0f};
@ -196,7 +194,7 @@ void enter_play_state(application* app)
nest::chamber chamber; nest::chamber chamber;
chamber.shaft = central_shaft; chamber.shaft = central_shaft;
chamber.depth = (i + 1) * 50.0f; chamber.depth = (i + 1) * 50.0f;
chamber.rotation = vmq::radians(0.0f);
chamber.rotation = math::radians(0.0f);
chamber.inner_radius = 4.0f; chamber.inner_radius = 4.0f;
chamber.outer_radius = 10.0f; chamber.outer_radius = 10.0f;
central_shaft->chambers.push_back(chamber); central_shaft->chambers.push_back(chamber);
@ -208,8 +206,8 @@ void enter_play_state(application* app)
{ {
ecs::cavity_component cavity; ecs::cavity_component cavity;
cavity.position = nest->extend_shaft(*nest->get_central_shaft()); 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::cavity_component>(ecs_registry.create(), cavity); ecs_registry.assign<ecs::cavity_component>(ecs_registry.create(), cavity);
} }
@ -222,8 +220,8 @@ void enter_play_state(application* app)
{ {
ecs::cavity_component cavity; ecs::cavity_component cavity;
cavity.position = nest->expand_chamber(central_shaft->chambers[i]); 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::cavity_component>(ecs_registry.create(), cavity); ecs_registry.assign<ecs::cavity_component>(ecs_registry.create(), cavity);
} }
@ -236,7 +234,7 @@ void enter_play_state(application* app)
ecs::assign_render_layers(ecs_registry, larva, 1); ecs::assign_render_layers(ecs_registry, larva, 1);
//ecs::warp_to(ecs_registry, larva, {0, -20, 0}); //ecs::warp_to(ecs_registry, larva, {0, -20, 0});
//auto& transform = ecs_registry.get<ecs::transform_component>(larva_entity); //auto& transform = ecs_registry.get<ecs::transform_component>(larva_entity);
//transform.transform = vmq::identity_transform<float>;
//transform.transform = math::identity_transform<float>;
//transform.transform.translation = nest->get_shaft_position(*central_shaft, central_shaft->depth[1]); //transform.transform.translation = nest->get_shaft_position(*central_shaft, central_shaft->depth[1]);
//transform.transform.translation.y -= 1.0f; //transform.transform.translation.y -= 1.0f;
} }

+ 3
- 4
src/systems/camera-system.cpp View File

@ -25,9 +25,8 @@
#include "orbit-cam.hpp" #include "orbit-cam.hpp"
#include "geometry/mesh.hpp" #include "geometry/mesh.hpp"
#include "geometry/intersection.hpp" #include "geometry/intersection.hpp"
#include <vmq/vmq.hpp>
#include "math/math.hpp"
using namespace vmq::operators;
using namespace ecs; using namespace ecs;
camera_system::camera_system(entt::registry& registry): camera_system::camera_system(entt::registry& registry):
@ -74,9 +73,9 @@ void camera_system::update(double t, double dt)
registry.view<transform_component, collision_component>().each( registry.view<transform_component, collision_component>().each(
[&](auto entity, auto& transform, auto& collision) [&](auto entity, auto& transform, auto& collision)
{ {
vmq::transform<float> inverse_transform = vmq::inverse(transform.transform);
math::transform<float> inverse_transform = math::inverse(transform.transform);
float3 origin = inverse_transform * pick_origin; 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<float> transformed_ray = {origin, direction}; ray<float> transformed_ray = {origin, direction};
// Broad phase AABB test // Broad phase AABB test

+ 1
- 2
src/systems/camera-system.hpp View File

@ -23,8 +23,7 @@
#include "entity-system.hpp" #include "entity-system.hpp"
#include "event/event-handler.hpp" #include "event/event-handler.hpp"
#include "input/input-events.hpp" #include "input/input-events.hpp"
#include <vmq/vmq.hpp>
using namespace vmq::types;
#include "utility/fundamental-types.hpp"
class camera; class camera;
class orbit_cam; class orbit_cam;

+ 1
- 1
src/systems/constraint-system.cpp View File

@ -23,9 +23,9 @@
#include "entity/components/copy-scale-component.hpp" #include "entity/components/copy-scale-component.hpp"
#include "entity/components/copy-transform-component.hpp" #include "entity/components/copy-transform-component.hpp"
#include "entity/components/transform-component.hpp" #include "entity/components/transform-component.hpp"
#include "utility/fundamental-types.hpp"
using namespace ecs; using namespace ecs;
using namespace vmq;
constraint_system::constraint_system(entt::registry& registry): constraint_system::constraint_system(entt::registry& registry):
entity_system(registry) entity_system(registry)

+ 21
- 23
src/systems/control-system.cpp View File

@ -24,9 +24,7 @@
#include "geometry/intersection.hpp" #include "geometry/intersection.hpp"
#include "animation/ease.hpp" #include "animation/ease.hpp"
#include "nest.hpp" #include "nest.hpp"
#include <vmq/vmq.hpp>
using namespace vmq::operators;
#include "math/math.hpp"
control_system::control_system(): control_system::control_system():
timestep(0.0f), timestep(0.0f),
@ -60,14 +58,14 @@ control_system::control_system():
} }
zoom_speed = 4.0f; //1 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; near_focal_distance = 2.0f;
far_focal_distance = 200.0f; far_focal_distance = 200.0f;
near_movement_speed = 10.0f; near_movement_speed = 10.0f;
far_movement_speed = 80.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; near_clip_near = 0.1f;
far_clip_near = 5.0f; far_clip_near = 5.0f;
near_clip_far = 100.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 -= zoom_speed * dt * zoom_out_control.get_current_value();
zoom = std::max<float>(0.0f, std::min<float>(1.0f, zoom)); zoom = std::max<float>(0.0f, std::min<float>(1.0f, zoom));
float focal_distance = ease<float>::log(near_focal_distance, far_focal_distance, 1.0f - zoom);
float focal_distance = math::log_lerp<float>(near_focal_distance, far_focal_distance, 1.0f - zoom);
float fov = ease<float>::log(near_fov, far_fov, 1.0f - zoom);
float fov = math::log_lerp<float>(near_fov, far_fov, 1.0f - zoom);
//float elevation_factor = (orbit_cam->get_target_elevation() - min_elevation) / max_elevation; //float elevation_factor = (orbit_cam->get_target_elevation() - min_elevation) / max_elevation;
//fov = ease<float>::log(near_fov, far_fov, elevation_factor);
float clip_near = ease<float>::log(near_clip_near, far_clip_near, 1.0f - zoom);
float clip_far = ease<float>::log(near_clip_far, far_clip_far, 1.0f - zoom);
float movement_speed = ease<float>::log(near_movement_speed * dt, far_movement_speed * dt, 1.0f - zoom);
//fov = math::log_lerp<float>(near_fov, far_fov, elevation_factor);
float clip_near = math::log_lerp<float>(near_clip_near, far_clip_near, 1.0f - zoom);
float clip_far = math::log_lerp<float>(near_clip_far, far_clip_far, 1.0f - zoom);
float movement_speed = math::log_lerp<float>(near_movement_speed * dt, far_movement_speed * dt, 1.0f - zoom);
orbit_cam->set_target_focal_distance(focal_distance); 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); 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(); movement[1] += move_back_control.get_current_value();
const float deadzone = 0.01f; 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 > deadzone)
{ {
if (magnitude_squared > 1.0f) if (magnitude_squared > 1.0f)
{ {
movement = vmq::normalize(movement);
movement = math::normalize(movement);
} }
orbit_cam->move(movement * movement_speed); 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_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_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<float> picking_ray = {pick_near, pick_direction}; ray<float> picking_ray = {pick_near, pick_direction};
plane<float> ground_plane = {float3{0, 1, 0}, 0.0f}; plane<float> 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 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; old_mouse_angle = mouse_angle;
mouse_angle = std::atan2(-mouse_direction.y, mouse_direction.x); 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<float>)
if (mouse_angle - old_mouse_angle <= -math::pi<float>)
flashlight_turns_i -= 1; flashlight_turns_i -= 1;
else if (mouse_angle - old_mouse_angle >= vmq::pi<float>)
else if (mouse_angle - old_mouse_angle >= math::pi<float>)
flashlight_turns_i += 1; flashlight_turns_i += 1;
flashlight_turns_f = (mouse_angle) / vmq::two_pi<float>;
flashlight_turns_f = (mouse_angle) / math::two_pi<float>;
flashlight_turns = flashlight_turns_i - flashlight_turns_f; flashlight_turns = flashlight_turns_i - flashlight_turns_f;
if (flashlight && nest) if (flashlight && nest)
{ {
transform<float> flashlight_transform = vmq::identity_transform<float>;
math::transform<float> flashlight_transform = math::identity_transform<float>;
float flashlight_depth = nest->get_shaft_depth(*nest->get_central_shaft(), flashlight_turns); float flashlight_depth = nest->get_shaft_depth(*nest->get_central_shaft(), flashlight_turns);
flashlight_transform.translation = {0.0f, -flashlight_depth, 0.0f}; flashlight_transform.translation = {0.0f, -flashlight_depth, 0.0f};
flashlight_transform.rotation = vmq::angle_axis(-flashlight_turns * vmq::two_pi<float> + vmq::half_pi<float>, {0, 1, 0});
flashlight_transform.rotation = math::angle_axis(-flashlight_turns * math::two_pi<float> + math::half_pi<float>, {0, 1, 0});
flashlight->set_transform(flashlight_transform); flashlight->set_transform(flashlight_transform);
flashlight_light_cone->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; 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; float elevation = orbit_cam->get_target_elevation() + elevation_factor * 0.25f * timestep;
elevation = std::min<float>(max_elevation, std::max<float>(min_elevation, elevation)); elevation = std::min<float>(max_elevation, std::max<float>(min_elevation, elevation));

+ 1
- 0
src/systems/control-system.hpp View File

@ -25,6 +25,7 @@
#include "input/control.hpp" #include "input/control.hpp"
#include "input/control-set.hpp" #include "input/control-set.hpp"
#include "scene/model-instance.hpp" #include "scene/model-instance.hpp"
#include "utility/fundamental-types.hpp"
class orbit_cam; class orbit_cam;
class nest; class nest;

+ 3
- 2
src/systems/nest-system.cpp View File

@ -19,6 +19,7 @@
#include "nest-system.hpp" #include "nest-system.hpp"
#include "nest.hpp" #include "nest.hpp"
#include "math/math.hpp"
using namespace ecs; 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->set_tunnel_radius(1.15f);
nest::shaft* central_shaft = nest->get_central_shaft(); nest::shaft* central_shaft = nest->get_central_shaft();
central_shaft->chirality = -1.0f; 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->depth = {0.0f, 100.0f};
central_shaft->current_depth = 0.0f; central_shaft->current_depth = 0.0f;
central_shaft->radius = {0.0f, 5.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; nest::chamber chamber;
chamber.shaft = central_shaft; chamber.shaft = central_shaft;
chamber.depth = (i + 1) * 23.0f; chamber.depth = (i + 1) * 23.0f;
chamber.rotation = vmq::radians(0.0f);
chamber.rotation = math::radians(0.0f);
chamber.inner_radius = 4.0f; chamber.inner_radius = 4.0f;
chamber.outer_radius = 10.0f; chamber.outer_radius = 10.0f;
central_shaft->chambers.push_back(chamber); central_shaft->chambers.push_back(chamber);

+ 3
- 2
src/systems/placement-system.cpp View File

@ -22,6 +22,7 @@
#include "entity/components/placement-component.hpp" #include "entity/components/placement-component.hpp"
#include "entity/components/transform-component.hpp" #include "entity/components/transform-component.hpp"
#include "entity/components/terrain-component.hpp" #include "entity/components/terrain-component.hpp"
#include "utility/fundamental-types.hpp"
using namespace ecs; using namespace ecs;
@ -42,9 +43,9 @@ void placement_system::update(double t, double dt)
[&](auto entity, auto& transform, auto& collision) [&](auto entity, auto& transform, auto& collision)
{ {
// Transform ray into local space of collision component // Transform ray into local space of collision component
vmq::transform<float> inverse_transform = vmq::inverse(transform.transform);
math::transform<float> inverse_transform = math::inverse(transform.transform);
float3 origin = inverse_transform * placement.ray.origin; 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<float> transformed_ray = {origin, direction}; ray<float> transformed_ray = {origin, direction};
// Broad phase AABB test // Broad phase AABB test

+ 10
- 10
src/systems/samara-system.cpp View File

@ -20,9 +20,9 @@
#include "samara-system.hpp" #include "samara-system.hpp"
#include "entity/components/transform-component.hpp" #include "entity/components/transform-component.hpp"
#include "entity/components/samara-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; using namespace ecs;
samara_system::samara_system(entt::registry& registry): samara_system::samara_system(entt::registry& registry):
@ -34,23 +34,23 @@ void samara_system::update(double t, double dt)
registry.view<samara_component, transform_component>().each( registry.view<samara_component, transform_component>().each(
[&](auto entity, auto& samara, auto& transform) [&](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.translation += samara.direction * 20.0f * (float)dt;
transform.transform.rotation = 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<float>{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<float>{1, 0, 0, 0});
if (transform.transform.translation.y < 0.0f) if (transform.transform.translation.y < 0.0f)
{ {
const float zone = 200.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; 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;
} }
}); });
} }

+ 6
- 8
src/systems/subterrain-system.cpp View File

@ -32,15 +32,13 @@
#include "geometry/intersection.hpp" #include "geometry/intersection.hpp"
#include "scene/scene.hpp" #include "scene/scene.hpp"
#include "scene/model-instance.hpp" #include "scene/model-instance.hpp"
#include "math.hpp"
using namespace vmq::operators;
using namespace ecs;
#include "utility/fundamental-types.hpp"
#include <array> #include <array>
#include <iostream> #include <iostream>
#include <limits> #include <limits>
using namespace ecs;
/** /**
* An octree containing cubes for the marching cubes algorithm. * An octree containing cubes for the marching cubes algorithm.
*/ */
@ -422,7 +420,7 @@ void subterrain_system::regenerate_subterrain_model()
edge = edge->previous->symmetric; edge = edge->previous->symmetric;
} }
while (edge != start); while (edge != start);
n = vmq::normalize(n);
n = math::normalize(n);
//float3 n = reinterpret_cast<const float3&>(face_normals[i * 3]); //float3 n = reinterpret_cast<const float3&>(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 (int i = 0; i < 8; ++i)
{ {
// For outside normals (also set node initial distance to +infinity) // 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]) // 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]) if (distance > node.distances[i])
node.distances[i] = distance; node.distances[i] = distance;
} }

+ 3
- 4
src/systems/subterrain-system.hpp View File

@ -23,6 +23,7 @@
#include "entity-system.hpp" #include "entity-system.hpp"
#include "geometry/mesh.hpp" #include "geometry/mesh.hpp"
#include "geometry/aabb.hpp" #include "geometry/aabb.hpp"
#include "utility/fundamental-types.hpp"
#include <unordered_map> #include <unordered_map>
class resource_manager; class resource_manager;
@ -33,8 +34,6 @@ struct cube_tree;
class scene; class scene;
class model_instance; class model_instance;
using namespace vmq::types;
template <std::int64_t Mantissa, std::int64_t Exponent> template <std::int64_t Mantissa, std::int64_t Exponent>
struct epsilon struct epsilon
{ {
@ -49,7 +48,7 @@ typedef epsilon<1, -5> epsilon_1en5;
template <class Epsilon, class T, std::size_t N> template <class Epsilon, class T, std::size_t N>
struct vector_hasher struct vector_hasher
{ {
typedef vmq::vector<T, N> vector_type;
typedef math::vector<T, N> vector_type;
std::size_t operator()(const vector_type& v) const noexcept std::size_t operator()(const vector_type& v) const noexcept
{ {
@ -69,7 +68,7 @@ struct vector_hasher
template <class Epsilon, class T, std::size_t N> template <class Epsilon, class T, std::size_t N>
struct vector_equals struct vector_equals
{ {
typedef vmq::vector<T, N> vector_type;
typedef math::vector<T, N> vector_type;
bool operator()(const vector_type& a, const vector_type& b) const noexcept bool operator()(const vector_type& a, const vector_type& b) const noexcept
{ {

+ 3
- 3
src/systems/terrain-system.cpp View File

@ -30,9 +30,9 @@
#include "rasterizer/vertex-buffer.hpp" #include "rasterizer/vertex-buffer.hpp"
#include "resources/resource-manager.hpp" #include "resources/resource-manager.hpp"
#include "resources/image.hpp" #include "resources/image.hpp"
#include "utility/fundamental-types.hpp"
#include <limits> #include <limits>
using namespace vmq::operators;
using namespace ecs; using namespace ecs;
terrain_system::terrain_system(entt::registry& registry, ::resource_manager* resource_manager): 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; edge = edge->previous->symmetric;
} }
while (edge != start); while (edge != start);
n = vmq::normalize(n);
n = math::normalize(n);
*(v++) = vertex->position[0]; *(v++) = vertex->position[0];
*(v++) = vertex->position[1]; *(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 // Assign the entity a transform component
transform_component transform; transform_component transform;
transform.transform = vmq::identity_transform<float>;
transform.transform = math::identity_transform<float>;
transform.transform.translation = float3{(float)component.x * patch_size, 0.0f, (float)component.z * patch_size}; transform.transform.translation = float3{(float)component.x * patch_size, 0.0f, (float)component.z * patch_size};
transform.warp = true; transform.warp = true;
registry.assign_or_replace<transform_component>(entity, transform); registry.assign_or_replace<transform_component>(entity, transform);

+ 10
- 12
src/systems/tool-system.cpp View File

@ -25,9 +25,8 @@
#include "orbit-cam.hpp" #include "orbit-cam.hpp"
#include "geometry/mesh.hpp" #include "geometry/mesh.hpp"
#include "geometry/intersection.hpp" #include "geometry/intersection.hpp"
#include <vmq/vmq.hpp>
#include "math/math.hpp"
using namespace vmq::operators;
using namespace ecs; using namespace ecs;
tool_system::tool_system(entt::registry& registry): 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_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_far = camera->unproject({mouse_position[0], viewport[3] - mouse_position[1], 1.0f}, viewport);
float3 pick_origin = pick_near; float3 pick_origin = pick_near;
float3 pick_direction = vmq::normalize(pick_far - pick_near);
float3 pick_direction = math::normalize(pick_far - pick_near);
ray<float> picking_ray = {pick_near, pick_direction}; ray<float> picking_ray = {pick_near, pick_direction};
float a = std::numeric_limits<float>::infinity(); float a = std::numeric_limits<float>::infinity();
@ -58,9 +57,9 @@ void tool_system::update(double t, double dt)
registry.view<transform_component, collision_component>().each( registry.view<transform_component, collision_component>().each(
[&](auto entity, auto& transform, auto& collision) [&](auto entity, auto& transform, auto& collision)
{ {
vmq::transform<float> inverse_transform = vmq::inverse(transform.transform);
math::transform<float> inverse_transform = math::inverse(transform.transform);
float3 origin = inverse_transform * pick_origin; 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<float> transformed_ray = {origin, direction}; ray<float> transformed_ray = {origin, direction};
// Broad phase AABB test // 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}; float3 camera_planar_position = float3{camera_position.x, 0, camera_position.z};
float pick_angle = 0.0f; 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_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; pick_angle = -pick_angle;
} }
@ -110,7 +109,7 @@ void tool_system::update(double t, double dt)
transform.transform.translation = pick; transform.transform.translation = pick;
} }
vmq::quaternion<float> rotation = vmq::angle_axis(orbit_cam->get_azimuth() + pick_angle, float3{0, 1, 0});
math::quaternion<float> rotation = math::angle_axis(orbit_cam->get_azimuth() + pick_angle, float3{0, 1, 0});
transform.transform.rotation = rotation; transform.transform.rotation = rotation;
}); });
} }
@ -143,4 +142,3 @@ void tool_system::handle_event(const mouse_moved_event& event)
mouse_position[1] = event.y; mouse_position[1] = event.y;
} }
} }

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save