diff --git a/README.md b/README.md index 3ee391b..24ff266 100644 --- a/README.md +++ b/README.md @@ -1841,18 +1841,18 @@ mat rotate_z(T angle); template < typename T > mat rotate_z(const mat& m, T angle); -template < typename T > -mat scale(T x, T y, T z); - -template < typename T > -mat scale(const mat& m, T x, T y, T z); - template < typename T > mat scale(const vec& v); template < typename T > mat scale(const mat& m, const vec& v); +template < typename T > +mat scale4(const vec& v); + +template < typename T > +mat scale4(const mat& m, const vec& v); + template < typename T > mat look_at_lh(const vec& dir, const vec& up); @@ -1887,18 +1887,18 @@ mat rotate(T angle); template < typename T > mat rotate(const mat& m, T angle); -template < typename T > -mat scale(T x, T y); - -template < typename T > -mat scale(const mat& m, T x, T y); - template < typename T > mat scale(const vec& v); template < typename T > mat scale(const mat& m, const vec& v); +template < typename T > +mat scale3(const vec& v); + +template < typename T > +mat scale3(const mat& m, const vec& v); + template < typename T > mat shear(T x, T y); diff --git a/headers/vmath.hpp/vmath_ext.hpp b/headers/vmath.hpp/vmath_ext.hpp index 47f42d2..a253aeb 100644 --- a/headers/vmath.hpp/vmath_ext.hpp +++ b/headers/vmath.hpp/vmath_ext.hpp @@ -389,24 +389,14 @@ namespace vmath_hpp // scale template < typename T > - [[nodiscard]] constexpr mat scale(T x, T y, T z) { + [[nodiscard]] constexpr mat scale(const vec& v) { /// REFERENCE: /// https://en.wikipedia.org/wiki/Scaling_(geometry) return { - { x, T{0}, T{0} }, - { T{0}, y, T{0} }, - { T{0}, T{0}, z }}; - } - - template < typename T > - [[nodiscard]] constexpr mat scale(const mat& m, T x, T y, T z) { - return m * scale(x, y, z); - } - - template < typename T > - [[nodiscard]] constexpr mat scale(const vec& v) { - return scale(v.x, v.y, v.z); + { v.x, T{0}, T{0} }, + { T{0}, v.y, T{0} }, + { T{0}, T{0}, v.z }}; } template < typename T > @@ -414,6 +404,25 @@ namespace vmath_hpp return m * scale(v); } + // scale4 + + template < typename T > + [[nodiscard]] constexpr mat scale4(const vec& v) { + /// REFERENCE: + /// https://en.wikipedia.org/wiki/Scaling_(geometry) + + return { + { v.x, T{0}, T{0}, T{0} }, + { T{0}, v.y, T{0}, T{0} }, + { T{0}, T{0}, v.z, T{0} }, + { T{0}, T{0}, T{0}, T{1} }}; + } + + template < typename T > + [[nodiscard]] constexpr mat scale4(const mat& m, const vec& v) { + return m * scale4(v); + } + // look_at template < typename T > @@ -557,23 +566,13 @@ namespace vmath_hpp // scale template < typename T > - [[nodiscard]] constexpr mat scale(T x, T y) { + [[nodiscard]] constexpr mat scale(const vec& v) { /// REFERENCE: /// https://en.wikipedia.org/wiki/Scaling_(geometry) return { - { x, T{0} }, - { T{0}, y }}; - } - - template < typename T > - [[nodiscard]] constexpr mat scale(const mat& m, T x, T y) { - return m * scale(x, y); - } - - template < typename T > - [[nodiscard]] constexpr mat scale(const vec& v) { - return scale(v.x, v.y); + { v.x, T{0} }, + { T{0}, v.y }}; } template < typename T > @@ -581,6 +580,24 @@ namespace vmath_hpp return m * scale(v); } + // scale3 + + template < typename T > + [[nodiscard]] constexpr mat scale3(const vec& v) { + /// REFERENCE: + /// https://en.wikipedia.org/wiki/Scaling_(geometry) + + return { + { v.x, T{0}, T{0} }, + { T{0}, v.y, T{0} }, + { T{0}, T{0}, T{1} }}; + } + + template < typename T > + [[nodiscard]] constexpr mat scale3(const mat& m, const vec& v) { + return m * scale3(v); + } + // shear template < typename T > diff --git a/untests/vmath_ext_tests.cpp b/untests/vmath_ext_tests.cpp index a2ac75d..84af38c 100644 --- a/untests/vmath_ext_tests.cpp +++ b/untests/vmath_ext_tests.cpp @@ -227,51 +227,57 @@ TEST_CASE("vmath/ext/matrix_transform") { } SUBCASE("rotate") { - CHECK(fvec4(0.f,1.f,0.f,1.f) * rotate_x(pi_2) == uapprox4(0.f,0.f,1.f,1.f)); - CHECK(fvec4(0.f,0.f,1.f,1.f) * rotate_y(pi_2) == uapprox4(1.f,0.f,0.f,1.f)); - CHECK(fvec4(1.f,0.f,0.f,1.f) * rotate_z(pi_2) == uapprox4(0.f,1.f,0.f,1.f)); + CHECK(fvec3(0.f,1.f,0.f) * rotate_x(pi_2) == uapprox3(0.f,0.f,1.f)); + CHECK(fvec3(0.f,0.f,1.f) * rotate_y(pi_2) == uapprox3(1.f,0.f,0.f)); + CHECK(fvec3(1.f,0.f,0.f) * rotate_z(pi_2) == uapprox3(0.f,1.f,0.f)); - CHECK(fvec4(0.f,1.f,0.f,1.f) * rotate_x(rotate_x(pi_4),pi_4) == uapprox4(0.f,0.f,1.f,1.f)); - CHECK(fvec4(0.f,0.f,1.f,1.f) * rotate_y(rotate_y(pi_4),pi_4) == uapprox4(1.f,0.f,0.f,1.f)); - CHECK(fvec4(1.f,0.f,0.f,1.f) * rotate_z(rotate_z(pi_4),pi_4) == uapprox4(0.f,1.f,0.f,1.f)); + CHECK(fvec3(0.f,1.f,0.f) * rotate_x(rotate_x(pi_4),pi_4) == uapprox3(0.f,0.f,1.f)); + CHECK(fvec3(0.f,0.f,1.f) * rotate_y(rotate_y(pi_4),pi_4) == uapprox3(1.f,0.f,0.f)); + CHECK(fvec3(1.f,0.f,0.f) * rotate_z(rotate_z(pi_4),pi_4) == uapprox3(0.f,1.f,0.f)); - CHECK(fvec3(2.f,3.f,1.f) * rotate(pi) == uapprox3(-2.f,-3.f,1.f)); - CHECK(fvec4(2.f,3.f,4.f,1.f) * rotate(pi,{0.f,0.f,1.f}) == uapprox4(-2.f,-3.f,4.f,1.f)); - CHECK(fvec4(2.f,3.f,4.f,1.f) * rotate(pi,fvec3{0.f,0.f,1.f}) == uapprox4(-2.f,-3.f,4.f,1.f)); - CHECK(fvec4(2.f,3.f,4.f,1.f) * rotate(qrotate(pi,fvec3{0.f,0.f,1.f})) == uapprox4(-2.f,-3.f,4.f,1.f)); + CHECK(fvec2(2.f,3.f) * rotate(pi) == uapprox2(-2.f,-3.f)); + CHECK(fvec3(2.f,3.f,4.f) * rotate(pi,{0.f,0.f,1.f}) == uapprox3(-2.f,-3.f,4.f)); + CHECK(fvec3(2.f,3.f,4.f) * rotate(pi,fvec3{0.f,0.f,1.f}) == uapprox3(-2.f,-3.f,4.f)); + CHECK(fvec3(2.f,3.f,4.f) * rotate(qrotate(pi,fvec3{0.f,0.f,1.f})) == uapprox3(-2.f,-3.f,4.f)); - CHECK(fvec3(2.f,3.f,1.f) * rotate(rotate(pi_2),pi_2) == uapprox3(-2.f,-3.f,1.f)); - CHECK(fvec4(2.f,3.f,4.f,1.f) * rotate(rotate(pi_2,{0.f,0.f,1.f}),pi_2,{0.f,0.f,1.f}) == uapprox4(-2.f,-3.f,4.f,1.f)); - CHECK(fvec4(2.f,3.f,4.f,1.f) * rotate(rotate(pi_2,fvec3{0.f,0.f,1.f}),pi_2,fvec3{0.f,0.f,1.f}) == uapprox4(-2.f,-3.f,4.f,1.f)); - CHECK(fvec4(2.f,3.f,4.f,1.f) * rotate(rotate(qrotate(pi_2,fvec3{0.f,0.f,1.f})),qrotate(pi_2,fvec3{0.f,0.f,1.f})) == uapprox4(-2.f,-3.f,4.f,1.f)); + CHECK(fvec2(2.f,3.f) * rotate(rotate(pi_2),pi_2) == uapprox2(-2.f,-3.f)); + CHECK(fvec3(2.f,3.f,4.f) * rotate(rotate(pi_2,{0.f,0.f,1.f}),pi_2,{0.f,0.f,1.f}) == uapprox3(-2.f,-3.f,4.f)); + CHECK(fvec3(2.f,3.f,4.f) * rotate(rotate(pi_2,fvec3{0.f,0.f,1.f}),pi_2,fvec3{0.f,0.f,1.f}) == uapprox3(-2.f,-3.f,4.f)); + CHECK(fvec3(2.f,3.f,4.f) * rotate(rotate(qrotate(pi_2,fvec3{0.f,0.f,1.f})),qrotate(pi_2,fvec3{0.f,0.f,1.f})) == uapprox3(-2.f,-3.f,4.f)); } - SUBCASE("scale") { - STATIC_CHECK(fvec3(2.f,3.f,1.f) * scale(fvec2{2.f,3.f}) == uapprox3(4.f,9.f,1.f)); - STATIC_CHECK(fvec4(2.f,3.f,4.f,1.f) * scale(fvec3{2.f,3.f,4.f}) == uapprox4(4.f,9.f,16.f,1.f)); - STATIC_CHECK(fvec4(2.f,3.f,4.f,1.f) * scale(fvec3{2.f,3.f,4.f}) == uapprox4(4.f,9.f,16.f,1.f)); + SUBCASE("scale2d") { + STATIC_CHECK(fvec2(2.f,3.f) * scale(fvec2{2.f,3.f}) == uapprox2(4.f,9.f)); + STATIC_CHECK(fvec3(2.f,3.f,1.f) * scale3(fvec2{2.f,3.f}) == uapprox3(4.f,9.f,1.f)); - STATIC_CHECK(fvec3(2.f,3.f,1.f) * scale(scale(fvec2{2.f,2.f}), {2.f,3.f}) == uapprox3(8.f,18.f,1.f)); - STATIC_CHECK(fvec4(2.f,3.f,4.f,1.f) * scale(scale(fvec3{2.f,2.f,2.f}), {2.f,3.f,4.f}) == uapprox4(8.f,18.f,32.f,1.f)); - STATIC_CHECK(fvec4(2.f,3.f,4.f,1.f) * scale(scale(fvec3{2.f,2.f,2.f}), fvec3{2.f,3.f,4.f}) == uapprox4(8.f,18.f,32.f,1.f)); + STATIC_CHECK(fvec2(2.f,3.f) * scale(scale(fvec2{2.f,2.f}), fvec2{2.f,3.f}) == uapprox2(8.f,18.f)); + STATIC_CHECK(fvec3(2.f,3.f,1.f) * scale3(scale3(fvec2{2.f,2.f}), fvec2{2.f,3.f}) == uapprox3(8.f,18.f,1.f)); + } + + SUBCASE("scale3d") { + STATIC_CHECK(fvec3(2.f,3.f,4.f) * scale(fvec3{2.f,3.f,4.f}) == uapprox3(4.f,9.f,16.f)); + STATIC_CHECK(fvec4(2.f,3.f,4.f,1.f) * scale4(fvec3{2.f,3.f,4.f}) == uapprox4(4.f,9.f,16.f,1.f)); + + STATIC_CHECK(fvec3(2.f,3.f,4.f) * scale(scale(fvec3{2.f,2.f,2.f}), fvec3{2.f,3.f,4.f}) == uapprox3(8.f,18.f,32.f)); + STATIC_CHECK(fvec4(2.f,3.f,4.f,1.f) * scale4(scale4(fvec3{2.f,2.f,2.f}), fvec3{2.f,3.f,4.f}) == uapprox4(8.f,18.f,32.f,1.f)); } SUBCASE("shear") { - STATIC_CHECK(fvec3(2.f,3.f,1.f) * shear_x(0.f) == uapprox3(2.f,3.f,1.f)); - STATIC_CHECK(fvec3(2.f,3.f,1.f) * shear_x(1.f) == uapprox3(5.f,3.f,1.f)); - STATIC_CHECK(fvec3(2.f,3.f,1.f) * shear_x(2.f) == uapprox3(8.f,3.f,1.f)); - STATIC_CHECK(fvec3(2.f,3.f,1.f) * shear_x(shear_x(1.f),1.f) == uapprox3(8.f,3.f,1.f)); + STATIC_CHECK(fvec2(2.f,3.f) * shear_x(0.f) == uapprox2(2.f,3.f)); + STATIC_CHECK(fvec2(2.f,3.f) * shear_x(1.f) == uapprox2(5.f,3.f)); + STATIC_CHECK(fvec2(2.f,3.f) * shear_x(2.f) == uapprox2(8.f,3.f)); + STATIC_CHECK(fvec2(2.f,3.f) * shear_x(shear_x(1.f),1.f) == uapprox2(8.f,3.f)); - STATIC_CHECK(fvec3(2.f,3.f,1.f) * shear_y(0.f) == uapprox3(2.f,3.f,1.f)); - STATIC_CHECK(fvec3(2.f,3.f,1.f) * shear_y(1.f) == uapprox3(2.f,5.f,1.f)); - STATIC_CHECK(fvec3(2.f,3.f,1.f) * shear_y(2.f) == uapprox3(2.f,7.f,1.f)); - STATIC_CHECK(fvec3(2.f,3.f,1.f) * shear_y(shear_y(1.f),1.f) == uapprox3(2.f,7.f,1.f)); + STATIC_CHECK(fvec2(2.f,3.f) * shear_y(0.f) == uapprox2(2.f,3.f)); + STATIC_CHECK(fvec2(2.f,3.f) * shear_y(1.f) == uapprox2(2.f,5.f)); + STATIC_CHECK(fvec2(2.f,3.f) * shear_y(2.f) == uapprox2(2.f,7.f)); + STATIC_CHECK(fvec2(2.f,3.f) * shear_y(shear_y(1.f),1.f) == uapprox2(2.f,7.f)); - STATIC_CHECK(fvec3(2.f,3.f,1.f) * shear(fvec2(0.f,0.f)) == uapprox3(2.f,3.f,1.f)); - STATIC_CHECK(fvec3(2.f,3.f,1.f) * shear(fvec2(2.f,0.f)) == uapprox3(8.f,3.f,1.f)); - STATIC_CHECK(fvec3(2.f,3.f,1.f) * shear(fvec2(0.f,2.f)) == uapprox3(2.f,7.f,1.f)); - STATIC_CHECK(fvec3(2.f,3.f,1.f) * shear(shear(fvec2(1.f,0.f)),fvec2(1.f,0.f)) == uapprox3(8.f,3.f,1.f)); - STATIC_CHECK(fvec3(2.f,3.f,1.f) * shear(shear(fvec2(0.f,1.f)),fvec2(0.f,1.f)) == uapprox3(2.f,7.f,1.f)); + STATIC_CHECK(fvec2(2.f,3.f) * shear(fvec2(0.f,0.f)) == uapprox2(2.f,3.f)); + STATIC_CHECK(fvec2(2.f,3.f) * shear(fvec2(2.f,0.f)) == uapprox2(8.f,3.f)); + STATIC_CHECK(fvec2(2.f,3.f) * shear(fvec2(0.f,2.f)) == uapprox2(2.f,7.f)); + STATIC_CHECK(fvec2(2.f,3.f) * shear(shear(fvec2(1.f,0.f)),fvec2(1.f,0.f)) == uapprox2(8.f,3.f)); + STATIC_CHECK(fvec2(2.f,3.f) * shear(shear(fvec2(0.f,1.f)),fvec2(0.f,1.f)) == uapprox2(2.f,7.f)); } SUBCASE("matrix look_at") { @@ -284,26 +290,26 @@ TEST_CASE("vmath/ext/matrix_projections") { SUBCASE("orthographic") { CHECK(all(approx( orthographic_lh(800.f, 600.f, 5.f, 10.f), - scale(1.f,1.f,-1.f) * orthographic_rh(800.f, 600.f, 5.f, 10.f)))); + scale4(vec{1.f,1.f,-1.f}) * orthographic_rh(800.f, 600.f, 5.f, 10.f)))); CHECK(all(approx( orthographic_lh(100.f, 800.f, 50.f, 640.f, 5.f, 10.f), - scale(1.f,1.f,-1.f) * orthographic_rh(100.f, 800.f, 50.f, 640.f, 5.f, 10.f)))); + scale4(vec{1.f,1.f,-1.f}) * orthographic_rh(100.f, 800.f, 50.f, 640.f, 5.f, 10.f)))); } SUBCASE("perspective") { CHECK(all(approx( perspective_lh(800.f, 600.f, 5.f, 10.f), - scale(1.f,1.f,-1.f) * perspective_rh(800.f, 600.f, 5.f, 10.f)))); + scale4(vec{1.f,1.f,-1.f}) * perspective_rh(800.f, 600.f, 5.f, 10.f)))); CHECK(all(approx( perspective_fov_lh(1.5f, 1.3f, 0.f, 10.f), - scale(1.f,1.f,-1.f) * perspective_fov_rh(1.5f, 1.3f, 0.f, 10.f)))); + scale4(vec{1.f,1.f,-1.f}) * perspective_fov_rh(1.5f, 1.3f, 0.f, 10.f)))); CHECK(all(approx( perspective_lh(100.f, 800.f, 50.f, 600.f, 5.f, 10.f), - scale(1.f,1.f,-1.f) * perspective_rh(100.f, 800.f, 50.f, 600.f, 5.f, 10.f)))); + scale4(vec{1.f,1.f,-1.f}) * perspective_rh(100.f, 800.f, 50.f, 600.f, 5.f, 10.f)))); } } @@ -343,24 +349,24 @@ TEST_CASE("vmath/ext/vector_transform") { TEST_CASE("vmath/ext/quaternion_transform") { SUBCASE("qrotate(m)") { CHECK(all(approx( - vec{4.f,3.f,2.f,1.f} * rotate(qrotate(fmat3(rotate(0.f, vec{1.f,2.f,3.f})))), - vec{4.f,3.f,2.f,1.f} * rotate(0.f, vec{1.f,2.f,3.f}), 0.001f))); + vec{4.f,3.f,2.f} * rotate(qrotate(rotate(0.f, vec{1.f,2.f,3.f}))), + vec{4.f,3.f,2.f} * rotate(0.f, vec{1.f,2.f,3.f}), 0.001f))); CHECK(all(approx( - vec{4.f,3.f,2.f,1.f} * rotate(qrotate(fmat3(rotate(radians(12.5f), vec{1.f,2.f,3.f})))), - vec{4.f,3.f,2.f,1.f} * rotate(radians(12.5f), vec{1.f,2.f,3.f}), 0.001f))); + vec{4.f,3.f,2.f} * rotate(qrotate(rotate(radians(12.5f), vec{1.f,2.f,3.f}))), + vec{4.f,3.f,2.f} * rotate(radians(12.5f), vec{1.f,2.f,3.f}), 0.001f))); CHECK(all(approx( - vec{4.f,3.f,2.f,1.f} * rotate(qrotate(fmat3(rotate(radians(-190.5f), vec{1.f,2.f,3.f})))), - vec{4.f,3.f,2.f,1.f} * rotate(radians(-190.5f), vec{1.f,2.f,3.f}), 0.001f))); + vec{4.f,3.f,2.f} * rotate(qrotate(rotate(radians(-190.5f), vec{1.f,2.f,3.f}))), + vec{4.f,3.f,2.f} * rotate(radians(-190.5f), vec{1.f,2.f,3.f}), 0.001f))); } SUBCASE("qrotate(q, m)") { CHECK(all(approx( vec{4.f,3.f,2.f} * qrotate( - qrotate(fmat3(rotate(0.f, vec{1.f,2.f,3.f}))), - fmat3(rotate(0.f, vec{3.f,2.f,1.f}))), + qrotate(rotate(0.f, vec{1.f,2.f,3.f})), + rotate(0.f, vec{3.f,2.f,1.f})), vec{4.f,3.f,2.f} * - fmat3(rotate(0.f, vec{1.f,2.f,3.f})) * - fmat3(rotate(0.f, vec{3.f,2.f,1.f}))))); + rotate(0.f, vec{1.f,2.f,3.f}) * + rotate(0.f, vec{3.f,2.f,1.f})))); } SUBCASE("qrotate(from, to)") { diff --git a/untests/vmath_fix_tests.cpp b/untests/vmath_fix_tests.cpp index be0657d..33fc7f6 100644 --- a/untests/vmath_fix_tests.cpp +++ b/untests/vmath_fix_tests.cpp @@ -402,10 +402,10 @@ namespace vmath_hpp template fix3x3f rotate_z(fix); template fix3x3f rotate_z(const fix3x3f&, fix); - template fix3x3f scale(fix, fix, fix); - template fix3x3f scale(const fix3x3f&, fix, fix, fix); template fix3x3f scale(const fix3f&); template fix3x3f scale(const fix3x3f&, const fix3f&); + template fix4x4f scale4(const fix3f&); + template fix4x4f scale4(const fix4x4f&, const fix3f&); template fix3x3f look_at_lh(const fix3f&, const fix3f&); template fix4x4f look_at_lh(const fix3f&, const fix3f&, const fix3f&); @@ -428,10 +428,10 @@ namespace vmath_hpp template fix2x2f rotate(fix); template fix2x2f rotate(const fix2x2f&, fix); - template fix2x2f scale(fix, fix); - template fix2x2f scale(const fix2x2f&, fix, fix); template fix2x2f scale(const fix2f&); template fix2x2f scale(const fix2x2f&, const fix2f&); + template fix3x3f scale3(const fix2f&); + template fix3x3f scale3(const fix3x3f&, const fix2f&); template fix2x2f shear(fix, fix); template fix2x2f shear(const fix2x2f&, fix, fix);