diff --git a/README.md b/README.md index 6b5b644..d4ba883 100644 --- a/README.md +++ b/README.md @@ -136,6 +136,7 @@ We run identical math operations across vmath, GLSL, [nim-glm](https://github.co | Quaternion to axis-angle | ✅ | ✅ | ✅ | ✅ | ✅ | | Matrix inverse | ✅ | ✅ | ✅ | ✅ | ✅ | | Cross product | ✅ | ✅ | ✅ | ✅ | ✅ | +| Orthogonal vector | ✅ | ❌ | ❌ | ❌ | ✅ | | Slerp | ✅ | ✅ | ✅ | ✅ | ✅ | | fromTwoVectors | ✅ | ✅ | ✅ | ✅ | ✅ | | Quat decomposition (sign) | ✅ | ✅ | ✅ | ✅ | ✅ | @@ -150,6 +151,8 @@ We run identical math operations across vmath, GLSL, [nim-glm](https://github.co ❌ **Element access note**: Jolt does convention differs from vmath's math-style `[row, col]` interpretation it follows the DirectX/HLSL convention. +❌ **Orthogonal vector note**: Jolt Physics provides `GetNormalizedPerpendicular()`. vmath's `orthogonal()` returns a perpendicular vector without normalizing it. GLSL and nim-GLM have no direct equivalent, while gl-matrix only computes one internally as part of `quat.rotationTo()`. + # 2.x.x to 3.0.0 vmath breaking changes: Version `3.0.0` changed rotation to be CCW (counter-clockwise) and updated the quaternion conventions to match GLSL, GLM, gl-matrix. Added a multi-library conformance suite. diff --git a/src/vmath.nim b/src/vmath.nim index a320736..62d3bfe 100644 --- a/src/vmath.nim +++ b/src/vmath.nim @@ -1908,14 +1908,14 @@ proc quatInverse*[T](q: GVec4[T]): GVec4[T] = proc orthogonal*[T](v: GVec3[T]): GVec3[T] = ## Returns orthogonal vector to given vector. let - v = abs(v) + vAbs = abs(v) other: type(v) = - if v.x < v.y: - if v.x < v.z: + if vAbs.x < vAbs.y: + if vAbs.x < vAbs.z: gvec3(T(1), 0, 0) # X_AXIS else: gvec3(T(0), 0, 1) # Z_AXIS - elif v.y < v.z: + elif vAbs.y < vAbs.z: gvec3(T(0), 1, 0) # Y_AXIS else: gvec3(T(0), 0, 1) # Z_AXIS diff --git a/tests/tests.nim b/tests/tests.nim index b035cf2..610700b 100644 --- a/tests/tests.nim +++ b/tests/tests.nim @@ -772,10 +772,10 @@ suite "quaternion nlerp": check dist(nl, sl) < 0.01f suite "orthogonal vector": - test "orthogonal is perpendicular to abs(v)": - # orthogonal() uses abs(v) internally, so result is perpendicular to abs(v) + test "orthogonal is perpendicular to v": for v in [vec3(1, 0, 0), vec3(0, 1, 0), vec3(0, 0, 1), - vec3(1, 1, 0), vec3(1, 1, 1), vec3(3, 2, 7)]: + vec3(1, 1, 0), vec3(1, 1, 1), vec3(3, 2, 7), + vec3(0, -1, 1), vec3(-3, 2, -7)]: let o = orthogonal(v) check abs(dot(v, o)) < 1e-5f @@ -1166,6 +1166,13 @@ suite "fromTwoVectors": q = fromTwoVectors(a, b) check q.mat4() * a ~= b + test "antiparallel mixed-sign vectors": + let + a = normalize(vec3(0, -1, 1)) + b = -a + q = fromTwoVectors(a, b) + check q.mat4() * a ~= b + test "fromTwoVectors fuzz": for _ in 0 ..< 1000: let