Mathter
A configurable 3D math library for game developers.
ViewBuilder.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 
4 #include "../Matrix/MatrixImpl.hpp"
5 #include "../Vector.hpp"
6 
7 
8 namespace mathter {
9 
10 
11 template <class T, int Dim, bool Packed>
12 class ViewBuilder {
14 
15 public:
16  ViewBuilder(const VectorT& eye, const VectorT& target, const std::array<VectorT, size_t(Dim - 2)>& bases, const std::array<bool, Dim>& flipAxes)
17  : eye(eye), target(target), bases(bases), flipAxes(flipAxes) {}
18  ViewBuilder& operator=(const ViewBuilder&) = delete;
19 
20  template <class U, eMatrixOrder Order, eMatrixLayout Layout, bool MPacked>
23  Set(m);
24  return m;
25  }
26 
27  template <class U, eMatrixLayout Layout, bool MPacked>
30  Set(m);
31  return m;
32  }
33 
34  template <class U, eMatrixLayout Layout, bool MPacked>
37  Set(m);
38  return m;
39  }
40 
41 
42 private:
43  template <class U, int Rows, int Columns, eMatrixOrder Order, eMatrixLayout Layout, bool MPacked>
44  void Set(Matrix<U, Rows, Columns, Order, Layout, MPacked>& matrix) const {
45  VectorT columns[Dim];
46  std::array<const VectorT*, Dim - 1> crossTable = {};
47  for (int i = 0; i < (int)bases.size(); ++i) {
48  crossTable[i] = &bases[i];
49  }
50  crossTable.back() = &columns[Dim - 1];
51  auto elem = [&matrix](int i, int j) -> T& {
52  return Order == eMatrixOrder::FOLLOW_VECTOR ? matrix(i, j) : matrix(j, i);
53  };
54 
55  // calculate columns of the rotation matrix
56  int j = Dim - 1;
57  columns[j] = Normalize(eye - target); // right-handed: camera look towards -Z
58  do {
59  --j;
60 
61  columns[Dim - j - 2] = Normalize(Cross(crossTable));
62 
63  // shift bases
64  for (int s = 0; s < j; ++s) {
65  crossTable[s] = crossTable[s + 1];
66  }
67  crossTable[j] = &columns[Dim - j - 2];
68  } while (j > 0);
69 
70  // flip columns
71  for (int i = 0; i < Dim; ++i) {
72  if (flipAxes[i]) {
73  columns[i] *= -T(1);
74  }
75  }
76 
77  // copy columns to matrix
78  for (int i = 0; i < Dim; ++i) {
79  for (int j = 0; j < Dim; ++j) {
80  elem(i, j) = columns[j][i];
81  }
82  }
83 
84  // calculate translation of the matrix
85  for (int j = 0; j < Dim; ++j) {
86  elem(Dim, j) = -Dot(eye, columns[j]);
87  }
88 
89  // clear additional elements
90  constexpr int AuxDim = Rows < Columns ? Rows : Columns;
91  if (AuxDim > Dim) {
92  for (int i = 0; i < Dim; ++i) {
93  elem(i, AuxDim - 1) = 0;
94  }
95  elem(Dim, AuxDim - 1) = 1;
96  }
97  }
98 
99  const VectorT eye;
100  const VectorT target;
101  const std::array<VectorT, size_t(Dim - 2)> bases;
102  const std::array<bool, Dim> flipAxes;
103 };
104 
105 
117 template <class T, int Dim, bool Packed, size_t BaseDim, size_t FlipDim>
119  const Vector<T, Dim, Packed>& target,
120  const std::array<Vector<T, Dim, Packed>, BaseDim>& bases,
121  const std::array<bool, FlipDim>& flipAxes) {
122  static_assert(BaseDim == Dim - 2, "You must provide 2 fewer bases than the dimension of the transform.");
123  static_assert(Dim == FlipDim, "You must provide the same number of flips as the dimension of the transform.");
124  return ViewBuilder<T, Dim, Packed>(eye, target, bases, flipAxes);
125 }
126 
127 
133 template <class T, bool Packed>
134 auto LookAt(const Vector<T, 2, Packed>& eye, const Vector<T, 2, Packed>& target, bool positiveYForward = true, bool flipX = false) {
135  return LookAt(eye, target, std::array<Vector<T, 2, Packed>, 0>{}, std::array{ flipX, positiveYForward });
136 }
137 
138 
146 template <class T, bool Packed>
147 auto LookAt(const Vector<T, 3, Packed>& eye, const Vector<T, 3, Packed>& target, const Vector<T, 3, Packed>& up, bool positiveZForward = true, bool flipX = false, bool flipY = false) {
148  return LookAt(eye, target, std::array<Vector<T, 3, Packed>, 1>{ up }, std::array<bool, 3>{ flipX, flipY, positiveZForward });
149 }
150 
151 
152 
153 
154 } // namespace mathter
Definition: ViewBuilder.hpp:12
Quaternion< T, Packed > Normalize(const Quaternion< T, Packed > &q)
Returns the unit quaternion of the same direction. Does not change this object.
Definition: QuaternionFunction.hpp:66
Represents a vector in N-dimensional space.
Definition: Definitions.hpp:57
T Dot(const Vector< T, Dim, Packed > &lhs, const Vector< T, Dim, Packed > &rhs)
Calculates the scalar product (dot product) of the two arguments.
Definition: VectorFunction.hpp:111
Definition: Approx.hpp:11
auto LookAt(const Vector< T, Dim, Packed > &eye, const Vector< T, Dim, Packed > &target, const std::array< Vector< T, Dim, Packed >, BaseDim > &bases, const std::array< bool, FlipDim > &flipAxes)
Creates a camera look-at matrix.
Definition: ViewBuilder.hpp:118
Definition: Definitions.hpp:63
auto Cross(const Vector< T, Dim, Packed > &head, Args &&... args) -> Vector< T, Dim, Packed >
Returns the generalized cross-product in N dimensions.
Definition: VectorFunction.hpp:223
ViewBuilder & operator=(const ViewBuilder &)=delete
ViewBuilder(const VectorT &eye, const VectorT &target, const std::array< VectorT, size_t(Dim - 2)> &bases, const std::array< bool, Dim > &flipAxes)
Definition: ViewBuilder.hpp:16