Skip to content

@carrot/engine-buffers ​

ts

CPU-side typed array wrappers for vertex attributes and triangle indices - the data layer between mesh generation and GPU upload.

Installation ​

bash
npm install @carrot/engine-buffers

Architecture / How It Works ​

This package provides two classes that sit between raw JavaScript arrays and the GPU:

  • FloatBuffer wraps a Float32Array. Used for positions (vec3), normals (vec3), tangents (vec4), UVs (vec2), colours (vec4), and any other float-based vertex attribute. Provides convenience methods for indexed access, bulk writes, slicing, and cloning.

  • IndexBuffer wraps either a Uint16Array or Uint32Array, automatically selecting based on the maximum index value. If all indices fit in 16 bits (max <= 65535), it uses Uint16Array for reduced memory. Otherwise it promotes to Uint32Array. The renderer checks is32Bit to pass the correct type to gl.drawElements.

Both classes are pure CPU data - no WebGL dependency. The renderer is responsible for uploading buffer contents via gl.bufferData.

Both implement [Symbol.iterator] so they work with for...of, spread, and destructuring.

Dependencies ​

None. This package has zero @carrot/* dependencies.

Build ​

bash
npm run build   # runs tsc

Usage Guide ​

CPU-side typed array wrappers for vertex attribute data and triangle indices.

Import ​

ts
import { FloatBuffer, IndexBuffer } from '@carrot/engine-buffers';

Common Patterns ​

1. Creating vertex position data ​

ts
// From an array of values (3 floats per vertex)
const positions = new FloatBuffer([
  -0.5, -0.5, 0,   // vertex 0
   0.5, -0.5, 0,   // vertex 1
   0.0,  0.5, 0,   // vertex 2
]);

2. Pre-allocating and filling ​

ts
const uvs = new FloatBuffer(vertexCount * 2);
for (let i = 0; i < vertexCount; i++) {
  uvs.set(i * 2, u);
  uvs.set(i * 2 + 1, v);
}

3. Bulk write at offset ​

ts
const buf = new FloatBuffer(12);
buf.setAt(0, [1, 0, 0]);   // first vec3
buf.setAt(3, [0, 1, 0]);   // second vec3

4. Index buffer (auto bit-width) ​

ts
// Small mesh - uses Uint16Array automatically
const indices = new IndexBuffer([0, 1, 2, 0, 2, 3]);
console.log(indices.is32Bit); // false

// Large mesh (indices > 65535) - promotes to Uint32Array
const bigIndices = new IndexBuffer([0, 1, 70000]);
console.log(bigIndices.is32Bit); // true

5. Copying between buffers ​

ts
const source = new FloatBuffer([1, 2, 3, 4, 5, 6]);
const dest = new FloatBuffer(6);
dest.copyFrom(source, 0, 0, 3); // copy first 3 elements

6. Iterating ​

ts
const buf = new FloatBuffer([10, 20, 30]);
for (const value of buf) {
  console.log(value); // 10, 20, 30
}

7. Cloning and slicing ​

ts
const original = new FloatBuffer([1, 2, 3, 4, 5, 6]);
const copy = original.clone();         // independent copy
const sub = original.slice(0, 3);      // first 3 elements as new FloatBuffer

Carrot