> ## Documentation Index
> Fetch the complete documentation index at: https://docs.spurdoverse.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Quaternion

> Rotations: bone orientation, composing and interpolating turns.

export const like_0 = "QuatLike"

export const name_0 = "Quaternion"

A rotation as `(x, y, z, w)`. Bone rotations come as quaternions. Global class, no import.

```ts theme={null}
const quarterTurn = Quaternion.fromAxisAngle([0, 0, 1], 90);
const q = new Quaternion([0, 0, 0]);   // w defaults to 1: the identity
```

Fields are 32-bit floats; assigning a non-number or NaN throws.

## Overview

<CardGroup cols={2}>
  <Card title="Common" icon="layer-group" href="#common">
    `from`, `set`, `mul`, `lerp`, `normalize`…
  </Card>

  <Card title="Creating" icon="plus" href="#creating">
    `identity`, `fromAngles`, `fromAxisAngle`.
  </Card>

  <Card title="Using" icon="arrows-spin" href="#using">
    `rotate`, `slerp`, `toAngles`, `toAxisAngle`.
  </Card>
</CardGroup>

***

## Common

Every argument takes any <code>{like_0}</code>, not just a <code>{name_0}</code>.

| Member | Does |
| :- | :- |
| <code>new {name_0}(value)</code>, <code>{name_0}.from(value)</code> | Copy from any <code>{like_0}</code>. |
| `set(...)` | Replaces every component in place, returns `this`. Same arguments as the constructor. |
| `clone()` | A copy. |
| `equals(other, epsilon?)` | Every component within `epsilon`. Default `0`, exact. |
| `toArray()`, `toJSON()` | Plain array, plain object. |
| `toString()` | <code>"{name_0}(…)"</code> |
| `add(other)`, `sub(other)` | Component-wise. |
| `scale(factor)` | Every component times `factor`. |
| `mul(x)`, `div(x)` | By a number, or component-wise by another value. Dividing by zero throws `RangeError`. |
| `lerp(other, t)` | Linear blend, `t` not clamped. |
| `normalize()`, `normalized()` | The first changes the value and returns `this`, the second returns a copy. |

Only `set()` and `normalize()` change the value. Nothing changes its arguments.

Unlike the other classes, `mul` and `div` with a quaternion compose rotations (below). `lerp` takes the shorter arc and returns a unit quaternion.

| Also | Returns |
| :- | :- |
| `dot(other)` | Dot product |
| `length()`, `lengthSqr()` | Length, squared length |
| `conjugate()` | New `Quaternion` |
| `inverse()` | New `Quaternion` |

### mul

<br />

```ts theme={null}
mul(factor: number | QuatLike): Quaternion
div(divisor: number | QuatLike): Quaternion
```

With a number, every component. With a quaternion, `a.mul(b)` applies `b` first, then `a`, and `a.div(b)` is `a * b⁻¹`.

```ts theme={null}
const both = spin.mul(tilt);   // tilt first, then spin
const delta = to.div(from);    // delta.mul(from) equals to
```

***

## Creating

| Static | Returns |
| :- | :- |
| `Quaternion.identity()` | `(0, 0, 0, 1)`, no rotation |
| `Quaternion.fromAngles(angles)` | The rotation of a [QAngle](/api/types/qangle), same as `angles.toQuaternion()` |

### fromAxisAngle

<br />

```ts theme={null}
Quaternion.fromAxisAngle(axis: Vec3Like, degrees: number): Quaternion
```

A turn of `degrees` around `axis`. The axis doesn't need to be unit length.

```ts theme={null}
const spin = Quaternion.fromAxisAngle([0, 0, 1], 45);   // 45° around world up
```

***

## Using

### rotate

<br />

```ts theme={null}
rotate(vector: Vec3Like): Vector
```

`vector` turned by this rotation. Expects a unit quaternion, so `normalize()` one you built by hand.

```ts theme={null}
Quaternion.fromAngles(view).rotate([1, 0, 0]);   // same as view.forward()
bone.rotation.rotate([0, 0, 10]);                // the bone's local +Z, 10 units long
```

### slerp

<br />

```ts theme={null}
slerp(other: QuatLike, t: number): Quaternion
```

Spherical blend along the shorter arc at constant angular speed. `t` isn't clamped. `lerp` is cheaper and close enough for small steps.

```ts theme={null}
const halfway = a.slerp(b, 0.5);
```

### toAngles

<br />

```ts theme={null}
toAngles(): QAngle
toAxisAngle(): { axis: Vector; degrees: number }
```

Back to view angles, or to a unit axis and `0`–`360` degrees.

```ts theme={null}
Quaternion.fromAxisAngle([0, 0, 1], 90).toAngles();   // QAngle(0, 90, 0)
```

***

## Example

Draws a short axis gizmo on every enemy's head bone.

```ts theme={null}
import entities from "@native/entities";
import render from "@native/render";

const axes: [Vec3Like, Color][] = [
    [[8, 0, 0], Color.red()],
    [[0, 8, 0], Color.green()],
    [[0, 0, 8], Color.blue()],
];

on("render", () => {
    const me = entities.getLocalPlayer();
    for (const enemy of entities.getPlayers({ skipLocal: true })) {
        const head = me && enemy.isEnemy(me) ? enemy.getBone("head_0") : null;
        const origin = head && render.worldToScreen(head.position);
        if (!head || !origin) continue;

        for (const [axis, color] of axes) {
            const end = render.worldToScreen(head.position.add(head.rotation.rotate(axis)));
            if (end) render.line(origin, end, color);
        }
    }
});
```
