@displayxr/inline3d 1.45.1 → 1.47.0
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/CHANGELOG.md +108 -0
- package/README.md +3 -0
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/cursor-depth.d.ts +41 -0
- package/depth.d.ts +184 -0
- package/dist/call.js +6 -6
- package/docs/making-3d-look-right.md +49 -0
- package/docs/woven-canvas-rules.md +378 -0
- package/index.d.ts +53 -3
- package/js/camera/pair-cursor.js +27 -1
- package/js/inline3d-cursor-depth-playcanvas.js +20 -2
- package/js/inline3d-cursor-depth.js +160 -1
- package/js/inline3d-depth-budget.js +342 -0
- package/js/inline3d-model-entry.js +15 -1
- package/js/inline3d-model-playcanvas.js +27 -2
- package/js/inline3d-model.js +22 -2
- package/js/inline3d-splat-deferred.js +2 -0
- package/js/inline3d-splat-pc-entry.js +2 -1
- package/js/inline3d-splat-playcanvas.js +46 -43
- package/js/inline3d-splat-shared.js +311 -0
- package/js/inline3d-splat.js +31 -3
- package/js/inline3d-three.js +75 -12
- package/js/inline3d-viewer.js +15 -1
- package/js/inline3d.js +71 -0
- package/llms.txt +21 -0
- package/model.d.ts +53 -0
- package/package.json +10 -1
- package/splat.d.ts +33 -0
- package/three.d.ts +19 -4
- package/viewer.d.ts +11 -0
package/js/inline3d.js
CHANGED
|
@@ -36,6 +36,20 @@ import { setSessionViewerEase } from './inline3d-viewer-ease.js';
|
|
|
36
36
|
export { ViewerEase, resolveViewerEaseOption, frameTrackingState, VIEWER_EASE_DEFAULT_MS } from './inline3d-viewer-ease.js';
|
|
37
37
|
export { DISPLAY_METRICS_DEFAULTS, displayMetricsFrom } from './inline3d-display-metrics.js';
|
|
38
38
|
import { displayMetricsFrom } from './inline3d-display-metrics.js';
|
|
39
|
+
// The depth budget: pure measurements (how deep is this scene, in % of the tile width) and the
|
|
40
|
+
// one-time rig warnings. Never a behaviour change — see ./inline3d-depth-budget.js.
|
|
41
|
+
export {
|
|
42
|
+
DEPTH_EYE_SEPARATION_M,
|
|
43
|
+
DEPTH_DEFAULT_VIEWER_M,
|
|
44
|
+
disparityPct,
|
|
45
|
+
cameraRigDisparityPct,
|
|
46
|
+
depthBudgetFromBounds,
|
|
47
|
+
comfortZone,
|
|
48
|
+
comfortDepthFactor,
|
|
49
|
+
cameraRigComfortFactor,
|
|
50
|
+
withheldReasonHint,
|
|
51
|
+
} from './inline3d-depth-budget.js';
|
|
52
|
+
import { warnViewRigOnce, withheldReasonHint } from './inline3d-depth-budget.js';
|
|
39
53
|
|
|
40
54
|
// The eased 2D<->3D transition. A pure state machine (no DOM, no WebXR) ported from the native
|
|
41
55
|
// `dxr::ModeSwitch`, so the browser eases the disparity around a mode switch the same way — and in
|
|
@@ -1272,8 +1286,47 @@ class Inline3D {
|
|
|
1272
1286
|
},
|
|
1273
1287
|
setViewRig: (rig) => {
|
|
1274
1288
|
win.viewRig = rig || null;
|
|
1289
|
+
// One-time console warnings for a rig that looks like a mistake (convergence at infinity,
|
|
1290
|
+
// factors > 1, a FOV in degrees). Read only: the rig goes out exactly as given.
|
|
1291
|
+
if (rig) warnViewRigOnce(win.rigWarned, rig);
|
|
1275
1292
|
return this._pushViewRig(win);
|
|
1276
1293
|
},
|
|
1294
|
+
/**
|
|
1295
|
+
* Runtime ADR-046 Amendment 4: the depth under the pointer for THIS window, forwarded to its
|
|
1296
|
+
* live layer's `setCursorDepth` — `{ disparityPx, u, v }` (device px between the outermost
|
|
1297
|
+
* views, < 0 in front, RAW content disparity; u/v element-normalised, v down; no
|
|
1298
|
+
* `disparityPx` = nothing 3D there), or nothing / null to withdraw. Returns whether a live
|
|
1299
|
+
* layer took it. The depth cursors call this for you under `cursor: 'depth'`.
|
|
1300
|
+
*/
|
|
1301
|
+
setCursorDepth: (depth) => {
|
|
1302
|
+
const layer = win.layer;
|
|
1303
|
+
if (!layer || typeof layer.setCursorDepth !== 'function') return false;
|
|
1304
|
+
try {
|
|
1305
|
+
if (depth) layer.setCursorDepth(depth);
|
|
1306
|
+
else layer.setCursorDepth();
|
|
1307
|
+
return true;
|
|
1308
|
+
} catch {
|
|
1309
|
+
return false;
|
|
1310
|
+
}
|
|
1311
|
+
},
|
|
1312
|
+
/**
|
|
1313
|
+
* "runtime" when the browser AND the runtime draw this window's cursor (the page then supplies
|
|
1314
|
+
* only the depth, setCursorDepth); "none" otherwise — including no live layer yet, so ask
|
|
1315
|
+
* again later. Never rejects.
|
|
1316
|
+
* @returns {Promise<'runtime'|'none'>}
|
|
1317
|
+
*/
|
|
1318
|
+
getCursorDepthSupport: () => {
|
|
1319
|
+
const layer = win.layer;
|
|
1320
|
+
if (!layer || typeof layer.getCursorDepthSupport !== 'function') return Promise.resolve('none');
|
|
1321
|
+
try {
|
|
1322
|
+
return Promise.resolve(layer.getCursorDepthSupport()).then(
|
|
1323
|
+
(s) => (s === 'runtime' ? 'runtime' : 'none'),
|
|
1324
|
+
() => 'none',
|
|
1325
|
+
);
|
|
1326
|
+
} catch {
|
|
1327
|
+
return Promise.resolve('none');
|
|
1328
|
+
}
|
|
1329
|
+
},
|
|
1277
1330
|
/**
|
|
1278
1331
|
* The panel this window is weaving on: physical size in metres, pixel size, and the view
|
|
1279
1332
|
* scale the runtime RECOMMENDS. Resolves null on a machine with no glasses-free display.
|
|
@@ -2331,6 +2384,10 @@ class Inline3D {
|
|
|
2331
2384
|
// and rebuilds layers behind the page's back: a tile that scrolls away and back would
|
|
2332
2385
|
// otherwise silently revert to the default display rig mid-scene.
|
|
2333
2386
|
viewRig: opts.viewRig || null,
|
|
2387
|
+
// Which one-time rig warnings this window has given (setViewRig / opts.viewRig), and
|
|
2388
|
+
// whether its 'withheld' reason has been logged. Diagnostics only.
|
|
2389
|
+
rigWarned: new Set(),
|
|
2390
|
+
warnedWithheld: false,
|
|
2334
2391
|
// The automatic 1-view collapse (the latch itself is manager-wide — the mode is the
|
|
2335
2392
|
// display's, not this window's). `stereoSaved` records the factors in force when the panel
|
|
2336
2393
|
// went flat, for diagnostics; the restore just re-pushes `viewRig`, which the flattening
|
|
@@ -2397,6 +2454,7 @@ class Inline3D {
|
|
|
2397
2454
|
win.fwPromise = new Promise((resolve) => {
|
|
2398
2455
|
win.fwResolve = resolve;
|
|
2399
2456
|
});
|
|
2457
|
+
if (win.viewRig) warnViewRigOnce(win.rigWarned, win.viewRig); // as handle.setViewRig: read only
|
|
2400
2458
|
this._windows.set(canvas, win);
|
|
2401
2459
|
if (this._lazy && this._observer) {
|
|
2402
2460
|
this._observer.observe(win.observeEl);
|
|
@@ -3394,7 +3452,19 @@ class Inline3D {
|
|
|
3394
3452
|
* the browser's report; a confirmed `woven: false` is a capped 'withheld' level, which can still
|
|
3395
3453
|
* recover, so it is NOT a terminal "will not weave" and leaves rewoven() usable.
|
|
3396
3454
|
*/
|
|
3455
|
+
/**
|
|
3456
|
+
* The browser REPORTED this layer withheld long enough to settle a firstWoven / rewoven on it:
|
|
3457
|
+
* say why, once per window (the reason is otherwise only in the settled result). A console line,
|
|
3458
|
+
* nothing else — the window keeps doing exactly what it did.
|
|
3459
|
+
*/
|
|
3460
|
+
_noteWithheld(win, woven, reason, confirmed) {
|
|
3461
|
+
if (woven || !confirmed || win.warnedWithheld || !reason || reason === 'pending' || reason === 'hold-capped') return;
|
|
3462
|
+
win.warnedWithheld = true;
|
|
3463
|
+
console.warn(`[inline3d] the browser withheld this canvas from the weave (${reason}): ${withheldReasonHint(reason)}.`, win.canvas);
|
|
3464
|
+
}
|
|
3465
|
+
|
|
3397
3466
|
_settleFirstWoven(win, woven, reason, confirmed = false) {
|
|
3467
|
+
this._noteWithheld(win, woven, reason, confirmed);
|
|
3398
3468
|
// Every "will not weave" path lands here, so a pending rewoven() is released with it, and a
|
|
3399
3469
|
// later one answers at once (firstWoven may have settled woven:true long before).
|
|
3400
3470
|
if (!woven && !confirmed) {
|
|
@@ -3462,6 +3532,7 @@ class Inline3D {
|
|
|
3462
3532
|
_settleRewoven(win, woven, reason, confirmed = false) {
|
|
3463
3533
|
const rw = win.rw;
|
|
3464
3534
|
if (!rw) return;
|
|
3535
|
+
this._noteWithheld(win, woven, reason, confirmed);
|
|
3465
3536
|
win.rw = null;
|
|
3466
3537
|
rw.resolve(Object.freeze({ woven, confirmed, reason, ms: Math.round(nowMs() - rw.calledAt) }));
|
|
3467
3538
|
}
|
package/llms.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# @displayxr/inline3d — DisplayXR inline-3D web SDK
|
|
2
|
+
|
|
3
|
+
> Glasses-free 3D for web pages on a DisplayXR spatial display: you render one image per eye into a
|
|
4
|
+
> canvas, the DisplayXR Browser weaves them for the panel; an ordinary browser shows the page in 2D.
|
|
5
|
+
|
|
6
|
+
Read first: docs/making-3d-look-right.md — nine depth and comfort rules from real panels
|
|
7
|
+
(keep the viewers' object placement and frame the first view, lay flat arrangements back into
|
|
8
|
+
depth, keep moving things' forward swing small, fixed convergence and no near geometry in worlds,
|
|
9
|
+
low contrast behind the subject, text as HTML near the glass, no coplanar surfaces, no sub-pixel
|
|
10
|
+
detail, a cover that always comes off). The SDK's defaults do the rest.
|
|
11
|
+
|
|
12
|
+
## Samples (they show the API, not a look to copy)
|
|
13
|
+
- samples/model/, samples/splat/, samples/hello-cube/, samples/camera-rig/, samples/display-modes/
|
|
14
|
+
|
|
15
|
+
## Reference
|
|
16
|
+
- docs/authoring-inline-3d.md — every API, both view rigs, comfort maths
|
|
17
|
+
- docs/woven-canvas-rules.md — what the browser does to a woven canvas; CSS, remount and cover rules
|
|
18
|
+
- docs/porting-three-js-apps.md — moving an existing three.js app over
|
|
19
|
+
- docs/authoring-motion-and-effects.md, docs/splat-effects.md — motion, reveals, depth envelopes
|
|
20
|
+
- index.d.ts, three.d.ts, viewer.d.ts, model.d.ts, splat.d.ts — the public API with JSDoc
|
|
21
|
+
- CHANGELOG.md — what changed per release
|
package/model.d.ts
CHANGED
|
@@ -30,6 +30,33 @@ export interface ModelOptions {
|
|
|
30
30
|
margin?: number;
|
|
31
31
|
/** Backstop on total depth, in display heights (default 4.0). Rarely binds. */
|
|
32
32
|
depthLimit?: number;
|
|
33
|
+
/**
|
|
34
|
+
* OPT-IN eye clear: `[r, g, b, a]` in 0..1 (alpha defaults to 1) or a CSS colour string (`#hex`,
|
|
35
|
+
* `rgb()`/`rgba()`, `transparent`, or any colour the browser parses). Unset: the transparent
|
|
36
|
+
* clear, exactly as before. An OPAQUE clear is recommended: where the weave reads an alpha-0
|
|
37
|
+
* pixel it can show stale or black pixels (web#198). Make the page colour behind the canvas
|
|
38
|
+
* match, so the 2D fallback and any feathered edge look the same. Unreadable → one warning,
|
|
39
|
+
* the default clear stays.
|
|
40
|
+
*/
|
|
41
|
+
clearColor?: [number, number, number] | [number, number, number, number] | string;
|
|
42
|
+
/**
|
|
43
|
+
* OPT-IN comfort depth (display rig only). `'auto'` (the Shibata zone of comfort) or
|
|
44
|
+
* `{ zone: 'shibata' | 'percival' | <diopters> }`. The SDK measures the framed subject's depth
|
|
45
|
+
* (tile heights in front of / behind the glass), the canvas's physical height
|
|
46
|
+
* (`displayMetrics()`) and the display's NOMINAL viewer distance (`getDisplayInfo()`, 0.6 m when
|
|
47
|
+
* it reports none — never the live head distance), and multiplies the display rig's `ipdFactor`
|
|
48
|
+
* and `parallaxFactor` (together) by `comfortDepthFactor()` of those, on top of
|
|
49
|
+
* `setStereo`'s values. It ONLY EVER LOWERS DEPTH (the factor is ≤ 1), because the same depth in
|
|
50
|
+
* tile heights carries more vergence load on a small or close device (a tablet at 0.4 m) than on
|
|
51
|
+
* a laptop at 0.6 m: where the subject already fits, nothing changes.
|
|
52
|
+
*
|
|
53
|
+
* Measured when the subject is first framed, when the canvas resizes and when the display
|
|
54
|
+
* reports a change — NOT on zoom or orbit (those are framing choices the developer owns; the box
|
|
55
|
+
* is the framed one at zoom 1), and not per frame. Read the factor in force from `depthFactor`.
|
|
56
|
+
* Ignored, with one console warning, on a camera rig or under `controls: 'page'`. Anything else
|
|
57
|
+
* throws at the call. Unset: nothing is measured or declared — the tile is exactly as before.
|
|
58
|
+
*/
|
|
59
|
+
depth?: 'auto' | { zone?: 'shibata' | 'percival' | number };
|
|
33
60
|
/**
|
|
34
61
|
* Fit the horizontal against the box's DIAGONAL (width and depth) rather than width alone,
|
|
35
62
|
* so a long subject still fits once the turntable turns it (default true).
|
|
@@ -203,6 +230,32 @@ export interface ModelHandle {
|
|
|
203
230
|
/** Resolves once the model has loaded and been framed; rejects if the load failed. */
|
|
204
231
|
readonly ready: Promise<ModelHandle>;
|
|
205
232
|
|
|
233
|
+
/**
|
|
234
|
+
* Live stereo strength — a depth slider, mirroring `SplatHandle.setStereo`. On the display rig
|
|
235
|
+
* (the default) the values are RELATIVE: 1 = what the display shows by construction, below 1 a
|
|
236
|
+
* comfort dial, 0 flat (above 1 exaggerates; sent as given, with a one-time warning). A key given
|
|
237
|
+
* replaces, a key set to `null` returns to 1, `setStereo(null)` clears both. `ipdScale` /
|
|
238
|
+
* `parallaxScale` are accepted too (a model's own values are 1, so they agree). Sticky; applied
|
|
239
|
+
* from the next frame with no cut (pose and framing stay). Re-declares the display rig
|
|
240
|
+
* explicitly (`handle.viewRig`); nothing is declared before the first call. Under
|
|
241
|
+
* `controls: 'page'` (PlayCanvas) the page's camera rig takes them, ABSOLUTE.
|
|
242
|
+
*/
|
|
243
|
+
setStereo(opts: { ipdFactor?: number | null; parallaxFactor?: number | null; ipdScale?: number | null; parallaxScale?: number | null } | null): ModelHandle;
|
|
244
|
+
/** The rig's stereo in force (read back; `setStereo` writes it). Null until the backend has loaded. */
|
|
245
|
+
readonly rig: {
|
|
246
|
+
readonly type: 'display' | 'camera';
|
|
247
|
+
readonly ipdFactor: number;
|
|
248
|
+
readonly parallaxFactor: number;
|
|
249
|
+
readonly stereoDefault: { readonly ipdFactor: number; readonly parallaxFactor: number };
|
|
250
|
+
} | null;
|
|
251
|
+
/**
|
|
252
|
+
* The `depth` option's comfort factor in force, in (0, 1]: what the display rig's ipdFactor and
|
|
253
|
+
* parallaxFactor are multiplied by (under `setStereo`'s values). 1 without the option, before
|
|
254
|
+
* the first measurement, and on a rig it does not apply to.
|
|
255
|
+
*/
|
|
256
|
+
readonly depthFactor: number;
|
|
257
|
+
/** The view-rig descriptor last declared by `setStereo` (or `controls: 'page'`), if any. */
|
|
258
|
+
readonly viewRig?: object;
|
|
206
259
|
/** Throws on `controls: 'page'`. */
|
|
207
260
|
setPose(pose?: OrbitPose): void;
|
|
208
261
|
/** Throws on `controls: 'page'`. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@displayxr/inline3d",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.47.0",
|
|
4
4
|
"description": "Turn any HTML <canvas> into a 3D window on a spatial display, inside an ordinary web page, for the DisplayXR Browser. Dependency-free; progressive enhancement (falls back to plain 2D everywhere else).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./index.d.ts",
|
|
@@ -19,6 +19,10 @@
|
|
|
19
19
|
"types": "./cursor-depth.d.ts",
|
|
20
20
|
"import": "./js/inline3d-cursor-depth.js"
|
|
21
21
|
},
|
|
22
|
+
"./depth": {
|
|
23
|
+
"types": "./depth.d.ts",
|
|
24
|
+
"import": "./js/inline3d-depth-budget.js"
|
|
25
|
+
},
|
|
22
26
|
"./viewer": {
|
|
23
27
|
"types": "./viewer.d.ts",
|
|
24
28
|
"import": "./js/inline3d-viewer.js"
|
|
@@ -67,9 +71,13 @@
|
|
|
67
71
|
"./dist/*.js"
|
|
68
72
|
],
|
|
69
73
|
"files": [
|
|
74
|
+
"llms.txt",
|
|
75
|
+
"docs/making-3d-look-right.md",
|
|
76
|
+
"docs/woven-canvas-rules.md",
|
|
70
77
|
"js/inline3d.js",
|
|
71
78
|
"js/inline3d-undock.js",
|
|
72
79
|
"js/inline3d-display-metrics.js",
|
|
80
|
+
"js/inline3d-depth-budget.js",
|
|
73
81
|
"js/inline3d-mode-switch.js",
|
|
74
82
|
"js/inline3d-buffer-limit.js",
|
|
75
83
|
"js/inline3d-viewer-ease.js",
|
|
@@ -111,6 +119,7 @@
|
|
|
111
119
|
"dist/",
|
|
112
120
|
"index.d.ts",
|
|
113
121
|
"three.d.ts",
|
|
122
|
+
"depth.d.ts",
|
|
114
123
|
"cursor-depth.d.ts",
|
|
115
124
|
"viewer.d.ts",
|
|
116
125
|
"splat.d.ts",
|
package/splat.d.ts
CHANGED
|
@@ -409,6 +409,33 @@ export interface SplatOptions {
|
|
|
409
409
|
margin?: number;
|
|
410
410
|
/** Backstop on total depth, in display heights (default 4.0). Rarely binds. */
|
|
411
411
|
depthLimit?: number;
|
|
412
|
+
/**
|
|
413
|
+
* OPT-IN eye clear: `[r, g, b, a]` in 0..1 (alpha defaults to 1) or a CSS colour string (`#hex`,
|
|
414
|
+
* `rgb()`/`rgba()`, `transparent`, or any colour the browser parses). Unset: the transparent
|
|
415
|
+
* clear, exactly as before. An OPAQUE clear is recommended: where the weave reads an alpha-0
|
|
416
|
+
* pixel it can show stale or black pixels (web#198). Make the page colour behind the canvas
|
|
417
|
+
* match, so the 2D fallback and any feathered edge look the same. Unreadable → one warning,
|
|
418
|
+
* the default clear stays.
|
|
419
|
+
*/
|
|
420
|
+
clearColor?: [number, number, number] | [number, number, number, number] | string;
|
|
421
|
+
/**
|
|
422
|
+
* OPT-IN comfort depth (display rig only). `'auto'` (the Shibata zone of comfort) or
|
|
423
|
+
* `{ zone: 'shibata' | 'percival' | <diopters> }`. The SDK measures the framed subject's depth
|
|
424
|
+
* (tile heights in front of / behind the glass), the canvas's physical height
|
|
425
|
+
* (`displayMetrics()`) and the display's NOMINAL viewer distance (`getDisplayInfo()`, 0.6 m when
|
|
426
|
+
* it reports none — never the live head distance), and multiplies the display rig's `ipdFactor`
|
|
427
|
+
* and `parallaxFactor` (together) by `comfortDepthFactor()` of those, on top of
|
|
428
|
+
* `setStereo`'s values (Spark has no setStereo: the factor is the rig's whole ipdFactor / parallaxFactor). It ONLY EVER LOWERS DEPTH (the factor is ≤ 1), because the same depth in
|
|
429
|
+
* tile heights carries more vergence load on a small or close device (a tablet at 0.4 m) than on
|
|
430
|
+
* a laptop at 0.6 m: where the subject already fits, nothing changes.
|
|
431
|
+
*
|
|
432
|
+
* Measured when the subject is first framed, when the canvas resizes and when the display
|
|
433
|
+
* reports a change — NOT on zoom or orbit (those are framing choices the developer owns; the box
|
|
434
|
+
* is the framed one at zoom 1), and not per frame. Read the factor in force from `depthFactor`.
|
|
435
|
+
* Ignored, with one console warning, on a camera rig (an asset with a capture camera, `rig: 'camera'`) or under `controls: 'page'`. Anything else
|
|
436
|
+
* throws at the call. Unset: nothing is measured or declared — the tile is exactly as before.
|
|
437
|
+
*/
|
|
438
|
+
depth?: 'auto' | { zone?: 'shibata' | 'percival' | number };
|
|
412
439
|
/**
|
|
413
440
|
* Fit the horizontal against the box's DIAGONAL (width and depth) rather than width alone,
|
|
414
441
|
* so a long subject still fits once the turntable turns it (default true).
|
|
@@ -1109,6 +1136,12 @@ export interface SplatHandle {
|
|
|
1109
1136
|
*/
|
|
1110
1137
|
warmEntity(entity: unknown, opts?: { timeoutMs?: number }): Promise<number>;
|
|
1111
1138
|
setStereo(opts: SplatStereoOptions | null): SplatHandle;
|
|
1139
|
+
/**
|
|
1140
|
+
* The `depth` option's comfort factor in force, in (0, 1]: what the display rig's ipdFactor and
|
|
1141
|
+
* parallaxFactor are multiplied by (under `setStereo`'s values). 1 without the option, before
|
|
1142
|
+
* the first measurement, and on a rig it does not apply to.
|
|
1143
|
+
*/
|
|
1144
|
+
readonly depthFactor: number;
|
|
1112
1145
|
/** This tile in physical units — the core `TileHandle.displayMetrics()`, on the splat handle. Never rejects. */
|
|
1113
1146
|
displayMetrics(): Promise<DisplayMetrics>;
|
|
1114
1147
|
/**
|
package/three.d.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// bundles three.js (it is an optional peer dependency).
|
|
4
4
|
|
|
5
5
|
import type { XRViewRigInit } from './index.js';
|
|
6
|
+
export { disparityPct, cameraRigDisparityPct, depthBudgetFromBounds, comfortZone, comfortDepthFactor, cameraRigComfortFactor } from './depth.js';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* A reusable three.js camera driven directly by an XRView's matrices. Construct once with your
|
|
@@ -88,8 +89,12 @@ export interface DisplayRigOptions {
|
|
|
88
89
|
* (so a camera parented under a dolly still reports world space) unless `attach` is set, which
|
|
89
90
|
* emits identity instead.
|
|
90
91
|
*
|
|
91
|
-
* Comfort rule
|
|
92
|
-
*
|
|
92
|
+
* Comfort rule: `ipdFactor × metersToVirtual × convergenceDiopters × N <= 1` (N = the nominal
|
|
93
|
+
* viewer distance the display reports, 0.6 m on a desktop panel). Nothing enforces it: the
|
|
94
|
+
* runtime applies an app-declared camera rig's gain as given (XR_DXR_view_rig §3) and clamps only
|
|
95
|
+
* values outside a field's sanity range. `convergence` 0 / unset (infinity: the whole scene in
|
|
96
|
+
* front of the glass) logs one console warning per page; the descriptor is built as asked.
|
|
97
|
+
* {@link cameraRigDisparityPct} measures the disparity a rig gives.
|
|
93
98
|
*
|
|
94
99
|
* @param THREE your imported three.js module namespace.
|
|
95
100
|
* @param camera a `THREE.PerspectiveCamera` (`.fov` degrees, `.matrixWorld`).
|
|
@@ -143,6 +148,7 @@ export class EdgeFeather {
|
|
|
143
148
|
): void;
|
|
144
149
|
}
|
|
145
150
|
|
|
151
|
+
import type { CursorRuntimeLink } from './cursor-depth.js';
|
|
146
152
|
import type { CursorAnchorMode, CursorPlacement, CursorShape, CursorShapeHit, CursorShapeOption, CursorSoftenOption, CursorSoftenParams, CursorSoftening, CursorView } from './cursor-depth.js';
|
|
147
153
|
|
|
148
154
|
/** One second of `debug` stats: each figure as `{ mean, p95, max, n }`. */
|
|
@@ -234,8 +240,17 @@ export class DepthCursor {
|
|
|
234
240
|
readonly softening: CursorSoftening | null;
|
|
235
241
|
/** The sprite drawn last: a name, 'none' or 'image'. */
|
|
236
242
|
readonly shape: CursorShape | 'none' | 'image';
|
|
237
|
-
/**
|
|
238
|
-
|
|
243
|
+
/** The runtime-drawn cursor link (runtime ADR-046 Amendment 4). */
|
|
244
|
+
readonly runtime: CursorRuntimeLink;
|
|
245
|
+
/** The layer this canvas weaves through, as last passed to `update(views, { layer })`. */
|
|
246
|
+
layer: unknown;
|
|
247
|
+
/**
|
|
248
|
+
* Place the sprite for this frame — call with the views you are about to render, before rendering.
|
|
249
|
+
* Pass `{ layer }` (addScene's second callback argument): where it says "runtime" (ADR-046
|
|
250
|
+
* Amendment 4) the depth goes to the layer and the browser's own cursor is lifted by the runtime;
|
|
251
|
+
* no sprite is drawn. A number is the time in ms, as before.
|
|
252
|
+
*/
|
|
253
|
+
update(views: ArrayLike<XRView | CursorView> | null, opts?: number | { nowMs?: number; layer?: unknown }): CursorPlacement | { active: false; runtime?: boolean };
|
|
239
254
|
/** Set the pointer directly (canvas-normalised, v down), or null — for scripted input. */
|
|
240
255
|
setPointer(u: number | null, v?: number): void;
|
|
241
256
|
/** Remove listeners, restore the CSS cursor, free the sprite's GPU resources. */
|
package/viewer.d.ts
CHANGED
|
@@ -48,6 +48,15 @@ export interface SceneViewerOptions {
|
|
|
48
48
|
* `createInline3D({ viewerEase })`, else on. `false` restores the snap.
|
|
49
49
|
*/
|
|
50
50
|
viewerEase?: ViewerEaseOption;
|
|
51
|
+
/**
|
|
52
|
+
* OPT-IN eye clear: `[r, g, b, a]` in 0..1 (alpha defaults to 1) or a CSS colour string (`#hex`,
|
|
53
|
+
* `rgb()`/`rgba()`, `transparent`, or any colour the browser parses). Unset: the transparent
|
|
54
|
+
* clear, exactly as before. An OPAQUE clear is recommended: where the weave reads an alpha-0
|
|
55
|
+
* pixel it can show stale or black pixels (web#198). Make the page colour behind the canvas
|
|
56
|
+
* match, so the 2D fallback and any feathered edge look the same. Unreadable → one warning,
|
|
57
|
+
* the default clear stays.
|
|
58
|
+
*/
|
|
59
|
+
clearColor?: [number, number, number] | [number, number, number, number] | string;
|
|
51
60
|
}
|
|
52
61
|
|
|
53
62
|
export interface OrbitPose {
|
|
@@ -117,6 +126,8 @@ export declare class SceneViewer {
|
|
|
117
126
|
*/
|
|
118
127
|
readonly effectiveRenderScale: number;
|
|
119
128
|
|
|
129
|
+
/** The `clearColor` option, parsed (`[r,g,b,a]`), or null = the transparent clear. */
|
|
130
|
+
readonly clearColor: number[] | null;
|
|
120
131
|
/** Centre the subject on the zero-disparity plane and scale it to the tile. */
|
|
121
132
|
fitTo(
|
|
122
133
|
center: number[] | { x: number; y: number; z: number },
|