p5.tree 0.0.1 → 0.0.3

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/dist/p5.tree.js CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  /**
5
5
  * @file Adds Tree rendering functions to the p5 prototype.
6
- * @version 0.0.1
6
+ * @version 0.0.3
7
7
  * @author JP Charalambos
8
8
  * @license GPL-3.0-only
9
9
  *
@@ -39,7 +39,7 @@
39
39
  const CONST = value => ({ value, writable: false, enumerable: true, configurable: false });
40
40
 
41
41
  Object.defineProperties(p5.Tree, {
42
- VERSION: CONST('0.0.1'),
42
+ VERSION: CONST('0.0.3'),
43
43
 
44
44
  NONE: CONST(0),
45
45
 
@@ -49,6 +49,7 @@
49
49
  NDC: CONST('NDC'),
50
50
  SCREEN: CONST('SCREEN'),
51
51
  MODEL: CONST('MODEL'),
52
+ OBJECT: CONST('MODEL'), // alias of MODEL (shader terminology)
52
53
 
53
54
  // Points and vectors
54
55
  ORIGIN: CONST(Object.freeze([0, 0, 0])),
@@ -69,9 +70,6 @@
69
70
  Z: CONST(1 << 4),
70
71
  _Z: CONST(1 << 5),
71
72
  LABELS: CONST(1 << 6),
72
-
73
- DOTS: CONST(0),
74
- SOLID: CONST(1),
75
73
 
76
74
  // bullsEye
77
75
  CIRCLE: CONST(0),
@@ -816,7 +814,7 @@
816
814
 
817
815
  /**
818
816
  * Interpolate camera pose at normalized global t in [0..1] along the whole path.
819
- * Also updates internal seg/f so playPath resumes from that location.
817
+ * Also updates internal seg/f so playPath resumes from that position.
820
818
  */
821
819
  const seekGlobal = function (cam, t) {
822
820
  const path = ensurePath(cam);
@@ -1442,7 +1440,7 @@
1442
1440
  };
1443
1441
 
1444
1442
  // ---------------------------------------------------------------------------
1445
- // Space transforms: transformPosition / transformDirection
1443
+ // Space transforms: mapLocation / mapDirection
1446
1444
  // ---------------------------------------------------------------------------
1447
1445
 
