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/README.md +86 -31
- package/dist/p5.tree.esm.js +113 -81
- package/dist/p5.tree.esm.js.map +1 -1
- package/dist/p5.tree.js +113 -81
- package/dist/p5.tree.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# p5.tree
|
|
2
|
+
[](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. `
|
|
192
|
-
2. `
|
|
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 =
|
|
204
|
-
const b =
|
|
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 =
|
|
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 `
|
|
238
|
-
5. The default `
|
|
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
|
|
@@ -265,43 +266,97 @@ A small collection of helpers commonly needed in interactive 3D sketches:
|
|
|
265
266
|
Debug / teaching primitives for visualizing common 3D concepts:
|
|
266
267
|
|
|
267
268
|
1. `axes({ size, colors, bits })`
|
|
268
|
-
2. `grid({ size, subdivisions
|
|
269
|
+
2. `grid({ size, subdivisions })`
|
|
269
270
|
3. `cross({ mMatrix, x, y, size, ... })`
|
|
270
271
|
4. `bullsEye({ mMatrix, x, y, size, shape, ... })`
|
|
271
272
|
5. `viewFrustum({ pg, bits, viewer, eMatrix, pMatrix, vMatrix })`
|
|
272
273
|
|
|
273
274
|
---
|
|
274
275
|
|
|
275
|
-
#
|
|
276
|
+
# Releases
|
|
276
277
|
|
|
277
|
-
|
|
278
|
+
- **Latest (v0.0.3):**
|
|
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
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
285
|
+
- **Current tagged version (v0.0.3):**
|
|
286
|
+
Use these if you want to lock to a specific version.
|
|
287
|
+
- [p5.tree@0.0.3.js (unminified, IIFE)](https://cdn.jsdelivr.net/npm/p5.tree@0.0.3/dist/p5.tree.js)
|
|
288
|
+
- [p5.tree@0.0.3.min.js (minified, IIFE)](https://cdn.jsdelivr.net/npm/p5.tree@0.0.3/dist/p5.tree.min.js)
|
|
289
|
+
- [p5.tree@0.0.3.esm.js (ES module)](https://cdn.jsdelivr.net/npm/p5.tree@0.0.3/dist/p5.tree.esm.js)
|
|
290
|
+
- [npm package (v0.0.3)](https://www.npmjs.com/package/p5.tree/v/0.0.3)
|
|
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) (Immediately Invoked Function Expression) format with `<script>` tags directly in the browser, along with [p5.js](https://beta.p5js.org/).
|
|
299
|
+
- **[npm](#npm-esm)**: Use the [ES module](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) version in modern projects with [Vite](https://vitejs.dev/) or another bundler.
|
|
300
|
+
|
|
301
|
+
## CDN
|
|
292
302
|
|
|
293
|
-
|
|
303
|
+
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
304
|
|
|
295
305
|
```html
|
|
296
|
-
|
|
306
|
+
<!-- index.html -->
|
|
307
|
+
<!-- Load p5.js first (required by p5.tree) -->
|
|
308
|
+
<script src="https://cdn.jsdelivr.net/npm/p5/lib/p5.min.js"></script>
|
|
309
|
+
|
|
310
|
+
<!-- Load p5.tree (latest stable version) -->
|
|
311
|
+
<script src="https://cdn.jsdelivr.net/npm/p5.tree/dist/p5.tree.js"></script>
|
|
312
|
+
|
|
313
|
+
<script>
|
|
314
|
+
function setup() {
|
|
315
|
+
createCanvas(600, 400, WEBGL)
|
|
316
|
+
|
|
317
|
+
// Example: draw world axes
|
|
318
|
+
axes(100)
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function draw() {
|
|
322
|
+
background(0.15)
|
|
323
|
+
orbitControl()
|
|
324
|
+
}
|
|
325
|
+
</script>
|
|
326
|
+
````
|
|
327
|
+
|
|
328
|
+
You can run the example, which uses global mode, by opening the `index.html` file in a browser, or by using [VSCodium](https://vscodium.com/) (recommended) or [Visual Studio Code](https://code.visualstudio.com/) with the [Live Server extension](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer).
|
|
329
|
+
|
|
330
|
+
## npm (ESM)
|
|
331
|
+
|
|
332
|
+
Install both [`p5`](https://www.npmjs.com/package/p5) and [`p5.tree`](https://www.npmjs.com/package/p5.tree) as dependencies:
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
npm i p5 p5.tree
|
|
297
336
|
```
|
|
298
337
|
|
|
299
|
-
|
|
338
|
+
Then import them in your project’s entry file (e.g. `main.js`) using a modern bundler like [Vite](https://vitejs.dev/), which runs in [instance mode](https://github.com/processing/p5.js/wiki/Global-and-instance-mode) only:
|
|
300
339
|
|
|
301
|
-
|
|
340
|
+
```js
|
|
341
|
+
// main.js
|
|
342
|
+
import p5 from 'p5'
|
|
343
|
+
import 'p5.tree'
|
|
344
|
+
|
|
345
|
+
const sketch = p => {
|
|
346
|
+
p.setup = () => {
|
|
347
|
+
p.createCanvas(600, 400, p.WEBGL)
|
|
348
|
+
|
|
349
|
+
// Example: draw world axes
|
|
350
|
+
p.axes(100)
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
p.draw = () => {
|
|
354
|
+
p.background(0.15)
|
|
355
|
+
p.orbitControl()
|
|
356
|
+
}
|
|
357
|
+
}
|
|
302
358
|
|
|
303
|
-
|
|
359
|
+
new p5(sketch)
|
|
360
|
+
```
|
|
304
361
|
|
|
305
|
-
|
|
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)
|
|
362
|
+
This approach provides full modularity, clean instance isolation, and compatibility with modern JavaScript tooling.
|
package/dist/p5.tree.esm.js
CHANGED
|
@@ -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.
|
|
5
|
+
* @version 0.0.3
|
|
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.
|
|
41
|
+
VERSION: CONST('0.0.3'),
|
|
42
42
|
|
|
43
43
|
NONE: CONST(0),
|
|
44
44
|
|
|
@@ -48,6 +48,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
48
48
|
NDC: CONST('NDC'),
|
|
49
49
|
SCREEN: CONST('SCREEN'),
|
|
50
50
|
MODEL: CONST('MODEL'),
|
|
51
|
+
OBJECT: CONST('MODEL'), // alias of MODEL (shader terminology)
|
|
51
52
|
|
|
52
53
|
// Points and vectors
|
|
53
54
|
ORIGIN: CONST(Object.freeze([0, 0, 0])),
|
|
@@ -68,9 +69,6 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
68
69
|
Z: CONST(1 << 4),
|
|
69
70
|
_Z: CONST(1 << 5),
|
|
70
71
|
LABELS: CONST(1 << 6),
|
|
71
|
-
|
|
72
|
-
DOTS: CONST(0),
|
|
73
|
-
SOLID: CONST(1),
|
|
74
72
|
|
|
75
73
|
// bullsEye
|
|
76
74
|
CIRCLE: CONST(0),
|
|
@@ -815,7 +813,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
815
813
|
|
|
816
814
|
/**
|
|
817
815
|
* 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
|
|
816
|
+
* Also updates internal seg/f so playPath resumes from that position.
|
|
819
817
|
*/
|
|
820
818
|
const seekGlobal = function (cam, t) {
|
|
821
819
|
const path = ensurePath(cam);
|
|
@@ -1441,7 +1439,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1441
1439
|
};
|
|
1442
1440
|
|
|
1443
1441
|
// ---------------------------------------------------------------------------
|
|
1444
|
-
// Space transforms:
|
|
1442
|
+
// Space transforms: mapLocation / mapDirection
|
|
1445
1443
|
// ---------------------------------------------------------------------------
|
|
1446
1444
|
|
|
1447
1445
|
p5.RendererGL.prototype._parseTransformArgs = function (defaultMainArg, ...args) {
|
|
@@ -1461,8 +1459,8 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1461
1459
|
// Points (positions)
|
|
1462
1460
|
// ---------------------------------------------------------------------------
|
|
1463
1461
|
|
|
1464
|
-
fn.
|
|
1465
|
-
return _rendererGL(this)?.
|
|
1462
|
+
fn.mapLocation = function (...args) {
|
|
1463
|
+
return _rendererGL(this)?.mapLocation(...args);
|
|
1466
1464
|
};
|
|
1467
1465
|
|
|
1468
1466
|
/**
|
|
@@ -1479,12 +1477,12 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1479
1477
|
* @param {p5.Matrix} [opts.ipvMatrix]
|
|
1480
1478
|
* @returns {p5.Vector}
|
|
1481
1479
|
*/
|
|
1482
|
-
p5.RendererGL.prototype.
|
|
1480
|
+
p5.RendererGL.prototype.mapLocation = function (...args) {
|
|
1483
1481
|
const { mainArg, options } = this._parseTransformArgs(p5.Tree.ORIGIN, ...args);
|
|
1484
|
-
return this.
|
|
1482
|
+
return this._location(mainArg, options);
|
|
1485
1483
|
};
|
|
1486
1484
|
|
|
1487
|
-
p5.RendererGL.prototype.
|
|
1485
|
+
p5.RendererGL.prototype._location = function (
|
|
1488
1486
|
point = p5.Tree.ORIGIN,
|
|
1489
1487
|
{
|
|
1490
1488
|
from = p5.Tree.EYE,
|
|
@@ -1506,25 +1504,25 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1506
1504
|
to = this.mMatrix({ eMatrix });
|
|
1507
1505
|
}
|
|
1508
1506
|
if ((from == p5.Tree.WORLD) && (to == p5.Tree.SCREEN)) {
|
|
1509
|
-
return this.
|
|
1507
|
+
return this._worldToScreenLocation({ point, pMatrix, vMatrix, pvMatrix });
|
|
1510
1508
|
}
|
|
1511
1509
|
if ((from == p5.Tree.SCREEN) && (to == p5.Tree.WORLD)) {
|
|
1512
|
-
return this.
|
|
1510
|
+
return this._screenToWorldLocation({ point, pMatrix, vMatrix, pvMatrix, ipvMatrix });
|
|
1513
1511
|
}
|
|
1514
1512
|
if (from == p5.Tree.SCREEN && to == p5.Tree.NDC) {
|
|
1515
|
-
return this.
|
|
1513
|
+
return this._screenToNDCLocation(point);
|
|
1516
1514
|
}
|
|
1517
1515
|
if (from == p5.Tree.NDC && to == p5.Tree.SCREEN) {
|
|
1518
|
-
return this.
|
|
1516
|
+
return this._ndcToScreenLocation(point);
|
|
1519
1517
|
}
|
|
1520
1518
|
if (from == p5.Tree.WORLD && to == p5.Tree.NDC) {
|
|
1521
|
-
return this.
|
|
1522
|
-
this.
|
|
1519
|
+
return this._screenToNDCLocation(
|
|
1520
|
+
this._worldToScreenLocation({ point, pMatrix, vMatrix, pvMatrix })
|
|
1523
1521
|
);
|
|
1524
1522
|
}
|
|
1525
1523
|
if (from == p5.Tree.NDC && to == p5.Tree.WORLD) {
|
|
1526
|
-
return this.
|
|
1527
|
-
point: this.
|
|
1524
|
+
return this._screenToWorldLocation({
|
|
1525
|
+
point: this._ndcToScreenLocation(point),
|
|
1528
1526
|
pMatrix,
|
|
1529
1527
|
vMatrix,
|
|
1530
1528
|
pvMatrix,
|
|
@@ -1536,8 +1534,8 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1536
1534
|
? (vMatrix ?? this.vMatrix())
|
|
1537
1535
|
: to.copy().invert(to)
|
|
1538
1536
|
).mult4(
|
|
1539
|
-
this.
|
|
1540
|
-
point: this.
|
|
1537
|
+
this._screenToWorldLocation({
|
|
1538
|
+
point: this._ndcToScreenLocation(point),
|
|
1541
1539
|
pMatrix,
|
|
1542
1540
|
vMatrix,
|
|
1543
1541
|
pvMatrix,
|
|
@@ -1546,8 +1544,8 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1546
1544
|
);
|
|
1547
1545
|
}
|
|
1548
1546
|
if ((from instanceof p5.Matrix || from == p5.Tree.EYE) && to == p5.Tree.NDC) {
|
|
1549
|
-
return this.
|
|
1550
|
-
this.
|
|
1547
|
+
return this._screenToNDCLocation(
|
|
1548
|
+
this._worldToScreenLocation({
|
|
1551
1549
|
point: (from == p5.Tree.EYE
|
|
1552
1550
|
? (eMatrix ?? this.eMatrix())
|
|
1553
1551
|
: from
|
|
@@ -1578,11 +1576,11 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1578
1576
|
? (vMatrix ?? this.vMatrix())
|
|
1579
1577
|
: to.copy().invert(to)
|
|
1580
1578
|
).mult4(
|
|
1581
|
-
this.
|
|
1579
|
+
this._screenToWorldLocation({ point, pMatrix, vMatrix, pvMatrix, ipvMatrix })
|
|
1582
1580
|
);
|
|
1583
1581
|
}
|
|
1584
1582
|
if ((from instanceof p5.Matrix || from == p5.Tree.EYE) && to == p5.Tree.SCREEN) {
|
|
1585
|
-
return this.
|
|
1583
|
+
return this._worldToScreenLocation({
|
|
1586
1584
|
point: (from == p5.Tree.EYE
|
|
1587
1585
|
? (eMatrix ?? this.eMatrix())
|
|
1588
1586
|
: from
|
|
@@ -1598,11 +1596,11 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1598
1596
|
if (from == p5.Tree.EYE && to instanceof p5.Matrix) {
|
|
1599
1597
|
return to.copy().invert(to).mult4((eMatrix ?? this.eMatrix()).mult4(point));
|
|
1600
1598
|
}
|
|
1601
|
-
console.error('couldn\'t parse your
|
|
1599
|
+
console.error('couldn\'t parse your mapLocation query!');
|
|
1602
1600
|
return point;
|
|
1603
1601
|
};
|
|
1604
1602
|
|
|
1605
|
-
p5.RendererGL.prototype.
|
|
1603
|
+
p5.RendererGL.prototype._ndcToScreenLocation = function (point) {
|
|
1606
1604
|
return new p5.Vector(
|
|
1607
1605
|
p5.prototype.map(point.x, -1, 1, 0, this.width),
|
|
1608
1606
|
p5.prototype.map(point.y, -1, 1, 0, this.height),
|
|
@@ -1610,7 +1608,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1610
1608
|
);
|
|
1611
1609
|
};
|
|
1612
1610
|
|
|
1613
|
-
p5.RendererGL.prototype.
|
|
1611
|
+
p5.RendererGL.prototype._screenToNDCLocation = function (point) {
|
|
1614
1612
|
return new p5.Vector(
|
|
1615
1613
|
p5.prototype.map(point.x, 0, this.width, -1, 1),
|
|
1616
1614
|
p5.prototype.map(point.y, 0, this.height, -1, 1),
|
|
@@ -1618,7 +1616,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1618
1616
|
);
|
|
1619
1617
|
};
|
|
1620
1618
|
|
|
1621
|
-
p5.RendererGL.prototype.
|
|
1619
|
+
p5.RendererGL.prototype._worldToScreenLocation = function ({
|
|
1622
1620
|
point = new p5.Vector(0, 0, 0.5),
|
|
1623
1621
|
pMatrix,
|
|
1624
1622
|
vMatrix,
|
|
@@ -1641,7 +1639,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1641
1639
|
return new p5.Vector(target[0], target[1], target[2]);
|
|
1642
1640
|
};
|
|
1643
1641
|
|
|
1644
|
-
p5.RendererGL.prototype.
|
|
1642
|
+
p5.RendererGL.prototype._screenToWorldLocation = function ({
|
|
1645
1643
|
point = new p5.Vector(this.width / 2, this.height / 2, 0.5),
|
|
1646
1644
|
pMatrix,
|
|
1647
1645
|
vMatrix,
|
|
@@ -1670,8 +1668,8 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1670
1668
|
// Directions (vector displacements)
|
|
1671
1669
|
// ---------------------------------------------------------------------------
|
|
1672
1670
|
|
|
1673
|
-
fn.
|
|
1674
|
-
return _rendererGL(this)?.
|
|
1671
|
+
fn.mapDirection = function (...args) {
|
|
1672
|
+
return _rendererGL(this)?.mapDirection(...args);
|
|
1675
1673
|
};
|
|
1676
1674
|
|
|
1677
1675
|
/**
|
|
@@ -1686,7 +1684,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1686
1684
|
* @param {p5.Matrix} [opts.pMatrix]
|
|
1687
1685
|
* @returns {p5.Vector}
|
|
1688
1686
|
*/
|
|
1689
|
-
p5.RendererGL.prototype.
|
|
1687
|
+
p5.RendererGL.prototype.mapDirection = function (...args) {
|
|
1690
1688
|
const { mainArg, options } = this._parseTransformArgs(p5.Tree._k, ...args);
|
|
1691
1689
|
return this._direction(mainArg, options);
|
|
1692
1690
|
};
|
|
@@ -1781,7 +1779,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1781
1779
|
this._screenToWorldDirection(this._ndcToScreenDirection(vector), pMatrix)
|
|
1782
1780
|
);
|
|
1783
1781
|
}
|
|
1784
|
-
console.error('[p5.tree]
|
|
1782
|
+
console.error('[p5.tree] mapDirection: could not parse query.');
|
|
1785
1783
|
return vector;
|
|
1786
1784
|
};
|
|
1787
1785
|
|
|
@@ -1792,7 +1790,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1792
1790
|
let dy = eyeVector.y;
|
|
1793
1791
|
const perspective = pMatrix.mat4[15] === 0;
|
|
1794
1792
|
if (perspective) {
|
|
1795
|
-
const zEye = this.
|
|
1793
|
+
const zEye = this._location(p5.Tree.ORIGIN, { from: p5.Tree.WORLD, to: p5.Tree.EYE }).z;
|
|
1796
1794
|
const k = Math.abs(zEye * Math.tan(pMatrix.fov() / 2));
|
|
1797
1795
|
dx /= 2 * k / this.height;
|
|
1798
1796
|
dy /= 2 * k / this.height;
|
|
@@ -1814,7 +1812,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1814
1812
|
|
|
1815
1813
|
const perspective = pMatrix.mat4[15] === 0;
|
|
1816
1814
|
if (perspective) {
|
|
1817
|
-
const zEye = this.
|
|
1815
|
+
const zEye = this._location(p5.Tree.ORIGIN, { from: p5.Tree.WORLD, to: p5.Tree.EYE }).z;
|
|
1818
1816
|
const k = Math.abs(zEye * Math.tan(pMatrix.fov() / 2));
|
|
1819
1817
|
dx *= 2 * k / this.height;
|
|
1820
1818
|
dy *= 2 * k / this.height;
|
|
@@ -1869,7 +1867,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1869
1867
|
return this.isOrtho()
|
|
1870
1868
|
? Math.abs(this.tPlane() - this.bPlane()) / this.height
|
|
1871
1869
|
: 2 * Math.abs(
|
|
1872
|
-
this.
|
|
1870
|
+
this.mapLocation(point, { from: p5.Tree.WORLD, to: p5.Tree.EYE }).z
|
|
1873
1871
|
) * Math.tan(this.fov() / 2) / this.height;
|
|
1874
1872
|
};
|
|
1875
1873
|
|
|
@@ -1965,6 +1963,49 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1965
1963
|
return this;
|
|
1966
1964
|
};
|
|
1967
1965
|
|
|
1966
|
+
/**
|
|
1967
|
+
* Draws 3D reference axes (X, Y, Z) centered at the origin in model space.
|
|
1968
|
+
*
|
|
1969
|
+
* Each axis can be enabled independently using bitwise flags, and optional
|
|
1970
|
+
* axis labels (X, Y, Z) can be rendered near the positive ends.
|
|
1971
|
+
*
|
|
1972
|
+
* This is a WEBGL-only utility intended for debugging, teaching, and spatial
|
|
1973
|
+
* orientation. Axes are drawn on the current Z=0 plane using the current
|
|
1974
|
+
* stroke settings.
|
|
1975
|
+
*
|
|
1976
|
+
* @method axes
|
|
1977
|
+
* @for p5.RendererGL
|
|
1978
|
+
* @param {Object} [opts] Axes options.
|
|
1979
|
+
* @param {Number} [opts.size=100] Length of each axis in world units.
|
|
1980
|
+
* @param {Array<String>} [opts.colors=['Red','Lime','DodgerBlue']]
|
|
1981
|
+
* Stroke colors for X, Y, and Z axes respectively.
|
|
1982
|
+
* @param {Number} [opts.bits=p5.Tree.LABELS | p5.Tree.X | p5.Tree.Y | p5.Tree.Z]
|
|
1983
|
+
* Bitmask controlling which axes and labels are drawn.
|
|
1984
|
+
*
|
|
1985
|
+
* @example
|
|
1986
|
+
* function draw() {
|
|
1987
|
+
* background(30);
|
|
1988
|
+
* orbitControl();
|
|
1989
|
+
* axes({ size: 300 });
|
|
1990
|
+
* }
|
|
1991
|
+
*
|
|
1992
|
+
* @example
|
|
1993
|
+
* // Draw only X and Z axes, no labels
|
|
1994
|
+
* axes({
|
|
1995
|
+
* size: 200,
|
|
1996
|
+
* bits: p5.Tree.X | p5.Tree.Z
|
|
1997
|
+
* });
|
|
1998
|
+
*
|
|
1999
|
+
* @example
|
|
2000
|
+
* // Draw full axes in both positive and negative directions
|
|
2001
|
+
* axes({
|
|
2002
|
+
* size: 150,
|
|
2003
|
+
* bits: p5.Tree.X | p5.Tree._X |
|
|
2004
|
+
* p5.Tree.Y | p5.Tree._Y |
|
|
2005
|
+
* p5.Tree.Z | p5.Tree._Z |
|
|
2006
|
+
* p5.Tree.LABELS
|
|
2007
|
+
* });
|
|
2008
|
+
*/
|
|
1968
2009
|
p5.RendererGL.prototype.axes = function ({
|
|
1969
2010
|
size = 100,
|
|
1970
2011
|
colors = ['Red', 'Lime', 'DodgerBlue'],
|
|
@@ -2014,47 +2055,38 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
2014
2055
|
return this;
|
|
2015
2056
|
};
|
|
2016
2057
|
|
|
2058
|
+
/**
|
|
2059
|
+
* Draws a simple X/Y reference grid on the Z=0 plane in the current model space.
|
|
2060
|
+
*
|
|
2061
|
+
* The grid is centered at the origin and spans from `-size` to `+size` on both X and Y.
|
|
2062
|
+
* It draws `subdivisions + 1` lines in each direction (including the borders).
|
|
2063
|
+
*
|
|
2064
|
+
* This is a WEBGL-only utility intended for debugging and spatial reference.
|
|
2065
|
+
*
|
|
2066
|
+
* @method grid
|
|
2067
|
+
* @for p5.RendererGL
|
|
2068
|
+
* @param {Object} [opts] Grid options.
|
|
2069
|
+
* @param {Number} [opts.size=100] Half-extent of the grid in world units.
|
|
2070
|
+
* @param {Number} [opts.subdivisions=10] Number of subdivisions per side (must be >= 1).
|
|
2071
|
+
* @example
|
|
2072
|
+
* function draw() {
|
|
2073
|
+
* background(30);
|
|
2074
|
+
* orbitControl();
|
|
2075
|
+
* grid({ size: 300, subdivisions: 20 });
|
|
2076
|
+
* }
|
|
2077
|
+
*/
|
|
2017
2078
|
p5.RendererGL.prototype.grid = function ({
|
|
2018
2079
|
size = 100,
|
|
2019
|
-
subdivisions = 10
|
|
2020
|
-
style = p5.Tree.SOLID,
|
|
2021
|
-
weight = 1,
|
|
2022
|
-
minorSubdivisions = 5
|
|
2080
|
+
subdivisions = 10
|
|
2023
2081
|
} = {}) {
|
|
2024
2082
|
const p = this._pInst;
|
|
2025
|
-
if (!p) return;
|
|
2083
|
+
if (!p) return;
|
|
2084
|
+
subdivisions = Math.max(1, subdivisions);
|
|
2026
2085
|
p.push();
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
p.
|
|
2031
|
-
p.beginShape(p.POINTS);
|
|
2032
|
-
for (let i = 0; i <= subdivisions; ++i) {
|
|
2033
|
-
posi = size * (2.0 * i / subdivisions - 1.0);
|
|
2034
|
-
for (let j = 0; j <= subdivisions; ++j) {
|
|
2035
|
-
posj = size * (2.0 * j / subdivisions - 1.0);
|
|
2036
|
-
p.vertex(posi, posj, 0);
|
|
2037
|
-
}
|
|
2038
|
-
}
|
|
2039
|
-
p.endShape();
|
|
2040
|
-
const internalSub = Math.max(1, minorSubdivisions | 0);
|
|
2041
|
-
const subSubdivisions = subdivisions * internalSub;
|
|
2042
|
-
p.strokeWeight(weight);
|
|
2043
|
-
p.beginShape(p.POINTS);
|
|
2044
|
-
for (let i = 0; i <= subSubdivisions; ++i) {
|
|
2045
|
-
posi = size * (2.0 * i / subSubdivisions - 1.0);
|
|
2046
|
-
for (let j = 0; j <= subSubdivisions; ++j) {
|
|
2047
|
-
posj = size * (2.0 * j / subSubdivisions - 1.0);
|
|
2048
|
-
((i % internalSub) !== 0 || (j % internalSub) !== 0) && p.vertex(posi, posj, 0);
|
|
2049
|
-
}
|
|
2050
|
-
}
|
|
2051
|
-
p.endShape();
|
|
2052
|
-
} else {
|
|
2053
|
-
for (let i = 0; i <= subdivisions; ++i) {
|
|
2054
|
-
const pos = size * (2.0 * i / subdivisions - 1.0);
|
|
2055
|
-
p.line(pos, -size, 0, pos, +size, 0);
|
|
2056
|
-
p.line(-size, pos, 0, size, pos, 0);
|
|
2057
|
-
}
|
|
2086
|
+
for (let i = 0; i <= subdivisions; ++i) {
|
|
2087
|
+
const pos = size * (2.0 * i / subdivisions - 1.0);
|
|
2088
|
+
p.line(pos, -size, 0, pos, +size, 0);
|
|
2089
|
+
p.line(-size, pos, 0, +size, pos, 0);
|
|
2058
2090
|
}
|
|
2059
2091
|
p.pop();
|
|
2060
2092
|
};
|
|
@@ -2158,10 +2190,10 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
2158
2190
|
// If target screen position not provided, derive it from mMatrix.
|
|
2159
2191
|
// In that case, treat `size` as world units and convert to pixels locally.
|
|
2160
2192
|
if (x == null || y == null) {
|
|
2161
|
-
const screen = this.
|
|
2193
|
+
const screen = this.mapLocation({ from: mMatrix, to: p5.Tree.SCREEN, pMatrix, vMatrix, pvMatrix });
|
|
2162
2194
|
x = screen.x;
|
|
2163
2195
|
y = screen.y;
|
|
2164
|
-
const world = this.
|
|
2196
|
+
const world = this.mapLocation({ from: mMatrix, to: p5.Tree.WORLD, eMatrix });
|
|
2165
2197
|
size = size / this.pixelRatio(world);
|
|
2166
2198
|
}
|
|
2167
2199
|
const r = size / 2.0;
|
|
@@ -2262,10 +2294,10 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
2262
2294
|
if (!p) return;
|
|
2263
2295
|
|
|
2264
2296
|
if (x == null || y == null) {
|
|
2265
|
-
const screen = this.
|
|
2297
|
+
const screen = this.mapLocation({ from: mMatrix, to: p5.Tree.SCREEN, pMatrix, vMatrix, pvMatrix });
|
|
2266
2298
|
x = screen.x;
|
|
2267
2299
|
y = screen.y;
|
|
2268
|
-
const world = this.
|
|
2300
|
+
const world = this.mapLocation({ from: mMatrix, to: p5.Tree.WORLD, eMatrix });
|
|
2269
2301
|
size = size / this.pixelRatio(world);
|
|
2270
2302
|
}
|
|
2271
2303
|
const half = size / 2.0;
|
|
@@ -2315,10 +2347,10 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
2315
2347
|
const p = this._pInst;
|
|
2316
2348
|
if (!p) return;
|
|
2317
2349
|
if (x == null || y == null) {
|
|
2318
|
-
const screen = this.
|
|
2350
|
+
const screen = this.mapLocation({ from: mMatrix, to: p5.Tree.SCREEN, pMatrix, vMatrix, pvMatrix });
|
|
2319
2351
|
x = screen.x;
|
|
2320
2352
|
y = screen.y;
|
|
2321
|
-
const world = this.
|
|
2353
|
+
const world = this.mapLocation({ from: mMatrix, to: p5.Tree.WORLD, eMatrix });
|
|
2322
2354
|
size = size / this.pixelRatio(world);
|
|
2323
2355
|
}
|
|
2324
2356
|
const half = size / 2.0;
|
|
@@ -2666,7 +2698,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
2666
2698
|
const normals = Array(6);
|
|
2667
2699
|
const distances = Array(6);
|
|
2668
2700
|
// Camera position and basis in world space.
|
|
2669
|
-
const pos = this.
|
|
2701
|
+
const pos = this._location([0, 0, 0], { from: p5.Tree.EYE, to: p5.Tree.WORLD, eMatrix });
|
|
2670
2702
|
const viewDir = this._direction([0, 0, -1], { from: p5.Tree.EYE, to: p5.Tree.WORLD, vMatrix });
|
|
2671
2703
|
const up = this._direction([0, 1, 0], { from: p5.Tree.EYE, to: p5.Tree.WORLD, vMatrix });
|
|
2672
2704
|
const right = this._direction([1, 0, 0], { from: p5.Tree.EYE, to: p5.Tree.WORLD, vMatrix });
|