Skip to content

Commit

Permalink
Add a quaternion utility method
Browse files Browse the repository at this point in the history
  • Loading branch information
yzrmn committed Jul 17, 2024
1 parent 35b78a0 commit 8a234ea
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 0 deletions.
17 changes: 17 additions & 0 deletions packages/redgeometry/src/primitives/quaternion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,23 @@ export class Quaternion implements QuaternionLike {
return new Quaternion(cos * v.len(), sin * v.x, sin * v.y, sin * v.z);
}

/**
* Returns a quaternion with minimal rotation from `v1` to `v2`.
*/
public static fromRotationBetween(v1: Vector3, v2: Vector3): Quaternion {
const v1u = v1.unit();
const v2u = v2.unit();

// Vector halfway between `v1` and `v2`
const vu = v1u.add(v2u).unitOrZero();

// If `v` is zero then `dot = 0` and `cross` just needs to be any normal of `v1`
const dot = v1u.dot(vu);
const cross = vu.isZero() ? v1u.normalAny() : v1u.cross(vu);

return new Quaternion(dot, cross.x, cross.y, cross.z);
}

public static fromRotationEuler(angleX: number, angleY: number, angleZ: number, order: RotationOrder): Quaternion {
const sinX = Math.sin(0.5 * angleX);
const cosX = Math.cos(0.5 * angleX);
Expand Down
13 changes: 13 additions & 0 deletions packages/redgeometry/src/primitives/vector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,19 @@ export class Vector3 implements Vector3Like {
return new Vector3(-this.x, -this.y, -this.z);
}

/**
* Returns a non-zero normal vector.
*/
public normalAny(): Vector3 {
if (this.x !== 0) {
return this.normalY();
} else if (this.y !== 0) {
return this.normalZ();
} else {
return this.normalX();
}
}

/**
* Returns the normal vector around the x-axis.
*
Expand Down

0 comments on commit 8a234ea

Please sign in to comment.