diff --git a/README.md b/README.md index e88e20f..e795a55 100644 --- a/README.md +++ b/README.md @@ -1286,6 +1286,9 @@ vec rotate(const vec& v, T angle, const vec& normal); template < typename T > vec rotate(const vec& v, T angle, const vec& normal); + +template < typename T, std::size_t Size > +vec project(const vec& v, const vec& normal); ``` ## [License (MIT)](./LICENSE.md) diff --git a/headers/vmath.hpp/vmath_ext.hpp b/headers/vmath.hpp/vmath_ext.hpp index f79bf57..435d2e5 100644 --- a/headers/vmath.hpp/vmath_ext.hpp +++ b/headers/vmath.hpp/vmath_ext.hpp @@ -636,4 +636,11 @@ namespace vmath_hpp [[nodiscard]] vec rotate(const vec& v, T angle, const vec& normal) { return v * rotate(angle, normal); } + + // project + + template < typename T, std::size_t Size > + [[nodiscard]] vec project(const vec& v, const vec& normal) { + return dot(v, normal) / length2(normal) * normal; + } } diff --git a/untests/vmath_ext_tests.cpp b/untests/vmath_ext_tests.cpp index 4a8516f..51446e9 100644 --- a/untests/vmath_ext_tests.cpp +++ b/untests/vmath_ext_tests.cpp @@ -221,4 +221,9 @@ TEST_CASE("vmath/ext") { REQUIRE(rotate(float3(1.5f,0.f,0.f), radians(90.f), float3(0,0,1)) == approx3(0.f,1.5f,0.f)); REQUIRE(rotate(float4(1.5f,0.f,0.f,1.f), radians(90.f), float3(0,0,1)) == approx4(0.f,1.5f,0.f,1.f)); } + + SUBCASE("vector project") { + REQUIRE(project(float2(2.f, 2.f), float2(0.f, 1.f)) == approx2(0.f, 2.f)); + REQUIRE(project(float3(2.f, 2.f, 2.f), float3(0.f, 0.f, 1.f)) == approx3(0.f, 0.f, 2.f)); + } }