p5.tree 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  # p5.tree
2
+ [![npm version](https://img.shields.io/npm/v/p5.tree)](https://www.npmjs.com/package/p5.tree)
2
3
 
3
4
  Shader development, camera keyframes interpolation and space transformations for [WEBGL](https://p5js.org/reference/#/p5/WEBGL) / WebGPU-ready [p5.js v2](https://beta.p5js.org/).
4
5
 
@@ -188,8 +189,8 @@ This section covers matrix operations, matrix/frustum queries, and coordinate sp
188
189
 
189
190
  ## Coordinate space conversions
190
191
 
191
- 1. `transformPosition(point = p5.Tree.ORIGIN, [{ [from = p5.Tree.EYE], [to = p5.Tree.WORLD], [pMatrix], [vMatrix], [eMatrix], [pvMatrix], [ipvMatrix] }])`
192
- 2. `transformDirection(vector = p5.Tree._k, [{ [from = p5.Tree.EYE], [to = p5.Tree.WORLD], [vMatrix], [eMatrix], [pMatrix] }])`
192
+ 1. `mapLocation(point = p5.Tree.ORIGIN, [{ [from = p5.Tree.EYE], [to = p5.Tree.WORLD], [pMatrix], [vMatrix], [eMatrix], [pvMatrix], [ipvMatrix] }])`
193
+ 2. `mapDirection(vector = p5.Tree._k, [{ [from = p5.Tree.EYE], [to = p5.Tree.WORLD], [vMatrix], [eMatrix], [pMatrix] }])`
193
194
 
194
195
  Pass matrix parameters when you have **cached** those matrices (see [Matrix queries](#matrix-queries)) to speed up repeated conversions:
195
196
 
@@ -200,8 +201,8 @@ function draw() {
200
201
  cachedPVI = ipvMatrix() // compute once per frame
201
202
 
202
203
  // many fast conversions using the cached matrix
203
- const a = transformPosition([0, 0, 0], { from: p5.Tree.WORLD, to: p5.Tree.SCREEN, ipvMatrix: cachedPVI })
204
- const b = transformPosition([100, 0, 0], { from: p5.Tree.WORLD, to: p5.Tree.SCREEN, ipvMatrix: cachedPVI })
204
+ const a = mapLocation([0, 0, 0], { from: p5.Tree.WORLD, to: p5.Tree.SCREEN, ipvMatrix: cachedPVI })
205
+ const b = mapLocation([100, 0, 0], { from: p5.Tree.WORLD, to: p5.Tree.SCREEN, ipvMatrix: cachedPVI })
205
206
  // ...
206
207
  }
207
208
  ```
@@ -222,7 +223,7 @@ function draw() {
222
223
  pop()
223
224
 
224
225
  // screen projection of the model origin
225
- const s = transformPosition(p5.Tree.ORIGIN, { from: model, to: p5.Tree.SCREEN })
226
+ const s = mapLocation(p5.Tree.ORIGIN, { from: model, to: p5.Tree.SCREEN })
226
227
  beginHUD()
227
228
  bullsEye({ x: s.x, y: s.y, size: 30 })
228
229
  endHUD()
@@ -234,8 +235,8 @@ function draw() {
234
235
  1. Returned vectors are `p5.Vector` instances.
235
236
  2. `from` and `to` may be matrices or any of: `p5.Tree.WORLD`, `p5.Tree.EYE`, `p5.Tree.SCREEN`, `p5.Tree.NDC`, `p5.Tree.MODEL`.
236
237
  3. When no matrix params are passed, current renderer values are used.
237
- 4. The default `transformPosition()` call (i.e. eye → world at origin) returns the camera world position.
238
- 5. The default `transformDirection()` call returns the normalized camera viewing direction.
238
+ 4. The default `mapLocation()` call (i.e. eye → world at origin) returns the camera world position.
239
+ 5. The default `mapDirection()` call returns the normalized camera viewing direction.
239
240
  6. Useful vector constants: `p5.Tree.ORIGIN`, `p5.Tree._k`, `p5.Tree.i`, `p5.Tree.j`, `p5.Tree.k`, `p5.Tree._i`, `p5.Tree._j`.
240
241
 
241
242
  ## Heads Up Display
@@ -272,36 +273,98 @@ Debug / teaching primitives for visualizing common 3D concepts:
272
273
 
273
274
  ---
274
275
 
275
- # Installation
276
+ # Releases
276
277
 
277
- Link `p5.tree.js` after you have linked in `p5.js`. For example:
278
+ - **Latest (v0.0.2):**
279
+ These links always point to the latest published version on npm.
280
+ - [p5.tree.js (unminified, IIFE)](https://cdn.jsdelivr.net/npm/p5.tree/dist/p5.tree.js)
281
+ - [p5.tree.min.js (minified, IIFE)](https://cdn.jsdelivr.net/npm/p5.tree/dist/p5.tree.min.js)
282
+ - [p5.tree.esm.js (ES module)](https://cdn.jsdelivr.net/npm/p5.tree/dist/p5.tree.esm.js)
283
+ - [npm package](https://www.npmjs.com/package/p5.tree)
278
284
 
279
- ```html
280
- <!doctype html>
281
- <html>
282
- <head>
283
- <script src="p5.js"></script>
284
- <script src="p5.sound.js"></script>
285
- <script src=https://cdn.jsdelivr.net/gh/VisualComputing/p5.tree/p5.tree.js></script>
286
- <script src="sketch.js"></script>
287
- </head>
288
- <body>
289
- </body>
290
- </html>
291
- ```
285
+ - **Current tagged version (v0.0.2):**
286
+ Use these if you want to lock to a specific version.
287
+ - [p5.tree@0.0.2.js (unminified, IIFE)](https://cdn.jsdelivr.net/npm/p5.tree@0.0.2/dist/p5.tree.js)
288
+ - [p5.tree@0.0.2.min.js (minified, IIFE)](https://cdn.jsdelivr.net/npm/p5.tree@0.0.2/dist/p5.tree.min.js)
289
+ - [p5.tree@0.0.2.esm.js (ES module)](https://cdn.jsdelivr.net/npm/p5.tree@0.0.2/dist/p5.tree.esm.js)
290
+ - [npm package (v0.0.2)](https://www.npmjs.com/package/p5.tree/v/0.0.2)
291
+
292
+ ---
293
+
294
+ # Usage
295
+
296
+ The library works in two setups:
297
+
298
+ - **[CDN](#cdn)**: Use the [IIFE](https://developer.mozilla.org/en-US/docs/Glossary/IIFE)
299
+ (Immediately Invoked Function Expression) format with `<script>` tags directly in the browser,
300
+ along with [p5.js](https://beta.p5js.org/).
301
+ - **[npm](#npm-esm)**: Use the
302
+ [ES module](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules)
303
+ version in modern projects with [Vite](https://vitejs.dev/) or another bundler.
304
+
305
+ ## CDN
292
306
 
293
- To include the minified build (when available):
307
+ Include both libraries using `<script>` tags, which run in both [global](https://github.com/processing/p5.js/wiki/Global-and-instance-mode) and [instance mode](https://github.com/processing/p5.js/wiki/Global-and-instance-mode).
294
308
 
295
309
  ```html
296
- <script src=https://cdn.jsdelivr.net/gh/VisualComputing/p5.tree/p5.tree.min.js></script>
310
+ <!-- index.html -->
311
+ <!-- Load p5.js first (required by p5.tree) -->
312
+ <script src="https://cdn.jsdelivr.net/npm/p5/lib/p5.min.js"></script>
313
+
314
+ <!-- Load p5.tree (latest stable version) -->
315
+ <script src="https://cdn.jsdelivr.net/npm/p5.tree/dist/p5.tree.js"></script>
316
+
317
+ <script>
318
+ function setup() {
319
+ createCanvas(600, 400, WEBGL)
320
+
321
+ // Example: draw world axes
322
+ axes(100)
323
+ }
324
+
325
+ function draw() {
326
+ background(0.15)
327
+ orbitControl()
328
+ }
329
+ </script>
330
+ ````
331
+
332
+ You can run the example, which uses global mode, by opening the `index.html` file in a browser, or by using
333
+ [VSCodium](https://vscodium.com/) (recommended) or [Visual Studio Code](https://code.visualstudio.com/)
334
+ with the [Live Server extension](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer).
335
+
336
+ ## npm (ESM)
337
+
338
+ Install both [`p5`](https://www.npmjs.com/package/p5) and [`p5.tree`](https://www.npmjs.com/package/p5.tree) as dependencies:
339
+
340
+ ```bash
341
+ npm i p5 p5.tree
297
342
  ```
298
343
 
299
- # [vs-code](https://code.visualstudio.com/) & [vs-codium](https://vscodium.com/) & [gitpod](https://www.gitpod.io/) hacking instructions
344
+ Then import them in your project’s entry file (e.g. `main.js`) using a
345
+ modern bundler like [Vite](https://vitejs.dev/), which runs in
346
+ [instance mode](https://github.com/processing/p5.js/wiki/Global-and-instance-mode) only:
300
347
 
301
- Clone the repo (`git clone https://github.com/VisualComputing/p5.tree`) and open it with your favorite editor.
348
+ ```js
349
+ // main.js
350
+ import p5 from 'p5'
351
+ import 'p5.tree'
352
+
353
+ const sketch = p => {
354
+ p.setup = () => {
355
+ p.createCanvas(600, 400, p.WEBGL)
356
+
357
+ // Example: draw world axes
358
+ p.axes(100)
359
+ }
360
+
361
+ p.draw = () => {
362
+ p.background(0.15)
363
+ p.orbitControl()
364
+ }
365
+ }
302
366
 
303
- If you are developing against p5 v2, keep an eye on:
367
+ new p5(sketch)
368
+ ```
304
369
 
305
- 1. [Creating libraries](https://beta.p5js.org/contribute/creating_libraries/)
306
- 2. [p5.js source architecture](https://github.com/processing/p5.js/blob/main/src/core/README.md)
307
- 3. [WEBGL mode architecture](https://github.com/processing/p5.js/blob/main/contributor_docs/webgl_mode_architecture.md)
370
+ This approach provides full modularity, clean instance isolation, and compatibility with modern JavaScript tooling.
@@ -2,7 +2,7 @@ import p5 from 'p5';
2
2
 
3
3
  /**
4
4
  * @file Adds Tree rendering functions to the p5 prototype.
5
- * @version 0.0.1
5
+ * @version 0.0.2
6
6
  * @author JP Charalambos
7
7
  * @license GPL-3.0-only
8
8
  *
@@ -38,7 +38,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
38
38
  const CONST = value => ({ value, writable: false, enumerable: true, configurable: false });
39
39
 
40
40
  Object.defineProperties(p5.Tree, {
41
- VERSION: CONST('0.0.1'),
41
+ VERSION: CONST('0.0.2'),
42
42
 
43
43
  NONE: CONST(0),
44
44
 
@@ -301,7 +301,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
301
301
 
302
302
  /**
303
303
  * lMatrix({ from, to }):
304
- * Location transform (mat4) mapping points from `from` space to `to` space.
304
+ * Position transform (mat4) mapping points from `from` space to `to` space.
305
305
  * treegl semantics: to^-1 * from.
306
306
  * @param {object} [opts]
307
307
  * @param {p5.Matrix} [opts.from=new p5.Matrix()] Source frame matrix.
@@ -317,7 +317,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
317
317
 
318
318
  /**
319
319
  * lMatrix({ from, to }):
320
- * Location transform (mat4) mapping points from `from` space to `to` space.
320
+ * Position transform (mat4) mapping points from `from` space to `to` space.
321
321
  * Requires WEBGL.
322
322
  * @param {object} [opts]
323
323
  * @param {p5.Matrix} [opts.from]
@@ -815,7 +815,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
815
815
 
816
816
  /**
817
817
  * Interpolate camera pose at normalized global t in [0..1] along the whole path.
818
- * Also updates internal seg/f so playPath resumes from that location.
818
+ * Also updates internal seg/f so playPath resumes from that position.
819
819
  */
820
820
  const seekGlobal = function (cam, t) {
821
821
  const path = ensurePath(cam);
@@ -1441,7 +1441,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
1441
1441
  };
1442
1442
 
1443
1443
  // ---------------------------------------------------------------------------
1444
- // Space transforms: transformPosition / transformDirection
1444
+ // Space transforms: mapLocation / mapDirection
1445
1445
  // ---------------------------------------------------------------------------
1446
1446
 
1447
1447
  p5.RendererGL.prototype._parseTransformArgs = function (defaultMainArg, ...args) {
@@ -1461,8 +1461,8 @@ p5.registerAddon((p5, fn, lifecycles) => {
1461
1461
  // Points (positions)
1462
1462
  // ---------------------------------------------------------------------------
1463
1463
 
1464
- fn.transformPosition = function (...args) {
1465
- return _rendererGL(this)?.transformPosition(...args);
1464
+ fn.mapLocation = function (...args) {
1465
+ return _rendererGL(this)?.mapLocation(...args);
1466
1466
  };
1467
1467
 
1468
1468
  /**
@@ -1479,12 +1479,12 @@ p5.registerAddon((p5, fn, lifecycles) => {
1479
1479
  * @param {p5.Matrix} [opts.ipvMatrix]
1480
1480
  * @returns {p5.Vector}
1481
1481
  */
1482
- p5.RendererGL.prototype.transformPosition = function (...args) {
1482
+ p5.RendererGL.prototype.mapLocation = function (...args) {
1483
1483
  const { mainArg, options } = this._parseTransformArgs(p5.Tree.ORIGIN, ...args);
1484
- return this._position(mainArg, options);
1484
+ return this._location(mainArg, options);
1485
1485
  };
1486
1486
 
1487
- p5.RendererGL.prototype._position = function (
1487
+ p5.RendererGL.prototype._location = function (
1488
1488
  point = p5.Tree.ORIGIN,
1489
1489
  {
1490
1490
  from = p5.Tree.EYE,
@@ -1598,7 +1598,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
1598
1598
  if (from == p5.Tree.EYE && to instanceof p5.Matrix) {
1599
1599
  return to.copy().invert(to).mult4((eMatrix ?? this.eMatrix()).mult4(point));
1600
1600
  }
1601
- console.error('couldn\'t parse your transformPosition query!');
1601
+ console.error('couldn\'t parse your mapLocation query!');
1602
1602
  return point;
1603
1603
  };
1604
1604
 
@@ -1670,8 +1670,8 @@ p5.registerAddon((p5, fn, lifecycles) => {
1670
1670
  // Directions (vector displacements)
1671
1671
  // ---------------------------------------------------------------------------
1672
1672
 
1673
- fn.transformDirection = function (...args) {
1674
- return _rendererGL(this)?.transformDirection(...args);
1673
+ fn.mapDirection = function (...args) {
1674
+ return _rendererGL(this)?.mapDirection(...args);
1675
1675
  };
1676
1676
 
1677
1677
  /**
@@ -1686,7 +1686,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
1686
1686
  * @param {p5.Matrix} [opts.pMatrix]
1687
1687
  * @returns {p5.Vector}
1688
1688
  */
1689
- p5.RendererGL.prototype.transformDirection = function (...args) {
1689
+ p5.RendererGL.prototype.mapDirection = function (...args) {
1690
1690
  const { mainArg, options } = this._parseTransformArgs(p5.Tree._k, ...args);
1691
1691
  return this._direction(mainArg, options);
1692
1692
  };
@@ -1781,7 +1781,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
1781
1781
  this._screenToWorldDirection(this._ndcToScreenDirection(vector), pMatrix)
1782
1782
  );
1783
1783
  }
1784
- console.error('[p5.tree] transformDirection: could not parse query.');
1784
+ console.error('[p5.tree] mapDirection: could not parse query.');
1785
1785
  return vector;
1786
1786
  };
1787
1787
 
@@ -1792,7 +1792,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
1792
1792
  let dy = eyeVector.y;
1793
1793
  const perspective = pMatrix.mat4[15] === 0;
1794
1794
  if (perspective) {
1795
- const zEye = this._position(p5.Tree.ORIGIN, { from: p5.Tree.WORLD, to: p5.Tree.EYE }).z;
1795
+ const zEye = this._location(p5.Tree.ORIGIN, { from: p5.Tree.WORLD, to: p5.Tree.EYE }).z;
1796
1796
  const k = Math.abs(zEye * Math.tan(pMatrix.fov() / 2));
1797
1797
  dx /= 2 * k / this.height;
1798
1798
  dy /= 2 * k / this.height;
@@ -1814,7 +1814,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
1814
1814
 
1815
1815
  const perspective = pMatrix.mat4[15] === 0;
1816
1816
  if (perspective) {
1817
- const zEye = this._position(p5.Tree.ORIGIN, { from: p5.Tree.WORLD, to: p5.Tree.EYE }).z;
1817
+ const zEye = this._location(p5.Tree.ORIGIN, { from: p5.Tree.WORLD, to: p5.Tree.EYE }).z;
1818
1818
  const k = Math.abs(zEye * Math.tan(pMatrix.fov() / 2));
1819
1819
  dx *= 2 * k / this.height;
1820
1820
  dy *= 2 * k / this.height;
@@ -1869,7 +1869,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
1869
1869
  return this.isOrtho()
1870
1870
  ? Math.abs(this.tPlane() - this.bPlane()) / this.height
1871
1871
  : 2 * Math.abs(
1872
- this.transformPosition(point, { from: p5.Tree.WORLD, to: p5.Tree.EYE }).z
1872
+ this.mapLocation(point, { from: p5.Tree.WORLD, to: p5.Tree.EYE }).z
1873
1873
  ) * Math.tan(this.fov() / 2) / this.height;
1874
1874
  };
1875
1875
 
@@ -2158,10 +2158,10 @@ p5.registerAddon((p5, fn, lifecycles) => {
2158
2158
  // If target screen position not provided, derive it from mMatrix.
2159
2159
  // In that case, treat `size` as world units and convert to pixels locally.
2160
2160
  if (x == null || y == null) {
2161
- const screen = this.transformPosition({ from: mMatrix, to: p5.Tree.SCREEN, pMatrix, vMatrix, pvMatrix });
2161
+ const screen = this.mapLocation({ from: mMatrix, to: p5.Tree.SCREEN, pMatrix, vMatrix, pvMatrix });
2162
2162
  x = screen.x;
2163
2163
  y = screen.y;
2164
- const world = this.transformPosition({ from: mMatrix, to: p5.Tree.WORLD, eMatrix });
2164
+ const world = this.mapLocation({ from: mMatrix, to: p5.Tree.WORLD, eMatrix });
2165
2165
  size = size / this.pixelRatio(world);
2166
2166
  }
2167
2167
  const r = size / 2.0;
@@ -2262,10 +2262,10 @@ p5.registerAddon((p5, fn, lifecycles) => {
2262
2262
  if (!p) return;
2263
2263
 
2264
2264
  if (x == null || y == null) {
2265
- const screen = this.transformPosition({ from: mMatrix, to: p5.Tree.SCREEN, pMatrix, vMatrix, pvMatrix });
2265
+ const screen = this.mapLocation({ from: mMatrix, to: p5.Tree.SCREEN, pMatrix, vMatrix, pvMatrix });
2266
2266
  x = screen.x;
2267
2267
  y = screen.y;
2268
- const world = this.transformPosition({ from: mMatrix, to: p5.Tree.WORLD, eMatrix });
2268
+ const world = this.mapLocation({ from: mMatrix, to: p5.Tree.WORLD, eMatrix });
2269
2269
  size = size / this.pixelRatio(world);
2270
2270
  }
2271
2271
  const half = size / 2.0;
@@ -2315,10 +2315,10 @@ p5.registerAddon((p5, fn, lifecycles) => {
2315
2315
  const p = this._pInst;
2316
2316
  if (!p) return;
2317
2317
  if (x == null || y == null) {
2318
- const screen = this.transformPosition({ from: mMatrix, to: p5.Tree.SCREEN, pMatrix, vMatrix, pvMatrix });
2318
+ const screen = this.mapLocation({ from: mMatrix, to: p5.Tree.SCREEN, pMatrix, vMatrix, pvMatrix });
2319
2319
  x = screen.x;
2320
2320
  y = screen.y;
2321
- const world = this.transformPosition({ from: mMatrix, to: p5.Tree.WORLD, eMatrix });
2321
+ const world = this.mapLocation({ from: mMatrix, to: p5.Tree.WORLD, eMatrix });
2322
2322
  size = size / this.pixelRatio(world);
2323
2323
  }
2324
2324
  const half = size / 2.0;
@@ -2666,7 +2666,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
2666
2666
  const normals = Array(6);
2667
2667
  const distances = Array(6);
2668
2668
  // Camera position and basis in world space.
2669
- const pos = this._position([0, 0, 0], { from: p5.Tree.EYE, to: p5.Tree.WORLD, eMatrix });
2669
+ const pos = this._location([0, 0, 0], { from: p5.Tree.EYE, to: p5.Tree.WORLD, eMatrix });
2670
2670
  const viewDir = this._direction([0, 0, -1], { from: p5.Tree.EYE, to: p5.Tree.WORLD, vMatrix });
2671
2671
  const up = this._direction([0, 1, 0], { from: p5.Tree.EYE, to: p5.Tree.WORLD, vMatrix });
2672
2672
  const right = this._direction([1, 0, 0], { from: p5.Tree.EYE, to: p5.Tree.WORLD, vMatrix });