JSPM

@thi.ng/vector-pools

1.0.52
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 52
  • Score
    100M100P100Q97149F
  • License Apache-2.0

Data structures for managing & working with strided, memory mapped vectors

Package Exports

  • @thi.ng/vector-pools

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@thi.ng/vector-pools) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

vector-pools

npm version npm downloads Twitter Follow

This project is part of the @thi.ng/umbrella monorepo.

About

Data structures for managing & working with strided, memory mapped vectors.

This still package provides several data structures for managing & working with memory mapped vectors. Together with @thi.ng/vectors, these structures enable high-level, zero-copy* manipulation of the underlying memory region and are largely intended for WebGL & WASM use cases, e.g. to provide JS friendly views of a structured data region of a WebGL or WASM memory buffer.

* The only copying taking place is to GPU memory

Status

ALPHA - bleeding edge / work-in-progress

Search or submit any issues for this package

This package might be merged with and/or superseded by @thi.ng/ecs / @thi.ng/soa.

  • @thi.ng/ecs - Entity Component System based around typed arrays & sparse sets
  • @thi.ng/malloc - ArrayBuffer based malloc() impl for hybrid JS/WASM use cases, based on thi.ng/tinyalloc
  • @thi.ng/soa - SOA & AOS memory mapped structured views with optional & extensible serialization
  • @thi.ng/unionstruct - C-style struct, union and bitfield read/write views of ArrayBuffers
  • @thi.ng/vectors - Optimized 2d/3d/4d and arbitrary length vector operations
  • @thi.ng/webgl - WebGL & GLSL abstraction layer

Installation

yarn add @thi.ng/vector-pools
// ES module
<script type="module" src="https://unpkg.com/@thi.ng/vector-pools?module" crossorigin></script>

// UMD
<script src="https://unpkg.com/@thi.ng/vector-pools/lib/index.umd.js" crossorigin></script>

Package sizes (gzipped, pre-treeshake): ESM: 3.07 KB / CJS: 3.14 KB / UMD: 3.22 KB

Dependencies

Usage examples

Several demos in this repo's /examples directory are using this package.

A selection:

Screenshot Description Live demo Source
WebGL MSDF text rendering & particle system Demo Source

API

Generated API docs

WebGL geometry definition / manipulation

import { AttribPool, GLType } from "@thi.ng/vector-pools";
import * as v from "@thi.ng/vectors";
import * as tx from "@thi.ng/transducers";

// create an interleaved (AOS layout) attribute buffer w/ default values
const geo = new AttribPool({
    // initial size in bytes (or provide ArrayBuffer or @thi.ng/malloc/MemPool)
    mem: { size: 0x200 },
    // num elements
    num: 4,
    // attrib specs (data mapping layout)
    attribs: {
        pos: { type: GLType.F32, size: 3, byteOffset: 0 },
        uv: { type: GLType.F32, size: 2, byteOffset: 12 },
        col: { type: GLType.F32, size: 3, default: [1, 1, 1], byteOffset: 20 },
        id: { type: GLType.U16, size: 1, byteOffset: 32 }
    }
});

// computed overall stride length
geo.byteStride
// 36

// set attrib values
geo.setAttribs({
    pos: { data: [[-5, 0, 0], [5, 0, 0], [5, 5, 0], [-5, 5, 0]]},
    uv: { data: [[0, 0], [1, 0], [1, 1], [0, 1]] }
});
// ...or individually
geo.setAttribValues("id", [0, 1, 2, 3]);

// get view of individual attrib val
geo.attribValue("pos", 3)
// Float32Array [ -5, 5, 0 ]

// zero-copy direct manipulation of mapped attrib val
v.mulN(null, geo.attribValue("pos", 3), 2);
// Float32Array [ -10, 10, 0 ]

// get iterator of mapped attrib vals (e.g. for batch processing)
[...geo.attribValues("pos")]
// [ Float32Array [ -5, 0, 0 ],
//   Float32Array [ 5, 0, 0 ],
//   Float32Array [ 5, 5, 0 ],
//   Float32Array [ -10, 10, 0 ] ]

// use with transducers, e.g. to map positions to colors
tx.run(
    tx.map(([pos, col]) => v.maddN(col, [0.5, 0.5, 0.5], v.normalize(col, pos), 0.5)),
    tx.zip(geo.attribValues("pos"), geo.attribValues("col"))
);

// updated colors
[...geo.attribValues("col")]
// [ Float32Array [ 0, 0.5, 0.5 ],
//   Float32Array [ 1, 0.5, 0.5 ],
//   Float32Array [ 0.8535534143447876, 0.8535534143447876, 0.5 ],
//   Float32Array [ 0.1464466154575348, 0.8535534143447876, 0.5 ] ]

// dynamically add another attrib
// this will change the overall stride length and re-align all existing attribs
geo.addAttribs({
    normal: { type: GLType.F32, size: 3, default: [0, 0, 1], byteOffset: 36 }
});

// updated overall stride length
geo.byteStride
// 48

// ...Webgl boilerplate omitted
const gl = ...

// only need to use & bind single (interleaved) buffer
// containing all attribs
buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
gl.bufferData(gl.ARRAY_BUFFER, geo.bytes(), gl.STATIC_DRAW);

// helper fn to bind a single shader attrib
const initAttrib = (gl, loc, attrib) => {
    gl.enableVertexAttribArray(loc);
    gl.vertexAttribPointer(
        loc,
        attrib.size,
        attrib.type,
        false,
        attrib.byteStride, // computed by pool
        attrib.byteOffset
    );
};

initAttrib(gl, attribLocPosition, geo.specs.pos);
initAttrib(gl, attribLocNormal, geo.specs.normal);
initAttrib(gl, attribLocUV, geo.specs.uv);

WASM interop

// main.c

#include <emscripten.h>
#include <stdint.h>

typedef struct {
    float pos[3];
    float uv[2];
    float col[3];
    uint16_t id;
} Vertex;

Vertex vertices[] = {
    {.pos = {-5, 0, 0}, .uv = {0, 0}, .col = {1, 0, 0}, .id = 0},
    {.pos = {5, 0, 0}, .uv = {1, 0}, .col = {0, 1, 0}, .id = 1},
    {.pos = {5, 5, 0}, .uv = {1, 1}, .col = {0, 0, 1}, .id = 2},
    {.pos = {-5, 5, 0}, .uv = {0, 1}, .col = {1, 0, 1}, .id = 3},
};

int main() { return 0; }

EMSCRIPTEN_KEEPALIVE Vertex* getVertices() {
    return vertices;
}

EMSCRIPTEN_KEEPALIVE int getNumVertices() {
    return sizeof(vertices) / sizeof(Vertex);
}
import { Type } from "@thi.ng/api";

// ... WASM / Emscripten boilerplate omitted
const Module = ...

// initialize pool from mapped WASM memory
const geo = new vp.AttribPool(
    // map WASM memory
    Module.buffer,
    // num elements (obtained from C function)
    Module._getNumVertices(),
    // attrib specs (data mapping layout)
    // don't specify attrib defaults to avoid overriding
    // values already initialized by WASM code
    {
        pos: { type: Type.F32, size: 3, byteOffset: 0 },
        uv:  { type: Type.F32, size: 2, byteOffset: 12 },
        col: { type: Type.F32, size: 3, byteOffset: 20 },
        id:  { type: Type.U16, size: 1, byteOffset: 32 }
    },
    // pool options
    {
        // don't allow resizing (since we're mapping a fixed sized C array)
        resizable: false,
        // initialize mem pool to start @ C `vertices` array
        mempool: {
            start: Module._getVertices(),
        }
    }
);

[...geo.attribValues("pos")]
// [ Float32Array [ -5, 0, 0 ],
//   Float32Array [ 5, 0, 0 ],
//   Float32Array [ 5, 5, 0 ],
//   Float32Array [ -5, 5, 0 ] ]

Authors

Karsten Schmidt

If this project contributes to an academic publication, please cite it as:

@misc{thing-vector-pools,
  title = "@thi.ng/vector-pools",
  author = "Karsten Schmidt",
  note = "https://thi.ng/vector-pools",
  year = 2018
}

License

© 2018 - 2020 Karsten Schmidt // Apache Software License 2.0