Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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) | ✅ | ✅ | ✅ | ✅ | ✅ |
Expand All @@ -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.
Expand Down
8 changes: 4 additions & 4 deletions src/vmath.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 10 additions & 3 deletions tests/tests.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down