It's now possible to conveniently transform 2D vectors and points with
3x3 matrices and 3D vectors/points with 4x4 matrices. Previous most
low-level solution:
Matrix4 m;
Vector3 v;
Vector3 a = (m*Vector4(v, 1.0f)).xyz();
Vector4 b = (m*Vector4(v, 0.0f)).xyz();
Another, more generalized solution for points was with Point2D/Point3D,
adding a lot of confusion (what is that class and what does .vector()?):
Vector3 a = (m*Point3D(v)).vector();
And the worst solution was with generic 2D/3D code (WTF!):
auto a = (m*typename DimensionTraits::PointType(v)).vector();
Now it is just this, similar for both dimensions:
Vector3 a = m.transformPoint(v);
Vector3 b = m.transformVector(v);
Note that transformation three-component vectors with 3x3 matrices or
four-component vectors with 4x4 matrices is easy enough so it doesn't
need any special convenience functions whatsoever:
Vector3 c = m.rotation()*v;
It is now possible to implicitly create one-element Vector and also
explicitly fill more-element Vector with one value without any ambiguous
overload conflicts:
Vector<1, int> a1 = 1; // calls implicit constructor
//Vector<3, int> a3 = 1; // error!
Vector<1, int> b1(1); // still calls the implicit constructor, the
// explicit is disabled for one-element vector
Vector<3, int> b3(1); // calls the explicit "filling" constructor,
// the implicit is disabled for only one argument
The downside of this is that now specifying improper element count in
constructor doesn't lead to static_assert with human readable error, but
rather cryptic "no match" error.
Was causing improper implicit conversions, such as here (example
directly from unit tests, where it was unintentionally used):
Vector3 normal;
Matrix4 transformation;
auto transformedNormal = transformation*normal;
Not only that it was possible to multiply 4x4 matrix with 3-component
vector, but the resulting type was Point3D which was absolutely
confusing. Currently it must be explicitly converted:
transformedNormal = transformation*Point3D(normal);
The comparisons have also SIMD instructions returning bool vector, this
future-proofs them. Also it isn't confusing anymore (a < b is true when
all are less or just one?).