@flighthq/geometry 0.3.1-next.780.12e6944 → 0.3.1-next.836.609b031

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flighthq/geometry",
3
- "version": "0.3.1-next.780.12e6944",
3
+ "version": "0.3.1-next.836.609b031",
4
4
  "author": "Joshua Granick and other contributors",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -38,9 +38,9 @@
38
38
  "clean:dist": "tsx ../../scripts/clean-package-dist.ts"
39
39
  },
40
40
  "dependencies": {
41
- "@flighthq/entity": "0.3.1-next.780.12e6944",
42
- "@flighthq/log": "0.3.1-next.780.12e6944",
43
- "@flighthq/types": "0.3.1-next.780.12e6944"
41
+ "@flighthq/entity": "0.3.1-next.836.609b031",
42
+ "@flighthq/log": "0.3.1-next.836.609b031",
43
+ "@flighthq/types": "0.3.1-next.836.609b031"
44
44
  },
45
45
  "devDependencies": {
46
46
  "typescript": "^5.3.0"
@@ -13,6 +13,7 @@ import {
13
13
  matrix4TransformPoint,
14
14
  multiplyQuaternion,
15
15
  normalizeQuaternion,
16
+ normalizeVector3,
16
17
  rotateVector3ByQuaternion,
17
18
  setMatrix4FromQuaternion,
18
19
  setQuaternion,
@@ -654,6 +655,46 @@ describe('slerpQuaternion', () => {
654
655
  expectQuaternionClose(out, b.x, b.y, b.z, b.w);
655
656
  });
656
657
 
658
+ it('halfway interpolates about a tilted axis, exercising every component', () => {
659
+ // Every other slerp case rotates about (0,1,0), which leaves x and z zero in BOTH inputs — so the
660
+ // x and z arms of the shortest-path negation and of the final blend cannot be observed at all, and
661
+ // a sign error in either would pass. A tilted, normalized axis gives all four components distinct
662
+ // non-zero magnitudes. The oracle is independent of slerp: halfway between identity and R(axis, θ)
663
+ // is R(axis, θ/2) by definition of the axis-angle form.
664
+ const axis = createVector3(1, 2, 3);
665
+ normalizeVector3(axis, axis);
666
+ const a = createQuaternion();
667
+ const b = createQuaternion();
668
+ setQuaternionFromAxisAngle(b, axis, Math.PI / 2);
669
+
670
+ const out = createQuaternion();
671
+ slerpQuaternion(out, a, b, 0.5);
672
+
673
+ const expected = createQuaternion();
674
+ setQuaternionFromAxisAngle(expected, axis, Math.PI / 4);
675
+ expectQuaternionClose(out, expected.x, expected.y, expected.z, expected.w);
676
+ });
677
+
678
+ it('takes the shortest path when the inputs face opposite hemispheres', () => {
679
+ // A quaternion and its negation are the SAME rotation, so slerping toward either must give the same
680
+ // result — that is what the cosHalfTheta < 0 branch exists to guarantee. Without an input pair whose
681
+ // dot product is negative, that branch never runs and its per-component sign flips are unobservable;
682
+ // the tilted axis then keeps bx and bz non-zero so a dropped flip on either actually moves the answer.
683
+ const axis = createVector3(1, 2, 3);
684
+ normalizeVector3(axis, axis);
685
+ const a = createQuaternion();
686
+ const far = createQuaternion();
687
+ setQuaternionFromAxisAngle(far, axis, Math.PI / 2);
688
+ const negated = createQuaternion(-far.x, -far.y, -far.z, -far.w);
689
+
690
+ const out = createQuaternion();
691
+ slerpQuaternion(out, a, negated, 0.5);
692
+
693
+ const expected = createQuaternion();
694
+ setQuaternionFromAxisAngle(expected, axis, Math.PI / 4);
695
+ expectQuaternionClose(out, expected.x, expected.y, expected.z, expected.w);
696
+ });
697
+
657
698
  it('halfway interpolates the angle', () => {
658
699
  const a = createQuaternion();
659
700
  const b = createQuaternion();