Skip to content

Commit 8252edf

Browse files
committed
fix(query, gizmos): correct projTop/projBottom and viewFrustum Y sign
deps/tree/src/query.js - projTop/projBottom formulas were swapped — returned geometric bottom/top respectively. Fix: projTop = (1−p[13])/p[5] ortho, (1+p[9])·n/p[5] persp; projBottom = (−1−p[13])/p[5] ortho, (p[9]−1)·n/p[5] persp. Sign contract now explicit in JSDoc: top > 0, bottom < 0, right > 0, left < 0. src/visibility.js - bounds(): rename eMatrix → mat4Eye for consistency with the rest of the bridge. - Sign contract added to module header (covers all of frustumPlanes, viewFrustum, projTop/Bottom/Left/Right, mat4Frustum/Ortho, and p5 v2 frustum()/ortho()). src/gizmos.js - viewFrustum: negate t/b when drawing into p5 main canvas / createGraphics (Y-down). projTop/projBottom are Y-up (OpenGL eye space); sign flip aligns the gizmo with screen geometry. l/r/n/f unaffected. - Remove the stale isOrtho conditional negation that was papering over the swapped formulas.
1 parent 3e63de6 commit 8252edf

File tree

7 files changed

+45
-15
lines changed

7 files changed

+45
-15
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,7 @@ Both accept the same options object:
590590
# Utilities
591591
592592
```js
593-
p5.Tree.VERSION // '0.0.32'
593+
p5.Tree.VERSION // '0.0.33'
594594
```
595595
596596
## Shader helpers
@@ -665,9 +665,9 @@ Latest:
665665
666666
Tagged:
667667
668-
* [https://cdn.jsdelivr.net/npm/p5.tree@0.0.32/dist/p5.tree.js](https://cdn.jsdelivr.net/npm/p5.tree@0.0.32/dist/p5.tree.js)
669-
* [https://cdn.jsdelivr.net/npm/p5.tree@0.0.32/dist/p5.tree.min.js](https://cdn.jsdelivr.net/npm/p5.tree@0.0.32/dist/p5.tree.min.js)
670-
* [https://cdn.jsdelivr.net/npm/p5.tree@0.0.32/dist/p5.tree.esm.js](https://cdn.jsdelivr.net/npm/p5.tree@0.0.32/dist/p5.tree.esm.js)
668+
* [https://cdn.jsdelivr.net/npm/p5.tree@0.0.33/dist/p5.tree.js](https://cdn.jsdelivr.net/npm/p5.tree@0.0.33/dist/p5.tree.js)
669+
* [https://cdn.jsdelivr.net/npm/p5.tree@0.0.33/dist/p5.tree.min.js](https://cdn.jsdelivr.net/npm/p5.tree@0.0.33/dist/p5.tree.min.js)
670+
* [https://cdn.jsdelivr.net/npm/p5.tree@0.0.33/dist/p5.tree.esm.js](https://cdn.jsdelivr.net/npm/p5.tree@0.0.33/dist/p5.tree.esm.js)
671671
672672
---
673673

deps/tree/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@nakednous/tree",
3-
"version": "0.0.13",
3+
"version": "0.0.14",
44
"description": "tree — pure numeric core. Zero dependencies.",
55
"type": "module",
66
"main": "dist/index.js",

deps/tree/src/query.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,22 @@ export function projFar(p) {
177177

178178
export function projLeft (p, ndcZMin) { return p[15]===1 ? -(1+p[12])/p[0] : projNear(p,ndcZMin)*(p[8]-1)/p[0]; }
179179
export function projRight (p, ndcZMin) { return p[15]===1 ? (1-p[12])/p[0] : projNear(p,ndcZMin)*(1+p[8])/p[0]; }
180-
export function projTop (p, ndcZMin) { return p[15]===1 ? (p[13]-1)/p[5] : projNear(p,ndcZMin)*(p[9]-1)/p[5]; }
181-
export function projBottom(p, ndcZMin) { return p[15]===1 ? (1+p[13])/p[5] : projNear(p,ndcZMin)*(1+p[9])/p[5]; }
180+
181+
/**
182+
* Top extent of the near plane in camera space (y_max).
183+
* Positive for a standard y-up camera.
184+
* @param {ArrayLike<number>} p Projection mat4.
185+
* @param {number} ndcZMin WEBGL (−1) or WEBGPU (0).
186+
*/
187+
export function projTop (p, ndcZMin) { return p[15]===1 ? (1+p[13])/p[5] : projNear(p,ndcZMin)*(1+p[9])/p[5]; }
188+
189+
/**
190+
* Bottom extent of the near plane in camera space (y_min).
191+
* Negative for a standard y-up camera.
192+
* @param {ArrayLike<number>} p Projection mat4.
193+
* @param {number} ndcZMin WEBGL (−1) or WEBGPU (0).
194+
*/
195+
export function projBottom(p, ndcZMin) { return p[15]===1 ? (p[13]-1)/p[5] : projNear(p,ndcZMin)*(p[9]-1)/p[5]; }
182196

183197
/** Vertical field of view in radians (perspective only). */
184198
export function projFov (p) { return Math.abs(2*Math.atan(1/p[5])); }

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "p5.tree",
3-
"version": "0.0.32",
3+
"version": "0.0.33",
44
"description": "Render pipeline for p5.js v2 — pose and camera interpolation, space transforms, frustum visibility, HUD, post-processing pipe, picking, and declarative control panels.",
55
"type": "module",
66
"main": "dist/p5.tree.esm.js",
@@ -49,7 +49,7 @@
4949
"p5": "^2.2.3"
5050
},
5151
"dependencies": {
52-
"@nakednous/tree": "^0.0.13",
52+
"@nakednous/tree": "^0.0.14",
5353
"@nakednous/ui": "^0.0.8"
5454
},
5555
"devDependencies": {

src/constants.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export function installConstants(p5) {
1212
const CONST = value => ({ value, writable: false, enumerable: true, configurable: false });
1313

1414
Object.defineProperties(p5.Tree, {
15-
VERSION: CONST('0.0.32'),
15+
VERSION: CONST('0.0.33'),
1616
NONE: CONST(0),
1717

1818
// Core constants (spaces, visibility, NDC, basis vectors)

src/gizmos.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,8 +254,11 @@ export function installGizmos(p5, fn) {
254254
const apex = !isOrtho && ((bits & p5.Tree.APEX) !== 0);
255255
const n = -projNear(pRaw, ndcZ), f = -projFar(pRaw);
256256
const l = projLeft(pRaw, ndcZ), r = projRight(pRaw, ndcZ);
257-
const t = isOrtho ? -projTop(pRaw, ndcZ) : projTop(pRaw, ndcZ);
258-
const b = isOrtho ? -projBottom(pRaw, ndcZ) : projBottom(pRaw, ndcZ);
257+
// projTop/projBottom are Y-up (OpenGL eye space). Negate y to draw in
258+
// p5.js main-canvas / createGraphics space, which is Y-down: y > 0 is lower
259+
// on screen than y < 0.
260+
const t = -projTop(pRaw, ndcZ);
261+
const b = -projBottom(pRaw, ndcZ);
259262
const ratio = isOrtho ? 1 : f/n;
260263
const _l=ratio*l, _r=ratio*r, _b=ratio*b, _t=ratio*t;
261264

src/visibility.js

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,19 @@
1515
* m._c1.set([px - hw, py - hh, pz - hd])
1616
* m._c2.set([px + hw, py + hh, pz + hd])
1717
* m.visibility = p.visibility({ corner1: m._c1, corner2: m._c2 })
18+
*
19+
* ── Sign contract ─────────────────────────────────────────────────────────
20+
*
21+
* Frustum extents are near-plane coordinates in camera space (y-up, z into
22+
* screen):
23+
*
24+
* top > 0 bottom < 0 (y axis)
25+
* right > 0 left < 0 (x axis)
26+
* near, far > 0 (positive distances along −z)
27+
*
28+
* All of frustumPlanes, viewFrustum, projTop/projBottom, projLeft/projRight,
29+
* mat4Frustum, mat4Ortho, and p5 v2's frustum()/ortho() share this contract.
30+
* p5 v2 call order: frustum(left, right, bottom, top, near, far).
1831
*/
1932

2033
'use strict';
@@ -234,11 +247,11 @@ export function installVisibility(p5, fn) {
234247
*
235248
* @method bounds
236249
* @for p5
237-
* @param {{ eMatrix?: Float32Array | ArrayLike | p5.Matrix }} [opts]
250+
* @param {{ mat4Eye?: Float32Array | ArrayLike | p5.Matrix }} [opts]
238251
* @returns {object}
239252
*/
240-
p5.Renderer3D.prototype.bounds = function ({ eMatrix } = {}) {
241-
const eRaw = _rawMat4(eMatrix) ?? (mat4Invert(_eye, _viewMat4(this)), _eye);
253+
p5.Renderer3D.prototype.bounds = function ({ mat4Eye } = {}) {
254+
const eRaw = _rawMat4(mat4Eye) ?? (mat4Invert(_eye, _viewMat4(this)), _eye);
242255
computePlanes(this, eRaw);
243256
const keys = [p5.Tree.LEFT, p5.Tree.RIGHT, p5.Tree.NEAR, p5.Tree.FAR, p5.Tree.TOP, p5.Tree.BOTTOM];
244257
const result = {};

0 commit comments

Comments
 (0)