gl-transform
A high-performance library for 3D coordinate transformations between orthogonal bases, optimized for graphics programming (WebGL, Three.js, and real-time rendering pipelines). It simplifies conversions between world space and local coordinate systems (e.g., camera view space, model space) with support for multiple vector types.
What is an Orthogonal Basis?
In 3D graphics, an orthogonal basis (or orthonormal coordinate system) is a set of 3 vectors [u, v, w] that satisfy:
- Orthogonality: Vectors are mutually perpendicular (
u · v = u · w = v · w = 0).
- Unit length: Each vector has a magnitude of 1 (
||u|| = ||v|| = ||w|| = 1).
Common examples in graphics:
- Camera view basis:
u (right), v (up), w (forward).
- Model local basis: Object's local X, Y, Z axes.
- Light space basis: Coordinate system aligned with a directional light.
Features
- Bidirectional Transformations: Convert vectors between world space and orthogonal bases (e.g., camera space ↔ world space).
- Multi-Vector Support: Works with
[number, number, number] (arrays), Float32Array (WebGL/GPU-friendly), and Float64Array (high precision).
- Validation Utility: Check if a set of vectors forms a valid orthogonal basis (critical for debugging coordinate systems).
- Zero Allocation: Reuses output vectors to avoid garbage collection, ideal for real-time rendering.
- Type Safety: Strict TypeScript types ensure consistent vector/basis usage.
Installation
Via npm
npm install gl-transform
Via CDN (IIFE)
<script src="https://unpkg.com/gl-transform@latest/dist/index.global.js"></script>
Quick Start
1. Basic Transformation (World ↔ Camera Space)
import { to, from, OrthoBasis } from 'gl-transform';
const cameraBasis: OrthoBasis<[number, number, number]> = [
[1, 0, 0],
[0, 1, 0],
[0, 0, -1]
];
const worldPoint: [number, number, number] = [5, 3, 2];
const cameraPoint: [number, number, number] = [0, 0, 0];
to(cameraPoint, worldPoint, cameraBasis);
console.log(cameraPoint);
const worldPoint2: [number, number, number] = [0, 0, 0];
from(worldPoint2, cameraPoint, cameraBasis);
console.log(worldPoint2);
2. WebGL Optimization with Float32Array
import { to32, from32, OrthoBasis } from 'gl-transform';
const modelBasis: OrthoBasis<Float32Array> = [
new Float32Array([0, 1, 0]),
new Float32Array([1, 0, 0]),
new Float32Array([0, 0, 1])
];
const localPoint = new Float32Array([1, 0, 0]);
const worldPoint = new Float32Array(3);
from32(worldPoint, localPoint, modelBasis);
console.log(Array.from(worldPoint));
3. Browser Global Usage
<script src="https://unpkg.com/gl-transform@latest/dist/index.global.js"></script>
<script>
const basis = [
[0, 0, 1], [1, 0, 0], [0, 1, 0]
];
console.log(glTransform.isOrthoBasis(basis));
const vector = [3, 4, 5];
const output = [0, 0, 0];
glTransform.to(output, vector, basis);
console.log(output);
</script>
API Reference
Types
Vector3 | 3D vector type, supporting: - [number, number, number] (array) - Float32Array (single-precision) - Float64Array (double-precision) |
OrthoBasis<T> | Orthogonal basis composed of 3 vectors of type T (e.g., OrthoBasis<Float32Array> for WebGL). |
Validation
isOrthoBasis(basis: OrthoBasis<T>, epsilon?: number): boolean
Checks if a set of vectors forms a valid orthogonal basis.
- Parameters:
basis: The basis to validate ([u, v, w]).
epsilon: Tolerance for floating-point errors (default: 1e-6).
- Returns:
true if the basis is orthogonal and unit-length.
Transformations: World → Basis
Convert a vector from world space to a local orthogonal basis.
to(out: [number, number, number], vec: [number, number, number], basis: OrthoBasis<[number, number, number]>): [number, number, number]
Array-based transformation.
to32(out: Float32Array, vec: Float32Array, basis: OrthoBasis<Float32Array>): Float32Array
Float32Array transformation (optimized for WebGL).
to64(out: Float64Array, vec: Float64Array, basis: OrthoBasis<Float64Array>): Float64Array
Float64Array transformation (high-precision).
Transformations: Basis → World
Convert a vector from a local orthogonal basis back to world space.
from(out: [number, number, number], vec: [number, number, number], basis: OrthoBasis<[number, number, number]>): [number, number, number]
Array-based transformation.
from32(out: Float32Array, vec: Float32Array, basis: OrthoBasis<Float32Array>): Float32Array
Float32Array transformation (optimized for WebGL).
from64(out: Float64Array, vec: Float64Array, basis: OrthoBasis<Float64Array>): Float64Array
Float64Array transformation (high-precision).
Performance
- Throughput: ~420 million operations/second (for
to32 in Node.js 20+ on Intel i7-12700H).
- Memory Efficiency:
Float32Array methods use 50% less memory than Float64Array, matching GPU memory constraints.
- No Garbage Collection: Reuses
out parameters to avoid temporary object allocation, critical for smooth real-time rendering.
Use Cases
- Camera view space ↔ World space conversions in 3D renderers.
- Model local space ↔ World space transformations (e.g., positioning objects).
- Light space calculations (shadow mapping, directional light alignment).
- Physics simulations (converting between object-local and world physics coordinates).
License
MIT