Skip to content

Instantly share code, notes, and snippets.

@bnolan
Last active September 18, 2025 00:15
Show Gist options
  • Select an option

  • Save bnolan/c33d36163bd88874dd1006e29270e81a to your computer and use it in GitHub Desktop.

Select an option

Save bnolan/c33d36163bd88874dd1006e29270e81a to your computer and use it in GitHub Desktop.
maths.ts
export type vec3 = [number, number, number]
export class Vector3 {
constructor(
public x: number,
public y: number,
public z: number,
) {}
static FromArray(arr: vec3): Vector3 {
return new Vector3(arr[0], arr[1], arr[2])
}
add(v: Vector3): Vector3 {
return new Vector3(this.x + v.x, this.y + v.y, this.z + v.z)
}
clone(): Vector3 {
return new Vector3(this.x, this.y, this.z)
}
subtract(v: Vector3): Vector3 {
return new Vector3(this.x - v.x, this.y - v.y, this.z - v.z)
}
static Zero(): Vector3 {
return new Vector3(0, 0, 0)
}
length(): number {
return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z)
}
normalize(): Vector3 {
const len = this.length()
return len === 0 ? Vector3.Zero() : new Vector3(this.x / len, this.y / len, this.z / len)
}
set(x: number, y: number, z: number) {
this.x = x
this.y = y
this.z = z
}
toArray(arr: vec3) {
arr[0] = this.x
arr[1] = this.y
arr[2] = this.z
// return [this.x, this.y, this.z]
}
asArray(): vec3 {
return [this.x, this.y, this.z]
}
}
export class Vector2 {
constructor(
public x: number,
public y: number,
) {}
}
export class Quaternion {
constructor(
public x: number,
public y: number,
public z: number,
public w: number,
) {}
multiply(q: Quaternion): Quaternion {
const ax = this.x,
ay = this.y,
az = this.z,
aw = this.w
const bx = q.x,
by = q.y,
bz = q.z,
bw = q.w
return new Quaternion(aw * bx + ax * bw + ay * bz - az * by, aw * by - ax * bz + ay * bw + az * bx, aw * bz + ax * by - ay * bx + az * bw, aw * bw - ax * bx - ay * by - az * bz)
}
static FromEulerAngles(x: number, y: number, z: number): Quaternion {
const cx = Math.cos(x / 2),
sx = Math.sin(x / 2)
const cy = Math.cos(y / 2),
sy = Math.sin(y / 2)
const cz = Math.cos(z / 2),
sz = Math.sin(z / 2)
return new Quaternion(sx * cy * cz - cx * sy * sz, cx * sy * cz + sx * cy * sz, cx * cy * sz - sx * sy * cz, cx * cy * cz + sx * sy * sz)
}
static FromEulerVector(v: Vector3): Quaternion {
return Quaternion.FromEulerAngles(v.x, v.y, v.z)
}
}
export class Color3 {
constructor(
public r: number,
public g: number,
public b: number,
) {}
static FromHexString(hex: string): Color3 {
const parsed = parseInt(hex.replace('#', ''), 16)
return new Color3(((parsed >> 16) & 255) / 255, ((parsed >> 8) & 255) / 255, (parsed & 255) / 255)
}
toHexString(): string {
const r = Math.round(this.r * 255)
.toString(16)
.padStart(2, '0')
const g = Math.round(this.g * 255)
.toString(16)
.padStart(2, '0')
const b = Math.round(this.b * 255)
.toString(16)
.padStart(2, '0')
return `#${r}${g}${b}`
}
}
export class Matrix {
// minimal stub
static Identity(): Matrix {
return new Matrix()
}
}
export class Animation {
name: string
targetProperty: string
framePerSecond: number
dataType: number
loopMode: number
keys: { frame: number; value: any }[] = []
static ANIMATIONTYPE_VECTOR3 = 1
constructor(name: string, property: string, framePerSecond: number, dataType: number, loopMode: number = 0) {
this.name = name
this.targetProperty = property
this.framePerSecond = framePerSecond
this.dataType = dataType
this.loopMode = loopMode
}
setKeys(keys: { frame: number; value: any }[]) {
this.keys = keys
}
clone(): Animation {
let a = new Animation(this.name, this.targetProperty, this.framePerSecond, this.dataType, this.loopMode)
a.keys = this.keys.slice().map((key) => Object.assign({}, key))
return a
}
getKeys(): { frame: number; value: any }[] {
return this.keys
}
serialize() {
return {
name: this.name,
targetProperty: this.targetProperty,
framePerSecond: this.framePerSecond,
dataType: this.dataType,
loopMode: this.loopMode,
keys: this.keys,
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment