From 33109d0ee1057b65f2e81be8b67e26ec94ee989d Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sun, 7 Apr 2019 17:34:04 +0100 Subject: [PATCH] feat(vector-pools): update AttribPool, add tests, update readme - add AttribPool.setAttribs() - add opt start index arg for setAttribValues() - update AttribSpec to include opt. initial values - fix readme example - add missing deps --- packages/vector-pools/README.md | 28 +++++----- packages/vector-pools/package.json | 3 ++ packages/vector-pools/src/api.ts | 4 +- packages/vector-pools/src/attrib-pool.ts | 41 +++++++++++---- packages/vector-pools/test/attribs.ts | 67 +++++++++++++++++++----- packages/vector-pools/test/index.ts | 6 --- 6 files changed, 104 insertions(+), 45 deletions(-) delete mode 100644 packages/vector-pools/test/index.ts diff --git a/packages/vector-pools/README.md b/packages/vector-pools/README.md index 5fd76ddb71..1c9b71c840 100644 --- a/packages/vector-pools/README.md +++ b/packages/vector-pools/README.md @@ -54,34 +54,37 @@ 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( +const geo = new AttribPool({ // initial size in bytes (or provide ArrayBuffer or @thi.ng/malloc/MemPool) - 0x200, + mem: { size: 0x200 }, // num elements - 4, + num: 4, // attrib specs (data mapping layout) - { - pos: { type: GLType.F32, size: 3, default: [0, 0, 0], byteOffset: 0 }, - uv: { type: GLType.F32, size: 2, default: [0, 0], byteOffset: 12 }, + 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, default: 0, byteOffset: 32 } + id: { type: GLType.U16, size: 1, byteOffset: 32 } } -); +}); // computed overall stride length geo.byteStride // 36 // set attrib values -geo.setAttribValues("pos", [[-5, 0, 0], [5, 0, 0], [5, 5, 0], [-5, 5, 0]]); -geo.setAttribValues("uv", [[0, 0], [1, 0], [1, 1], [0, 1]]); +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 attrib val +// zero-copy direct manipulation of mapped attrib val v.mulN(null, geo.attribValue("pos", 3), 2); // Float32Array [ -10, 10, 0 ] @@ -95,7 +98,7 @@ v.mulN(null, geo.attribValue("pos", 3), 2); // 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.tuples(geo.attribValues("pos"), geo.attribValues("col")) + tx.zip(geo.attribValues("pos"), geo.attribValues("col")) ); // updated colors @@ -140,7 +143,6 @@ const initAttrib = (gl, loc, attrib) => { initAttrib(gl, attribLocPosition, geo.specs.pos); initAttrib(gl, attribLocNormal, geo.specs.normal); initAttrib(gl, attribLocUV, geo.specs.uv); -initAttrib(gl, attribLocID, geo.specs.id); ``` ### WASM interop diff --git a/packages/vector-pools/package.json b/packages/vector-pools/package.json index f26386a57a..d1d3abd7e9 100644 --- a/packages/vector-pools/package.json +++ b/packages/vector-pools/package.json @@ -33,7 +33,10 @@ }, "dependencies": { "@thi.ng/api": "^6.0.1", + "@thi.ng/binary": "^1.0.5", + "@thi.ng/checks": "^2.1.5", "@thi.ng/malloc": "^2.0.8", + "@thi.ng/transducers": "^5.3.3", "@thi.ng/vectors": "^2.5.2" }, "keywords": [ diff --git a/packages/vector-pools/src/api.ts b/packages/vector-pools/src/api.ts index 5216a5dd13..6d2a9418ec 100644 --- a/packages/vector-pools/src/api.ts +++ b/packages/vector-pools/src/api.ts @@ -5,9 +5,11 @@ import { ReadonlyVec, StridedVec, Vec } from "@thi.ng/vectors"; export interface AttribSpec { type: GLType | Type; size: number; - default?: number | ReadonlyVec; byteOffset: number; stride?: number; + default?: number | ReadonlyVec; + data?: ReadonlyVec | ReadonlyVec[]; + index?: number; } export interface AttribPoolOpts { diff --git a/packages/vector-pools/src/attrib-pool.ts b/packages/vector-pools/src/attrib-pool.ts index 36c82eefeb..a2920b5eea 100644 --- a/packages/vector-pools/src/attrib-pool.ts +++ b/packages/vector-pools/src/attrib-pool.ts @@ -1,19 +1,26 @@ -import { assert, IObjectOf, IRelease, TypedArray } from "@thi.ng/api"; +import { + assert, + IObjectOf, + IRelease, + TypedArray +} from "@thi.ng/api"; import { align, Pow2 } from "@thi.ng/binary"; import { MemPool, SIZEOF, wrap } from "@thi.ng/malloc"; import { range } from "@thi.ng/transducers"; import { ReadonlyVec, Vec, zeroes } from "@thi.ng/vectors"; -import { asNativeType } from "./convert"; import { AttribPoolOpts, AttribSpec } from "./api"; +import { asNativeType } from "./convert"; /* + * 0x00 0x08 0x10 0x18 + * ^ ^ ^ ^ * WASM mem : 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ... * typedarr : 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ... global offset = 4 (bytes) * pos (f32) : X X X X Y Y Y Y X ... offset = 0 (bytes), size = 2 (f32) * uv (f32) : U U U U V V V V ... offset = 8 (bytes), size = 2 (f32) * col (u16) : R R G G B B A A ... offset = 16 (bytes), size = 4 (u16) * - * global stride: 24 + * stride : 24 */ export class AttribPool implements IRelease { attribs: IObjectOf; @@ -77,6 +84,7 @@ export class AttribPool implements IRelease { this.addr = addr; } this.initDefaults(specs); + this.setAttribs(specs); } attribValue(id: string, i: number): number | Vec { @@ -131,17 +139,17 @@ export class AttribPool implements IRelease { return this; } - setAttribValues(id: string, vals: (number | ReadonlyVec)[]) { + setAttribValues(id: string, vals: ReadonlyVec | ReadonlyVec[], index = 0) { const spec = this.specs[id]; assert(!!spec, `invalid attrib: ${id}`); const n = vals.length; - const v = vals[0]; + this.ensure(index + n); const stride = spec.stride; - this.ensure(n); const buf = this.attribs[id]; + const v = vals[0]; const isNum = typeof v === "number"; assert( - () => (!isNum && spec.size > 1) || (isNum && spec.size === 1), + (!isNum && spec.size > 1) || (isNum && spec.size === 1), `incompatible value(s) for attrib: ${id}` ); if (!isNum) { @@ -151,16 +159,27 @@ export class AttribPool implements IRelease { (v).length }` ); - for (let i = 0; i < n; i++) { - buf.set(vals[i], i * stride); + for (let i = 0, j = index * stride; i < n; i++, j += stride) { + buf.set(vals[i], j); } } else { - for (let i = 0; i < n; i++) { - buf[i * stride] = vals[i]; + for (let i = 0, j = index * stride; i < n; i++, j += stride) { + buf[j] = vals[i]; } } } + setAttribs( + specs: IObjectOf< + Partial<{ data: ReadonlyVec | ReadonlyVec[]; index: number }> + > + ) { + for (let id in specs) { + const spec = specs[id]; + spec.data && this.setAttribValues(id, spec.data, spec.index || 0); + } + } + removeAttrib(id: string) { if (!this.attribs[id]) return false; delete this.attribs[id]; diff --git a/packages/vector-pools/test/attribs.ts b/packages/vector-pools/test/attribs.ts index 8fe1a65413..323ea40ec4 100644 --- a/packages/vector-pools/test/attribs.ts +++ b/packages/vector-pools/test/attribs.ts @@ -1,6 +1,6 @@ -import { AttribPool } from "../src/attrib-pool"; import { Type } from "@thi.ng/malloc"; -// import * as assert from "assert"; +import * as assert from "assert"; +import { AttribPool } from "../src/attrib-pool"; describe("vector-pools", () => { it("attribs", () => { @@ -8,19 +8,58 @@ describe("vector-pools", () => { mem: { size: 0x100 }, num: 8, attribs: { - pos: { type: Type.F32, default: [0, 0], size: 2, byteOffset: 0 }, - id: { type: Type.U32, default: 0, size: 1, byteOffset: 8 }, - index: { type: Type.U16, default: 0, size: 1, byteOffset: 12 }, - col: { type: Type.I8, default: [0, 0, 0, 0], size: 4, byteOffset: 14 }, + pos: { + type: Type.F32, + size: 2, // 8 bytes + byteOffset: 0, + data: [[1, 2], [3, 4]] + }, + id: { + type: Type.U32, + size: 1, // 4 bytes + byteOffset: 8, + data: [1, 2], + index: 4 + }, + index: { + type: Type.U16, + size: 1, // 2 bytes + byteOffset: 12, + data: [10, 20] + }, + col: { + type: Type.U8, + size: 4, // 4 bytes + byteOffset: 14, + data: [[128, 129, 130, 131], [255, 254, 253, 252]], + index: 6 + } } }); - pool.setAttribValue("pos", 0, [1, 2]); - pool.setAttribValue("id", 0, 1); - pool.setAttribValue("index", 0, 10); - pool.setAttribValue("col", 0, [128, 129, 130, 131]); - pool.setAttribValue("pos", 1, [3, 4]); - pool.setAttribValue("id", 1, 2); - pool.setAttribValue("index", 1, 20); - pool.setAttribValue("col", 1, [255, 254, 253, 252]); + assert.deepEqual( + [...pool.attribValues("pos")], + [[1, 2], [3, 4], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0]] + ); + assert.deepEqual( + [...pool.attribValues("id")], + [0, 0, 0, 0, 1, 2, 0, 0] + ); + assert.deepEqual( + [...pool.attribValues("index")], + [10, 20, 0, 0, 0, 0, 0, 0] + ); + assert.deepEqual( + [...pool.attribValues("col")], + [ + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [128, 129, 130, 131], + [255, 254, 253, 252] + ] + ); }); }); diff --git a/packages/vector-pools/test/index.ts b/packages/vector-pools/test/index.ts deleted file mode 100644 index b8c58a8837..0000000000 --- a/packages/vector-pools/test/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// import * as assert from "assert"; -// import * as vp from "../src/index"; - -describe("vector-pools", () => { - it("tests pending"); -});