1448
1446
  p5.RendererGL.prototype._parseTransformArgs = function (defaultMainArg, ...args) {
@@ -1462,8 +1460,8 @@
1462
1460
  // Points (positions)
1463
1461
  // ---------------------------------------------------------------------------
1464
1462
 
1465
- fn.transformPosition = function (...args) {
1466
- return _rendererGL(this)?.transformPosition(...args);
1463
+ fn.mapLocation = function (...args) {
1464
+ return _rendererGL(this)?.mapLocation(...args);
1467
1465
  };
1468
1466
 
1469
1467
  /**
@@ -1480,12 +1478,12 @@
1480
1478
  * @param {p5.Matrix} [opts.ipvMatrix]
1481
1479
  * @returns {p5.Vector}
1482
1480
  */
1483
- p5.RendererGL.prototype.transformPosition = function (...args) {
1481
+ p5.RendererGL.prototype.mapLocation = function (...args) {
1484
1482
  const { mainArg, options } = this._parseTransformArgs(p5.Tree.ORIGIN, ...args);
1485
- return this._position(mainArg, options);
1483
+ return this._location(mainArg, options);
1486
1484
  };
1487
1485
 
1488
- p5.RendererGL.prototype._position = function (
1486
+ p5.RendererGL.prototype._location = function (
1489
1487
  point = p5.Tree.ORIGIN,
1490
1488
  {
1491
1489
  from = p5.Tree.EYE,
@@ -1507,25 +1505,25 @@
1507
1505
  to = this.mMatrix({ eMatrix });
1508
1506
  }
1509
1507
  if ((from == p5.Tree.WORLD) && (to == p5.Tree.SCREEN)) {
1510
- return this._worldToScreenPosition({ point, pMatrix, vMatrix, pvMatrix });
1508
+ return this._worldToScreenLocation({ point, pMatrix, vMatrix, pvMatrix });
1511
1509
  }
1512
1510
  if ((from == p5.Tree.SCREEN) && (to == p5.Tree.WORLD)) {
1513
- return this._screenToWorldPosition({ point, pMatrix, vMatrix, pvMatrix, ipvMatrix });
1511
+ return this._screenToWorldLocation({ point, pMatrix, vMatrix, pvMatrix, ipvMatrix });
1514
1512
  }
1515
1513
  if (from == p5.Tree.SCREEN && to == p5.Tree.NDC) {
1516
- return this._screenToNDCPosition(point);
1514
+ return this._screenToNDCLocation(point);
1517
1515
  }
1518
1516
  if (from == p5.Tree.NDC && to == p5.Tree.SCREEN) {
1519
- return this._ndcToScreenPosition(point);
1517
+ return this._ndcToScreenLocation(point);
1520
1518
  }
1521
1519
  if (from == p5.Tree.WORLD && to == p5.Tree.NDC) {
1522
- return this._screenToNDCPosition(
1523
- this._worldToScreenPosition({ point, pMatrix, vMatrix, pvMatrix })
1520
+ return this._screenToNDCLocation(
1521
+ this._worldToScreenLocation({ point, pMatrix, vMatrix, pvMatrix })
1524
1522
  );
1525
1523
  }
1526
1524
  if (from == p5.Tree.NDC && to == p5.Tree.WORLD) {
1527
- return this._screenToWorldPosition({
1528
- point: this._ndcToScreenPosition(point),
1525
+ return this._screenToWorldLocation({
1526
+ point: this._ndcToScreenLocation(point),
1529
1527
  pMatrix,
1530
1528
  vMatrix,
1531
1529
  pvMatrix,
@@ -1537,8 +1535,8 @@
1537
1535
  ? (vMatrix ?? this.vMatrix())
1538
1536
  : to.copy().invert(to)
1539
1537
  ).mult4(
1540
- this._screenToWorldPosition({
1541
- point: this._ndcToScreenPosition(point),
1538
+ this._screenToWorldLocation({
1539
+ point: this._ndcToScreenLocation(point),
1542
1540
  pMatrix,
1543
1541
  vMatrix,
1544
1542
  pvMatrix,
@@ -1547,8 +1545,8 @@
1547
1545
  );
1548
1546
  }
1549
1547
  if ((from instanceof p5.Matrix || from == p5.Tree.EYE) && to == p5.Tree.NDC) {
1550
- return this._screenToNDCPosition(
1551
- this._worldToScreenPosition({
1548
+ return this._screenToNDCLocation(
1549
+ this._worldToScreenLocation({
1552
1550
  point: (from == p5.Tree.EYE
1553
1551
  ? (eMatrix ?? this.eMatrix())
1554
1552
  : from
@@ -1579,11 +1577,11 @@
1579
1577
  ? (vMatrix ?? this.vMatrix())
1580
1578
  : to.copy().invert(to)
1581
1579
  ).mult4(
1582
- this._screenToWorldPosition({ point, pMatrix, vMatrix, pvMatrix, ipvMatrix })
1580
+ this._screenToWorldLocation({ point, pMatrix, vMatrix, pvMatrix, ipvMatrix })
1583
1581
  );
1584
1582
  }
1585
1583
  if ((from instanceof p5.Matrix || from == p5.Tree.EYE) && to == p5.Tree.SCREEN) {
1586
- return this._worldToScreenPosition({
1584
+ return this._worldToScreenLocation({
1587
1585
  point: (from == p5.Tree.EYE
1588
1586
  ? (eMatrix ?? this.eMatrix())
1589
1587
  : from
@@ -1599,11 +1597,11 @@
1599
1597
  if (from == p5.Tree.EYE && to instanceof p5.Matrix) {
1600
1598
  return to.copy().invert(to).mult4((eMatrix ?? this.eMatrix()).mult4(point));
1601
1599
  }
1602
- console.error('couldn\'t parse your transformPosition query!');
1600
+ console.error('couldn\'t parse your mapLocation query!');
1603
1601
  return point;
1604
1602
  };
1605
1603
 
1606
- p5.RendererGL.prototype._ndcToScreenPosition = function (point) {
1604
+ p5.RendererGL.prototype._ndcToScreenLocation = function (point) {
1607
1605
  return new p5.Vector(
1608
1606
  p5.prototype.map(point.x, -1, 1, 0, this.width),
1609
1607
  p5.prototype.map(point.y, -1, 1, 0, this.height),
@@ -1611,7 +1609,7 @@
1611
1609
  );
1612
1610
  };
1613
1611
 
1614
- p5.RendererGL.prototype._screenToNDCPosition = function (point) {
1612
+ p5.RendererGL.prototype._screenToNDCLocation = function (point) {
1615
1613
  return new p5.Vector(
1616
1614
  p5.prototype.map(point.x, 0, this.width, -1, 1),
1617
1615
  p5.prototype.map(point.y, 0, this.height, -1, 1),
@@ -1619,7 +1617,7 @@
1619
1617
  );
1620
1618
  };
1621
1619
 
1622
- p5.RendererGL.prototype._worldToScreenPosition = function ({
1620
+ p5.RendererGL.prototype._worldToScreenLocation = function ({
1623
1621
  point = new p5.Vector(0, 0, 0.5),
1624
1622
  pMatrix,
1625
1623
  vMatrix,
@@ -1642,7 +1640,7 @@
1642
1640
  return new p5.Vector(target[0], target[1], target[2]);
1643
1641
  };
1644
1642
 
1645
- p5.RendererGL.prototype._screenToWorldPosition = function ({
1643
+ p5.RendererGL.prototype._screenToWorldLocation = function ({
1646
1644
  point = new p5.Vector(this.width / 2, this.height / 2, 0.5),
1647
1645
  pMatrix,
1648
1646
  vMatrix,
@@ -1671,8 +1669,8 @@
1671
1669
  // Directions (vector displacements)
1672
1670
  // ---------------------------------------------------------------------------
1673
1671
 
1674
- fn.transformDirection = function (...args) {
1675
- return _rendererGL(this)?.transformDirection(...args);
1672
+ fn.mapDirection = function (...args) {
1673
+ return _rendererGL(this)?.mapDirection(...args);
1676
1674
  };
1677
1675
 
1678
1676
  /**
@@ -1687,7 +1685,7 @@
1687
1685
  * @param {p5.Matrix} [opts.pMatrix]
1688
1686
  * @returns {p5.Vector}
1689
1687
  */
1690
- p5.RendererGL.prototype.transformDirection = function (...args) {
1688
+ p5.RendererGL.prototype.mapDirection = function (...args) {
1691
1689
  const { mainArg, options } = this._parseTransformArgs(p5.Tree._k, ...args);
1692
1690
  return this._direction(mainArg, options);
1693
1691
  };
@@ -1782,7 +1780,7 @@
1782
1780
  this._screenToWorldDirection(this._ndcToScreenDirection(vector), pMatrix)
1783
1781
  );
1784
1782
  }
1785
- console.error('[p5.tree] transformDirection: could not parse query.');
1783
+ console.error('[p5.tree] mapDirection: could not parse query.');
1786
1784
  return vector;
1787
1785
  };
1788
1786
 
@@ -1793,7 +1791,7 @@
1793
1791
  let dy = eyeVector.y;
1794
1792
  const perspective = pMatrix.mat4[15] === 0;
1795
1793
  if (perspective) {
1796
- const zEye = this._position(p5.Tree.ORIGIN, { from: p5.Tree.WORLD, to: p5.Tree.EYE }).z;
1794
+ const zEye = this._location(p5.Tree.ORIGIN, { from: p5.Tree.WORLD, to: p5.Tree.EYE }).z;
1797
1795
  const k = Math.abs(zEye * Math.tan(pMatrix.fov() / 2));
1798
1796
  dx /= 2 * k / this.height;
1799
1797
  dy /= 2 * k / this.height;
@@ -1815,7 +1813,7 @@
1815
1813
 
1816
1814
  const perspective = pMatrix.mat4[15] === 0;
1817
1815
  if (perspective) {
1818
- const zEye = this._position(p5.Tree.ORIGIN, { from: p5.Tree.WORLD, to: p5.Tree.EYE }).z;
1816
+ const zEye = this._location(p5.Tree.ORIGIN, { from: p5.Tree.WORLD, to: p5.Tree.EYE }).z;
1819
1817
  const k = Math.abs(zEye * Math.tan(pMatrix.fov() / 2));
1820
1818
  dx *= 2 * k / this.height;
1821
1819
  dy *= 2 * k / this.height;
@@ -1870,7 +1868,7 @@
1870
1868
  return this.isOrtho()
1871
1869
  ? Math.abs(this.tPlane() - this.bPlane()) / this.height
1872
1870
  : 2 * Math.abs(
1873
- this.transformPosition(point, { from: p5.Tree.WORLD, to: p5.Tree.EYE }).z
1871
+ this.mapLocation(point, { from: p5.Tree.WORLD, to: p5.Tree.EYE }).z
1874
1872
  ) * Math.tan(this.fov() / 2) / this.height;
1875
1873
  };
1876
1874
 
@@ -1966,6 +1964,49 @@
1966
1964
  return this;
1967
1965
  };
1968
1966
 
1967
+ /**
1968
+ * Draws 3D reference axes (X, Y, Z) centered at the origin in model space.
1969
+ *
1970
+ * Each axis can be enabled independently using bitwise flags, and optional
1971
+ * axis labels (X, Y, Z) can be rendered near the positive ends.
1972
+ *
1973
+ * This is a WEBGL-only utility intended for debugging, teaching, and spatial
1974
+ * orientation. Axes are drawn on the current Z=0 plane using the current
1975
+ * stroke settings.
1976
+ *
1977
+ * @method axes
1978
+ * @for p5.RendererGL
1979
+ * @param {Object} [opts] Axes options.
1980
+ * @param {Number} [opts.size=100] Length of each axis in world units.
1981
+ * @param {Array<String>} [opts.colors=['Red','Lime','DodgerBlue']]
1982
+ * Stroke colors for X, Y, and Z axes respectively.
1983
+ * @param {Number} [opts.bits=p5.Tree.LABELS | p5.Tree.X | p5.Tree.Y | p5.Tree.Z]
1984
+ * Bitmask controlling which axes and labels are drawn.
1985
+ *
1986
+ * @example
1987
+ * function draw() {
1988
+ * background(30);
1989
+ * orbitControl();
1990
+ * axes({ size: 300 });
1991
+ * }
1992
+ *
1993
+ * @example
1994
+ * // Draw only X and Z axes, no labels
1995
+ * axes({
1996
+ * size: 200,
1997
+ * bits: p5.Tree.X | p5.Tree.Z
1998
+ * });
1999
+ *
2000
+ * @example
2001
+ * // Draw full axes in both positive and negative directions
2002
+ * axes({
2003
+ * size: 150,
2004
+ * bits: p5.Tree.X | p5.Tree._X |
2005
+ * p5.Tree.Y | p5.Tree._Y |
2006
+ * p5.Tree.Z | p5.Tree._Z |
2007
+ * p5.Tree.LABELS
2008
+ * });
2009
+ */
1969
2010
  p5.RendererGL.prototype.axes = function ({
1970
2011
  size = 100,
1971
2012
  colors = ['Red', 'Lime', 'DodgerBlue'],
@@ -2015,47 +2056,38 @@
2015
2056
  return this;
2016
2057
  };
2017
2058
 
2059
+ /**
2060
+ * Draws a simple X/Y reference grid on the Z=0 plane in the current model space.
2061
+ *
2062
+ * The grid is centered at the origin and spans from `-size` to `+size` on both X and Y.
2063
+ * It draws `subdivisions + 1` lines in each direction (including the borders).
2064
+ *
2065
+ * This is a WEBGL-only utility intended for debugging and spatial reference.
2066
+ *
2067
+ * @method grid
2068
+ * @for p5.RendererGL
2069
+ * @param {Object} [opts] Grid options.
2070
+ * @param {Number} [opts.size=100] Half-extent of the grid in world units.
2071
+ * @param {Number} [opts.subdivisions=10] Number of subdivisions per side (must be >= 1).
2072
+ * @example
2073
+ * function draw() {
2074
+ * background(30);
2075
+ * orbitControl();
2076
+ * grid({ size: 300, subdivisions: 20 });
2077
+ * }
2078
+ */
2018
2079
  p5.RendererGL.prototype.grid = function ({
2019
2080
  size = 100,
2020
- subdivisions = 10,
2021
- style = p5.Tree.SOLID,
2022
- weight = 1,
2023
- minorSubdivisions = 5
2081
+ subdivisions = 10
2024
2082
  } = {}) {
2025
2083
  const p = this._pInst;
2026
- if (!p) return;
2084
+ if (!p) return;
2085
+ subdivisions = Math.max(1, subdivisions);
2027
2086
  p.push();
2028
- if (style === p5.Tree.DOTS) {
2029
- let posi = 0;
2030
- let posj = 0;
2031
- p.strokeWeight(weight * 2);
2032
- p.beginShape(p.POINTS);
2033
- for (let i = 0; i <= subdivisions; ++i) {
2034
- posi = size * (2.0 * i / subdivisions - 1.0);
2035
- for (let j = 0; j <= subdivisions; ++j) {
2036
- posj = size * (2.0 * j / subdivisions - 1.0);
2037
- p.vertex(posi, posj, 0);
2038
- }
2039
- }
2040
- p.endShape();
2041
- const internalSub = Math.max(1, minorSubdivisions | 0);
2042
- const subSubdivisions = subdivisions * internalSub;
2043
- p.strokeWeight(weight);
2044
- p.beginShape(p.POINTS);
2045
- for (let i = 0; i <= subSubdivisions; ++i) {
2046
- posi = size * (2.0 * i / subSubdivisions - 1.0);
2047
- for (let j = 0; j <= subSubdivisions; ++j) {
2048
- posj = size * (2.0 * j / subSubdivisions - 1.0);
2049
- ((i % internalSub) !== 0 || (j % internalSub) !== 0) && p.vertex(posi, posj, 0);
2050
- }
2051
- }
2052
- p.endShape();
2053
- } else {
2054
- for (let i = 0; i <= subdivisions; ++i) {
2055
- const pos = size * (2.0 * i / subdivisions - 1.0);
2056
- p.line(pos, -size, 0, pos, +size, 0);
2057
- p.line(-size, pos, 0, size, pos, 0);
2058
- }
2087
+ for (let i = 0; i <= subdivisions; ++i) {
2088
+ const pos = size * (2.0 * i / subdivisions - 1.0);
2089
+ p.line(pos, -size, 0, pos, +size, 0);
2090
+ p.line(-size, pos, 0, +size, pos, 0);
2059
2091
  }
2060
2092
  p.pop();
2061
2093
  };
@@ -2159,10 +2191,10 @@
2159
2191
  // If target screen position not provided, derive it from mMatrix.
2160
2192
  // In that case, treat `size` as world units and convert to pixels locally.
2161
2193
  if (x == null || y == null) {
2162
- const screen = this.transformPosition({ from: mMatrix, to: p5.Tree.SCREEN, pMatrix, vMatrix, pvMatrix });
2194
+ const screen = this.mapLocation({ from: mMatrix, to: p5.Tree.SCREEN, pMatrix, vMatrix, pvMatrix });
2163
2195
  x = screen.x;
2164
2196
  y = screen.y;
2165
- const world = this.transformPosition({ from: mMatrix, to: p5.Tree.WORLD, eMatrix });
2197
+ const world = this.mapLocation({ from: mMatrix, to: p5.Tree.WORLD, eMatrix });
2166
2198
  size = size / this.pixelRatio(world);
2167
2199
  }
2168
2200
  const r = size / 2.0;
@@ -2263,10 +2295,10 @@
2263
2295
  if (!p) return;
2264
2296
 
2265
2297
  if (x == null || y == null) {
2266
- const screen = this.transformPosition({ from: mMatrix, to: p5.Tree.SCREEN, pMatrix, vMatrix, pvMatrix });
2298
+ const screen = this.mapLocation({ from: mMatrix, to: p5.Tree.SCREEN, pMatrix, vMatrix, pvMatrix });
2267
2299
  x = screen.x;
2268
2300
  y = screen.y;
2269
- const world = this.transformPosition({ from: mMatrix, to: p5.Tree.WORLD, eMatrix });
2301
+ const world = this.mapLocation({ from: mMatrix, to: p5.Tree.WORLD, eMatrix });
2270
2302
  size = size / this.pixelRatio(world);
2271
2303
  }
2272
2304
  const half = size / 2.0;
@@ -2316,10 +2348,10 @@
2316
2348
  const p = this._pInst;
2317
2349
  if (!p) return;
2318
2350
  if (x == null || y == null) {
2319
- const screen = this.transformPosition({ from: mMatrix, to: p5.Tree.SCREEN, pMatrix, vMatrix, pvMatrix });
2351
+ const screen = this.mapLocation({ from: mMatrix, to: p5.Tree.SCREEN, pMatrix, vMatrix, pvMatrix });
2320
2352
  x = screen.x;
2321
2353
  y = screen.y;
2322
- const world = this.transformPosition({ from: mMatrix, to: p5.Tree.WORLD, eMatrix });
2354
+ const world = this.mapLocation({ from: mMatrix, to: p5.Tree.WORLD, eMatrix });
2323
2355
  size = size / this.pixelRatio(world);
2324
2356
  }
2325
2357
  const half = size / 2.0;
@@ -2667,7 +2699,7 @@
2667
2699
  const normals = Array(6);
2668
2700
  const distances = Array(6);
2669
2701
  // Camera position and basis in world space.
2670
- const pos = this._position([0, 0, 0], { from: p5.Tree.EYE, to: p5.Tree.WORLD, eMatrix });
2702
+ const pos = this._location([0, 0, 0], { from: p5.Tree.EYE, to: p5.Tree.WORLD, eMatrix });
2671
2703
  const viewDir = this._direction([0, 0, -1], { from: p5.Tree.EYE, to: p5.Tree.WORLD, vMatrix });
2672
2704
  const up = this._direction([0, 1, 0], { from: p5.Tree.EYE, to: p5.Tree.WORLD, vMatrix });
2673
2705
  const right = this._direction([1, 0, 0], { from: p5.Tree.EYE, to: p5.Tree.WORLD, vMatrix });