p5.tree 0.0.2 → 0.0.4
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 +12 -20
- package/dist/p5.tree.esm.js +238 -203
- package/dist/p5.tree.esm.js.map +1 -1
- package/dist/p5.tree.js +238 -203
- package/dist/p5.tree.js.map +1 -1
- package/package.json +3 -3
package/dist/p5.tree.esm.js
CHANGED
|
@@ -2,16 +2,16 @@ 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.4
|
|
6
6
|
* @author JP Charalambos
|
|
7
7
|
* @license GPL-3.0-only
|
|
8
8
|
*
|
|
9
9
|
* @description
|
|
10
|
-
* A p5.js
|
|
10
|
+
* A p5.js 3D addon for matrix queries, shader workflows, and space transformations.
|
|
11
11
|
*
|
|
12
12
|
* Camera path recording/playback section.
|
|
13
13
|
*
|
|
14
|
-
* Requires
|
|
14
|
+
* Requires 3D renderer (p5.Camera).
|
|
15
15
|
*
|
|
16
16
|
* Camera API:
|
|
17
17
|
* camera.path : p5.Camera[]
|
|
@@ -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.4'),
|
|
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),
|
|
@@ -99,13 +97,13 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
99
97
|
|
|
100
98
|
/**
|
|
101
99
|
* @private
|
|
102
|
-
* Returns the
|
|
103
|
-
* @param {p5} pInst
|
|
104
|
-
* @returns {p5.
|
|
100
|
+
* Returns the active 3D renderer (WEBGL or WEBGPU) or undefined.
|
|
101
|
+
* @param {p5} pInst - The p5 instance.
|
|
102
|
+
* @returns {p5.Renderer3D|undefined} The active 3D renderer if available.
|
|
105
103
|
*/
|
|
106
|
-
const
|
|
107
|
-
const r = pInst
|
|
108
|
-
return r instanceof p5.
|
|
104
|
+
const _renderer3D = function (pInst) {
|
|
105
|
+
const r = pInst?._renderer;
|
|
106
|
+
return r instanceof p5.Renderer3D ? r : undefined;
|
|
109
107
|
};
|
|
110
108
|
|
|
111
109
|
// ---------------------------------------------------------------------------
|
|
@@ -218,34 +216,34 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
218
216
|
* Returns the current projection matrix (immutable copy).
|
|
219
217
|
* @returns {p5.Matrix}
|
|
220
218
|
*/
|
|
221
|
-
p5.
|
|
219
|
+
p5.Renderer3D.prototype.pMatrix = function () {
|
|
222
220
|
return this.states.uPMatrix.clone();
|
|
223
221
|
};
|
|
224
222
|
|
|
225
223
|
/**
|
|
226
224
|
* Returns the current projection matrix (immutable copy).
|
|
227
|
-
* Requires
|
|
225
|
+
* Requires 3D renderer.
|
|
228
226
|
* @returns {p5.Matrix}
|
|
229
227
|
*/
|
|
230
228
|
fn.pMatrix = function () {
|
|
231
|
-
return
|
|
229
|
+
return _renderer3D(this).pMatrix();
|
|
232
230
|
};
|
|
233
231
|
|
|
234
232
|
/**
|
|
235
233
|
* Returns the current model matrix (immutable copy).
|
|
236
234
|
* @returns {p5.Matrix}
|
|
237
235
|
*/
|
|
238
|
-
p5.
|
|
236
|
+
p5.Renderer3D.prototype.mMatrix = function () {
|
|
239
237
|
return this.states.uModelMatrix.clone();
|
|
240
238
|
};
|
|
241
239
|
|
|
242
240
|
/**
|
|
243
241
|
* Returns the current model matrix (immutable copy).
|
|
244
|
-
* Requires
|
|
242
|
+
* Requires 3D renderer.
|
|
245
243
|
* @returns {p5.Matrix}
|
|
246
244
|
*/
|
|
247
245
|
fn.mMatrix = function () {
|
|
248
|
-
return
|
|
246
|
+
return _renderer3D(this).mMatrix();
|
|
249
247
|
};
|
|
250
248
|
|
|
251
249
|
/**
|
|
@@ -269,46 +267,46 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
269
267
|
* Prefers the renderer cached view matrix when available.
|
|
270
268
|
* @returns {p5.Matrix}
|
|
271
269
|
*/
|
|
272
|
-
p5.
|
|
270
|
+
p5.Renderer3D.prototype.vMatrix = function () {
|
|
273
271
|
return (this.states.uViewMatrix || this.states.curCamera.cameraMatrix).clone();
|
|
274
272
|
};
|
|
275
273
|
|
|
276
274
|
/**
|
|
277
275
|
* Returns the current view matrix (world -> camera) (immutable copy).
|
|
278
|
-
* Requires
|
|
276
|
+
* Requires 3D renderer.
|
|
279
277
|
* @returns {p5.Matrix}
|
|
280
278
|
*/
|
|
281
279
|
fn.vMatrix = function () {
|
|
282
|
-
return
|
|
280
|
+
return _renderer3D(this).vMatrix();
|
|
283
281
|
};
|
|
284
282
|
|
|
285
283
|
/**
|
|
286
284
|
* Returns the current eye matrix (camera -> world) (immutable).
|
|
287
285
|
* @returns {p5.Matrix}
|
|
288
286
|
*/
|
|
289
|
-
p5.
|
|
287
|
+
p5.Renderer3D.prototype.eMatrix = function () {
|
|
290
288
|
return _invert(this.states.uViewMatrix || this.states.curCamera.cameraMatrix);
|
|
291
289
|
};
|
|
292
290
|
|
|
293
291
|
/**
|
|
294
292
|
* Returns the current eye matrix (camera -> world) (immutable).
|
|
295
|
-
* Requires
|
|
293
|
+
* Requires 3D renderer.
|
|
296
294
|
* @returns {p5.Matrix}
|
|
297
295
|
*/
|
|
298
296
|
fn.eMatrix = function () {
|
|
299
|
-
return
|
|
297
|
+
return _renderer3D(this).eMatrix();
|
|
300
298
|
};
|
|
301
299
|
|
|
302
300
|
/**
|
|
303
301
|
* lMatrix({ from, to }):
|
|
304
|
-
*
|
|
302
|
+
* Location transform (mat4) mapping points from `from` space to `to` space.
|
|
305
303
|
* treegl semantics: to^-1 * from.
|
|
306
304
|
* @param {object} [opts]
|
|
307
305
|
* @param {p5.Matrix} [opts.from=new p5.Matrix()] Source frame matrix.
|
|
308
306
|
* @param {p5.Matrix} [opts.to=this.eMatrix()] Target frame matrix.
|
|
309
307
|
* @returns {p5.Matrix}
|
|
310
308
|
*/
|
|
311
|
-
p5.
|
|
309
|
+
p5.Renderer3D.prototype.lMatrix = function ({
|
|
312
310
|
from = new p5.Matrix(4),
|
|
313
311
|
to = this.eMatrix()
|
|
314
312
|
} = {}) {
|
|
@@ -317,15 +315,15 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
317
315
|
|
|
318
316
|
/**
|
|
319
317
|
* lMatrix({ from, to }):
|
|
320
|
-
*
|
|
321
|
-
* Requires
|
|
318
|
+
* Location transform (mat4) mapping points from `from` space to `to` space.
|
|
319
|
+
* Requires 3D renderer.
|
|
322
320
|
* @param {object} [opts]
|
|
323
321
|
* @param {p5.Matrix} [opts.from]
|
|
324
322
|
* @param {p5.Matrix} [opts.to]
|
|
325
323
|
* @returns {p5.Matrix}
|
|
326
324
|
*/
|
|
327
325
|
fn.lMatrix = function (opts = {}) {
|
|
328
|
-
return
|
|
326
|
+
return _renderer3D(this).lMatrix(opts);
|
|
329
327
|
};
|
|
330
328
|
|
|
331
329
|
/**
|
|
@@ -339,7 +337,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
339
337
|
* @param {p5.Matrix} [opts.matrix] Precomputed mat4 override.
|
|
340
338
|
* @returns {p5.Matrix} mat3
|
|
341
339
|
*/
|
|
342
|
-
p5.
|
|
340
|
+
p5.Renderer3D.prototype.dMatrix = function ({
|
|
343
341
|
from = new p5.Matrix(4),
|
|
344
342
|
to = this.eMatrix(),
|
|
345
343
|
matrix
|
|
@@ -357,7 +355,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
357
355
|
/**
|
|
358
356
|
* dMatrix({ from, to, matrix }):
|
|
359
357
|
* Direction transform (mat3) mapping vectors from `from` space to `to` space.
|
|
360
|
-
* Requires
|
|
358
|
+
* Requires 3D renderer.
|
|
361
359
|
* @param {object} [opts]
|
|
362
360
|
* @param {p5.Matrix} [opts.from]
|
|
363
361
|
* @param {p5.Matrix} [opts.to]
|
|
@@ -365,7 +363,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
365
363
|
* @returns {p5.Matrix} mat3
|
|
366
364
|
*/
|
|
367
365
|
fn.dMatrix = function (opts = {}) {
|
|
368
|
-
return
|
|
366
|
+
return _renderer3D(this).dMatrix(opts);
|
|
369
367
|
};
|
|
370
368
|
|
|
371
369
|
/**
|
|
@@ -376,7 +374,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
376
374
|
* @param {p5.Matrix} [opts.mMatrix=this.mMatrix()] Model matrix.
|
|
377
375
|
* @returns {p5.Matrix}
|
|
378
376
|
*/
|
|
379
|
-
p5.
|
|
377
|
+
p5.Renderer3D.prototype.mvMatrix = function ({
|
|
380
378
|
vMatrix = this.vMatrix(),
|
|
381
379
|
mMatrix
|
|
382
380
|
} = {}) {
|
|
@@ -386,14 +384,14 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
386
384
|
/**
|
|
387
385
|
* mvMatrix({ vMatrix, mMatrix }):
|
|
388
386
|
* ModelView matrix (mat4) = M * V (p5-v2 convention).
|
|
389
|
-
* Requires
|
|
387
|
+
* Requires 3D renderer.
|
|
390
388
|
* @param {object} [opts]
|
|
391
389
|
* @param {p5.Matrix} [opts.vMatrix]
|
|
392
390
|
* @param {p5.Matrix} [opts.mMatrix]
|
|
393
391
|
* @returns {p5.Matrix}
|
|
394
392
|
*/
|
|
395
393
|
fn.mvMatrix = function (opts = {}) {
|
|
396
|
-
return
|
|
394
|
+
return _renderer3D(this).mvMatrix(opts);
|
|
397
395
|
};
|
|
398
396
|
|
|
399
397
|
/**
|
|
@@ -405,7 +403,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
405
403
|
* @param {p5.Matrix} [opts.mvMatrix=this.mvMatrix({ mMatrix, vMatrix })] Optional MV matrix override.
|
|
406
404
|
* @returns {p5.Matrix} mat3
|
|
407
405
|
*/
|
|
408
|
-
p5.
|
|
406
|
+
p5.Renderer3D.prototype.nMatrix = function ({
|
|
409
407
|
vMatrix,
|
|
410
408
|
mMatrix,
|
|
411
409
|
mvMatrix = this.mvMatrix({ mMatrix, vMatrix })
|
|
@@ -416,7 +414,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
416
414
|
/**
|
|
417
415
|
* nMatrix({ vMatrix, mMatrix, mvMatrix }):
|
|
418
416
|
* Normal matrix (mat3) = inverseTranspose(linear_part(MV)).
|
|
419
|
-
* Requires
|
|
417
|
+
* Requires 3D renderer.
|
|
420
418
|
* @param {object} [opts]
|
|
421
419
|
* @param {p5.Matrix} [opts.vMatrix]
|
|
422
420
|
* @param {p5.Matrix} [opts.mMatrix]
|
|
@@ -424,7 +422,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
424
422
|
* @returns {p5.Matrix} mat3
|
|
425
423
|
*/
|
|
426
424
|
fn.nMatrix = function (opts = {}) {
|
|
427
|
-
return
|
|
425
|
+
return _renderer3D(this).nMatrix(opts);
|
|
428
426
|
};
|
|
429
427
|
|
|
430
428
|
/**
|
|
@@ -437,7 +435,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
437
435
|
* @param {p5.Matrix} [opts.mvMatrix=this.mvMatrix({ mMatrix, vMatrix })] Optional MV matrix override.
|
|
438
436
|
* @returns {p5.Matrix}
|
|
439
437
|
*/
|
|
440
|
-
p5.
|
|
438
|
+
p5.Renderer3D.prototype.pmvMatrix = function ({
|
|
441
439
|
pMatrix = this.pMatrix(),
|
|
442
440
|
vMatrix,
|
|
443
441
|
mMatrix,
|
|
@@ -449,7 +447,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
449
447
|
/**
|
|
450
448
|
* pmvMatrix({ pMatrix, vMatrix, mMatrix, mvMatrix }):
|
|
451
449
|
* PMV (mat4) = M * V * P (p5-v2 convention).
|
|
452
|
-
* Requires
|
|
450
|
+
* Requires 3D renderer.
|
|
453
451
|
* @param {object} [opts]
|
|
454
452
|
* @param {p5.Matrix} [opts.pMatrix]
|
|
455
453
|
* @param {p5.Matrix} [opts.vMatrix]
|
|
@@ -458,7 +456,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
458
456
|
* @returns {p5.Matrix}
|
|
459
457
|
*/
|
|
460
458
|
fn.pmvMatrix = function (opts = {}) {
|
|
461
|
-
return
|
|
459
|
+
return _renderer3D(this).pmvMatrix(opts);
|
|
462
460
|
};
|
|
463
461
|
|
|
464
462
|
/**
|
|
@@ -469,7 +467,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
469
467
|
* @param {p5.Matrix} [opts.vMatrix=this.vMatrix()] View matrix.
|
|
470
468
|
* @returns {p5.Matrix}
|
|
471
469
|
*/
|
|
472
|
-
p5.
|
|
470
|
+
p5.Renderer3D.prototype.pvMatrix = function ({
|
|
473
471
|
pMatrix = this.pMatrix(),
|
|
474
472
|
vMatrix
|
|
475
473
|
} = {}) {
|
|
@@ -479,14 +477,14 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
479
477
|
/**
|
|
480
478
|
* pvMatrix({ pMatrix, vMatrix }):
|
|
481
479
|
* PV (mat4) = V * P (p5-v2 convention).
|
|
482
|
-
* Requires
|
|
480
|
+
* Requires 3D renderer.
|
|
483
481
|
* @param {object} [opts]
|
|
484
482
|
* @param {p5.Matrix} [opts.pMatrix]
|
|
485
483
|
* @param {p5.Matrix} [opts.vMatrix]
|
|
486
484
|
* @returns {p5.Matrix}
|
|
487
485
|
*/
|
|
488
486
|
fn.pvMatrix = function (opts = {}) {
|
|
489
|
-
return
|
|
487
|
+
return _renderer3D(this).pvMatrix(opts);
|
|
490
488
|
};
|
|
491
489
|
|
|
492
490
|
/**
|
|
@@ -498,7 +496,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
498
496
|
* @param {p5.Matrix} [opts.pvMatrix=this.pvMatrix({ pMatrix, vMatrix })] Optional PV matrix override.
|
|
499
497
|
* @returns {p5.Matrix}
|
|
500
498
|
*/
|
|
501
|
-
p5.
|
|
499
|
+
p5.Renderer3D.prototype.ipvMatrix = function ({
|
|
502
500
|
pMatrix,
|
|
503
501
|
vMatrix,
|
|
504
502
|
pvMatrix = this.pvMatrix({ pMatrix, vMatrix })
|
|
@@ -508,12 +506,12 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
508
506
|
|
|
509
507
|
/**
|
|
510
508
|
* ipvMatrix({ pMatrix, vMatrix, pvMatrix }):
|
|
511
|
-
* Inverse(PV) (mat4). Requires
|
|
509
|
+
* Inverse(PV) (mat4). Requires 3D renderer.
|
|
512
510
|
* @param {object} [opts]
|
|
513
511
|
* @returns {p5.Matrix}
|
|
514
512
|
*/
|
|
515
513
|
fn.ipvMatrix = function (opts = {}) {
|
|
516
|
-
return
|
|
514
|
+
return _renderer3D(this).ipvMatrix(opts);
|
|
517
515
|
};
|
|
518
516
|
|
|
519
517
|
// ---------------------------------------------------------------------------
|
|
@@ -532,17 +530,17 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
532
530
|
* Returns true if the current projection is orthographic.
|
|
533
531
|
* @returns {boolean}
|
|
534
532
|
*/
|
|
535
|
-
p5.
|
|
533
|
+
p5.Renderer3D.prototype.isOrtho = function () {
|
|
536
534
|
return this.pMatrix().isOrtho();
|
|
537
535
|
};
|
|
538
536
|
|
|
539
537
|
/**
|
|
540
538
|
* Returns true if the current projection is orthographic.
|
|
541
|
-
* Requires
|
|
539
|
+
* Requires 3D renderer.
|
|
542
540
|
* @returns {boolean}
|
|
543
541
|
*/
|
|
544
542
|
fn.isOrtho = function () {
|
|
545
|
-
return
|
|
543
|
+
return _renderer3D(this).isOrtho();
|
|
546
544
|
};
|
|
547
545
|
|
|
548
546
|
/**
|
|
@@ -603,7 +601,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
603
601
|
* Near plane distance for the current projection.
|
|
604
602
|
* @returns {number}
|
|
605
603
|
*/
|
|
606
|
-
p5.
|
|
604
|
+
p5.Renderer3D.prototype.nPlane = function () {
|
|
607
605
|
return this.pMatrix().nPlane();
|
|
608
606
|
};
|
|
609
607
|
|
|
@@ -611,7 +609,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
611
609
|
* Far plane distance for the current projection.
|
|
612
610
|
* @returns {number}
|
|
613
611
|
*/
|
|
614
|
-
p5.
|
|
612
|
+
p5.Renderer3D.prototype.fPlane = function () {
|
|
615
613
|
return this.pMatrix().fPlane();
|
|
616
614
|
};
|
|
617
615
|
|
|
@@ -619,7 +617,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
619
617
|
* Left plane for the current projection.
|
|
620
618
|
* @returns {number}
|
|
621
619
|
*/
|
|
622
|
-
p5.
|
|
620
|
+
p5.Renderer3D.prototype.lPlane = function () {
|
|
623
621
|
return this.pMatrix().lPlane();
|
|
624
622
|
};
|
|
625
623
|
|
|
@@ -627,7 +625,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
627
625
|
* Right plane for the current projection.
|
|
628
626
|
* @returns {number}
|
|
629
627
|
*/
|
|
630
|
-
p5.
|
|
628
|
+
p5.Renderer3D.prototype.rPlane = function () {
|
|
631
629
|
return this.pMatrix().rPlane();
|
|
632
630
|
};
|
|
633
631
|
|
|
@@ -635,7 +633,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
635
633
|
* Top plane for the current projection.
|
|
636
634
|
* @returns {number}
|
|
637
635
|
*/
|
|
638
|
-
p5.
|
|
636
|
+
p5.Renderer3D.prototype.tPlane = function () {
|
|
639
637
|
return this.pMatrix().tPlane();
|
|
640
638
|
};
|
|
641
639
|
|
|
@@ -643,62 +641,62 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
643
641
|
* Bottom plane for the current projection.
|
|
644
642
|
* @returns {number}
|
|
645
643
|
*/
|
|
646
|
-
p5.
|
|
644
|
+
p5.Renderer3D.prototype.bPlane = function () {
|
|
647
645
|
return this.pMatrix().bPlane();
|
|
648
646
|
};
|
|
649
647
|
|
|
650
648
|
/**
|
|
651
649
|
* Near plane distance for the current projection.
|
|
652
|
-
* Requires
|
|
650
|
+
* Requires 3D renderer.
|
|
653
651
|
* @returns {number}
|
|
654
652
|
*/
|
|
655
653
|
fn.nPlane = function () {
|
|
656
|
-
return
|
|
654
|
+
return _renderer3D(this).nPlane();
|
|
657
655
|
};
|
|
658
656
|
|
|
659
657
|
/**
|
|
660
658
|
* Far plane distance for the current projection.
|
|
661
|
-
* Requires
|
|
659
|
+
* Requires 3D renderer.
|
|
662
660
|
* @returns {number}
|
|
663
661
|
*/
|
|
664
662
|
fn.fPlane = function () {
|
|
665
|
-
return
|
|
663
|
+
return _renderer3D(this).fPlane();
|
|
666
664
|
};
|
|
667
665
|
|
|
668
666
|
/**
|
|
669
667
|
* Left plane for the current projection.
|
|
670
|
-
* Requires
|
|
668
|
+
* Requires 3D renderer.
|
|
671
669
|
* @returns {number}
|
|
672
670
|
*/
|
|
673
671
|
fn.lPlane = function () {
|
|
674
|
-
return
|
|
672
|
+
return _renderer3D(this).lPlane();
|
|
675
673
|
};
|
|
676
674
|
|
|
677
675
|
/**
|
|
678
676
|
* Right plane for the current projection.
|
|
679
|
-
* Requires
|
|
677
|
+
* Requires 3D renderer.
|
|
680
678
|
* @returns {number}
|
|
681
679
|
*/
|
|
682
680
|
fn.rPlane = function () {
|
|
683
|
-
return
|
|
681
|
+
return _renderer3D(this).rPlane();
|
|
684
682
|
};
|
|
685
683
|
|
|
686
684
|
/**
|
|
687
685
|
* Top plane for the current projection.
|
|
688
|
-
* Requires
|
|
686
|
+
* Requires 3D renderer.
|
|
689
687
|
* @returns {number}
|
|
690
688
|
*/
|
|
691
689
|
fn.tPlane = function () {
|
|
692
|
-
return
|
|
690
|
+
return _renderer3D(this).tPlane();
|
|
693
691
|
};
|
|
694
692
|
|
|
695
693
|
/**
|
|
696
694
|
* Bottom plane for the current projection.
|
|
697
|
-
* Requires
|
|
695
|
+
* Requires 3D renderer.
|
|
698
696
|
* @returns {number}
|
|
699
697
|
*/
|
|
700
698
|
fn.bPlane = function () {
|
|
701
|
-
return
|
|
699
|
+
return _renderer3D(this).bPlane();
|
|
702
700
|
};
|
|
703
701
|
|
|
704
702
|
/**
|
|
@@ -729,7 +727,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
729
727
|
* Vertical field of view (radians) of the current projection.
|
|
730
728
|
* @returns {number|undefined}
|
|
731
729
|
*/
|
|
732
|
-
p5.
|
|
730
|
+
p5.Renderer3D.prototype.fov = function () {
|
|
733
731
|
return this.pMatrix().fov();
|
|
734
732
|
};
|
|
735
733
|
|
|
@@ -737,26 +735,26 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
737
735
|
* Horizontal field of view (radians) of the current projection.
|
|
738
736
|
* @returns {number|undefined}
|
|
739
737
|
*/
|
|
740
|
-
p5.
|
|
738
|
+
p5.Renderer3D.prototype.hfov = function () {
|
|
741
739
|
return this.pMatrix().hfov();
|
|
742
740
|
};
|
|
743
741
|
|
|
744
742
|
/**
|
|
745
743
|
* Vertical field of view (radians) of the current projection.
|
|
746
|
-
* Requires
|
|
744
|
+
* Requires 3D renderer.
|
|
747
745
|
* @returns {number|undefined}
|
|
748
746
|
*/
|
|
749
747
|
fn.fov = function () {
|
|
750
|
-
return
|
|
748
|
+
return _renderer3D(this).fov();
|
|
751
749
|
};
|
|
752
750
|
|
|
753
751
|
/**
|
|
754
752
|
* Horizontal field of view (radians) of the current projection.
|
|
755
|
-
* Requires
|
|
753
|
+
* Requires 3D renderer.
|
|
756
754
|
* @returns {number|undefined}
|
|
757
755
|
*/
|
|
758
756
|
fn.hfov = function () {
|
|
759
|
-
return
|
|
757
|
+
return _renderer3D(this).hfov();
|
|
760
758
|
};
|
|
761
759
|
|
|
762
760
|
// --- private keys (shared internal state across protos) ---
|
|
@@ -1339,7 +1337,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1339
1337
|
|
|
1340
1338
|
/*
|
|
1341
1339
|
// treegl approach:
|
|
1342
|
-
p5.
|
|
1340
|
+
p5.Renderer3D.prototype.beginHUD = function () {
|
|
1343
1341
|
if (this._hudActive === true) return;
|
|
1344
1342
|
const p = this._pInst;
|
|
1345
1343
|
const gl = this.drawingContext;
|
|
@@ -1376,7 +1374,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1376
1374
|
this._hudActive = true;
|
|
1377
1375
|
};
|
|
1378
1376
|
|
|
1379
|
-
p5.
|
|
1377
|
+
p5.Renderer3D.prototype.endHUD = function () {
|
|
1380
1378
|
if (this._hudActive !== true) return;
|
|
1381
1379
|
const p = this._pInst;
|
|
1382
1380
|
const gl = this.drawingContext;
|
|
@@ -1397,46 +1395,54 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1397
1395
|
};
|
|
1398
1396
|
*/
|
|
1399
1397
|
|
|
1400
|
-
p5.
|
|
1398
|
+
p5.Renderer3D.prototype.beginHUD = function () {
|
|
1401
1399
|
if (this._hudActive === true) return;
|
|
1402
1400
|
const p = this._pInst;
|
|
1403
|
-
if (!p) return;
|
|
1404
|
-
const gl = this.drawingContext;
|
|
1405
1401
|
const states = this.states;
|
|
1406
|
-
if (!
|
|
1407
|
-
p.push();
|
|
1402
|
+
if (!p || !states) return;
|
|
1403
|
+
p.push();
|
|
1408
1404
|
p.resetShader();
|
|
1409
|
-
// Ensure HUD space does NOT inherit the user's current model transforms
|
|
1410
|
-
// (e.g. push()/translate()
|
|
1411
1405
|
p.resetMatrix();
|
|
1412
|
-
// ---------------------
|
|
1413
|
-
// --- HUD setup ---
|
|
1414
1406
|
this._hudPrevCam = states.curCamera;
|
|
1415
|
-
this.
|
|
1416
|
-
|
|
1417
|
-
|
|
1407
|
+
this._hudDepthMode = undefined;
|
|
1408
|
+
this._hudDepthWasEnabled = undefined;
|
|
1409
|
+
if (typeof this.clearDepth === 'function') {
|
|
1410
|
+
this.flushDraw?.();
|
|
1411
|
+
this.clearDepth(1);
|
|
1412
|
+
this._hudDepthMode = 'clearDepth';
|
|
1413
|
+
} else {
|
|
1414
|
+
const gl = this.drawingContext;
|
|
1415
|
+
if (gl && typeof gl.isEnabled === 'function' && gl.DEPTH_TEST !== undefined) {
|
|
1416
|
+
this._hudDepthWasEnabled = gl.isEnabled(gl.DEPTH_TEST);
|
|
1417
|
+
gl.flush?.();
|
|
1418
|
+
gl.disable(gl.DEPTH_TEST);
|
|
1419
|
+
this._hudDepthMode = 'depthTestToggle';
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1418
1422
|
if (this._hudCam === undefined) this._hudCam = p.createCamera();
|
|
1419
1423
|
const z = 1e6;
|
|
1420
|
-
// HUD coordinates: x in [0, width], y in [0, height]
|
|
1421
1424
|
this._hudCam.ortho(0, p.width, -p.height, 0, -z, z);
|
|
1422
|
-
// this._hudCam.ortho(0, p.width, 0, -p.height, -z, z); // <- flipped
|
|
1423
1425
|
this._hudCam.camera(0, 0, 1, 0, 0, 0, 0, 1, 0);
|
|
1424
1426
|
p.setCamera(this._hudCam);
|
|
1425
1427
|
this._hudActive = true;
|
|
1426
1428
|
};
|
|
1427
1429
|
|
|
1428
|
-
p5.
|
|
1430
|
+
p5.Renderer3D.prototype.endHUD = function () {
|
|
1429
1431
|
if (this._hudActive !== true) return;
|
|
1430
1432
|
const p = this._pInst;
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1433
|
+
if (!p) return;
|
|
1434
|
+
if (this._hudDepthMode === 'depthTestToggle') {
|
|
1435
|
+
const gl = this.drawingContext;
|
|
1436
|
+
if (gl && gl.DEPTH_TEST !== undefined) {
|
|
1437
|
+
gl.flush?.();
|
|
1438
|
+
this._hudDepthWasEnabled ? gl.enable(gl.DEPTH_TEST) : gl.disable(gl.DEPTH_TEST);
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
p.pop();
|
|
1437
1442
|
this._hudPrevCam !== undefined && p.setCamera(this._hudPrevCam);
|
|
1438
1443
|
this._hudPrevCam = undefined;
|
|
1439
1444
|
this._hudDepthWasEnabled = undefined;
|
|
1445
|
+
this._hudDepthMode = undefined;
|
|
1440
1446
|
this._hudActive = false;
|
|
1441
1447
|
};
|
|
1442
1448
|
|
|
@@ -1444,7 +1450,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1444
1450
|
// Space transforms: mapLocation / mapDirection
|
|
1445
1451
|
// ---------------------------------------------------------------------------
|
|
1446
1452
|
|
|
1447
|
-
p5.
|
|
1453
|
+
p5.Renderer3D.prototype._parseTransformArgs = function (defaultMainArg, ...args) {
|
|
1448
1454
|
let mainArg = defaultMainArg;
|
|
1449
1455
|
const options = {};
|
|
1450
1456
|
for (const arg of args) {
|
|
@@ -1462,7 +1468,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1462
1468
|
// ---------------------------------------------------------------------------
|
|
1463
1469
|
|
|
1464
1470
|
fn.mapLocation = function (...args) {
|
|
1465
|
-
return
|
|
1471
|
+
return _renderer3D(this)?.mapLocation(...args);
|
|
1466
1472
|
};
|
|
1467
1473
|
|
|
1468
1474
|
/**
|
|
@@ -1479,12 +1485,12 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1479
1485
|
* @param {p5.Matrix} [opts.ipvMatrix]
|
|
1480
1486
|
* @returns {p5.Vector}
|
|
1481
1487
|
*/
|
|
1482
|
-
p5.
|
|
1488
|
+
p5.Renderer3D.prototype.mapLocation = function (...args) {
|
|
1483
1489
|
const { mainArg, options } = this._parseTransformArgs(p5.Tree.ORIGIN, ...args);
|
|
1484
1490
|
return this._location(mainArg, options);
|
|
1485
1491
|
};
|
|
1486
1492
|
|
|
1487
|
-
p5.
|
|
1493
|
+
p5.Renderer3D.prototype._location = function (
|
|
1488
1494
|
point = p5.Tree.ORIGIN,
|
|
1489
1495
|
{
|
|
1490
1496
|
from = p5.Tree.EYE,
|
|
@@ -1506,25 +1512,25 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1506
1512
|
to = this.mMatrix({ eMatrix });
|
|
1507
1513
|
}
|
|
1508
1514
|
if ((from == p5.Tree.WORLD) && (to == p5.Tree.SCREEN)) {
|
|
1509
|
-
return this.
|
|
1515
|
+
return this._worldToScreenLocation({ point, pMatrix, vMatrix, pvMatrix });
|
|
1510
1516
|
}
|
|
1511
1517
|
if ((from == p5.Tree.SCREEN) && (to == p5.Tree.WORLD)) {
|
|
1512
|
-
return this.
|
|
1518
|
+
return this._screenToWorldLocation({ point, pMatrix, vMatrix, pvMatrix, ipvMatrix });
|
|
1513
1519
|
}
|
|
1514
1520
|
if (from == p5.Tree.SCREEN && to == p5.Tree.NDC) {
|
|
1515
|
-
return this.
|
|
1521
|
+
return this._screenToNDCLocation(point);
|
|
1516
1522
|
}
|
|
1517
1523
|
if (from == p5.Tree.NDC && to == p5.Tree.SCREEN) {
|
|
1518
|
-
return this.
|
|
1524
|
+
return this._ndcToScreenLocation(point);
|
|
1519
1525
|
}
|
|
1520
1526
|
if (from == p5.Tree.WORLD && to == p5.Tree.NDC) {
|
|
1521
|
-
return this.
|
|
1522
|
-
this.
|
|
1527
|
+
return this._screenToNDCLocation(
|
|
1528
|
+
this._worldToScreenLocation({ point, pMatrix, vMatrix, pvMatrix })
|
|
1523
1529
|
);
|
|
1524
1530
|
}
|
|
1525
1531
|
if (from == p5.Tree.NDC && to == p5.Tree.WORLD) {
|
|
1526
|
-
return this.
|
|
1527
|
-
point: this.
|
|
1532
|
+
return this._screenToWorldLocation({
|
|
1533
|
+
point: this._ndcToScreenLocation(point),
|
|
1528
1534
|
pMatrix,
|
|
1529
1535
|
vMatrix,
|
|
1530
1536
|
pvMatrix,
|
|
@@ -1536,8 +1542,8 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1536
1542
|
? (vMatrix ?? this.vMatrix())
|
|
1537
1543
|
: to.copy().invert(to)
|
|
1538
1544
|
).mult4(
|
|
1539
|
-
this.
|
|
1540
|
-
point: this.
|
|
1545
|
+
this._screenToWorldLocation({
|
|
1546
|
+
point: this._ndcToScreenLocation(point),
|
|
1541
1547
|
pMatrix,
|
|
1542
1548
|
vMatrix,
|
|
1543
1549
|
pvMatrix,
|
|
@@ -1546,8 +1552,8 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1546
1552
|
);
|
|
1547
1553
|
}
|
|
1548
1554
|
if ((from instanceof p5.Matrix || from == p5.Tree.EYE) && to == p5.Tree.NDC) {
|
|
1549
|
-
return this.
|
|
1550
|
-
this.
|
|
1555
|
+
return this._screenToNDCLocation(
|
|
1556
|
+
this._worldToScreenLocation({
|
|
1551
1557
|
point: (from == p5.Tree.EYE
|
|
1552
1558
|
? (eMatrix ?? this.eMatrix())
|
|
1553
1559
|
: from
|
|
@@ -1578,11 +1584,11 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1578
1584
|
? (vMatrix ?? this.vMatrix())
|
|
1579
1585
|
: to.copy().invert(to)
|
|
1580
1586
|
).mult4(
|
|
1581
|
-
this.
|
|
1587
|
+
this._screenToWorldLocation({ point, pMatrix, vMatrix, pvMatrix, ipvMatrix })
|
|
1582
1588
|
);
|
|
1583
1589
|
}
|
|
1584
1590
|
if ((from instanceof p5.Matrix || from == p5.Tree.EYE) && to == p5.Tree.SCREEN) {
|
|
1585
|
-
return this.
|
|
1591
|
+
return this._worldToScreenLocation({
|
|
1586
1592
|
point: (from == p5.Tree.EYE
|
|
1587
1593
|
? (eMatrix ?? this.eMatrix())
|
|
1588
1594
|
: from
|
|
@@ -1602,7 +1608,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1602
1608
|
return point;
|
|
1603
1609
|
};
|
|
1604
1610
|
|
|
1605
|
-
p5.
|
|
1611
|
+
p5.Renderer3D.prototype._ndcToScreenLocation = function (point) {
|
|
1606
1612
|
return new p5.Vector(
|
|
1607
1613
|
p5.prototype.map(point.x, -1, 1, 0, this.width),
|
|
1608
1614
|
p5.prototype.map(point.y, -1, 1, 0, this.height),
|
|
@@ -1610,7 +1616,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1610
1616
|
);
|
|
1611
1617
|
};
|
|
1612
1618
|
|
|
1613
|
-
p5.
|
|
1619
|
+
p5.Renderer3D.prototype._screenToNDCLocation = function (point) {
|
|
1614
1620
|
return new p5.Vector(
|
|
1615
1621
|
p5.prototype.map(point.x, 0, this.width, -1, 1),
|
|
1616
1622
|
p5.prototype.map(point.y, 0, this.height, -1, 1),
|
|
@@ -1618,7 +1624,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1618
1624
|
);
|
|
1619
1625
|
};
|
|
1620
1626
|
|
|
1621
|
-
p5.
|
|
1627
|
+
p5.Renderer3D.prototype._worldToScreenLocation = function ({
|
|
1622
1628
|
point = new p5.Vector(0, 0, 0.5),
|
|
1623
1629
|
pMatrix,
|
|
1624
1630
|
vMatrix,
|
|
@@ -1641,7 +1647,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1641
1647
|
return new p5.Vector(target[0], target[1], target[2]);
|
|
1642
1648
|
};
|
|
1643
1649
|
|
|
1644
|
-
p5.
|
|
1650
|
+
p5.Renderer3D.prototype._screenToWorldLocation = function ({
|
|
1645
1651
|
point = new p5.Vector(this.width / 2, this.height / 2, 0.5),
|
|
1646
1652
|
pMatrix,
|
|
1647
1653
|
vMatrix,
|
|
@@ -1671,7 +1677,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1671
1677
|
// ---------------------------------------------------------------------------
|
|
1672
1678
|
|
|
1673
1679
|
fn.mapDirection = function (...args) {
|
|
1674
|
-
return
|
|
1680
|
+
return _renderer3D(this)?.mapDirection(...args);
|
|
1675
1681
|
};
|
|
1676
1682
|
|
|
1677
1683
|
/**
|
|
@@ -1686,12 +1692,12 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1686
1692
|
* @param {p5.Matrix} [opts.pMatrix]
|
|
1687
1693
|
* @returns {p5.Vector}
|
|
1688
1694
|
*/
|
|
1689
|
-
p5.
|
|
1695
|
+
p5.Renderer3D.prototype.mapDirection = function (...args) {
|
|
1690
1696
|
const { mainArg, options } = this._parseTransformArgs(p5.Tree._k, ...args);
|
|
1691
1697
|
return this._direction(mainArg, options);
|
|
1692
1698
|
};
|
|
1693
1699
|
|
|
1694
|
-
p5.
|
|
1700
|
+
p5.Renderer3D.prototype._direction = function (
|
|
1695
1701
|
vector = p5.Tree._k,
|
|
1696
1702
|
{
|
|
1697
1703
|
from = p5.Tree.EYE,
|
|
@@ -1785,7 +1791,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1785
1791
|
return vector;
|
|
1786
1792
|
};
|
|
1787
1793
|
|
|
1788
|
-
p5.
|
|
1794
|
+
p5.Renderer3D.prototype._worldToScreenDirection = function (vector, pMatrix) {
|
|
1789
1795
|
pMatrix = pMatrix ?? this.pMatrix();
|
|
1790
1796
|
const eyeVector = this._direction(vector, { from: p5.Tree.WORLD, to: p5.Tree.EYE });
|
|
1791
1797
|
let dx = eyeVector.x;
|
|
@@ -1806,7 +1812,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1806
1812
|
return new p5.Vector(dx, dy, dz);
|
|
1807
1813
|
};
|
|
1808
1814
|
|
|
1809
|
-
p5.
|
|
1815
|
+
p5.Renderer3D.prototype._screenToWorldDirection = function (vector, pMatrix) {
|
|
1810
1816
|
pMatrix = pMatrix ?? this.pMatrix();
|
|
1811
1817
|
|
|
1812
1818
|
let dx = vector.x;
|
|
@@ -1830,11 +1836,11 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1830
1836
|
return this._direction(new p5.Vector(dx, dy, dz), { from: p5.Tree.EYE, to: p5.Tree.WORLD });
|
|
1831
1837
|
};
|
|
1832
1838
|
|
|
1833
|
-
p5.
|
|
1839
|
+
p5.Renderer3D.prototype._ndcToScreenDirection = function (vector) {
|
|
1834
1840
|
return new p5.Vector(this.width * vector.x / 2, this.height * vector.y / 2, vector.z / 2);
|
|
1835
1841
|
};
|
|
1836
1842
|
|
|
1837
|
-
p5.
|
|
1843
|
+
p5.Renderer3D.prototype._screenToNDCDirection = function (vector) {
|
|
1838
1844
|
return new p5.Vector(2 * vector.x / this.width, 2 * vector.y / this.height, 2 * vector.z);
|
|
1839
1845
|
};
|
|
1840
1846
|
|
|
@@ -1851,13 +1857,13 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1851
1857
|
* - In orthographic projection, the ratio is constant.
|
|
1852
1858
|
* - In perspective projection, the ratio depends on eye-space depth.
|
|
1853
1859
|
*
|
|
1854
|
-
* Requires
|
|
1860
|
+
* Requires 3D renderer.
|
|
1855
1861
|
*
|
|
1856
1862
|
* @param {p5.Vector|number[]} [point=p5.Tree.ORIGIN] World-space point.
|
|
1857
1863
|
* @returns {number|undefined} World units per pixel at the given point.
|
|
1858
1864
|
*/
|
|
1859
1865
|
fn.pixelRatio = function (point) {
|
|
1860
|
-
return
|
|
1866
|
+
return _renderer3D(this)?.pixelRatio(point);
|
|
1861
1867
|
};
|
|
1862
1868
|
|
|
1863
1869
|
/**
|
|
@@ -1865,7 +1871,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1865
1871
|
* @param {p5.Vector|number[]} [point=p5.Tree.ORIGIN]
|
|
1866
1872
|
* @returns {number}
|
|
1867
1873
|
*/
|
|
1868
|
-
p5.
|
|
1874
|
+
p5.Renderer3D.prototype.pixelRatio = function (point = p5.Tree.ORIGIN) {
|
|
1869
1875
|
return this.isOrtho()
|
|
1870
1876
|
? Math.abs(this.tPlane() - this.bPlane()) / this.height
|
|
1871
1877
|
: 2 * Math.abs(
|
|
@@ -1898,27 +1904,27 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1898
1904
|
|
|
1899
1905
|
/**
|
|
1900
1906
|
* Returns a pointer position in *pixel* coordinates from an arbitrary (x, y) pair.
|
|
1901
|
-
* Delegates to the
|
|
1907
|
+
* Delegates to the active 3D renderer.
|
|
1902
1908
|
*
|
|
1903
1909
|
* Accepts parameters in any order:
|
|
1904
1910
|
* - `number, number` → pointerX, pointerY
|
|
1905
1911
|
* - optional `boolean` → `flip`
|
|
1906
1912
|
*
|
|
1907
1913
|
* @param {...(number|boolean)} args
|
|
1908
|
-
* @returns {number[]|undefined} `[x, y]` in pixels, or undefined if
|
|
1914
|
+
* @returns {number[]|undefined} `[x, y]` in pixels, or undefined if no 3D renderer is active.
|
|
1909
1915
|
*/
|
|
1910
1916
|
fn.pointerPosition = function (...args) {
|
|
1911
|
-
return
|
|
1917
|
+
return _renderer3D(this)?.pointerPosition(...args);
|
|
1912
1918
|
};
|
|
1913
1919
|
|
|
1914
1920
|
/**
|
|
1915
1921
|
* Returns the canvas resolution in *pixel* coordinates.
|
|
1916
|
-
* Delegates to the
|
|
1922
|
+
* Delegates to the active 3D renderer.
|
|
1917
1923
|
*
|
|
1918
|
-
* @returns {number[]|undefined} `[width, height]` in pixels, or undefined if
|
|
1924
|
+
* @returns {number[]|undefined} `[width, height]` in pixels, or undefined if no 3D renderer is active.
|
|
1919
1925
|
*/
|
|
1920
1926
|
fn.resolution = function () {
|
|
1921
|
-
return
|
|
1927
|
+
return _renderer3D(this)?.resolution();
|
|
1922
1928
|
};
|
|
1923
1929
|
|
|
1924
1930
|
/**
|
|
@@ -1931,7 +1937,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1931
1937
|
* @param {...(number|boolean)} args
|
|
1932
1938
|
* @returns {number[]} `[x, y]` in pixels (includes pixelDensity scaling).
|
|
1933
1939
|
*/
|
|
1934
|
-
p5.
|
|
1940
|
+
p5.Renderer3D.prototype.pointerPosition = function (...args) {
|
|
1935
1941
|
let pointerX;
|
|
1936
1942
|
let pointerY;
|
|
1937
1943
|
let flip = true;
|
|
@@ -1951,7 +1957,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1951
1957
|
* Returns the canvas resolution in *pixel* coordinates.
|
|
1952
1958
|
* @returns {number[]} `[width, height]` in pixels (includes pixelDensity scaling).
|
|
1953
1959
|
*/
|
|
1954
|
-
p5.
|
|
1960
|
+
p5.Renderer3D.prototype.resolution = function () {
|
|
1955
1961
|
const pd = this.pixelDensity();
|
|
1956
1962
|
return [pd * this.width, pd * this.height];
|
|
1957
1963
|
};
|
|
@@ -1961,11 +1967,51 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
1961
1967
|
// -------------------------------------------------------------------------
|
|
1962
1968
|
|
|
1963
1969
|
fn.axes = function (opts) {
|
|
1964
|
-
|
|
1970
|
+
_renderer3D(this)?.axes(opts);
|
|
1965
1971
|
return this;
|
|
1966
1972
|
};
|
|
1967
1973
|
|
|
1968
|
-
|
|
1974
|
+
/**
|
|
1975
|
+
* Draws 3D reference axes (X, Y, Z) centered at the origin in model space,
|
|
1976
|
+
* using the current stroke settings.
|
|
1977
|
+
*
|
|
1978
|
+
* Each axis can be enabled independently using bitwise flags, and optional
|
|
1979
|
+
* axis labels (X, Y, Z) can be rendered near the positive ends.
|
|
1980
|
+
*
|
|
1981
|
+
* @method axes
|
|
1982
|
+
* @for p5.Renderer3D
|
|
1983
|
+
* @param {Object} [opts] Axes options.
|
|
1984
|
+
* @param {Number} [opts.size=100] Length of each axis in world units.
|
|
1985
|
+
* @param {Array<String>} [opts.colors=['Red','Lime','DodgerBlue']]
|
|
1986
|
+
* Stroke colors for X, Y, and Z axes respectively.
|
|
1987
|
+
* @param {Number} [opts.bits=p5.Tree.LABELS | p5.Tree.X | p5.Tree.Y | p5.Tree.Z]
|
|
1988
|
+
* Bitmask controlling which axes and labels are drawn.
|
|
1989
|
+
*
|
|
1990
|
+
* @example
|
|
1991
|
+
* function draw() {
|
|
1992
|
+
* background(30);
|
|
1993
|
+
* orbitControl();
|
|
1994
|
+
* axes({ size: 300 });
|
|
1995
|
+
* }
|
|
1996
|
+
*
|
|
1997
|
+
* @example
|
|
1998
|
+
* // Draw only X and Z axes, no labels
|
|
1999
|
+
* axes({
|
|
2000
|
+
* size: 200,
|
|
2001
|
+
* bits: p5.Tree.X | p5.Tree.Z
|
|
2002
|
+
* });
|
|
2003
|
+
*
|
|
2004
|
+
* @example
|
|
2005
|
+
* // Draw full axes in both positive and negative directions
|
|
2006
|
+
* axes({
|
|
2007
|
+
* size: 150,
|
|
2008
|
+
* bits: p5.Tree.X | p5.Tree._X |
|
|
2009
|
+
* p5.Tree.Y | p5.Tree._Y |
|
|
2010
|
+
* p5.Tree.Z | p5.Tree._Z |
|
|
2011
|
+
* p5.Tree.LABELS
|
|
2012
|
+
* });
|
|
2013
|
+
*/
|
|
2014
|
+
p5.Renderer3D.prototype.axes = function ({
|
|
1969
2015
|
size = 100,
|
|
1970
2016
|
colors = ['Red', 'Lime', 'DodgerBlue'],
|
|
1971
2017
|
bits = p5.Tree.LABELS | p5.Tree.X | p5.Tree.Y | p5.Tree.Z
|
|
@@ -2010,51 +2056,40 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
2010
2056
|
};
|
|
2011
2057
|
|
|
2012
2058
|
fn.grid = function (opts) {
|
|
2013
|
-
|
|
2059
|
+
_renderer3D(this)?.grid(opts);
|
|
2014
2060
|
return this;
|
|
2015
2061
|
};
|
|
2016
2062
|
|
|
2017
|
-
|
|
2063
|
+
/**
|
|
2064
|
+
* Draws a simple X/Y reference grid on the Z=0 plane in the current model space.
|
|
2065
|
+
*
|
|
2066
|
+
* The grid is centered at the origin and spans from `-size` to `+size` on both X and Y.
|
|
2067
|
+
* It draws `subdivisions + 1` lines in each direction (including the borders).
|
|
2068
|
+
*
|
|
2069
|
+
* @method grid
|
|
2070
|
+
* @for p5.Renderer3D
|
|
2071
|
+
* @param {Object} [opts] Grid options.
|
|
2072
|
+
* @param {Number} [opts.size=100] Half-extent of the grid in world units.
|
|
2073
|
+
* @param {Number} [opts.subdivisions=10] Number of subdivisions per side (must be >= 1).
|
|
2074
|
+
* @example
|
|
2075
|
+
* function draw() {
|
|
2076
|
+
* background(30);
|
|
2077
|
+
* orbitControl();
|
|
2078
|
+
* grid({ size: 300, subdivisions: 20 });
|
|
2079
|
+
* }
|
|
2080
|
+
*/
|
|
2081
|
+
p5.Renderer3D.prototype.grid = function ({
|
|
2018
2082
|
size = 100,
|
|
2019
|
-
subdivisions = 10
|
|
2020
|
-
style = p5.Tree.SOLID,
|
|
2021
|
-
weight = 1,
|
|
2022
|
-
minorSubdivisions = 5
|
|
2083
|
+
subdivisions = 10
|
|
2023
2084
|
} = {}) {
|
|
2024
2085
|
const p = this._pInst;
|
|
2025
|
-
if (!p) return;
|
|
2086
|
+
if (!p) return;
|
|
2087
|
+
subdivisions = Math.max(1, subdivisions);
|
|
2026
2088
|
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
|
-
}
|
|
2089
|
+
for (let i = 0; i <= subdivisions; ++i) {
|
|
2090
|
+
const pos = size * (2.0 * i / subdivisions - 1.0);
|
|
2091
|
+
p.line(pos, -size, 0, pos, +size, 0);
|
|
2092
|
+
p.line(-size, pos, 0, +size, pos, 0);
|
|
2058
2093
|
}
|
|
2059
2094
|
p.pop();
|
|
2060
2095
|
};
|
|
@@ -2070,7 +2105,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
2070
2105
|
* `p5.Tree.SCREEN`. In that case, `size` is interpreted in *world units* and
|
|
2071
2106
|
* converted to pixels using `pixelRatio()` at the corresponding world point.
|
|
2072
2107
|
*
|
|
2073
|
-
* Requires
|
|
2108
|
+
* Requires 3D renderer.
|
|
2074
2109
|
*
|
|
2075
2110
|
* @param {object} [opts]
|
|
2076
2111
|
* @param {p5.Matrix} [opts.mMatrix] Model-space matrix origin to compute (x, y) from.
|
|
@@ -2085,7 +2120,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
2085
2120
|
* @returns {boolean|undefined}
|
|
2086
2121
|
*/
|
|
2087
2122
|
fn.mousePicking = function (opts) {
|
|
2088
|
-
return
|
|
2123
|
+
return _renderer3D(this)?.mousePicking(opts);
|
|
2089
2124
|
};
|
|
2090
2125
|
|
|
2091
2126
|
/**
|
|
@@ -2095,16 +2130,16 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
2095
2130
|
* `p5.Tree.SCREEN`. In that case, `size` is interpreted in *world units* and
|
|
2096
2131
|
* converted to pixels using `pixelRatio()` at the corresponding world point.
|
|
2097
2132
|
*
|
|
2098
|
-
* Requires
|
|
2133
|
+
* Requires 3D renderer.
|
|
2099
2134
|
*
|
|
2100
2135
|
* @param {...any} args
|
|
2101
2136
|
* @returns {boolean|undefined}
|
|
2102
2137
|
*/
|
|
2103
2138
|
fn.pointerPicking = function (...args) {
|
|
2104
|
-
return
|
|
2139
|
+
return _renderer3D(this)?.pointerPicking(...args);
|
|
2105
2140
|
};
|
|
2106
2141
|
|
|
2107
|
-
p5.
|
|
2142
|
+
p5.Renderer3D.prototype.mousePicking = function ({
|
|
2108
2143
|
mMatrix = this.mMatrix(),
|
|
2109
2144
|
x,
|
|
2110
2145
|
y,
|
|
@@ -2130,7 +2165,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
2130
2165
|
* @param {...any} args
|
|
2131
2166
|
* @returns {boolean}
|
|
2132
2167
|
*/
|
|
2133
|
-
p5.
|
|
2168
|
+
p5.Renderer3D.prototype.pointerPicking = function (...args) {
|
|
2134
2169
|
let pointerX;
|
|
2135
2170
|
let pointerY;
|
|
2136
2171
|
const config = {};
|
|
@@ -2192,7 +2227,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
2192
2227
|
* @param {number} [opts.radius=100] Radius in current space.
|
|
2193
2228
|
* @param {number} [opts.detail=50] Segment count.
|
|
2194
2229
|
*/
|
|
2195
|
-
p5.
|
|
2230
|
+
p5.Renderer3D.prototype._circle = function ({
|
|
2196
2231
|
filled = false,
|
|
2197
2232
|
x = this.width / 2,
|
|
2198
2233
|
y = this.height / 2,
|
|
@@ -2244,11 +2279,11 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
2244
2279
|
* @param {p5.Matrix} [opts.pvMatrix] Projection-view matrix override.
|
|
2245
2280
|
*/
|
|
2246
2281
|
fn.cross = function (opts) {
|
|
2247
|
-
|
|
2282
|
+
_renderer3D(this)?.cross(opts);
|
|
2248
2283
|
return this;
|
|
2249
2284
|
};
|
|
2250
2285
|
|
|
2251
|
-
p5.
|
|
2286
|
+
p5.Renderer3D.prototype.cross = function ({
|
|
2252
2287
|
mMatrix = this.mMatrix(),
|
|
2253
2288
|
x,
|
|
2254
2289
|
y,
|
|
@@ -2297,11 +2332,11 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
2297
2332
|
* @param {p5.Matrix} [opts.pvMatrix] Projection-view matrix override.
|
|
2298
2333
|
*/
|
|
2299
2334
|
fn.bullsEye = function (opts) {
|
|
2300
|
-
|
|
2335
|
+
_renderer3D(this)?.bullsEye(opts);
|
|
2301
2336
|
return this;
|
|
2302
2337
|
};
|
|
2303
2338
|
|
|
2304
|
-
p5.
|
|
2339
|
+
p5.Renderer3D.prototype.bullsEye = function ({
|
|
2305
2340
|
mMatrix = this.mMatrix(),
|
|
2306
2341
|
x,
|
|
2307
2342
|
y,
|
|
@@ -2348,22 +2383,22 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
2348
2383
|
// ---------------------------------------------------------------------------
|
|
2349
2384
|
|
|
2350
2385
|
fn.viewFrustum = function (opts) {
|
|
2351
|
-
|
|
2386
|
+
_renderer3D(this)?.viewFrustum(opts);
|
|
2352
2387
|
return this;
|
|
2353
2388
|
};
|
|
2354
2389
|
|
|
2355
2390
|
/**
|
|
2356
|
-
* Displays a view frustum, either from a pg (p5.Graphics / p5.
|
|
2391
|
+
* Displays a view frustum, either from a pg (p5.Graphics / p5.Renderer3D) or from eMatrix/pMatrix.
|
|
2357
2392
|
*
|
|
2358
2393
|
* @param {Object} [opts]
|
|
2359
2394
|
* @param {p5.Matrix} [opts.vMatrix=this.vMatrix()] desired view matrix (world -> this eye) for drawing the frustum.
|
|
2360
|
-
* @param {p5.
|
|
2395
|
+
* @param {p5.Renderer3D|p5.Graphics} [opts.pg] renderer/pg whose frustum is to be displayed.
|
|
2361
2396
|
* @param {p5.Matrix} [opts.eMatrix=pg?.eMatrix()] eye matrix defining frustum pose (eye -> world).
|
|
2362
2397
|
* @param {p5.Matrix} [opts.pMatrix=pg?.pMatrix()] projection matrix defining frustum projection.
|
|
2363
2398
|
* @param {number} [opts.bits=p5.Tree.NEAR|p5.Tree.FAR] bitmask (NEAR/FAR/BODY/APEX).
|
|
2364
2399
|
* @param {Function|false|null} [opts.viewer=...] callback drawn at the frustum origin (in frustum space).
|
|
2365
2400
|
*/
|
|
2366
|
-
p5.
|
|
2401
|
+
p5.Renderer3D.prototype.viewFrustum = function ({
|
|
2367
2402
|
vMatrix = this.vMatrix(),
|
|
2368
2403
|
pg,
|
|
2369
2404
|
eMatrix = pg?.eMatrix(),
|
|
@@ -2494,7 +2529,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
2494
2529
|
* @returns {number} One of p5.Tree.VISIBLE, p5.Tree.INVISIBLE, p5.Tree.SEMIVISIBLE.
|
|
2495
2530
|
*/
|
|
2496
2531
|
fn.visibility = function (...args) {
|
|
2497
|
-
return
|
|
2532
|
+
return _renderer3D(this).visibility(...args);
|
|
2498
2533
|
};
|
|
2499
2534
|
|
|
2500
2535
|
/**
|
|
@@ -2502,7 +2537,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
2502
2537
|
* @returns {Object}
|
|
2503
2538
|
*/
|
|
2504
2539
|
fn.bounds = function (opts = {}) {
|
|
2505
|
-
return
|
|
2540
|
+
return _renderer3D(this).bounds(opts);
|
|
2506
2541
|
};
|
|
2507
2542
|
|
|
2508
2543
|
/**
|
|
@@ -2510,7 +2545,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
2510
2545
|
* @returns {number}
|
|
2511
2546
|
*/
|
|
2512
2547
|
fn.distanceToBound = function (...args) {
|
|
2513
|
-
return
|
|
2548
|
+
return _renderer3D(this).distanceToBound(...args);
|
|
2514
2549
|
};
|
|
2515
2550
|
|
|
2516
2551
|
/**
|
|
@@ -2522,7 +2557,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
2522
2557
|
*
|
|
2523
2558
|
* @private
|
|
2524
2559
|
*/
|
|
2525
|
-
p5.
|
|
2560
|
+
p5.Renderer3D.prototype._parseVisibilityArgs = function (...args) {
|
|
2526
2561
|
let corner1;
|
|
2527
2562
|
let corner2;
|
|
2528
2563
|
let center;
|
|
@@ -2591,7 +2626,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
2591
2626
|
* @param {Object} [opts.bounds] Frustum plane equations (defaults to this.bounds()).
|
|
2592
2627
|
* @returns {number} One of p5.Tree.VISIBLE, p5.Tree.INVISIBLE, p5.Tree.SEMIVISIBLE.
|
|
2593
2628
|
*/
|
|
2594
|
-
p5.
|
|
2629
|
+
p5.Renderer3D.prototype.visibility = function (...args) {
|
|
2595
2630
|
const { corner1, corner2, center, radius, bounds } = this._parseVisibilityArgs(...args);
|
|
2596
2631
|
const b = bounds ?? this.bounds();
|
|
2597
2632
|
return center ? (radius ? this._ballVisibility(center, radius, b) : this._pointVisibility(center, b))
|
|
@@ -2599,7 +2634,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
2599
2634
|
: (console.error('[p5.tree] visibility: could not parse query.'), p5.Tree.INVISIBLE));
|
|
2600
2635
|
};
|
|
2601
2636
|
|
|
2602
|
-
p5.
|
|
2637
|
+
p5.Renderer3D.prototype._pointVisibility = function (point, bounds = this.bounds()) {
|
|
2603
2638
|
for (const key in bounds) {
|
|
2604
2639
|
const d = this.distanceToBound(point, key, bounds);
|
|
2605
2640
|
if (d > 0) return p5.Tree.INVISIBLE;
|
|
@@ -2608,7 +2643,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
2608
2643
|
return p5.Tree.VISIBLE;
|
|
2609
2644
|
};
|
|
2610
2645
|
|
|
2611
|
-
p5.
|
|
2646
|
+
p5.Renderer3D.prototype._ballVisibility = function (center, radius, bounds = this.bounds()) {
|
|
2612
2647
|
let allInForAllPlanes = true;
|
|
2613
2648
|
for (const key in bounds) {
|
|
2614
2649
|
const d = this.distanceToBound(center, key, bounds);
|
|
@@ -2618,7 +2653,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
2618
2653
|
return allInForAllPlanes ? p5.Tree.VISIBLE : p5.Tree.SEMIVISIBLE;
|
|
2619
2654
|
};
|
|
2620
2655
|
|
|
2621
|
-
p5.
|
|
2656
|
+
p5.Renderer3D.prototype._boxVisibility = function (corner1, corner2, bounds = this.bounds()) {
|
|
2622
2657
|
const asVec3 = v =>
|
|
2623
2658
|
v instanceof p5.Vector ? v : new p5.Vector(v?.[0] ?? 0, v?.[1] ?? 0, v?.[2] ?? 0);
|
|
2624
2659
|
corner1 = asVec3(corner1);
|
|
@@ -2653,7 +2688,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
2653
2688
|
* @param {p5.Matrix} [opts.eMatrix] Eye matrix (eye -> world).
|
|
2654
2689
|
* @returns {Object} Object keyed by p5.Tree.LEFT/RIGHT/NEAR/FAR/TOP/BOTTOM.
|
|
2655
2690
|
*/
|
|
2656
|
-
p5.
|
|
2691
|
+
p5.Renderer3D.prototype.bounds = function ({
|
|
2657
2692
|
vMatrix,
|
|
2658
2693
|
eMatrix
|
|
2659
2694
|
} = {}) {
|
|
@@ -2725,7 +2760,7 @@ p5.registerAddon((p5, fn, lifecycles) => {
|
|
|
2725
2760
|
* @param {Object} [bounds] Plane equations (defaults to this.bounds()).
|
|
2726
2761
|
* @returns {number}
|
|
2727
2762
|
*/
|
|
2728
|
-
p5.
|
|
2763
|
+
p5.Renderer3D.prototype.distanceToBound = function (...args) {
|
|
2729
2764
|
let point;
|
|
2730
2765
|
let key;
|
|
2731
2766
|
let bounds = this.bounds();
|