@idetik/core 0.40.0 → 0.40.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/worker_kernel-CBlE4MBI.js.map +1 -1
- package/dist/index.d.ts +1717 -381
- package/dist/index.js +981 -193
- package/dist/index.js.map +1 -1
- package/dist/index.umd.cjs +32 -32
- package/dist/index.umd.cjs.map +1 -1
- package/dist/types/src/core/channel.d.ts +7 -1
- package/dist/types/src/core/channel.d.ts.map +1 -1
- package/dist/types/src/core/image_source_policy.d.ts +4 -4
- package/dist/types/src/core/image_source_policy.d.ts.map +1 -1
- package/dist/types/src/core/layer.d.ts +136 -21
- package/dist/types/src/core/layer.d.ts.map +1 -1
- package/dist/types/src/core/renderable_object.d.ts +108 -3
- package/dist/types/src/core/renderable_object.d.ts.map +1 -1
- package/dist/types/src/core/viewport.d.ts +82 -2
- package/dist/types/src/core/viewport.d.ts.map +1 -1
- package/dist/types/src/data/chunk.d.ts +37 -2
- package/dist/types/src/data/chunk.d.ts.map +1 -1
- package/dist/types/src/data/chunk_manager.d.ts +5 -0
- package/dist/types/src/data/chunk_manager.d.ts.map +1 -1
- package/dist/types/src/data/ome_zarr/image_source.d.ts +56 -13
- package/dist/types/src/data/ome_zarr/image_source.d.ts.map +1 -1
- package/dist/types/src/data/ome_zarr/metadata_loaders.d.ts +4 -4
- package/dist/types/src/data/ome_zarr/metadata_loaders.d.ts.map +1 -1
- package/dist/types/src/idetik.d.ts +129 -59
- package/dist/types/src/idetik.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +29 -8
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/layers/axes_layer.d.ts +30 -5
- package/dist/types/src/layers/axes_layer.d.ts.map +1 -1
- package/dist/types/src/layers/image_layer.d.ts +106 -12
- package/dist/types/src/layers/image_layer.d.ts.map +1 -1
- package/dist/types/src/layers/label_layer.d.ts +106 -5
- package/dist/types/src/layers/label_layer.d.ts.map +1 -1
- package/dist/types/src/layers/point_picking.d.ts +7 -2
- package/dist/types/src/layers/point_picking.d.ts.map +1 -1
- package/dist/types/src/layers/volume_layer.d.ts +87 -5
- package/dist/types/src/layers/volume_layer.d.ts.map +1 -1
- package/dist/types/src/math/axes.d.ts +3 -0
- package/dist/types/src/math/axes.d.ts.map +1 -1
- package/dist/types/src/math/box2.d.ts +34 -4
- package/dist/types/src/math/box2.d.ts.map +1 -1
- package/dist/types/src/math/box3.d.ts +38 -4
- package/dist/types/src/math/box3.d.ts.map +1 -1
- package/dist/types/src/math/color.d.ts +49 -2
- package/dist/types/src/math/color.d.ts.map +1 -1
- package/dist/types/src/math/frustum.d.ts +28 -0
- package/dist/types/src/math/frustum.d.ts.map +1 -1
- package/dist/types/src/math/transforms.d.ts +57 -0
- package/dist/types/src/math/transforms.d.ts.map +1 -1
- package/dist/types/src/objects/cameras/camera.d.ts +55 -0
- package/dist/types/src/objects/cameras/camera.d.ts.map +1 -1
- package/dist/types/src/objects/cameras/controls.d.ts +88 -1
- package/dist/types/src/objects/cameras/controls.d.ts.map +1 -1
- package/dist/types/src/objects/cameras/orbit_controls.d.ts +56 -1
- package/dist/types/src/objects/cameras/orbit_controls.d.ts.map +1 -1
- package/dist/types/src/objects/cameras/orthographic_camera.d.ts +90 -13
- package/dist/types/src/objects/cameras/orthographic_camera.d.ts.map +1 -1
- package/dist/types/src/objects/cameras/perspective_camera.d.ts +65 -3
- package/dist/types/src/objects/cameras/perspective_camera.d.ts.map +1 -1
- package/dist/types/src/objects/renderable/image_renderable.d.ts +48 -3
- package/dist/types/src/objects/renderable/image_renderable.d.ts.map +1 -1
- package/dist/types/src/objects/renderable/label_image_renderable.d.ts +66 -4
- package/dist/types/src/objects/renderable/label_image_renderable.d.ts.map +1 -1
- package/dist/types/src/objects/renderable/points_renderable.d.ts +47 -2
- package/dist/types/src/objects/renderable/points_renderable.d.ts.map +1 -1
- package/dist/types/src/objects/renderable/projected_line_renderable.d.ts +27 -3
- package/dist/types/src/objects/renderable/projected_line_renderable.d.ts.map +1 -1
- package/dist/types/src/objects/renderable/volume_renderable.d.ts +63 -3
- package/dist/types/src/objects/renderable/volume_renderable.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1079,30 +1079,53 @@ function TI(g, A) {
|
|
|
1079
1079
|
};
|
|
1080
1080
|
})();
|
|
1081
1081
|
class SA {
|
|
1082
|
+
/** Minimum corner of the box. */
|
|
1082
1083
|
min;
|
|
1084
|
+
/** Maximum corner of the box. */
|
|
1083
1085
|
max;
|
|
1084
1086
|
/**
|
|
1085
|
-
*
|
|
1086
|
-
*
|
|
1087
|
-
*
|
|
1088
|
-
*
|
|
1087
|
+
* Creates a box from optional corner points. The corners are cloned.
|
|
1088
|
+
* When a corner is omitted the box starts empty.
|
|
1089
|
+
*
|
|
1090
|
+
* @param min - The minimum corner.
|
|
1091
|
+
* @param max - The maximum corner.
|
|
1089
1092
|
*/
|
|
1090
1093
|
constructor(A, I) {
|
|
1091
1094
|
this.min = A ? EA(A) : p(1 / 0, 1 / 0, 1 / 0), this.max = I ? EA(I) : p(-1 / 0, -1 / 0, -1 / 0);
|
|
1092
1095
|
}
|
|
1096
|
+
/** Returns a deep copy of the box. */
|
|
1093
1097
|
clone() {
|
|
1094
1098
|
return new SA(this.min, this.max);
|
|
1095
1099
|
}
|
|
1100
|
+
/** Returns `true` when the box encloses no volume. */
|
|
1096
1101
|
isEmpty() {
|
|
1097
1102
|
return this.max[0] <= this.min[0] || this.max[1] <= this.min[1] || this.max[2] <= this.min[2];
|
|
1098
1103
|
}
|
|
1099
|
-
|
|
1104
|
+
/**
|
|
1105
|
+
* Tests whether two boxes overlap. Boxes are treated as half-open
|
|
1106
|
+
* intervals so touching faces do not count as overlap.
|
|
1107
|
+
*
|
|
1108
|
+
* @param a - The first box.
|
|
1109
|
+
* @param b - The second box.
|
|
1110
|
+
*/
|
|
1100
1111
|
static intersects(A, I) {
|
|
1101
1112
|
return !(A.max[0] <= I.min[0] || A.min[0] >= I.max[0] || A.max[1] <= I.min[1] || A.min[1] >= I.max[1] || A.max[2] <= I.min[2] || A.min[2] >= I.max[2]);
|
|
1102
1113
|
}
|
|
1114
|
+
/**
|
|
1115
|
+
* Grows the box in place to contain the given point.
|
|
1116
|
+
*
|
|
1117
|
+
* @param p - The point to include.
|
|
1118
|
+
*/
|
|
1103
1119
|
expandWithPoint(A) {
|
|
1104
1120
|
A[0] < this.min[0] && (this.min[0] = A[0]), A[1] < this.min[1] && (this.min[1] = A[1]), A[2] < this.min[2] && (this.min[2] = A[2]), A[0] > this.max[0] && (this.max[0] = A[0]), A[1] > this.max[1] && (this.max[1] = A[1]), A[2] > this.max[2] && (this.max[2] = A[2]);
|
|
1105
1121
|
}
|
|
1122
|
+
/**
|
|
1123
|
+
* Transforms the box in place by the given matrix. The result is the
|
|
1124
|
+
* axis-aligned box of the eight transformed corners so the box can grow
|
|
1125
|
+
* under rotation.
|
|
1126
|
+
*
|
|
1127
|
+
* @param matrix - The transform to apply.
|
|
1128
|
+
*/
|
|
1106
1129
|
applyTransform(A) {
|
|
1107
1130
|
const { min: I, max: B } = this, C = [
|
|
1108
1131
|
p(I[0], I[1], I[2]),
|
|
@@ -1611,36 +1634,55 @@ class wQ {
|
|
|
1611
1634
|
}
|
|
1612
1635
|
}
|
|
1613
1636
|
class AA {
|
|
1637
|
+
/** Minimum corner of the box. */
|
|
1614
1638
|
min;
|
|
1639
|
+
/** Maximum corner of the box. */
|
|
1615
1640
|
max;
|
|
1616
1641
|
/**
|
|
1617
|
-
*
|
|
1618
|
-
*
|
|
1619
|
-
*
|
|
1620
|
-
*
|
|
1642
|
+
* Creates a box from optional corner points. The corners are cloned.
|
|
1643
|
+
* When a corner is omitted the box starts empty.
|
|
1644
|
+
*
|
|
1645
|
+
* @param min - The minimum corner.
|
|
1646
|
+
* @param max - The maximum corner.
|
|
1621
1647
|
*/
|
|
1622
1648
|
constructor(A, I) {
|
|
1623
1649
|
this.min = A ? zg(A) : V(1 / 0, 1 / 0), this.max = I ? zg(I) : V(-1 / 0, -1 / 0);
|
|
1624
1650
|
}
|
|
1651
|
+
/** Returns a deep copy of the box. */
|
|
1625
1652
|
clone() {
|
|
1626
1653
|
return new AA(this.min, this.max);
|
|
1627
1654
|
}
|
|
1655
|
+
/** Returns `true` when the box encloses no area. */
|
|
1628
1656
|
isEmpty() {
|
|
1629
1657
|
return this.max[0] <= this.min[0] || this.max[1] <= this.min[1];
|
|
1630
1658
|
}
|
|
1631
|
-
|
|
1659
|
+
/**
|
|
1660
|
+
* Tests whether two boxes overlap. Boxes are treated as half-open
|
|
1661
|
+
* intervals so touching edges do not count as overlap.
|
|
1662
|
+
*
|
|
1663
|
+
* @param a - The first box.
|
|
1664
|
+
* @param b - The second box.
|
|
1665
|
+
*/
|
|
1632
1666
|
static intersects(A, I) {
|
|
1633
1667
|
return !(A.max[0] <= I.min[0] || A.min[0] >= I.max[0] || A.max[1] <= I.min[1] || A.min[1] >= I.max[1]);
|
|
1634
1668
|
}
|
|
1669
|
+
/**
|
|
1670
|
+
* Tests whether two boxes have exactly equal corners.
|
|
1671
|
+
*
|
|
1672
|
+
* @param a - The first box.
|
|
1673
|
+
* @param b - The second box.
|
|
1674
|
+
*/
|
|
1635
1675
|
static equals(A, I) {
|
|
1636
1676
|
return _g(A.min, I.min) && _g(A.max, I.max);
|
|
1637
1677
|
}
|
|
1678
|
+
/** Returns a copy with both corners floored componentwise. */
|
|
1638
1679
|
floor() {
|
|
1639
1680
|
return new AA(
|
|
1640
1681
|
V(Math.floor(this.min[0]), Math.floor(this.min[1])),
|
|
1641
1682
|
V(Math.floor(this.max[0]), Math.floor(this.max[1]))
|
|
1642
1683
|
);
|
|
1643
1684
|
}
|
|
1685
|
+
/** Converts the box to an `x, y, width, height` rectangle. */
|
|
1644
1686
|
toRect() {
|
|
1645
1687
|
const A = this.min[0], I = this.min[1], B = this.max[0] - this.min[0], C = this.max[1] - this.min[1];
|
|
1646
1688
|
return { x: A, y: I, width: B, height: C };
|
|
@@ -2975,16 +3017,22 @@ class mQ {
|
|
|
2975
3017
|
}
|
|
2976
3018
|
}
|
|
2977
3019
|
class uQ {
|
|
3020
|
+
/** The viewport's unique identifier. */
|
|
2978
3021
|
id;
|
|
3022
|
+
/** The host element defining the viewport's area. */
|
|
2979
3023
|
element;
|
|
3024
|
+
/** The camera the viewport renders with. */
|
|
2980
3025
|
camera;
|
|
3026
|
+
/** The pointer and wheel event dispatcher for the host element. */
|
|
2981
3027
|
events;
|
|
3028
|
+
/** Input controls driving the camera. */
|
|
2982
3029
|
cameraControls;
|
|
2983
3030
|
// Carried only to relay to `layer.onAttached` / `layer.onDetached`.
|
|
2984
3031
|
// To be removed when the chunk-infrastructure refactor folds chunk management
|
|
2985
3032
|
// into the source and the attach lifecycle goes away.
|
|
2986
3033
|
context_;
|
|
2987
3034
|
layers_ = [];
|
|
3035
|
+
/** @hidden */
|
|
2988
3036
|
constructor(A) {
|
|
2989
3037
|
this.id = A.id, this.element = A.element, this.camera = A.camera, this.context_ = A.context, this.cameraControls = A.cameraControls, this.updateAspectRatio(), this.events = new fQ(this.element), this.events.addEventListener((I) => {
|
|
2990
3038
|
if (I.event instanceof PointerEvent || I.event instanceof WheelEvent) {
|
|
@@ -3000,26 +3048,51 @@ class uQ {
|
|
|
3000
3048
|
for (const I of A.layers ?? [])
|
|
3001
3049
|
this.addLayer(I);
|
|
3002
3050
|
}
|
|
3051
|
+
/**
|
|
3052
|
+
* The layers rendered by this viewport in order. Layers with `occludes`
|
|
3053
|
+
* set draw before non-occluding layers regardless of stack order.
|
|
3054
|
+
*/
|
|
3003
3055
|
get layers() {
|
|
3004
3056
|
return this.layers_;
|
|
3005
3057
|
}
|
|
3058
|
+
/**
|
|
3059
|
+
* Adds a layer to the top of the stack.
|
|
3060
|
+
*
|
|
3061
|
+
* @param layer - The layer to add.
|
|
3062
|
+
*/
|
|
3006
3063
|
addLayer(A) {
|
|
3007
3064
|
A.onAttached(this.context_), this.layers_.push(A);
|
|
3008
3065
|
}
|
|
3066
|
+
/**
|
|
3067
|
+
* Removes a previously added layer.
|
|
3068
|
+
*
|
|
3069
|
+
* @param layer - The layer to remove.
|
|
3070
|
+
*/
|
|
3009
3071
|
removeLayer(A) {
|
|
3010
3072
|
const I = this.layers_.indexOf(A);
|
|
3011
3073
|
if (I === -1)
|
|
3012
3074
|
throw new Error(`Layer to remove not found: ${A}`);
|
|
3013
3075
|
this.layers_.splice(I, 1), A.onDetached(this.context_);
|
|
3014
3076
|
}
|
|
3077
|
+
/** Removes all layers from the viewport. */
|
|
3015
3078
|
removeAllLayers() {
|
|
3016
3079
|
for (const A of this.layers_)
|
|
3017
3080
|
A.onDetached(this.context_);
|
|
3018
3081
|
this.layers_ = [];
|
|
3019
3082
|
}
|
|
3083
|
+
/**
|
|
3084
|
+
* Syncs the camera's aspect ratio to the host element's size. Called
|
|
3085
|
+
* automatically when the host element resizes.
|
|
3086
|
+
*/
|
|
3020
3087
|
updateSize() {
|
|
3021
3088
|
this.updateAspectRatio();
|
|
3022
3089
|
}
|
|
3090
|
+
/**
|
|
3091
|
+
* Computes the viewport's box relative to the given canvas in device pixels.
|
|
3092
|
+
*
|
|
3093
|
+
* @param canvas - The canvas to compute the box against.
|
|
3094
|
+
* @returns The viewport's box in the canvas's coordinate space.
|
|
3095
|
+
*/
|
|
3023
3096
|
getBoxRelativeTo(A) {
|
|
3024
3097
|
const I = this.getBox().toRect(), B = A.getBoundingClientRect(), C = window.devicePixelRatio || 1, Q = B.left * C, E = B.top * C, i = B.height * C, o = I.x - Q, a = I.y - E, s = Math.floor(o), D = Math.floor(i - a - I.height), h = Math.floor(I.width), t = Math.floor(I.height);
|
|
3025
3098
|
return new AA(
|
|
@@ -3027,9 +3100,19 @@ class uQ {
|
|
|
3027
3100
|
V(s + h, D + t)
|
|
3028
3101
|
);
|
|
3029
3102
|
}
|
|
3103
|
+
/**
|
|
3104
|
+
* The viewport's rectangle in the drawing buffer in device pixels.
|
|
3105
|
+
*/
|
|
3030
3106
|
getBufferRect() {
|
|
3031
3107
|
return this.getBoxRelativeTo(this.element).toRect();
|
|
3032
3108
|
}
|
|
3109
|
+
/**
|
|
3110
|
+
* Converts a client-space position to clip space. The `y` axis points
|
|
3111
|
+
* down, matching the renderer's mirrored projection.
|
|
3112
|
+
*
|
|
3113
|
+
* @param position - The client-space position to convert.
|
|
3114
|
+
* @param depth - The clip-space z value.
|
|
3115
|
+
*/
|
|
3033
3116
|
clientToClip(A, I = 0) {
|
|
3034
3117
|
const [B, C] = A, Q = this.element.getBoundingClientRect();
|
|
3035
3118
|
return p(
|
|
@@ -3038,6 +3121,13 @@ class uQ {
|
|
|
3038
3121
|
I
|
|
3039
3122
|
);
|
|
3040
3123
|
}
|
|
3124
|
+
/**
|
|
3125
|
+
* Converts a client-space position such as a pointer location to world
|
|
3126
|
+
* space.
|
|
3127
|
+
*
|
|
3128
|
+
* @param position - The client-space position to convert.
|
|
3129
|
+
* @param depth - The clip-space z value.
|
|
3130
|
+
*/
|
|
3041
3131
|
clientToWorld(A, I = 0) {
|
|
3042
3132
|
const B = this.clientToClip(A, I);
|
|
3043
3133
|
return this.camera.clipToWorld(B);
|
|
@@ -3153,63 +3243,22 @@ class xQ {
|
|
|
3153
3243
|
}
|
|
3154
3244
|
const WQ = 2048;
|
|
3155
3245
|
class no {
|
|
3246
|
+
/** The canvas element the renderer draws into. */
|
|
3247
|
+
canvas;
|
|
3248
|
+
/** The registered overlays that update once per frame in order. */
|
|
3249
|
+
overlays;
|
|
3156
3250
|
chunkManager_;
|
|
3157
3251
|
context_;
|
|
3158
3252
|
renderer_;
|
|
3159
3253
|
viewports_;
|
|
3160
|
-
canvas;
|
|
3161
|
-
overlays;
|
|
3162
3254
|
stats_;
|
|
3163
3255
|
sizeObserver_;
|
|
3164
3256
|
lastAnimationId_;
|
|
3165
|
-
// this value will be set after start
|
|
3166
3257
|
lastTimestamp_ = 0;
|
|
3167
3258
|
/**
|
|
3168
|
-
* Creates
|
|
3169
|
-
*
|
|
3170
|
-
* @param params - Configuration parameters for the Idetik instance
|
|
3171
|
-
* @param params.canvas - HTMLCanvasElement to render to
|
|
3172
|
-
* @param params.viewports - Optional array of viewport configurations.
|
|
3173
|
-
* Each viewport renders with its own camera, layers, and controls.
|
|
3174
|
-
* The `element` property is optional and defaults to the canvas if not provided.
|
|
3175
|
-
* Elements must be unique across viewports.
|
|
3176
|
-
* The `id` property is optional but useful for referencing specific viewports later.
|
|
3177
|
-
* @param params.overlays - Optional array of overlay objects that update each frame (e.g., for HUD elements)
|
|
3178
|
-
* @param params.showStats - Optional flag to display performance statistics
|
|
3179
|
-
*
|
|
3180
|
-
* @example
|
|
3181
|
-
* // Single viewport (element defaults to canvas)
|
|
3182
|
-
* const camera = new OrthographicCamera({ left: 0, right: 1024, top: 0, bottom: 1024 });
|
|
3183
|
-
* const idetik = new Idetik({
|
|
3184
|
-
* canvas: document.querySelector('canvas')!,
|
|
3185
|
-
* viewports: [{
|
|
3186
|
-
* camera: camera,
|
|
3187
|
-
* layers: [imageLayer],
|
|
3188
|
-
* cameraControls: new PanZoomControls(camera)
|
|
3189
|
-
* }]
|
|
3190
|
-
* });
|
|
3259
|
+
* Creates an Idetik runtime for the given canvas.
|
|
3191
3260
|
*
|
|
3192
|
-
* @
|
|
3193
|
-
* // Multiple viewports - one defaults to canvas, others use separate elements
|
|
3194
|
-
* const idetik = new Idetik({
|
|
3195
|
-
* canvas: document.querySelector('canvas')!,
|
|
3196
|
-
* viewports: [
|
|
3197
|
-
* {
|
|
3198
|
-
* id: 'main',
|
|
3199
|
-
* // element omitted - defaults to canvas
|
|
3200
|
-
* camera: camera1,
|
|
3201
|
-
* layers: [layer1]
|
|
3202
|
-
* },
|
|
3203
|
-
* {
|
|
3204
|
-
* id: 'minimap',
|
|
3205
|
-
* element: document.querySelector('#minimap')!,
|
|
3206
|
-
* camera: camera2,
|
|
3207
|
-
* layers: [layer2]
|
|
3208
|
-
* }
|
|
3209
|
-
* ]
|
|
3210
|
-
* });
|
|
3211
|
-
*
|
|
3212
|
-
* @throws {Error} If viewports have duplicate IDs or shared elements
|
|
3261
|
+
* @param params - Initialization properties.
|
|
3213
3262
|
*/
|
|
3214
3263
|
constructor(A) {
|
|
3215
3264
|
this.canvas = A.canvas, this.renderer_ = new RQ(this.canvas);
|
|
@@ -3237,9 +3286,11 @@ class no {
|
|
|
3237
3286
|
Q.updateSize(), this.renderer_.render(Q);
|
|
3238
3287
|
});
|
|
3239
3288
|
}
|
|
3289
|
+
/** Counts of queued and in-flight chunk requests. */
|
|
3240
3290
|
get chunkQueueStats() {
|
|
3241
3291
|
return this.chunkManager_.queueStats;
|
|
3242
3292
|
}
|
|
3293
|
+
/** A snapshot of current CPU/GPU/JS heap memory usage. */
|
|
3243
3294
|
get memoryStats() {
|
|
3244
3295
|
const A = performance.memory;
|
|
3245
3296
|
return {
|
|
@@ -3250,28 +3301,52 @@ class no {
|
|
|
3250
3301
|
jsHeapLimitBytes: A?.jsHeapSizeLimit
|
|
3251
3302
|
};
|
|
3252
3303
|
}
|
|
3304
|
+
/** The number of objects drawn in the last rendered frame. */
|
|
3253
3305
|
get renderedObjects() {
|
|
3254
3306
|
return this.renderer_.renderedObjects;
|
|
3255
3307
|
}
|
|
3308
|
+
/** The width of the rendering surface in pixels. */
|
|
3256
3309
|
get width() {
|
|
3257
3310
|
return this.renderer_.width;
|
|
3258
3311
|
}
|
|
3312
|
+
/** The height of the rendering surface in pixels. */
|
|
3259
3313
|
get height() {
|
|
3260
3314
|
return this.renderer_.height;
|
|
3261
3315
|
}
|
|
3316
|
+
/** The viewports in render order. */
|
|
3262
3317
|
get viewports() {
|
|
3263
3318
|
return this.viewports_;
|
|
3264
3319
|
}
|
|
3320
|
+
/** Whether the render loop is running. */
|
|
3265
3321
|
get running() {
|
|
3266
3322
|
return this.lastAnimationId_ !== void 0;
|
|
3267
3323
|
}
|
|
3324
|
+
/**
|
|
3325
|
+
* Finds a viewport by its id.
|
|
3326
|
+
*
|
|
3327
|
+
* @param id - The id given in the viewport's definition.
|
|
3328
|
+
* @returns The matching viewport or `undefined` if none matches.
|
|
3329
|
+
*/
|
|
3268
3330
|
getViewport(A) {
|
|
3269
3331
|
return this.viewports_.find((I) => I.id === A);
|
|
3270
3332
|
}
|
|
3333
|
+
/**
|
|
3334
|
+
* Adds a viewport at runtime.
|
|
3335
|
+
*
|
|
3336
|
+
* @param props - The viewport definition. The `element` defaults to the
|
|
3337
|
+
* canvas and must be unique across viewports.
|
|
3338
|
+
* @returns The created viewport.
|
|
3339
|
+
*/
|
|
3271
3340
|
addViewport(A) {
|
|
3272
3341
|
const [I] = gB([A], this.canvas, this.context_);
|
|
3273
3342
|
return $B(I, this.viewports_), this.viewports_.push(I), this.running && (I.events.connect(), I.element !== this.canvas && this.sizeObserver_.observe(I.element)), k.info("Idetik", `Added viewport "${I.id}"`), I;
|
|
3274
3343
|
}
|
|
3344
|
+
/**
|
|
3345
|
+
* Removes a previously added viewport.
|
|
3346
|
+
*
|
|
3347
|
+
* @param viewport - The viewport to remove.
|
|
3348
|
+
* @returns `true` if the viewport was found and removed.
|
|
3349
|
+
*/
|
|
3275
3350
|
removeViewport(A) {
|
|
3276
3351
|
const I = this.viewports_.indexOf(A);
|
|
3277
3352
|
return I === -1 ? (k.warn(
|
|
@@ -3279,16 +3354,37 @@ class no {
|
|
|
3279
3354
|
`Viewport "${A.id}" not found, nothing to remove`
|
|
3280
3355
|
), !1) : (this.running && (A.events.disconnect(), A.element !== this.canvas && this.sizeObserver_.unobserve(A.element)), this.viewports_.splice(I, 1), k.info("Idetik", `Removed viewport "${A.id}"`), !0);
|
|
3281
3356
|
}
|
|
3357
|
+
/**
|
|
3358
|
+
* Registers an overlay that updates once per frame.
|
|
3359
|
+
*
|
|
3360
|
+
* @param overlay - The overlay to add.
|
|
3361
|
+
*/
|
|
3282
3362
|
addOverlay(A) {
|
|
3283
3363
|
this.overlays.push(A);
|
|
3284
3364
|
}
|
|
3365
|
+
/**
|
|
3366
|
+
* Removes a previously added overlay.
|
|
3367
|
+
*
|
|
3368
|
+
* @param overlay - The overlay to remove.
|
|
3369
|
+
* @returns `true` if the overlay was found and removed.
|
|
3370
|
+
*/
|
|
3285
3371
|
removeOverlay(A) {
|
|
3286
3372
|
const I = this.overlays.indexOf(A);
|
|
3287
3373
|
return I === -1 ? (k.warn("Idetik", "Overlay not found, nothing to remove"), !1) : (this.overlays.splice(I, 1), !0);
|
|
3288
3374
|
}
|
|
3375
|
+
/**
|
|
3376
|
+
* Sets the memory budget for chunk data at runtime.
|
|
3377
|
+
*
|
|
3378
|
+
* @param memoryLimitMB - The new budget in megabytes.
|
|
3379
|
+
*/
|
|
3289
3380
|
setMemoryLimitMB(A) {
|
|
3290
3381
|
this.chunkManager_.memoryLimitBytes = A * 1024 * 1024;
|
|
3291
3382
|
}
|
|
3383
|
+
/**
|
|
3384
|
+
* Starts the render loop and connects input handlers.
|
|
3385
|
+
*
|
|
3386
|
+
* @returns The instance, for chaining.
|
|
3387
|
+
*/
|
|
3292
3388
|
start() {
|
|
3293
3389
|
if (k.info("Idetik", "Idetik runtime starting"), this.running)
|
|
3294
3390
|
k.warn("Idetik", "Idetik runtime already started");
|
|
@@ -3314,6 +3410,9 @@ class no {
|
|
|
3314
3410
|
(B) => this.animate(B)
|
|
3315
3411
|
);
|
|
3316
3412
|
}
|
|
3413
|
+
/**
|
|
3414
|
+
* Stops the render loop and disconnects input handlers.
|
|
3415
|
+
*/
|
|
3317
3416
|
stop() {
|
|
3318
3417
|
if (k.info("Idetik", "Idetik runtime stopping"), !this.running)
|
|
3319
3418
|
k.warn("Idetik", "Idetik runtime not started");
|
|
@@ -11989,7 +12088,9 @@ ${JSON.stringify(g)}`);
|
|
|
11989
12088
|
}
|
|
11990
12089
|
}
|
|
11991
12090
|
class ZA {
|
|
12091
|
+
/** The zarr store location the image was opened from. */
|
|
11992
12092
|
location;
|
|
12093
|
+
/** The OME-Zarr version passed at creation if any. */
|
|
11993
12094
|
version;
|
|
11994
12095
|
loader_;
|
|
11995
12096
|
constructor(A) {
|
|
@@ -12017,33 +12118,45 @@ class ZA {
|
|
|
12017
12118
|
);
|
|
12018
12119
|
return new WE({ metadata: i, arrays: a, arrayParams: o });
|
|
12019
12120
|
}
|
|
12121
|
+
/**
|
|
12122
|
+
* Returns per-axis dimension metadata for the image.
|
|
12123
|
+
*
|
|
12124
|
+
* Each axis entry lists one record per level of detail with its size,
|
|
12125
|
+
* chunk size, scale, and translation. Use these to convert between
|
|
12126
|
+
* array indices and world coordinates, pick slice coordinates, and
|
|
12127
|
+
* frame cameras around the image extent.
|
|
12128
|
+
*/
|
|
12020
12129
|
getDimensions() {
|
|
12021
12130
|
return this.loader_.getSourceDimensionMap();
|
|
12022
12131
|
}
|
|
12132
|
+
/**
|
|
12133
|
+
* Returns the number of channels in the image.
|
|
12134
|
+
*/
|
|
12023
12135
|
getChannelCount() {
|
|
12024
12136
|
return this.getDimensions().c?.lods[0].size ?? 1;
|
|
12025
12137
|
}
|
|
12138
|
+
/** The chunk loader that streams this image's data. */
|
|
12026
12139
|
get loader() {
|
|
12027
12140
|
return this.loader_;
|
|
12028
12141
|
}
|
|
12029
12142
|
/**
|
|
12030
|
-
*
|
|
12143
|
+
* Opens an OME-Zarr image over HTTP(S).
|
|
12031
12144
|
*
|
|
12032
|
-
* @param props
|
|
12033
|
-
* @param props.version OME-Zarr version
|
|
12145
|
+
* @param props - The store url and optional version.
|
|
12034
12146
|
*/
|
|
12035
12147
|
static async fromHttp(A) {
|
|
12036
12148
|
const I = new CA(new zA(A.url)), B = await ZA.openLoader(I, A.version);
|
|
12037
12149
|
return new ZA({ location: I, version: A.version, loader: B });
|
|
12038
12150
|
}
|
|
12039
12151
|
/**
|
|
12040
|
-
*
|
|
12152
|
+
* Opens an OME-Zarr image from a local directory.
|
|
12153
|
+
*
|
|
12154
|
+
* Uses the File System Access API so it only works in Chromium-based
|
|
12155
|
+
* browsers. Pass the handle returned by `window.showDirectoryPicker()`.
|
|
12156
|
+
* The optional path lets an application ask once for root permission
|
|
12157
|
+
* and open many images.
|
|
12041
12158
|
*
|
|
12042
|
-
* @param
|
|
12043
|
-
* permission to access a directory (only works in Chrome/Edge)
|
|
12044
|
-
* @param version OME-Zarr version
|
|
12045
|
-
* @param path path to image, beginning with "/". This argument allows the application to only
|
|
12046
|
-
* ask the user once for permission to the root directory
|
|
12159
|
+
* @param props - The directory handle, optional version, and path.
|
|
12047
12160
|
*/
|
|
12048
12161
|
static async fromFileSystem(A) {
|
|
12049
12162
|
const I = new CA(
|
|
@@ -12054,14 +12167,33 @@ class ZA {
|
|
|
12054
12167
|
}
|
|
12055
12168
|
}
|
|
12056
12169
|
class qI {
|
|
12170
|
+
/**
|
|
12171
|
+
* How the layer's output blends with previously drawn content. Also
|
|
12172
|
+
* applies to blending between objects within the layer.
|
|
12173
|
+
*/
|
|
12174
|
+
blendMode;
|
|
12175
|
+
/**
|
|
12176
|
+
* Whether the layer writes depth and hides content drawn behind it.
|
|
12177
|
+
*
|
|
12178
|
+
* Occluding layers render a depth pass and always draw before
|
|
12179
|
+
* non-occluding layers regardless of their order in the viewport. When
|
|
12180
|
+
* not set explicitly this value is inferred from `blendMode` at
|
|
12181
|
+
* construction only. Reassigning {@link blendMode} later does not update
|
|
12182
|
+
* it.
|
|
12183
|
+
*/
|
|
12184
|
+
occludes;
|
|
12185
|
+
/** Set to `true` by subclasses whose shaders read scene depth. */
|
|
12186
|
+
requiresSceneDepth_ = !1;
|
|
12057
12187
|
coverageGroups_ = /* @__PURE__ */ new Map();
|
|
12058
12188
|
state_ = "initialized";
|
|
12059
12189
|
attached_ = !1;
|
|
12060
12190
|
callbacks_ = [];
|
|
12061
12191
|
opacity_;
|
|
12062
|
-
|
|
12063
|
-
|
|
12064
|
-
|
|
12192
|
+
/**
|
|
12193
|
+
* Creates a layer with the given presentation state.
|
|
12194
|
+
*
|
|
12195
|
+
* @param props - Initialization properties.
|
|
12196
|
+
*/
|
|
12065
12197
|
constructor({
|
|
12066
12198
|
opacity: A = 1,
|
|
12067
12199
|
blendMode: I = "none",
|
|
@@ -12069,20 +12201,41 @@ class qI {
|
|
|
12069
12201
|
} = {}) {
|
|
12070
12202
|
this.opacity_ = hA(A, 0, 1), this.blendMode = I, this.occludes = B ?? I === "none";
|
|
12071
12203
|
}
|
|
12204
|
+
/**
|
|
12205
|
+
* Whether the layer's shaders read scene depth. When `true` the renderer
|
|
12206
|
+
* draws occluding layers to a depth texture the layer's shaders can
|
|
12207
|
+
* sample. A layer cannot both occlude and read scene depth.
|
|
12208
|
+
*/
|
|
12072
12209
|
get requiresSceneDepth() {
|
|
12073
12210
|
return this.requiresSceneDepth_;
|
|
12074
12211
|
}
|
|
12212
|
+
/** The layer's opacity in `[0, 1]`. Values outside are clamped. */
|
|
12075
12213
|
get opacity() {
|
|
12076
12214
|
return this.opacity_;
|
|
12077
12215
|
}
|
|
12216
|
+
/** @param value - The new opacity in `[0, 1]`. */
|
|
12078
12217
|
set opacity(A) {
|
|
12079
12218
|
(A < 0 || A > 1) && k.warn(
|
|
12080
12219
|
"Layer",
|
|
12081
12220
|
`Opacity out of bounds: ${A} — clamping to [0.0, 1.0]`
|
|
12082
12221
|
), this.opacity_ = hA(A, 0, 1);
|
|
12083
12222
|
}
|
|
12223
|
+
/**
|
|
12224
|
+
* Handles a pointer or wheel event from the owning viewport. Called
|
|
12225
|
+
* automatically for each event before the camera controls. The default
|
|
12226
|
+
* implementation does nothing.
|
|
12227
|
+
*
|
|
12228
|
+
* @param _event - The event with clip and world coordinates attached.
|
|
12229
|
+
*/
|
|
12084
12230
|
onEvent(A) {
|
|
12085
12231
|
}
|
|
12232
|
+
/**
|
|
12233
|
+
* Lifecycle hook that is called automatically when a layer is
|
|
12234
|
+
* is attached to a viewport. A layer can only be attached to one viewport
|
|
12235
|
+
* at a time.
|
|
12236
|
+
*
|
|
12237
|
+
* @param context - The shared runtime context.
|
|
12238
|
+
*/
|
|
12086
12239
|
onAttached(A) {
|
|
12087
12240
|
if (this.attached_)
|
|
12088
12241
|
throw new Error(
|
|
@@ -12092,42 +12245,79 @@ class qI {
|
|
|
12092
12245
|
throw new Error(`${this.type} cannot both occlude and read scene depth.`);
|
|
12093
12246
|
this.attach(A), this.attached_ = !0;
|
|
12094
12247
|
}
|
|
12248
|
+
/**
|
|
12249
|
+
* Lifecycle hook that is called automatically when a layer is detached
|
|
12250
|
+
* from a viewport.
|
|
12251
|
+
*
|
|
12252
|
+
* @param context - The shared runtime context.
|
|
12253
|
+
*/
|
|
12095
12254
|
onDetached(A) {
|
|
12096
12255
|
this.attached_ && (this.detach(A), this.attached_ = !1);
|
|
12097
12256
|
}
|
|
12257
|
+
/** @hidden */
|
|
12098
12258
|
attach(A) {
|
|
12099
12259
|
}
|
|
12260
|
+
/** @hidden */
|
|
12100
12261
|
detach(A) {
|
|
12101
12262
|
}
|
|
12263
|
+
/**
|
|
12264
|
+
* The layer's renderable objects grouped by coverage group. Objects in
|
|
12265
|
+
* a group draw each pixel at most once, letting chunks at multiple
|
|
12266
|
+
* levels of detail overlap correctly.
|
|
12267
|
+
*/
|
|
12102
12268
|
get coverageGroups() {
|
|
12103
12269
|
return this.coverageGroups_;
|
|
12104
12270
|
}
|
|
12271
|
+
/** The layer's current lifecycle state. */
|
|
12105
12272
|
get state() {
|
|
12106
12273
|
return this.state_;
|
|
12107
12274
|
}
|
|
12275
|
+
/**
|
|
12276
|
+
* Registers a callback invoked after every state change.
|
|
12277
|
+
*
|
|
12278
|
+
* @param callback - Receives the new and previous states.
|
|
12279
|
+
*/
|
|
12108
12280
|
addStateChangeCallback(A) {
|
|
12109
12281
|
this.callbacks_.push(A);
|
|
12110
12282
|
}
|
|
12283
|
+
/**
|
|
12284
|
+
* Removes a previously registered state change callback.
|
|
12285
|
+
*
|
|
12286
|
+
* @param callback - The callback to remove.
|
|
12287
|
+
*/
|
|
12111
12288
|
removeStateChangeCallback(A) {
|
|
12112
12289
|
const I = this.callbacks_.indexOf(A);
|
|
12113
12290
|
if (I === -1)
|
|
12114
12291
|
throw new Error(`Callback to remove could not be found: ${A}`);
|
|
12115
12292
|
this.callbacks_.splice(I, 1);
|
|
12116
12293
|
}
|
|
12294
|
+
/**
|
|
12295
|
+
* Sets the lifecycle state and notifies state change callbacks.
|
|
12296
|
+
*
|
|
12297
|
+
* @param newState - The state to enter.
|
|
12298
|
+
*/
|
|
12117
12299
|
setState(A) {
|
|
12118
12300
|
const I = this.state_;
|
|
12119
12301
|
this.state_ = A, this.callbacks_.forEach((B) => B(A, I));
|
|
12120
12302
|
}
|
|
12303
|
+
/**
|
|
12304
|
+
* Registers a renderable object for drawing. Objects in the same
|
|
12305
|
+
* coverage group draw each pixel at most once.
|
|
12306
|
+
*
|
|
12307
|
+
* @param object - The object to add.
|
|
12308
|
+
* @param coverageGroup - The group key.
|
|
12309
|
+
*/
|
|
12121
12310
|
addObject(A, I = null) {
|
|
12122
12311
|
const B = this.coverageGroups_.get(I);
|
|
12123
12312
|
B ? B.push(A) : this.coverageGroups_.set(I, [A]);
|
|
12124
12313
|
}
|
|
12314
|
+
/** Removes all registered renderable objects. */
|
|
12125
12315
|
clearObjects() {
|
|
12126
12316
|
this.coverageGroups_.clear();
|
|
12127
12317
|
}
|
|
12128
12318
|
/**
|
|
12129
|
-
*
|
|
12130
|
-
*
|
|
12319
|
+
* Returns uniform name-value pairs applied to every object drawn by
|
|
12320
|
+
* this layer. Override in subclasses that need custom shader uniforms.
|
|
12131
12321
|
*/
|
|
12132
12322
|
getUniforms() {
|
|
12133
12323
|
return {};
|
|
@@ -12214,41 +12404,82 @@ class eC {
|
|
|
12214
12404
|
rotation_ = hI();
|
|
12215
12405
|
translation_ = d();
|
|
12216
12406
|
scale_ = p(1, 1, 1);
|
|
12407
|
+
/**
|
|
12408
|
+
* Composes the given rotation onto the current rotation.
|
|
12409
|
+
*
|
|
12410
|
+
* @param q - The rotation to apply.
|
|
12411
|
+
*/
|
|
12217
12412
|
addRotation(A) {
|
|
12218
12413
|
EQ(this.rotation_, this.rotation_, A), this.dirty_ = !0;
|
|
12219
12414
|
}
|
|
12415
|
+
/**
|
|
12416
|
+
* Replaces the rotation with the given quaternion.
|
|
12417
|
+
*
|
|
12418
|
+
* @param q - The new rotation.
|
|
12419
|
+
*/
|
|
12220
12420
|
setRotation(A) {
|
|
12221
12421
|
oQ(this.rotation_, A), this.dirty_ = !0;
|
|
12222
12422
|
}
|
|
12423
|
+
/** A copy of the rotation quaternion. */
|
|
12223
12424
|
get rotation() {
|
|
12224
12425
|
return iQ(this.rotation_);
|
|
12225
12426
|
}
|
|
12427
|
+
/**
|
|
12428
|
+
* Adds the given offset to the translation.
|
|
12429
|
+
*
|
|
12430
|
+
* @param vec - The offset to add.
|
|
12431
|
+
*/
|
|
12226
12432
|
addTranslation(A) {
|
|
12227
12433
|
aI(this.translation_, this.translation_, A), this.dirty_ = !0;
|
|
12228
12434
|
}
|
|
12435
|
+
/**
|
|
12436
|
+
* Replaces the translation with the given vector.
|
|
12437
|
+
*
|
|
12438
|
+
* @param vec - The new translation.
|
|
12439
|
+
*/
|
|
12229
12440
|
setTranslation(A) {
|
|
12230
12441
|
jI(this.translation_, A), this.dirty_ = !0;
|
|
12231
12442
|
}
|
|
12443
|
+
/** A copy of the translation vector. */
|
|
12232
12444
|
get translation() {
|
|
12233
12445
|
return EA(this.translation_);
|
|
12234
12446
|
}
|
|
12447
|
+
/**
|
|
12448
|
+
* Multiplies the scale componentwise by the given vector.
|
|
12449
|
+
*
|
|
12450
|
+
* @param vec - The scale factors to apply.
|
|
12451
|
+
*/
|
|
12235
12452
|
addScale(A) {
|
|
12236
12453
|
zC(this.scale_, this.scale_, A), this.dirty_ = !0;
|
|
12237
12454
|
}
|
|
12455
|
+
/**
|
|
12456
|
+
* Replaces the scale with the given vector.
|
|
12457
|
+
*
|
|
12458
|
+
* @param vec - The new scale.
|
|
12459
|
+
*/
|
|
12238
12460
|
setScale(A) {
|
|
12239
12461
|
jI(this.scale_, A), this.dirty_ = !0;
|
|
12240
12462
|
}
|
|
12463
|
+
/**
|
|
12464
|
+
* Rotates the transform to face the given target point. Uses `+Y` as
|
|
12465
|
+
* world up.
|
|
12466
|
+
*
|
|
12467
|
+
* @param target - The world-space point to face.
|
|
12468
|
+
*/
|
|
12241
12469
|
targetTo(A) {
|
|
12242
12470
|
Gg(this.translation_, A) && (A = EA(A), A[2] += T);
|
|
12243
12471
|
const I = XC($(), this.translation_, A, fi), B = xC(VB(), I);
|
|
12244
12472
|
wg(this.rotation_, B), MI(this.rotation_, this.rotation_), this.dirty_ = !0;
|
|
12245
12473
|
}
|
|
12474
|
+
/** A copy of the scale vector. */
|
|
12246
12475
|
get scale() {
|
|
12247
12476
|
return EA(this.scale_);
|
|
12248
12477
|
}
|
|
12478
|
+
/** The composed transform matrix. Recomputed when stale. */
|
|
12249
12479
|
get matrix() {
|
|
12250
12480
|
return this.dirty_ && (this.computeMatrix(), this.dirty_ = !1), this.matrix_;
|
|
12251
12481
|
}
|
|
12482
|
+
/** The inverse of the composed transform matrix. */
|
|
12252
12483
|
get inverse() {
|
|
12253
12484
|
return OA($(), this.matrix);
|
|
12254
12485
|
}
|
|
@@ -12262,17 +12493,34 @@ class eC {
|
|
|
12262
12493
|
}
|
|
12263
12494
|
}
|
|
12264
12495
|
class x {
|
|
12496
|
+
/** Opaque red `#ff0000`. */
|
|
12265
12497
|
static RED = new x(1, 0, 0);
|
|
12498
|
+
/** Opaque green `#00ff00`. */
|
|
12266
12499
|
static GREEN = new x(0, 1, 0);
|
|
12500
|
+
/** Opaque blue `#0000ff`. */
|
|
12267
12501
|
static BLUE = new x(0, 0, 1);
|
|
12502
|
+
/** Opaque yellow `#ffff00`. */
|
|
12268
12503
|
static YELLOW = new x(1, 1, 0);
|
|
12504
|
+
/** Opaque magenta `#ff00ff`. */
|
|
12269
12505
|
static MAGENTA = new x(1, 0, 1);
|
|
12506
|
+
/** Opaque cyan `#00ffff`. */
|
|
12270
12507
|
static CYAN = new x(0, 1, 1);
|
|
12508
|
+
/** Opaque black `#000000`. */
|
|
12271
12509
|
static BLACK = new x(0, 0, 0);
|
|
12510
|
+
/** Opaque white `#ffffff`. */
|
|
12272
12511
|
static WHITE = new x(1, 1, 1);
|
|
12512
|
+
/** Fully transparent black. */
|
|
12273
12513
|
static TRANSPARENT = new x(0, 0, 0, 0);
|
|
12274
12514
|
// RGBA color values in the range [0, 1]
|
|
12275
12515
|
rgba_;
|
|
12516
|
+
/**
|
|
12517
|
+
* Creates a color from RGBA components in `[0, 1]`.
|
|
12518
|
+
*
|
|
12519
|
+
* @param r - The red component.
|
|
12520
|
+
* @param g - The green component.
|
|
12521
|
+
* @param b - The blue component.
|
|
12522
|
+
* @param a - The alpha component. Defaults to `1`.
|
|
12523
|
+
*/
|
|
12276
12524
|
constructor(A, I, B, C) {
|
|
12277
12525
|
if (A < 0 || A > 1 || I < 0 || I > 1 || B < 0 || B > 1)
|
|
12278
12526
|
throw new Error("RGB values must be in the range [0, 1]");
|
|
@@ -12280,30 +12528,43 @@ class x {
|
|
|
12280
12528
|
throw new Error("Alpha value must be in the range [0, 1]");
|
|
12281
12529
|
this.rgba_ = [A, I, B, C ?? 1];
|
|
12282
12530
|
}
|
|
12531
|
+
/** The RGB components as a three-element array. */
|
|
12283
12532
|
get rgb() {
|
|
12284
12533
|
return [this.rgba_[0], this.rgba_[1], this.rgba_[2]];
|
|
12285
12534
|
}
|
|
12535
|
+
/** The RGBA components as a four-element array. */
|
|
12286
12536
|
get rgba() {
|
|
12287
12537
|
return this.rgba_;
|
|
12288
12538
|
}
|
|
12539
|
+
/** The red component. */
|
|
12289
12540
|
get r() {
|
|
12290
12541
|
return this.rgba_[0];
|
|
12291
12542
|
}
|
|
12543
|
+
/** The green component. */
|
|
12292
12544
|
get g() {
|
|
12293
12545
|
return this.rgba_[1];
|
|
12294
12546
|
}
|
|
12547
|
+
/** The blue component. */
|
|
12295
12548
|
get b() {
|
|
12296
12549
|
return this.rgba_[2];
|
|
12297
12550
|
}
|
|
12551
|
+
/** The alpha component. */
|
|
12298
12552
|
get a() {
|
|
12299
12553
|
return this.rgba_[3];
|
|
12300
12554
|
}
|
|
12555
|
+
/** The color as a `#rrggbb` hex string. Alpha is dropped. */
|
|
12301
12556
|
get rgbHex() {
|
|
12302
12557
|
return `#${this.toHexComponent(this.r)}${this.toHexComponent(this.g)}${this.toHexComponent(this.b)}`;
|
|
12303
12558
|
}
|
|
12559
|
+
/** The color packed into a 32-bit integer as RGBA bytes. */
|
|
12304
12560
|
get packed() {
|
|
12305
12561
|
return Math.round(this.r * 255) << 24 | Math.round(this.g * 255) << 16 | Math.round(this.b * 255) << 8 | Math.round(this.a * 255);
|
|
12306
12562
|
}
|
|
12563
|
+
/**
|
|
12564
|
+
* Converts a {@link ColorLike} value to a `Color`.
|
|
12565
|
+
*
|
|
12566
|
+
* @param colorLike - The value to convert.
|
|
12567
|
+
*/
|
|
12307
12568
|
static from(A) {
|
|
12308
12569
|
if (A instanceof x)
|
|
12309
12570
|
return A;
|
|
@@ -12313,6 +12574,11 @@ class x {
|
|
|
12313
12574
|
return x.fromRgbHex(A);
|
|
12314
12575
|
throw new Error("Unsupported color format");
|
|
12315
12576
|
}
|
|
12577
|
+
/**
|
|
12578
|
+
* Parses a `#rrggbb` hex string into an opaque color.
|
|
12579
|
+
*
|
|
12580
|
+
* @param hex - The hex string with or without the leading `#`.
|
|
12581
|
+
*/
|
|
12316
12582
|
static fromRgbHex(A) {
|
|
12317
12583
|
const I = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(A);
|
|
12318
12584
|
if (!I)
|
|
@@ -12330,8 +12596,17 @@ class x {
|
|
|
12330
12596
|
}
|
|
12331
12597
|
}
|
|
12332
12598
|
class gI extends YI {
|
|
12599
|
+
/**
|
|
12600
|
+
* Draws the geometry's wireframe on top of the normal pass. Layers use
|
|
12601
|
+
* this as a chunk debugging aid. Defaults to `false`.
|
|
12602
|
+
*/
|
|
12333
12603
|
wireframeEnabled = !1;
|
|
12604
|
+
/** The color of the wireframe overlay. Defaults to `Color.WHITE`. */
|
|
12334
12605
|
wireframeColor = x.WHITE;
|
|
12606
|
+
/**
|
|
12607
|
+
* Whether the object is depth tested when drawn. Objects that opt out
|
|
12608
|
+
* are also left out of the depth prepass. Defaults to `true`.
|
|
12609
|
+
*/
|
|
12335
12610
|
depthTest = !0;
|
|
12336
12611
|
textures_ = [];
|
|
12337
12612
|
staleTextures_ = [];
|
|
@@ -12341,59 +12616,124 @@ class gI extends YI {
|
|
|
12341
12616
|
programName_ = null;
|
|
12342
12617
|
depthProgramName_ = null;
|
|
12343
12618
|
cullFaceMode_ = "none";
|
|
12619
|
+
/**
|
|
12620
|
+
* Assigns a texture to the given texture unit. The renderer binds each
|
|
12621
|
+
* entry of {@link textures} to its matching unit before drawing.
|
|
12622
|
+
*
|
|
12623
|
+
* @param index - The texture unit to bind to.
|
|
12624
|
+
* @param texture - The texture to assign.
|
|
12625
|
+
*/
|
|
12344
12626
|
setTexture(A, I) {
|
|
12345
12627
|
this.textures_[A] = I;
|
|
12346
12628
|
}
|
|
12629
|
+
/**
|
|
12630
|
+
* Removes all assigned textures.
|
|
12631
|
+
*/
|
|
12347
12632
|
clearTextures() {
|
|
12348
12633
|
this.textures_.length = 0;
|
|
12349
12634
|
}
|
|
12635
|
+
/**
|
|
12636
|
+
* Queues a replaced texture for GPU disposal. Subclasses call this when
|
|
12637
|
+
* swapping out a texture they own. The renderer drains the queue
|
|
12638
|
+
* through {@link popStaleTextures} before the next draw. Passing
|
|
12639
|
+
* `undefined` is a no-op.
|
|
12640
|
+
*
|
|
12641
|
+
* @param texture - The texture that is no longer in use.
|
|
12642
|
+
*/
|
|
12350
12643
|
markStaleTexture(A) {
|
|
12351
12644
|
A !== void 0 && this.staleTextures_.push(A);
|
|
12352
12645
|
}
|
|
12646
|
+
/**
|
|
12647
|
+
* Drains the queue of textures marked stale. Called automatically by
|
|
12648
|
+
* the renderer, which disposes the GPU resources of each returned
|
|
12649
|
+
* texture.
|
|
12650
|
+
*
|
|
12651
|
+
* @returns The textures queued since the last call.
|
|
12652
|
+
*/
|
|
12353
12653
|
popStaleTextures() {
|
|
12354
12654
|
const A = this.staleTextures_;
|
|
12355
12655
|
return this.staleTextures_ = [], A;
|
|
12356
12656
|
}
|
|
12657
|
+
/**
|
|
12658
|
+
* The geometry drawn for this object.
|
|
12659
|
+
*/
|
|
12357
12660
|
get geometry() {
|
|
12358
12661
|
return this.geometry_;
|
|
12359
12662
|
}
|
|
12663
|
+
/**
|
|
12664
|
+
* A line-segment version of {@link geometry} used for the wireframe
|
|
12665
|
+
* overlay. Built lazily on first access and cached until the geometry
|
|
12666
|
+
* changes.
|
|
12667
|
+
*/
|
|
12360
12668
|
get wireframeGeometry() {
|
|
12361
12669
|
return this.wireframeGeometry_ ??= new li(this.geometry), this.wireframeGeometry_;
|
|
12362
12670
|
}
|
|
12671
|
+
/** The assigned textures indexed by texture unit. */
|
|
12363
12672
|
get textures() {
|
|
12364
12673
|
return this.textures_;
|
|
12365
12674
|
}
|
|
12675
|
+
/**
|
|
12676
|
+
* The object's world transform as translation, rotation, and scale.
|
|
12677
|
+
* Layers position, orient, and size renderables through it.
|
|
12678
|
+
*/
|
|
12366
12679
|
get transform() {
|
|
12367
12680
|
return this.transform_;
|
|
12368
12681
|
}
|
|
12682
|
+
/** @param geometry - The geometry to draw. */
|
|
12369
12683
|
set geometry(A) {
|
|
12370
12684
|
this.geometry_ = A, this.wireframeGeometry_ = null;
|
|
12371
12685
|
}
|
|
12686
|
+
/**
|
|
12687
|
+
* The name of a shader program that draws the object. The
|
|
12688
|
+
* renderer skips objects whose program name is `null`.
|
|
12689
|
+
*/
|
|
12372
12690
|
get programName() {
|
|
12373
12691
|
return this.programName_;
|
|
12374
12692
|
}
|
|
12693
|
+
/**
|
|
12694
|
+
* The name of the shader program used in the depth prepass or `null`
|
|
12695
|
+
* to stay out of it. Objects without one never occlude other layers.
|
|
12696
|
+
*/
|
|
12375
12697
|
get depthProgramName() {
|
|
12376
12698
|
return this.depthProgramName_;
|
|
12377
12699
|
}
|
|
12700
|
+
/**
|
|
12701
|
+
* The geometry's bounding box transformed to world space. The renderer
|
|
12702
|
+
* culls objects whose box falls outside the view frustum.
|
|
12703
|
+
*/
|
|
12378
12704
|
get boundingBox() {
|
|
12379
12705
|
const A = this.geometry_.boundingBox.clone();
|
|
12380
12706
|
return A.applyTransform(this.transform_.matrix), A;
|
|
12381
12707
|
}
|
|
12708
|
+
/**
|
|
12709
|
+
* @param programName - The shader program name.
|
|
12710
|
+
*/
|
|
12382
12711
|
set programName(A) {
|
|
12383
12712
|
this.programName_ = A;
|
|
12384
12713
|
}
|
|
12714
|
+
/**
|
|
12715
|
+
* Selects the shader program for the depth prepass. Subclasses set
|
|
12716
|
+
* this so the object writes depth and occludes content in other
|
|
12717
|
+
* layers.
|
|
12718
|
+
*
|
|
12719
|
+
* @param programName - The shader program name.
|
|
12720
|
+
*/
|
|
12385
12721
|
set depthProgramName(A) {
|
|
12386
12722
|
this.depthProgramName_ = A;
|
|
12387
12723
|
}
|
|
12724
|
+
/** Which triangle faces are culled when drawing. Defaults to `"none"`. */
|
|
12388
12725
|
get cullFaceMode() {
|
|
12389
12726
|
return this.cullFaceMode_;
|
|
12390
12727
|
}
|
|
12728
|
+
/** @param mode - The culling mode to apply. */
|
|
12391
12729
|
set cullFaceMode(A) {
|
|
12392
12730
|
this.cullFaceMode_ = A;
|
|
12393
12731
|
}
|
|
12394
12732
|
/**
|
|
12395
|
-
*
|
|
12396
|
-
*
|
|
12733
|
+
* Returns the uniform values to upload before drawing. Override in
|
|
12734
|
+
* subclasses that need custom uniforms. Values are matched to shader
|
|
12735
|
+
* uniforms by name and take precedence over the owning layer's
|
|
12736
|
+
* uniforms.
|
|
12397
12737
|
*/
|
|
12398
12738
|
getUniforms() {
|
|
12399
12739
|
return {};
|
|
@@ -12402,24 +12742,35 @@ class gI extends YI {
|
|
|
12402
12742
|
class pi extends gI {
|
|
12403
12743
|
color_;
|
|
12404
12744
|
width_;
|
|
12745
|
+
/**
|
|
12746
|
+
* Creates a projected line renderable for the given path geometry.
|
|
12747
|
+
*
|
|
12748
|
+
* @param props - Initialization properties.
|
|
12749
|
+
*/
|
|
12405
12750
|
constructor({ geometry: A, color: I, width: B }) {
|
|
12406
12751
|
super(), this.geometry = A, this.color_ = x.from(I), this.width_ = B, this.programName = "projectedLine", this.depthProgramName = "projectedLineDepth";
|
|
12407
12752
|
}
|
|
12753
|
+
/** Identifies the renderable type as `ProjectedLineRenderable`. */
|
|
12408
12754
|
get type() {
|
|
12409
12755
|
return "ProjectedLineRenderable";
|
|
12410
12756
|
}
|
|
12757
|
+
/** The line color. Assignable from any {@link ColorLike} value. */
|
|
12411
12758
|
get color() {
|
|
12412
12759
|
return this.color_;
|
|
12413
12760
|
}
|
|
12761
|
+
/** @param value - The new line color. */
|
|
12414
12762
|
set color(A) {
|
|
12415
12763
|
this.color_ = x.from(A);
|
|
12416
12764
|
}
|
|
12765
|
+
/** The line width in pixels. */
|
|
12417
12766
|
get width() {
|
|
12418
12767
|
return this.width_;
|
|
12419
12768
|
}
|
|
12769
|
+
/** @param value - The new width in pixels. */
|
|
12420
12770
|
set width(A) {
|
|
12421
12771
|
this.width_ = A;
|
|
12422
12772
|
}
|
|
12773
|
+
/** Returns the color and width uniforms for the line shader. */
|
|
12423
12774
|
getUniforms() {
|
|
12424
12775
|
return {
|
|
12425
12776
|
u_lineColor: this.color.rgb,
|
|
@@ -12428,7 +12779,13 @@ class pi extends gI {
|
|
|
12428
12779
|
}
|
|
12429
12780
|
}
|
|
12430
12781
|
class Ro extends qI {
|
|
12782
|
+
/** Identifies the layer type as `AxesLayer`. */
|
|
12431
12783
|
type = "AxesLayer";
|
|
12784
|
+
/**
|
|
12785
|
+
* Creates an axes layer with the given dimensions.
|
|
12786
|
+
*
|
|
12787
|
+
* @param props - Initialization properties.
|
|
12788
|
+
*/
|
|
12432
12789
|
constructor(A) {
|
|
12433
12790
|
super();
|
|
12434
12791
|
const { length: I, width: B } = A;
|
|
@@ -12452,6 +12809,7 @@ class Ro extends qI {
|
|
|
12452
12809
|
})
|
|
12453
12810
|
), this.setState("ready");
|
|
12454
12811
|
}
|
|
12812
|
+
/** Performs no per-frame work. The axes are built at construction. */
|
|
12455
12813
|
update() {
|
|
12456
12814
|
}
|
|
12457
12815
|
}
|
|
@@ -12620,8 +12978,18 @@ class wC extends mA {
|
|
|
12620
12978
|
}
|
|
12621
12979
|
}
|
|
12622
12980
|
class Ti extends gI {
|
|
12623
|
-
|
|
12981
|
+
/**
|
|
12982
|
+
* A matrix mapping world space to the texture's normalized coordinate
|
|
12983
|
+
* space. Layers derive it from the chunk's offset, scale, and shape.
|
|
12984
|
+
*/
|
|
12624
12985
|
worldToTexCoord = $();
|
|
12986
|
+
channels_;
|
|
12987
|
+
/**
|
|
12988
|
+
* Creates an image renderable drawing the given texture. The texture's
|
|
12989
|
+
* data type selects the matching scalar image shader.
|
|
12990
|
+
*
|
|
12991
|
+
* @param props - Initialization properties.
|
|
12992
|
+
*/
|
|
12625
12993
|
constructor({
|
|
12626
12994
|
width: A,
|
|
12627
12995
|
height: I,
|
|
@@ -12630,12 +12998,27 @@ class Ti extends gI {
|
|
|
12630
12998
|
}) {
|
|
12631
12999
|
super(), this.geometry = new wC(A, I, 1, 1), this.setTexture(0, B), this.channels_ = tg(B, C), this.programName = xi(B), this.depthProgramName = "meshDepth";
|
|
12632
13000
|
}
|
|
13001
|
+
/** Identifies the renderable type as `ImageRenderable`. */
|
|
12633
13002
|
get type() {
|
|
12634
13003
|
return "ImageRenderable";
|
|
12635
13004
|
}
|
|
13005
|
+
/**
|
|
13006
|
+
* Replaces the channel appearance settings and revalidates them
|
|
13007
|
+
* against the current texture. Only the first entry affects rendering.
|
|
13008
|
+
*
|
|
13009
|
+
* @param channels - The new channel settings.
|
|
13010
|
+
*/
|
|
12636
13011
|
setChannelProps(A) {
|
|
12637
13012
|
this.channels_ = tg(this.textures[0], A);
|
|
12638
13013
|
}
|
|
13014
|
+
/**
|
|
13015
|
+
* Updates one property of the channel at the given index and
|
|
13016
|
+
* revalidates the channel against the current texture.
|
|
13017
|
+
*
|
|
13018
|
+
* @param channelIndex - The channel to update.
|
|
13019
|
+
* @param property - The property name to set.
|
|
13020
|
+
* @param value - The new value.
|
|
13021
|
+
*/
|
|
12639
13022
|
setChannelProperty(A, I, B) {
|
|
12640
13023
|
const C = jA(this.textures[0], {
|
|
12641
13024
|
...this.channels_[A],
|
|
@@ -12643,6 +13026,10 @@ class Ti extends gI {
|
|
|
12643
13026
|
});
|
|
12644
13027
|
this.channels_[A] = C;
|
|
12645
13028
|
}
|
|
13029
|
+
/**
|
|
13030
|
+
* Returns the sampler, contrast, color, opacity, and world-to-texture
|
|
13031
|
+
* uniforms for the scalar image shaders.
|
|
13032
|
+
*/
|
|
12646
13033
|
getUniforms() {
|
|
12647
13034
|
const A = this.textures[0];
|
|
12648
13035
|
if (!A)
|
|
@@ -12737,6 +13124,7 @@ class xg {
|
|
|
12737
13124
|
}
|
|
12738
13125
|
}
|
|
12739
13126
|
class rC extends qI {
|
|
13127
|
+
/** Identifies the layer type as `ImageLayer`. */
|
|
12740
13128
|
type = "ImageLayer";
|
|
12741
13129
|
source_;
|
|
12742
13130
|
sliceCoords_;
|
|
@@ -12764,6 +13152,11 @@ class rC extends qI {
|
|
|
12764
13152
|
new x(0.4, 0.4, 0.7),
|
|
12765
13153
|
new x(0.6, 0.5, 0.3)
|
|
12766
13154
|
];
|
|
13155
|
+
/**
|
|
13156
|
+
* Creates an image layer for the given source and slice.
|
|
13157
|
+
*
|
|
13158
|
+
* @param props - Initialization properties.
|
|
13159
|
+
*/
|
|
12767
13160
|
constructor({
|
|
12768
13161
|
source: A,
|
|
12769
13162
|
sliceCoords: I,
|
|
@@ -12775,6 +13168,7 @@ class rC extends qI {
|
|
|
12775
13168
|
}) {
|
|
12776
13169
|
super({ blendMode: "additive", occludes: !0, ...i }), this.setState("initialized"), this.source_ = A, this.policy_ = B ?? ug(), this.sliceCoords_ = I, this.orientation_ = C ?? "XY", this.axes_ = MA(this.orientation_), this.planeRotation_ = dA(this.axes_), this.channelProps_ = Q, this.initialChannelProps_ = Q, this.onPickValue_ = E;
|
|
12777
13170
|
}
|
|
13171
|
+
/** @hidden */
|
|
12778
13172
|
attach(A) {
|
|
12779
13173
|
this.context_ = A, this.chunkStoreView_ = A.chunkManager.addView(
|
|
12780
13174
|
this.source_,
|
|
@@ -12785,9 +13179,15 @@ class rC extends qI {
|
|
|
12785
13179
|
this.chunkStoreView_.channelCount
|
|
12786
13180
|
);
|
|
12787
13181
|
}
|
|
13182
|
+
/** @hidden */
|
|
12788
13183
|
detach(A) {
|
|
12789
13184
|
this.releaseAndRemoveChunks(this.visibleChunks_.keys()), this.orderedChunks_ = [], this.clearObjects(), this.chunkStoreView_?.dispose(), this.chunkStoreView_ = void 0, this.context_ = void 0;
|
|
12790
13185
|
}
|
|
13186
|
+
/**
|
|
13187
|
+
* Streams chunks for the current view and refreshes the visible slice.
|
|
13188
|
+
*
|
|
13189
|
+
* @param viewport - The viewport being rendered.
|
|
13190
|
+
*/
|
|
12791
13191
|
update(A) {
|
|
12792
13192
|
if (!A || !this.chunkStoreView_) return;
|
|
12793
13193
|
const I = A.camera, B = I.type === "OrthographicCamera" ? I.getWorldViewRect() : this.chunkStoreView_.getWholePlaneRect();
|
|
@@ -12798,12 +13198,16 @@ class rC extends qI {
|
|
|
12798
13198
|
for (const [C, Q] of this.visibleChunks_)
|
|
12799
13199
|
this.updateSlicePosition(Q, C);
|
|
12800
13200
|
}
|
|
13201
|
+
/** The slice plane the layer displays. */
|
|
12801
13202
|
get orientation() {
|
|
12802
13203
|
return this.orientation_;
|
|
12803
13204
|
}
|
|
12804
13205
|
/**
|
|
12805
|
-
* Changes the slice orientation at runtime. Visible renderables are
|
|
12806
|
-
* for the new plane
|
|
13206
|
+
* Changes the slice orientation at runtime. Visible renderables are
|
|
13207
|
+
* rebuilt for the new plane and chunks already resident in the shared
|
|
13208
|
+
* cache are reused.
|
|
13209
|
+
*
|
|
13210
|
+
* @param orientation - The new slice plane.
|
|
12807
13211
|
*/
|
|
12808
13212
|
setOrientation(A) {
|
|
12809
13213
|
A !== this.orientation_ && (this.releaseAndRemoveChunks(this.visibleChunks_.keys()), this.orderedChunks_ = [], this.clearObjects(), this.chunkStoreView_?.dispose(), this.lastPresentationTimeStamp_ = void 0, this.lastPresentationTimeCoord_ = void 0, this.orientation_ = A, this.axes_ = MA(A), this.planeRotation_ = dA(this.axes_), this.context_ && (this.chunkStoreView_ = this.context_.chunkManager.addView(
|
|
@@ -12839,12 +13243,19 @@ class rC extends qI {
|
|
|
12839
13243
|
I === void 0 || this.channelProps_?.[B]?.visible === !1 || this.addObject(I, B);
|
|
12840
13244
|
}
|
|
12841
13245
|
}
|
|
13246
|
+
/** The `t` coordinate of the most recently presented slice. */
|
|
12842
13247
|
get lastPresentationTimeCoord() {
|
|
12843
13248
|
return this.lastPresentationTimeCoord_;
|
|
12844
13249
|
}
|
|
12845
13250
|
isPresentationStale() {
|
|
12846
13251
|
return this.lastPresentationTimeStamp_ === void 0 ? !1 : performance.now() - this.lastPresentationTimeStamp_ > rC.STALE_PRESENTATION_MS_;
|
|
12847
13252
|
}
|
|
13253
|
+
/**
|
|
13254
|
+
* Handles click picking for `onPickValue`. Called automatically for
|
|
13255
|
+
* each pointer event.
|
|
13256
|
+
*
|
|
13257
|
+
* @param event - The event with clip and world coordinates attached.
|
|
13258
|
+
*/
|
|
12848
13259
|
onEvent(A) {
|
|
12849
13260
|
this.pointerDownPos_ = FC(
|
|
12850
13261
|
A,
|
|
@@ -12866,18 +13277,30 @@ class rC extends qI {
|
|
|
12866
13277
|
return i === null ? null : { world: E, value: i };
|
|
12867
13278
|
}
|
|
12868
13279
|
// exposed for use in chunk info overlay
|
|
13280
|
+
/** The layer's chunk store view for diagnostic overlays. */
|
|
12869
13281
|
get chunkStoreView() {
|
|
12870
13282
|
return this.chunkStoreView_;
|
|
12871
13283
|
}
|
|
13284
|
+
/**
|
|
13285
|
+
* The slice coordinates the layer displays. This is the object passed
|
|
13286
|
+
* at construction and may be mutated to move through the data.
|
|
13287
|
+
*/
|
|
12872
13288
|
get sliceCoords() {
|
|
12873
13289
|
return this.sliceCoords_;
|
|
12874
13290
|
}
|
|
13291
|
+
/** The chunked image source the layer streams from. */
|
|
12875
13292
|
get source() {
|
|
12876
13293
|
return this.source_;
|
|
12877
13294
|
}
|
|
13295
|
+
/**
|
|
13296
|
+
* The streaming policy in effect. Assign a new policy to reschedule
|
|
13297
|
+
* loading at runtime, for example when switching between exploration
|
|
13298
|
+
* and playback.
|
|
13299
|
+
*/
|
|
12878
13300
|
get imageSourcePolicy() {
|
|
12879
13301
|
return this.policy_;
|
|
12880
13302
|
}
|
|
13303
|
+
/** @param newPolicy - The policy to apply. */
|
|
12881
13304
|
set imageSourcePolicy(A) {
|
|
12882
13305
|
this.policy_ !== A && (this.policy_ = A, this.chunkStoreView_ && this.chunkStoreView_.setImageSourcePolicy(
|
|
12883
13306
|
A,
|
|
@@ -12920,6 +13343,14 @@ class rC extends qI {
|
|
|
12920
13343
|
const { u: B, v: C } = this.axes_;
|
|
12921
13344
|
A.transform.setScale([I.scale[B], I.scale[C], 1]), A.transform.setRotation(this.planeRotation_), this.updateSlicePosition(A, I), A.worldToTexCoord = _B(I, this.axes_);
|
|
12922
13345
|
}
|
|
13346
|
+
/**
|
|
13347
|
+
* Reads the data value at a world position from the resident chunks.
|
|
13348
|
+
* Prefers the current level of detail and falls back to other resident
|
|
13349
|
+
* levels.
|
|
13350
|
+
*
|
|
13351
|
+
* @param world - The world-space position to sample.
|
|
13352
|
+
* @returns The sampled value or `null` if no resident chunk covers it.
|
|
13353
|
+
*/
|
|
12923
13354
|
async getValueAtWorld(A) {
|
|
12924
13355
|
const I = this.chunkStoreView_?.currentLOD ?? 0;
|
|
12925
13356
|
for (const B of [!0, !1])
|
|
@@ -12941,17 +13372,26 @@ class rC extends qI {
|
|
|
12941
13372
|
const s = { x: 0, y: 0, z: 0 };
|
|
12942
13373
|
return s[Q] = o, s[E] = a, s[i] = this.sliceIndexForChunk(A), await I.textures[0].readTexel?.(s.x, s.y, s.z) ?? null;
|
|
12943
13374
|
}
|
|
13375
|
+
/** Whether chunk wireframes are drawn colored by level of detail. */
|
|
12944
13376
|
get debugMode() {
|
|
12945
13377
|
return this.debugMode_;
|
|
12946
13378
|
}
|
|
13379
|
+
/** @param debug - Whether to draw chunk wireframes. */
|
|
12947
13380
|
set debugMode(A) {
|
|
12948
13381
|
this.debugMode_ = A, this.visibleChunks_.forEach((I, B) => {
|
|
12949
13382
|
I.wireframeEnabled = this.debugMode_, this.debugMode_ && (I.wireframeColor = this.wireframeColors_[B.lod % this.wireframeColors_.length]);
|
|
12950
13383
|
});
|
|
12951
13384
|
}
|
|
13385
|
+
/** The current per-channel appearance settings. */
|
|
12952
13386
|
get channelProps() {
|
|
12953
13387
|
return this.channelProps_;
|
|
12954
13388
|
}
|
|
13389
|
+
/**
|
|
13390
|
+
* Applies new per-channel appearance settings to all visible chunks
|
|
13391
|
+
* and notifies channel change callbacks.
|
|
13392
|
+
*
|
|
13393
|
+
* @param channelProps - One entry per source channel.
|
|
13394
|
+
*/
|
|
12955
13395
|
setChannelProps(A) {
|
|
12956
13396
|
this.channelProps_ = A, this.visibleChunks_.forEach((I, B) => {
|
|
12957
13397
|
I.setChannelProps(this.getChannelPropsForChunk(B));
|
|
@@ -12959,12 +13399,23 @@ class rC extends qI {
|
|
|
12959
13399
|
I();
|
|
12960
13400
|
});
|
|
12961
13401
|
}
|
|
13402
|
+
/** Restores the channel settings passed at construction. */
|
|
12962
13403
|
resetChannelProps() {
|
|
12963
13404
|
this.initialChannelProps_ !== void 0 && this.setChannelProps(this.initialChannelProps_);
|
|
12964
13405
|
}
|
|
13406
|
+
/**
|
|
13407
|
+
* Registers a callback invoked after every channel settings change.
|
|
13408
|
+
*
|
|
13409
|
+
* @param callback - The callback to add.
|
|
13410
|
+
*/
|
|
12965
13411
|
addChannelChangeCallback(A) {
|
|
12966
13412
|
this.channelChangeCallbacks_.push(A);
|
|
12967
13413
|
}
|
|
13414
|
+
/**
|
|
13415
|
+
* Removes a previously registered channel change callback.
|
|
13416
|
+
*
|
|
13417
|
+
* @param callback - The callback to remove.
|
|
13418
|
+
*/
|
|
12968
13419
|
removeChannelChangeCallback(A) {
|
|
12969
13420
|
const I = this.channelChangeCallbacks_.indexOf(A);
|
|
12970
13421
|
if (I === -1)
|
|
@@ -13034,16 +13485,35 @@ class Wi extends mA {
|
|
|
13034
13485
|
}
|
|
13035
13486
|
}
|
|
13036
13487
|
class bi extends gI {
|
|
13488
|
+
/**
|
|
13489
|
+
* World size of a voxel along each axis. Layers set it from the chunk
|
|
13490
|
+
* scale so ray march steps account for anisotropic voxels. Defaults to
|
|
13491
|
+
* `[1, 1, 1]`.
|
|
13492
|
+
*/
|
|
13037
13493
|
voxelScale = p(1, 1, 1);
|
|
13038
13494
|
channels_;
|
|
13039
13495
|
loadedChannels_ = /* @__PURE__ */ new Set();
|
|
13040
13496
|
channelToTextureIndex_ = /* @__PURE__ */ new Map();
|
|
13497
|
+
/**
|
|
13498
|
+
* Creates an empty volume renderable.
|
|
13499
|
+
*
|
|
13500
|
+
* @param props - Initialization properties.
|
|
13501
|
+
*/
|
|
13041
13502
|
constructor({ channelProps: A = [] } = {}) {
|
|
13042
13503
|
super(), this.geometry = new Wi(1, 1, 1, 1, 1, 1), this.cullFaceMode = "front", this.depthTest = !1, this.channels_ = [], this.setChannelProps(A);
|
|
13043
13504
|
}
|
|
13505
|
+
/** Identifies the renderable type as `VolumeRenderable`. */
|
|
13044
13506
|
get type() {
|
|
13045
13507
|
return "VolumeRenderable";
|
|
13046
13508
|
}
|
|
13509
|
+
/**
|
|
13510
|
+
* Loads or refreshes the texture for the chunk's channel. The channel
|
|
13511
|
+
* index comes from the chunk and the texture's data type selects the
|
|
13512
|
+
* volume shader, so every channel must share one data type. Chunks
|
|
13513
|
+
* without a texture are ignored.
|
|
13514
|
+
*
|
|
13515
|
+
* @param chunk - The chunk holding the channel texture.
|
|
13516
|
+
*/
|
|
13047
13517
|
updateVolumeWithChunk(A) {
|
|
13048
13518
|
if (!A.texture) return;
|
|
13049
13519
|
const I = A.chunkIndex.c, B = this.channelToTextureIndex_.get(I);
|
|
@@ -13062,12 +13532,25 @@ class bi extends gI {
|
|
|
13062
13532
|
updateChannelTexture(A, I) {
|
|
13063
13533
|
this.setTexture(A, I);
|
|
13064
13534
|
}
|
|
13535
|
+
/**
|
|
13536
|
+
* Marks all channels as not loaded so they stop rendering until the
|
|
13537
|
+
* next chunk update. The textures themselves are kept.
|
|
13538
|
+
*/
|
|
13065
13539
|
clearLoadedChannels() {
|
|
13066
13540
|
this.loadedChannels_ = /* @__PURE__ */ new Set();
|
|
13067
13541
|
}
|
|
13542
|
+
/**
|
|
13543
|
+
* Clears all textures and channel state so the renderable can be
|
|
13544
|
+
* pooled and reused for another chunk.
|
|
13545
|
+
*/
|
|
13068
13546
|
reset() {
|
|
13069
13547
|
this.clearTextures(), this.channelToTextureIndex_.clear(), this.clearLoadedChannels();
|
|
13070
13548
|
}
|
|
13549
|
+
/**
|
|
13550
|
+
* Returns per-channel sampler, color, contrast, opacity, and
|
|
13551
|
+
* visibility uniforms for up to 4 loaded channels plus the voxel
|
|
13552
|
+
* scale.
|
|
13553
|
+
*/
|
|
13071
13554
|
getUniforms() {
|
|
13072
13555
|
const A = [0, 0, 0, 0], I = [
|
|
13073
13556
|
1,
|
|
@@ -13121,12 +13604,25 @@ class bi extends gI {
|
|
|
13121
13604
|
const I = this.channelToTextureIndex_.values().next().value;
|
|
13122
13605
|
return I !== void 0 ? this.textures[I] : null;
|
|
13123
13606
|
}
|
|
13607
|
+
/**
|
|
13608
|
+
* Replaces the appearance settings for all channels.
|
|
13609
|
+
*
|
|
13610
|
+
* @param channels - The new channel settings.
|
|
13611
|
+
*/
|
|
13124
13612
|
setChannelProps(A) {
|
|
13125
13613
|
this.channels_ = tg(
|
|
13126
13614
|
this.getAvailableChannelTexture(),
|
|
13127
13615
|
A
|
|
13128
13616
|
);
|
|
13129
13617
|
}
|
|
13618
|
+
/**
|
|
13619
|
+
* Updates one property of the channel at the given index and
|
|
13620
|
+
* revalidates it against the channel's texture when available.
|
|
13621
|
+
*
|
|
13622
|
+
* @param channelIndex - The channel to update.
|
|
13623
|
+
* @param property - The property name to set.
|
|
13624
|
+
* @param value - The new value.
|
|
13625
|
+
*/
|
|
13130
13626
|
setChannelProperty(A, I, B) {
|
|
13131
13627
|
const C = jA(
|
|
13132
13628
|
this.getAvailableChannelTexture(A),
|
|
@@ -13154,7 +13650,17 @@ function Zi(g) {
|
|
|
13154
13650
|
}
|
|
13155
13651
|
const Pi = 2;
|
|
13156
13652
|
class Uo extends qI {
|
|
13653
|
+
/** Identifies the layer type as `VolumeLayer`. */
|
|
13157
13654
|
type = "VolumeLayer";
|
|
13655
|
+
/** Highlights rays of zero length for debugging. Defaults to `false`. */
|
|
13656
|
+
debugShowDegenerateRays = !1;
|
|
13657
|
+
/** Ray march step size relative to voxel size. Defaults to `1`. */
|
|
13658
|
+
relativeStepSize = 1;
|
|
13659
|
+
/** Scales sample opacity during compositing. Defaults to `1`. */
|
|
13660
|
+
opacityMultiplier = 1;
|
|
13661
|
+
/** Alpha where a ray stops early. Defaults to `0.99`. */
|
|
13662
|
+
earlyTerminationAlpha = 0.99;
|
|
13663
|
+
/** Volume ray marching reads scene depth to composite with occluding layers. */
|
|
13158
13664
|
requiresSceneDepth_ = !0;
|
|
13159
13665
|
source_;
|
|
13160
13666
|
sliceCoords_;
|
|
@@ -13171,13 +13677,11 @@ class Uo extends qI {
|
|
|
13171
13677
|
interactiveStepSizeScale_ = 1;
|
|
13172
13678
|
// TODO: Make a debug config object to manage debug options
|
|
13173
13679
|
debugShowWireframes_ = !1;
|
|
13174
|
-
|
|
13175
|
-
relativeStepSize = 1;
|
|
13176
|
-
opacityMultiplier = 1;
|
|
13177
|
-
earlyTerminationAlpha = 0.99;
|
|
13680
|
+
/** Whether chunk bounding wireframes are drawn for debugging. */
|
|
13178
13681
|
get debugShowWireframes() {
|
|
13179
13682
|
return this.debugShowWireframes_;
|
|
13180
13683
|
}
|
|
13684
|
+
/** @param value - Whether to draw chunk wireframes. */
|
|
13181
13685
|
set debugShowWireframes(A) {
|
|
13182
13686
|
if (this.debugShowWireframes_ !== A) {
|
|
13183
13687
|
for (const I of this.currentVolumes_.values())
|
|
@@ -13185,12 +13689,24 @@ class Uo extends qI {
|
|
|
13185
13689
|
this.debugShowWireframes_ = A;
|
|
13186
13690
|
}
|
|
13187
13691
|
}
|
|
13692
|
+
/**
|
|
13693
|
+
* Sets the streaming policy at runtime and reschedules loading. The
|
|
13694
|
+
* volume renders the level of detail given by the policy's `lod.min`.
|
|
13695
|
+
*
|
|
13696
|
+
* @param newPolicy - The policy to apply.
|
|
13697
|
+
*/
|
|
13188
13698
|
set imageSourcePolicy(A) {
|
|
13189
13699
|
this.policy_ !== A && (this.policy_ = A, this.chunkStoreView_ && this.chunkStoreView_.setImageSourcePolicy(
|
|
13190
13700
|
A,
|
|
13191
13701
|
dI
|
|
13192
13702
|
));
|
|
13193
13703
|
}
|
|
13704
|
+
/**
|
|
13705
|
+
* Applies new per-channel appearance settings to all visible volumes
|
|
13706
|
+
* and notifies channel change callbacks.
|
|
13707
|
+
*
|
|
13708
|
+
* @param channelProps - One entry per source channel.
|
|
13709
|
+
*/
|
|
13194
13710
|
setChannelProps(A) {
|
|
13195
13711
|
this.channelProps_ = A;
|
|
13196
13712
|
for (const I of this.currentVolumes_.values())
|
|
@@ -13199,21 +13715,38 @@ class Uo extends qI {
|
|
|
13199
13715
|
I();
|
|
13200
13716
|
});
|
|
13201
13717
|
}
|
|
13718
|
+
/** The current per-channel appearance settings. */
|
|
13202
13719
|
get channelProps() {
|
|
13203
13720
|
return this.channelProps_;
|
|
13204
13721
|
}
|
|
13722
|
+
/** Restores the channel settings passed at construction. */
|
|
13205
13723
|
resetChannelProps() {
|
|
13206
13724
|
this.initialChannelProps_ !== void 0 && this.setChannelProps(this.initialChannelProps_);
|
|
13207
13725
|
}
|
|
13726
|
+
/**
|
|
13727
|
+
* Registers a callback invoked after every channel settings change.
|
|
13728
|
+
*
|
|
13729
|
+
* @param callback - The callback to add.
|
|
13730
|
+
*/
|
|
13208
13731
|
addChannelChangeCallback(A) {
|
|
13209
13732
|
this.channelChangeCallbacks_.push(A);
|
|
13210
13733
|
}
|
|
13734
|
+
/**
|
|
13735
|
+
* Removes a previously registered channel change callback.
|
|
13736
|
+
*
|
|
13737
|
+
* @param callback - The callback to remove.
|
|
13738
|
+
*/
|
|
13211
13739
|
removeChannelChangeCallback(A) {
|
|
13212
13740
|
const I = this.channelChangeCallbacks_.indexOf(A);
|
|
13213
13741
|
if (I === -1)
|
|
13214
13742
|
throw new Error(`Callback to remove could not be found: ${A}`);
|
|
13215
13743
|
this.channelChangeCallbacks_.splice(I, 1);
|
|
13216
13744
|
}
|
|
13745
|
+
/**
|
|
13746
|
+
* Creates a volume layer for the given source.
|
|
13747
|
+
*
|
|
13748
|
+
* @param props - Initialization properties.
|
|
13749
|
+
*/
|
|
13217
13750
|
constructor({ source: A, sliceCoords: I, policy: B, channelProps: C }) {
|
|
13218
13751
|
super({ blendMode: "premultipliedOver" }), this.source_ = A, this.sliceCoords_ = I, this.policy_ = B ?? ug(), this.initialChannelProps_ = C, this.channelProps_ = C, this.setState("initialized");
|
|
13219
13752
|
}
|
|
@@ -13228,6 +13761,7 @@ class Uo extends qI {
|
|
|
13228
13761
|
for (const E of I) Q.updateVolumeWithChunk(E);
|
|
13229
13762
|
return this.updateVolumeTransform(Q, I[0]), Q;
|
|
13230
13763
|
}
|
|
13764
|
+
/** @hidden */
|
|
13231
13765
|
attach(A) {
|
|
13232
13766
|
this.chunkStoreView_ = A.chunkManager.addView(
|
|
13233
13767
|
this.source_,
|
|
@@ -13237,6 +13771,7 @@ class Uo extends qI {
|
|
|
13237
13771
|
this.chunkStoreView_.channelCount
|
|
13238
13772
|
);
|
|
13239
13773
|
}
|
|
13774
|
+
/** @hidden */
|
|
13240
13775
|
detach(A) {
|
|
13241
13776
|
for (const I of this.currentVolumes_.values())
|
|
13242
13777
|
this.releaseAndRemoveVolume(I);
|
|
@@ -13277,6 +13812,12 @@ class Uo extends qI {
|
|
|
13277
13812
|
releaseAndRemoveVolume(A) {
|
|
13278
13813
|
A.reset(), this.pool_.release(this.volumeToPoolKey_.get(A), A), this.volumeToPoolKey_.delete(A);
|
|
13279
13814
|
}
|
|
13815
|
+
/**
|
|
13816
|
+
* Streams chunks for the current view and rebuilds the volume set
|
|
13817
|
+
* sorted front to back. Called automatically once per frame.
|
|
13818
|
+
*
|
|
13819
|
+
* @param viewport - The viewport being rendered.
|
|
13820
|
+
*/
|
|
13280
13821
|
update(A) {
|
|
13281
13822
|
if (!A || !this.chunkStoreView_) return;
|
|
13282
13823
|
this.chunkStoreView_.updateChunksForVolume(
|
|
@@ -13292,6 +13833,7 @@ class Uo extends qI {
|
|
|
13292
13833
|
for (const B of I)
|
|
13293
13834
|
this.addObject(B);
|
|
13294
13835
|
}
|
|
13836
|
+
/** Returns the ray marching uniforms for this layer. */
|
|
13295
13837
|
getUniforms() {
|
|
13296
13838
|
return {
|
|
13297
13839
|
u_debugShowDegenerateRays: Number(this.debugShowDegenerateRays),
|
|
@@ -13390,17 +13932,32 @@ function Io(g) {
|
|
|
13390
13932
|
return SC.has(g.dataType) ? "intLabelImage" : "labelImage";
|
|
13391
13933
|
}
|
|
13392
13934
|
class go extends gI {
|
|
13935
|
+
/**
|
|
13936
|
+
* A matrix mapping world space to the texture's normalized coordinate
|
|
13937
|
+
* space. Layers derive it from the chunk's offset, scale, and shape.
|
|
13938
|
+
*/
|
|
13939
|
+
worldToTexCoord = $();
|
|
13393
13940
|
outlineSelected_;
|
|
13394
13941
|
selectedValue_;
|
|
13395
|
-
|
|
13942
|
+
/**
|
|
13943
|
+
* Creates a label renderable drawing the given label texture. The
|
|
13944
|
+
* texture's data type selects the matching label shader.
|
|
13945
|
+
*
|
|
13946
|
+
* @param props - Initialization properties.
|
|
13947
|
+
*/
|
|
13396
13948
|
constructor(A) {
|
|
13397
13949
|
super(), this.geometry = new wC(A.width, A.height, 1, 1), this.setTexture(0, Ao(A.imageData));
|
|
13398
13950
|
const I = JI(A.colorMap);
|
|
13399
13951
|
this.setTexture(1, this.makeColorCycleTexture(I.cycle)), this.setTexture(2, this.makeColorLookupTableTexture(I.lookupTable)), this.outlineSelected_ = A.outlineSelected ?? !1, this.selectedValue_ = A.selectedValue ?? null, this.programName = Io(A.imageData), this.depthProgramName = "meshDepth";
|
|
13400
13952
|
}
|
|
13953
|
+
/** Identifies the renderable type as `LabelImageRenderable`. */
|
|
13401
13954
|
get type() {
|
|
13402
13955
|
return "LabelImageRenderable";
|
|
13403
13956
|
}
|
|
13957
|
+
/**
|
|
13958
|
+
* Returns the sampler, color map, and selection uniforms for the label
|
|
13959
|
+
* image shaders.
|
|
13960
|
+
*/
|
|
13404
13961
|
getUniforms() {
|
|
13405
13962
|
return {
|
|
13406
13963
|
u_imageSampler: 0,
|
|
@@ -13411,10 +13968,23 @@ class go extends gI {
|
|
|
13411
13968
|
u_worldToTexCoord: this.worldToTexCoord
|
|
13412
13969
|
};
|
|
13413
13970
|
}
|
|
13971
|
+
/**
|
|
13972
|
+
* Replaces the label color map. The previous color map textures are
|
|
13973
|
+
* marked stale for GPU disposal.
|
|
13974
|
+
*
|
|
13975
|
+
* @param colorMap - The new color map.
|
|
13976
|
+
*/
|
|
13414
13977
|
setColorMap(A) {
|
|
13415
13978
|
const I = JI(A);
|
|
13416
13979
|
this.markStaleTexture(this.textures[1]), this.markStaleTexture(this.textures[2]), this.setTexture(1, this.makeColorCycleTexture(I.cycle)), this.setTexture(2, this.makeColorLookupTableTexture(I.lookupTable));
|
|
13417
13980
|
}
|
|
13981
|
+
/**
|
|
13982
|
+
* Sets the label value drawn as selected or `null` to clear the
|
|
13983
|
+
* selection. The selected region is outlined when the renderable was
|
|
13984
|
+
* constructed with `outlineSelected`.
|
|
13985
|
+
*
|
|
13986
|
+
* @param value - The label value to select.
|
|
13987
|
+
*/
|
|
13418
13988
|
setSelectedValue(A) {
|
|
13419
13989
|
this.selectedValue_ = A;
|
|
13420
13990
|
}
|
|
@@ -13431,6 +14001,7 @@ class go extends gI {
|
|
|
13431
14001
|
}
|
|
13432
14002
|
}
|
|
13433
14003
|
class RC extends qI {
|
|
14004
|
+
/** Identifies the layer type as `LabelLayer`. */
|
|
13434
14005
|
type = "LabelLayer";
|
|
13435
14006
|
source_;
|
|
13436
14007
|
sliceCoords_;
|
|
@@ -13450,6 +14021,11 @@ class RC extends qI {
|
|
|
13450
14021
|
static STALE_PRESENTATION_MS_ = 1e3;
|
|
13451
14022
|
lastPresentationTimeStamp_;
|
|
13452
14023
|
lastPresentationTimeCoord_;
|
|
14024
|
+
/**
|
|
14025
|
+
* Creates a label layer for the given source and slice.
|
|
14026
|
+
*
|
|
14027
|
+
* @param props - Initialization properties.
|
|
14028
|
+
*/
|
|
13453
14029
|
constructor({
|
|
13454
14030
|
source: A,
|
|
13455
14031
|
sliceCoords: I,
|
|
@@ -13462,6 +14038,7 @@ class RC extends qI {
|
|
|
13462
14038
|
}) {
|
|
13463
14039
|
super(o), this.setState("initialized"), this.source_ = A, this.policy_ = B ?? ug(), this.sliceCoords_ = I, this.orientation_ = C ?? "XY", this.axes_ = MA(this.orientation_), this.planeRotation_ = dA(this.axes_), this.colorMap_ = JI(Q), this.onPickValue_ = E, this.outlineSelected_ = i;
|
|
13464
14040
|
}
|
|
14041
|
+
/** @hidden */
|
|
13465
14042
|
attach(A) {
|
|
13466
14043
|
if (this.context_ = A, this.chunkStoreView_ = A.chunkManager.addView(
|
|
13467
14044
|
this.source_,
|
|
@@ -13472,9 +14049,16 @@ class RC extends qI {
|
|
|
13472
14049
|
`LabelLayer does not support multi-channel sources (found ${this.chunkStoreView_.channelCount} channels). Label data must be single-channel.`
|
|
13473
14050
|
);
|
|
13474
14051
|
}
|
|
14052
|
+
/** @hidden */
|
|
13475
14053
|
detach(A) {
|
|
13476
14054
|
this.releaseAndRemoveChunks(this.visibleChunks_.keys()), this.clearObjects(), this.chunkStoreView_?.dispose(), this.chunkStoreView_ = void 0, this.context_ = void 0;
|
|
13477
14055
|
}
|
|
14056
|
+
/**
|
|
14057
|
+
* Streams chunks for the current view and refreshes the visible slice.
|
|
14058
|
+
* Called automatically once per frame.
|
|
14059
|
+
*
|
|
14060
|
+
* @param viewport - The viewport being rendered.
|
|
14061
|
+
*/
|
|
13478
14062
|
update(A) {
|
|
13479
14063
|
if (!A || !this.chunkStoreView_) return;
|
|
13480
14064
|
const I = A.camera, B = I.type === "OrthographicCamera" ? I.getWorldViewRect() : this.chunkStoreView_.getWholePlaneRect();
|
|
@@ -13485,12 +14069,16 @@ class RC extends qI {
|
|
|
13485
14069
|
for (const [C, Q] of this.visibleChunks_)
|
|
13486
14070
|
this.updateSlicePosition(Q, C);
|
|
13487
14071
|
}
|
|
14072
|
+
/** The slice plane the layer displays. */
|
|
13488
14073
|
get orientation() {
|
|
13489
14074
|
return this.orientation_;
|
|
13490
14075
|
}
|
|
13491
14076
|
/**
|
|
13492
|
-
* Changes the slice orientation at runtime. Visible renderables are
|
|
13493
|
-
* for the new plane
|
|
14077
|
+
* Changes the slice orientation at runtime. Visible renderables are
|
|
14078
|
+
* rebuilt for the new plane and chunks already resident in the shared
|
|
14079
|
+
* cache are reused.
|
|
14080
|
+
*
|
|
14081
|
+
* @param orientation - The new slice plane.
|
|
13494
14082
|
*/
|
|
13495
14083
|
setOrientation(A) {
|
|
13496
14084
|
A !== this.orientation_ && (this.releaseAndRemoveChunks(this.visibleChunks_.keys()), this.clearObjects(), this.chunkStoreView_?.dispose(), this.lastPresentationTimeStamp_ = void 0, this.lastPresentationTimeCoord_ = void 0, this.orientation_ = A, this.axes_ = MA(A), this.planeRotation_ = dA(this.axes_), this.context_ && (this.chunkStoreView_ = this.context_.chunkManager.addView(
|
|
@@ -13520,6 +14108,12 @@ class RC extends qI {
|
|
|
13520
14108
|
isPresentationStale() {
|
|
13521
14109
|
return this.lastPresentationTimeStamp_ === void 0 ? !1 : performance.now() - this.lastPresentationTimeStamp_ > RC.STALE_PRESENTATION_MS_;
|
|
13522
14110
|
}
|
|
14111
|
+
/**
|
|
14112
|
+
* Handles click picking and selection outlining. Called automatically
|
|
14113
|
+
* for each pointer event on the owning viewport.
|
|
14114
|
+
*
|
|
14115
|
+
* @param event - The event with clip and world coordinates attached.
|
|
14116
|
+
*/
|
|
13523
14117
|
onEvent(A) {
|
|
13524
14118
|
this.pointerDownPos_ = FC(
|
|
13525
14119
|
A,
|
|
@@ -13542,28 +14136,52 @@ class RC extends qI {
|
|
|
13542
14136
|
const i = await this.getValueAtWorld(E);
|
|
13543
14137
|
return i === null ? null : { world: E, value: i };
|
|
13544
14138
|
}
|
|
14139
|
+
/** The validated color map currently in effect. */
|
|
13545
14140
|
get colorMap() {
|
|
13546
14141
|
return this.colorMap_;
|
|
13547
14142
|
}
|
|
14143
|
+
/**
|
|
14144
|
+
* Replaces the color map and recolors all visible chunks.
|
|
14145
|
+
*
|
|
14146
|
+
* @param colorMap - Colors for label values. Omitted fields fall back
|
|
14147
|
+
* to defaults.
|
|
14148
|
+
*/
|
|
13548
14149
|
setColorMap(A) {
|
|
13549
14150
|
this.colorMap_ = JI(A), this.visibleChunks_.forEach((I) => {
|
|
13550
14151
|
I.setColorMap(this.colorMap_);
|
|
13551
14152
|
});
|
|
13552
14153
|
}
|
|
14154
|
+
/**
|
|
14155
|
+
* Sets the label value drawn as selected or `null` to clear the
|
|
14156
|
+
* selection.
|
|
14157
|
+
*
|
|
14158
|
+
* @param value - The label value to select.
|
|
14159
|
+
*/
|
|
13553
14160
|
setSelectedValue(A) {
|
|
13554
14161
|
this.selectedValue_ = A, this.visibleChunks_.forEach((I) => {
|
|
13555
14162
|
I.setSelectedValue(this.selectedValue_);
|
|
13556
14163
|
});
|
|
13557
14164
|
}
|
|
14165
|
+
/**
|
|
14166
|
+
* The slice coordinates the layer displays. This is the object passed
|
|
14167
|
+
* at construction and may be mutated to move through the data.
|
|
14168
|
+
*/
|
|
13558
14169
|
get sliceCoords() {
|
|
13559
14170
|
return this.sliceCoords_;
|
|
13560
14171
|
}
|
|
14172
|
+
/** The chunked label source the layer streams from. */
|
|
13561
14173
|
get source() {
|
|
13562
14174
|
return this.source_;
|
|
13563
14175
|
}
|
|
14176
|
+
/**
|
|
14177
|
+
* The streaming policy in effect. Assign a new policy to reschedule
|
|
14178
|
+
* loading at runtime, for example when switching between exploration
|
|
14179
|
+
* and playback.
|
|
14180
|
+
*/
|
|
13564
14181
|
get imageSourcePolicy() {
|
|
13565
14182
|
return this.policy_;
|
|
13566
14183
|
}
|
|
14184
|
+
/** @param newPolicy - The policy to apply. */
|
|
13567
14185
|
set imageSourcePolicy(A) {
|
|
13568
14186
|
this.policy_ !== A && (this.policy_ = A, this.chunkStoreView_ && this.chunkStoreView_.setImageSourcePolicy(
|
|
13569
14187
|
A,
|
|
@@ -13571,12 +14189,22 @@ class RC extends qI {
|
|
|
13571
14189
|
));
|
|
13572
14190
|
}
|
|
13573
14191
|
// exposed for use in chunk info overlay
|
|
14192
|
+
/** The layer's chunk store view for diagnostic overlays. */
|
|
13574
14193
|
get chunkStoreView() {
|
|
13575
14194
|
return this.chunkStoreView_;
|
|
13576
14195
|
}
|
|
14196
|
+
/** The `t` coordinate of the most recently presented slice. */
|
|
13577
14197
|
get lastPresentationTimeCoord() {
|
|
13578
14198
|
return this.lastPresentationTimeCoord_;
|
|
13579
14199
|
}
|
|
14200
|
+
/**
|
|
14201
|
+
* Reads the label value at a world position from the resident chunks.
|
|
14202
|
+
* Prefers the current level of detail and falls back to other resident
|
|
14203
|
+
* levels.
|
|
14204
|
+
*
|
|
14205
|
+
* @param world - The world-space position to sample.
|
|
14206
|
+
* @returns The label value or `null` if no resident chunk covers it.
|
|
14207
|
+
*/
|
|
13580
14208
|
async getValueAtWorld(A) {
|
|
13581
14209
|
const I = this.chunkStoreView_?.currentLOD ?? 0;
|
|
13582
14210
|
for (const B of [!0, !1])
|
|
@@ -13665,6 +14293,11 @@ const NC = {
|
|
|
13665
14293
|
triangle: 2
|
|
13666
14294
|
};
|
|
13667
14295
|
class ko extends gI {
|
|
14296
|
+
/**
|
|
14297
|
+
* Creates a renderable drawing one marker per entry.
|
|
14298
|
+
*
|
|
14299
|
+
* @param points - The points to draw.
|
|
14300
|
+
*/
|
|
13668
14301
|
constructor(A) {
|
|
13669
14302
|
super(), this.programName = "points", this.depthProgramName = "pointsDepth";
|
|
13670
14303
|
const I = A.flatMap((C) => {
|
|
@@ -13699,6 +14332,7 @@ class ko extends gI {
|
|
|
13699
14332
|
offset: B.strideBytes
|
|
13700
14333
|
}), this.geometry = B, this.setTexture(0, Co());
|
|
13701
14334
|
}
|
|
14335
|
+
/** Identifies the renderable type as `PointsRenderable`. */
|
|
13702
14336
|
get type() {
|
|
13703
14337
|
return "PointsRenderable";
|
|
13704
14338
|
}
|
|
@@ -13733,6 +14367,152 @@ function Qo() {
|
|
|
13733
14367
|
const o = new Bo(i, 256, 256);
|
|
13734
14368
|
return o.wrapR = "clamp_to_edge", o.wrapS = "clamp_to_edge", o.wrapT = "clamp_to_edge", o;
|
|
13735
14369
|
}
|
|
14370
|
+
class Eo {
|
|
14371
|
+
planes_;
|
|
14372
|
+
/**
|
|
14373
|
+
* Creates a frustum from a view-projection matrix.
|
|
14374
|
+
*
|
|
14375
|
+
* @param m - The combined view-projection matrix.
|
|
14376
|
+
*/
|
|
14377
|
+
constructor(A) {
|
|
14378
|
+
this.planes_ = [
|
|
14379
|
+
new sA(d(), 0),
|
|
14380
|
+
new sA(d(), 0),
|
|
14381
|
+
new sA(d(), 0),
|
|
14382
|
+
new sA(d(), 0),
|
|
14383
|
+
new sA(d(), 0),
|
|
14384
|
+
new sA(d(), 0)
|
|
14385
|
+
], this.setWithViewProjection(A);
|
|
14386
|
+
}
|
|
14387
|
+
// Uses the fast plane-extraction algorithm described in
|
|
14388
|
+
// Gribb & Hartmann (1997): https://tinyurl.com/5x5htcwm
|
|
14389
|
+
/**
|
|
14390
|
+
* Re-extracts the six planes from a view-projection matrix.
|
|
14391
|
+
*
|
|
14392
|
+
* @param m - The combined view-projection matrix.
|
|
14393
|
+
*/
|
|
14394
|
+
setWithViewProjection(A) {
|
|
14395
|
+
const I = d();
|
|
14396
|
+
this.planes_[0].set(
|
|
14397
|
+
rA(I, A[3] + A[0], A[7] + A[4], A[11] + A[8]),
|
|
14398
|
+
A[15] + A[12]
|
|
14399
|
+
), this.planes_[1].set(
|
|
14400
|
+
rA(I, A[3] - A[0], A[7] - A[4], A[11] - A[8]),
|
|
14401
|
+
A[15] - A[12]
|
|
14402
|
+
), this.planes_[2].set(
|
|
14403
|
+
rA(I, A[3] - A[1], A[7] - A[5], A[11] - A[9]),
|
|
14404
|
+
A[15] - A[13]
|
|
14405
|
+
), this.planes_[3].set(
|
|
14406
|
+
rA(I, A[3] + A[1], A[7] + A[5], A[11] + A[9]),
|
|
14407
|
+
A[15] + A[13]
|
|
14408
|
+
), this.planes_[4].set(
|
|
14409
|
+
rA(I, A[3] + A[2], A[7] + A[6], A[11] + A[10]),
|
|
14410
|
+
A[15] + A[14]
|
|
14411
|
+
), this.planes_[5].set(
|
|
14412
|
+
rA(I, A[3] - A[2], A[7] - A[6], A[11] - A[10]),
|
|
14413
|
+
A[15] - A[14]
|
|
14414
|
+
);
|
|
14415
|
+
for (const B of this.planes_) B.normalize();
|
|
14416
|
+
}
|
|
14417
|
+
/**
|
|
14418
|
+
* Tests whether a box is at least partly inside the frustum. The test
|
|
14419
|
+
* is conservative. A box outside the frustum but near a corner can be
|
|
14420
|
+
* reported as intersecting, which only costs a draw of an offscreen
|
|
14421
|
+
* object.
|
|
14422
|
+
*
|
|
14423
|
+
* @param box - The world-space box to test.
|
|
14424
|
+
*/
|
|
14425
|
+
intersectsWithBox3(A) {
|
|
14426
|
+
const I = d();
|
|
14427
|
+
for (const B of this.planes_) {
|
|
14428
|
+
const C = B.normal;
|
|
14429
|
+
if (I[0] = C[0] > 0 ? A.max[0] : A.min[0], I[1] = C[1] > 0 ? A.max[1] : A.min[1], I[2] = C[2] > 0 ? A.max[2] : A.min[2], B.signedDistanceToPoint(I) < 0) return !1;
|
|
14430
|
+
}
|
|
14431
|
+
return !0;
|
|
14432
|
+
}
|
|
14433
|
+
}
|
|
14434
|
+
class cC extends YI {
|
|
14435
|
+
transform_ = new eC();
|
|
14436
|
+
/** @hidden */
|
|
14437
|
+
projectionMatrix_ = $();
|
|
14438
|
+
/** @hidden */
|
|
14439
|
+
near_ = 0;
|
|
14440
|
+
/** @hidden */
|
|
14441
|
+
far_ = 0;
|
|
14442
|
+
/** Recomputes the camera's projection matrix. */
|
|
14443
|
+
update() {
|
|
14444
|
+
this.updateProjectionMatrix();
|
|
14445
|
+
}
|
|
14446
|
+
/** The camera's projection matrix. */
|
|
14447
|
+
get projectionMatrix() {
|
|
14448
|
+
return this.projectionMatrix_;
|
|
14449
|
+
}
|
|
14450
|
+
/** The camera's world-space transform. */
|
|
14451
|
+
get transform() {
|
|
14452
|
+
return this.transform_;
|
|
14453
|
+
}
|
|
14454
|
+
/** The view matrix: the inverse of the camera's world transform. */
|
|
14455
|
+
get viewMatrix() {
|
|
14456
|
+
return this.transform.inverse;
|
|
14457
|
+
}
|
|
14458
|
+
/** The camera's local right axis in world space. */
|
|
14459
|
+
get right() {
|
|
14460
|
+
const A = this.transform.matrix;
|
|
14461
|
+
return p(A[0], A[1], A[2]);
|
|
14462
|
+
}
|
|
14463
|
+
/** The camera's local up axis in world space. */
|
|
14464
|
+
get up() {
|
|
14465
|
+
const A = this.transform.matrix;
|
|
14466
|
+
return p(A[4], A[5], A[6]);
|
|
14467
|
+
}
|
|
14468
|
+
/**
|
|
14469
|
+
* Computes the combined view-projection matrix.
|
|
14470
|
+
*
|
|
14471
|
+
* @returns The projection matrix multiplied by the view matrix.
|
|
14472
|
+
*/
|
|
14473
|
+
getViewProjection() {
|
|
14474
|
+
return QI($(), this.projectionMatrix, this.viewMatrix);
|
|
14475
|
+
}
|
|
14476
|
+
/** The view frustum derived from the current view-projection. */
|
|
14477
|
+
get frustum() {
|
|
14478
|
+
return new Eo(this.getViewProjection());
|
|
14479
|
+
}
|
|
14480
|
+
/**
|
|
14481
|
+
* Moves the camera by the given world-space offset.
|
|
14482
|
+
*
|
|
14483
|
+
* @param vec - The translation to add to the camera's position.
|
|
14484
|
+
*/
|
|
14485
|
+
pan(A) {
|
|
14486
|
+
this.transform.addTranslation(A);
|
|
14487
|
+
}
|
|
14488
|
+
/** The camera's world-space position. */
|
|
14489
|
+
get position() {
|
|
14490
|
+
return this.transform.translation;
|
|
14491
|
+
}
|
|
14492
|
+
/**
|
|
14493
|
+
* Transforms a position from clip space to world space.
|
|
14494
|
+
*
|
|
14495
|
+
* @param position - The clip-space position to transform.
|
|
14496
|
+
* @returns The corresponding world-space position.
|
|
14497
|
+
*/
|
|
14498
|
+
clipToWorld(A) {
|
|
14499
|
+
const I = DI(A[0], A[1], A[2], 1), B = OA(
|
|
14500
|
+
$(),
|
|
14501
|
+
this.projectionMatrix_
|
|
14502
|
+
), C = VA(
|
|
14503
|
+
YA(),
|
|
14504
|
+
I,
|
|
14505
|
+
B
|
|
14506
|
+
);
|
|
14507
|
+
BQ(C, C, 1 / C[3]);
|
|
14508
|
+
const Q = VA(
|
|
14509
|
+
YA(),
|
|
14510
|
+
C,
|
|
14511
|
+
this.transform.matrix
|
|
14512
|
+
);
|
|
14513
|
+
return p(Q[0], Q[1], Q[2]);
|
|
14514
|
+
}
|
|
14515
|
+
}
|
|
13736
14516
|
class TB {
|
|
13737
14517
|
radius;
|
|
13738
14518
|
phi;
|
|
@@ -13749,7 +14529,7 @@ class TB {
|
|
|
13749
14529
|
);
|
|
13750
14530
|
}
|
|
13751
14531
|
}
|
|
13752
|
-
const vI = -1, xB = 0,
|
|
14532
|
+
const vI = -1, xB = 0, io = 1, WB = 9e-3, oo = 1e-3, ao = 9e-4, so = 0.5, Do = 60;
|
|
13753
14533
|
class Lo {
|
|
13754
14534
|
camera_;
|
|
13755
14535
|
orbitVelocity_ = new TB(0, 0, 0);
|
|
@@ -13758,32 +14538,49 @@ class Lo {
|
|
|
13758
14538
|
currCenter_ = d();
|
|
13759
14539
|
dampingFactor_;
|
|
13760
14540
|
currMouseButton_ = vI;
|
|
14541
|
+
/**
|
|
14542
|
+
* Creates orbit controls and moves the camera to the initial pose.
|
|
14543
|
+
*
|
|
14544
|
+
* @param camera - The perspective camera to control.
|
|
14545
|
+
* @param params - Initialization properties.
|
|
14546
|
+
*/
|
|
13761
14547
|
constructor(A, I) {
|
|
13762
14548
|
this.camera_ = A, this.currPos_ = new TB(
|
|
13763
14549
|
I?.radius ?? 1,
|
|
13764
14550
|
I?.yaw ?? 0,
|
|
13765
14551
|
I?.pitch ?? 0
|
|
13766
14552
|
), I?.target && jI(this.currCenter_, I.target), this.dampingFactor_ = hA(
|
|
13767
|
-
I?.dampingFactor ??
|
|
14553
|
+
I?.dampingFactor ?? so,
|
|
13768
14554
|
0,
|
|
13769
14555
|
1
|
|
13770
14556
|
), this.updateCamera();
|
|
13771
14557
|
}
|
|
14558
|
+
/** The current distance from the target in world units. */
|
|
13772
14559
|
get radius() {
|
|
13773
14560
|
return this.currPos_.radius;
|
|
13774
14561
|
}
|
|
14562
|
+
/** The current azimuth angle in radians. */
|
|
13775
14563
|
get yaw() {
|
|
13776
14564
|
return this.currPos_.phi;
|
|
13777
14565
|
}
|
|
14566
|
+
/** The current elevation angle in radians. */
|
|
13778
14567
|
get pitch() {
|
|
13779
14568
|
return this.currPos_.theta;
|
|
13780
14569
|
}
|
|
14570
|
+
/** A copy of the point the camera orbits. */
|
|
13781
14571
|
get target() {
|
|
13782
14572
|
return EA(this.currCenter_);
|
|
13783
14573
|
}
|
|
14574
|
+
/** Whether any orbit, pan, or zoom velocity remains. */
|
|
13784
14575
|
get isMoving() {
|
|
13785
14576
|
return this.orbitVelocity_.phi !== 0 || this.orbitVelocity_.theta !== 0 || this.orbitVelocity_.radius !== 0 || this.panVelocity_[0] !== 0 || this.panVelocity_[1] !== 0 || this.panVelocity_[2] !== 0;
|
|
13786
14577
|
}
|
|
14578
|
+
/**
|
|
14579
|
+
* Handles a pointer or wheel event. Called automatically by the owning
|
|
14580
|
+
* viewport unless a layer stops propagation.
|
|
14581
|
+
*
|
|
14582
|
+
* @param event - The event with clip and world coordinates attached.
|
|
14583
|
+
*/
|
|
13787
14584
|
onEvent(A) {
|
|
13788
14585
|
switch (A.type) {
|
|
13789
14586
|
case "pointerdown":
|
|
@@ -13801,13 +14598,19 @@ class Lo {
|
|
|
13801
14598
|
break;
|
|
13802
14599
|
}
|
|
13803
14600
|
}
|
|
14601
|
+
/**
|
|
14602
|
+
* Applies pending velocities to the camera and decays them toward zero.
|
|
14603
|
+
* Called automatically by the render loop once per frame.
|
|
14604
|
+
*
|
|
14605
|
+
* @param dt - Time since the last frame in seconds.
|
|
14606
|
+
*/
|
|
13804
14607
|
onUpdate(A) {
|
|
13805
14608
|
if (this.orbitVelocity_.phi === 0 && this.orbitVelocity_.theta === 0 && this.orbitVelocity_.radius === 0 && Gg(this.panVelocity_, p(0, 0, 0)))
|
|
13806
14609
|
return;
|
|
13807
14610
|
this.currPos_.phi += this.orbitVelocity_.phi, this.currPos_.theta += this.orbitVelocity_.theta, this.currPos_.radius += this.orbitVelocity_.radius * this.currPos_.radius, aI(this.currCenter_, this.currCenter_, this.panVelocity_);
|
|
13808
14611
|
const I = Math.PI / 2 - T;
|
|
13809
14612
|
this.currPos_.theta = hA(this.currPos_.theta, -I, I), this.currPos_.radius = Math.max(0.01, this.currPos_.radius), this.updateCamera();
|
|
13810
|
-
const B = Math.pow(1 - this.dampingFactor_, A *
|
|
14613
|
+
const B = Math.pow(1 - this.dampingFactor_, A * Do);
|
|
13811
14614
|
this.orbitVelocity_.phi *= B, this.orbitVelocity_.theta *= B, this.orbitVelocity_.radius *= B, zI(this.panVelocity_, this.panVelocity_, B), this.cutoffLowVelocity();
|
|
13812
14615
|
}
|
|
13813
14616
|
onPointerDown(A) {
|
|
@@ -13816,7 +14619,7 @@ class Lo {
|
|
|
13816
14619
|
}
|
|
13817
14620
|
onPointerMove(A) {
|
|
13818
14621
|
if (this.currMouseButton_ == vI) return;
|
|
13819
|
-
const I = A.event, B = I.movementX ?? 0, C = I.movementY ?? 0, Q = this.currMouseButton_ === xB && !I.shiftKey, E = this.currMouseButton_ === xB && I.shiftKey || this.currMouseButton_ ===
|
|
14622
|
+
const I = A.event, B = I.movementX ?? 0, C = I.movementY ?? 0, Q = this.currMouseButton_ === xB && !I.shiftKey, E = this.currMouseButton_ === xB && I.shiftKey || this.currMouseButton_ === io;
|
|
13820
14623
|
Q && this.orbit(B, C), E && this.pan(B, C);
|
|
13821
14624
|
}
|
|
13822
14625
|
onWheel(A) {
|
|
@@ -13834,11 +14637,11 @@ class Lo {
|
|
|
13834
14637
|
this.orbitVelocity_.phi -= A * WB, this.orbitVelocity_.theta += I * WB;
|
|
13835
14638
|
}
|
|
13836
14639
|
pan(A, I) {
|
|
13837
|
-
const B = this.currPos_.radius *
|
|
14640
|
+
const B = this.currPos_.radius * oo, C = d();
|
|
13838
14641
|
_I(C, C, this.camera_.right, A), _I(C, C, this.camera_.up, I), zI(C, C, B), $I(this.panVelocity_, this.panVelocity_, C);
|
|
13839
14642
|
}
|
|
13840
14643
|
zoom(A) {
|
|
13841
|
-
this.orbitVelocity_.radius += A *
|
|
14644
|
+
this.orbitVelocity_.radius += A * ao;
|
|
13842
14645
|
}
|
|
13843
14646
|
updateCamera() {
|
|
13844
14647
|
const A = aI(d(), this.currCenter_, this.currPos_.toVec3());
|
|
@@ -13848,107 +14651,6 @@ class Lo {
|
|
|
13848
14651
|
Math.abs(this.orbitVelocity_.phi) < T && (this.orbitVelocity_.phi = 0), Math.abs(this.orbitVelocity_.theta) < T && (this.orbitVelocity_.theta = 0), Math.abs(this.orbitVelocity_.radius) < T && (this.orbitVelocity_.radius = 0), yg(this.panVelocity_) < T && $C(this.panVelocity_);
|
|
13849
14652
|
}
|
|
13850
14653
|
}
|
|
13851
|
-
class Do {
|
|
13852
|
-
planes_;
|
|
13853
|
-
constructor(A) {
|
|
13854
|
-
this.planes_ = [
|
|
13855
|
-
new sA(d(), 0),
|
|
13856
|
-
new sA(d(), 0),
|
|
13857
|
-
new sA(d(), 0),
|
|
13858
|
-
new sA(d(), 0),
|
|
13859
|
-
new sA(d(), 0),
|
|
13860
|
-
new sA(d(), 0)
|
|
13861
|
-
], this.setWithViewProjection(A);
|
|
13862
|
-
}
|
|
13863
|
-
// Uses the fast plane-extraction algorithm described in
|
|
13864
|
-
// Gribb & Hartmann (1997): https://tinyurl.com/5x5htcwm
|
|
13865
|
-
setWithViewProjection(A) {
|
|
13866
|
-
const I = d();
|
|
13867
|
-
this.planes_[0].set(
|
|
13868
|
-
rA(I, A[3] + A[0], A[7] + A[4], A[11] + A[8]),
|
|
13869
|
-
A[15] + A[12]
|
|
13870
|
-
), this.planes_[1].set(
|
|
13871
|
-
rA(I, A[3] - A[0], A[7] - A[4], A[11] - A[8]),
|
|
13872
|
-
A[15] - A[12]
|
|
13873
|
-
), this.planes_[2].set(
|
|
13874
|
-
rA(I, A[3] - A[1], A[7] - A[5], A[11] - A[9]),
|
|
13875
|
-
A[15] - A[13]
|
|
13876
|
-
), this.planes_[3].set(
|
|
13877
|
-
rA(I, A[3] + A[1], A[7] + A[5], A[11] + A[9]),
|
|
13878
|
-
A[15] + A[13]
|
|
13879
|
-
), this.planes_[4].set(
|
|
13880
|
-
rA(I, A[3] + A[2], A[7] + A[6], A[11] + A[10]),
|
|
13881
|
-
A[15] + A[14]
|
|
13882
|
-
), this.planes_[5].set(
|
|
13883
|
-
rA(I, A[3] - A[2], A[7] - A[6], A[11] - A[10]),
|
|
13884
|
-
A[15] - A[14]
|
|
13885
|
-
);
|
|
13886
|
-
for (const B of this.planes_) B.normalize();
|
|
13887
|
-
}
|
|
13888
|
-
intersectsWithBox3(A) {
|
|
13889
|
-
const I = d();
|
|
13890
|
-
for (const B of this.planes_) {
|
|
13891
|
-
const C = B.normal;
|
|
13892
|
-
if (I[0] = C[0] > 0 ? A.max[0] : A.min[0], I[1] = C[1] > 0 ? A.max[1] : A.min[1], I[2] = C[2] > 0 ? A.max[2] : A.min[2], B.signedDistanceToPoint(I) < 0) return !1;
|
|
13893
|
-
}
|
|
13894
|
-
return !0;
|
|
13895
|
-
}
|
|
13896
|
-
}
|
|
13897
|
-
class cC extends YI {
|
|
13898
|
-
transform_ = new eC();
|
|
13899
|
-
projectionMatrix_ = $();
|
|
13900
|
-
near_ = 0;
|
|
13901
|
-
far_ = 0;
|
|
13902
|
-
update() {
|
|
13903
|
-
this.updateProjectionMatrix();
|
|
13904
|
-
}
|
|
13905
|
-
get projectionMatrix() {
|
|
13906
|
-
return this.projectionMatrix_;
|
|
13907
|
-
}
|
|
13908
|
-
get transform() {
|
|
13909
|
-
return this.transform_;
|
|
13910
|
-
}
|
|
13911
|
-
get viewMatrix() {
|
|
13912
|
-
return this.transform.inverse;
|
|
13913
|
-
}
|
|
13914
|
-
get right() {
|
|
13915
|
-
const A = this.transform.matrix;
|
|
13916
|
-
return p(A[0], A[1], A[2]);
|
|
13917
|
-
}
|
|
13918
|
-
get up() {
|
|
13919
|
-
const A = this.transform.matrix;
|
|
13920
|
-
return p(A[4], A[5], A[6]);
|
|
13921
|
-
}
|
|
13922
|
-
getViewProjection() {
|
|
13923
|
-
return QI($(), this.projectionMatrix, this.viewMatrix);
|
|
13924
|
-
}
|
|
13925
|
-
get frustum() {
|
|
13926
|
-
return new Do(this.getViewProjection());
|
|
13927
|
-
}
|
|
13928
|
-
pan(A) {
|
|
13929
|
-
this.transform.addTranslation(A);
|
|
13930
|
-
}
|
|
13931
|
-
get position() {
|
|
13932
|
-
return this.transform.translation;
|
|
13933
|
-
}
|
|
13934
|
-
clipToWorld(A) {
|
|
13935
|
-
const I = DI(A[0], A[1], A[2], 1), B = OA(
|
|
13936
|
-
$(),
|
|
13937
|
-
this.projectionMatrix_
|
|
13938
|
-
), C = VA(
|
|
13939
|
-
YA(),
|
|
13940
|
-
I,
|
|
13941
|
-
B
|
|
13942
|
-
);
|
|
13943
|
-
BQ(C, C, 1 / C[3]);
|
|
13944
|
-
const Q = VA(
|
|
13945
|
-
YA(),
|
|
13946
|
-
C,
|
|
13947
|
-
this.transform.matrix
|
|
13948
|
-
);
|
|
13949
|
-
return p(Q[0], Q[1], Q[2]);
|
|
13950
|
-
}
|
|
13951
|
-
}
|
|
13952
14654
|
const UC = 1.77, bB = 128, ZB = 128 / UC, ho = -1e6, to = 1e6;
|
|
13953
14655
|
class Jo extends cC {
|
|
13954
14656
|
// width_ and height_ should always be defined by constructor (see setFrame)
|
|
@@ -13962,27 +14664,48 @@ class Jo extends cC {
|
|
|
13962
14664
|
/**
|
|
13963
14665
|
* Creates an orthographic camera framing the given world-space rectangle.
|
|
13964
14666
|
*
|
|
13965
|
-
* @param props -
|
|
13966
|
-
* plane distances (default `-1e6` and `1e6`), and the slice orientation
|
|
13967
|
-
* the camera faces (default `"XY"`).
|
|
14667
|
+
* @param props - Initialization properties.
|
|
13968
14668
|
*/
|
|
13969
14669
|
constructor(A) {
|
|
13970
14670
|
super(), this.near_ = A.near ?? ho, this.far_ = A.far ?? to, this.orientation_ = A.orientation ?? "XY", this.axes_ = MA(this.orientation_), this.rotation_ = dA(this.axes_), this.setFrame(A), this.updateProjectionMatrix();
|
|
13971
14671
|
}
|
|
14672
|
+
/**
|
|
14673
|
+
* The world-space size of the rendered view as `[width, height]`.
|
|
14674
|
+
*
|
|
14675
|
+
* This is the camera frame padded to match the viewport's aspect ratio, so
|
|
14676
|
+
* it reflects what is actually visible rather than the frame that was set.
|
|
14677
|
+
*/
|
|
13972
14678
|
get viewportSize() {
|
|
13973
14679
|
return this.viewportSize_;
|
|
13974
14680
|
}
|
|
14681
|
+
/**
|
|
14682
|
+
* Sets the aspect ratio (width / height) of the viewport the camera renders
|
|
14683
|
+
* into. Called automatically by the owning viewport when it resizes.
|
|
14684
|
+
*
|
|
14685
|
+
* @param aspectRatio - The viewport's width divided by its height.
|
|
14686
|
+
*/
|
|
13975
14687
|
setAspectRatio(A) {
|
|
13976
14688
|
this.viewportAspectRatio_ = A, this.updateProjectionMatrix();
|
|
13977
14689
|
}
|
|
14690
|
+
/**
|
|
14691
|
+
* Reframes the camera to the given world-space rectangle, resetting any
|
|
14692
|
+
* accumulated zoom and pan.
|
|
14693
|
+
*
|
|
14694
|
+
* The frame may be padded horizontally or vertically at render time to
|
|
14695
|
+
* match the viewport's aspect ratio (see {@link viewportSize}).
|
|
14696
|
+
*
|
|
14697
|
+
* @param frame - The view frame edges in world units.
|
|
14698
|
+
*/
|
|
13978
14699
|
setFrame({ left: A, right: I, top: B, bottom: C }) {
|
|
13979
14700
|
this.width_ = Math.abs(I - A), this.height_ = Math.abs(B - C), this.updateProjectionMatrix();
|
|
13980
14701
|
const Q = d();
|
|
13981
14702
|
Q[W[this.axes_.u]] = 0.5 * (A + I), Q[W[this.axes_.v]] = 0.5 * (C + B), this.transform.setTranslation(Q), this.transform.setScale([1, 1, 1]), this.transform.setRotation(this.rotation_);
|
|
13982
14703
|
}
|
|
14704
|
+
/** Identifies the camera type as `OrthographicCamera`. */
|
|
13983
14705
|
get type() {
|
|
13984
14706
|
return "OrthographicCamera";
|
|
13985
14707
|
}
|
|
14708
|
+
/** The slice orientation the camera faces. */
|
|
13986
14709
|
get orientation() {
|
|
13987
14710
|
return this.orientation_;
|
|
13988
14711
|
}
|
|
@@ -13990,6 +14713,8 @@ class Jo extends cC {
|
|
|
13990
14713
|
* Changes the slice orientation the camera faces. The current frame and
|
|
13991
14714
|
* zoom carry over numerically to the new plane axes. Call {@link setFrame}
|
|
13992
14715
|
* to reframe the view for the new plane.
|
|
14716
|
+
*
|
|
14717
|
+
* @param orientation - The slice plane for the camera to face.
|
|
13993
14718
|
*/
|
|
13994
14719
|
setOrientation(A) {
|
|
13995
14720
|
if (A === this.orientation_)
|
|
@@ -13999,12 +14724,25 @@ class Jo extends cC {
|
|
|
13999
14724
|
const C = d();
|
|
14000
14725
|
C[W[this.axes_.u]] = I, C[W[this.axes_.v]] = B, this.transform.setTranslation(C), this.transform.setRotation(this.rotation_);
|
|
14001
14726
|
}
|
|
14727
|
+
/**
|
|
14728
|
+
* Zooms the view by the given factor relative to the current zoom level.
|
|
14729
|
+
* Factors greater than `1` zoom in and factors between `0` and `1` zoom
|
|
14730
|
+
* out.
|
|
14731
|
+
*
|
|
14732
|
+
* @param factor - The magnification factor to apply.
|
|
14733
|
+
*/
|
|
14002
14734
|
zoom(A) {
|
|
14003
14735
|
if (A <= 0)
|
|
14004
14736
|
throw new Error(`Invalid zoom factor: ${A}`);
|
|
14005
14737
|
const I = 1 / A;
|
|
14006
14738
|
this.transform.addScale([I, I, 1]);
|
|
14007
14739
|
}
|
|
14740
|
+
/**
|
|
14741
|
+
* Computes the world-space rectangle currently visible in the viewport,
|
|
14742
|
+
* accounting for zoom, pan, and aspect-ratio padding.
|
|
14743
|
+
*
|
|
14744
|
+
* @returns The visible rectangle on the camera's slice plane.
|
|
14745
|
+
*/
|
|
14008
14746
|
getWorldViewRect() {
|
|
14009
14747
|
let A = DI(-1, -1, 0, 1), I = DI(1, 1, 0, 1);
|
|
14010
14748
|
const B = OA($(), this.getViewProjection());
|
|
@@ -14015,6 +14753,7 @@ class Jo extends cC {
|
|
|
14015
14753
|
V(I[C], I[Q])
|
|
14016
14754
|
);
|
|
14017
14755
|
}
|
|
14756
|
+
/** @hidden */
|
|
14018
14757
|
updateProjectionMatrix() {
|
|
14019
14758
|
const A = this.width_, I = this.height_, B = A / I;
|
|
14020
14759
|
let C = 0.5 * A, Q = 0.5 * I;
|
|
@@ -14034,12 +14773,24 @@ class Yo {
|
|
|
14034
14773
|
camera_;
|
|
14035
14774
|
dragActive_ = !1;
|
|
14036
14775
|
dragStart_ = d();
|
|
14776
|
+
/**
|
|
14777
|
+
* Creates pan and zoom controls for the given camera.
|
|
14778
|
+
*
|
|
14779
|
+
* @param camera - The orthographic camera to control.
|
|
14780
|
+
*/
|
|
14037
14781
|
constructor(A) {
|
|
14038
14782
|
this.camera_ = A;
|
|
14039
14783
|
}
|
|
14784
|
+
/** Whether a pan drag is in progress. */
|
|
14040
14785
|
get isMoving() {
|
|
14041
14786
|
return this.dragActive_;
|
|
14042
14787
|
}
|
|
14788
|
+
/**
|
|
14789
|
+
* Handles a pointer or wheel event. Called automatically by the owning
|
|
14790
|
+
* viewport unless a layer stops propagation.
|
|
14791
|
+
*
|
|
14792
|
+
* @param event - The event with clip and world coordinates attached.
|
|
14793
|
+
*/
|
|
14043
14794
|
onEvent(A) {
|
|
14044
14795
|
switch (A.type) {
|
|
14045
14796
|
case "wheel":
|
|
@@ -14057,6 +14808,11 @@ class Yo {
|
|
|
14057
14808
|
break;
|
|
14058
14809
|
}
|
|
14059
14810
|
}
|
|
14811
|
+
/**
|
|
14812
|
+
* Does nothing. Pan and zoom apply immediately with no inertia.
|
|
14813
|
+
*
|
|
14814
|
+
* @param _delta - Time since the last frame in seconds. Unused.
|
|
14815
|
+
*/
|
|
14060
14816
|
onUpdate(A) {
|
|
14061
14817
|
}
|
|
14062
14818
|
onWheel(A) {
|
|
@@ -14086,6 +14842,11 @@ const yo = 60, eo = 1.77, oI = 0.1, XI = 180 - oI;
|
|
|
14086
14842
|
class Mo extends cC {
|
|
14087
14843
|
fov_;
|
|
14088
14844
|
aspectRatio_;
|
|
14845
|
+
/**
|
|
14846
|
+
* Creates a perspective camera from the given projection settings.
|
|
14847
|
+
*
|
|
14848
|
+
* @param props - Initialization properties.
|
|
14849
|
+
*/
|
|
14089
14850
|
constructor(A = {}) {
|
|
14090
14851
|
const {
|
|
14091
14852
|
fov: I = yo,
|
|
@@ -14100,20 +14861,40 @@ class Mo extends cC {
|
|
|
14100
14861
|
);
|
|
14101
14862
|
super(), this.fov_ = I, this.aspectRatio_ = B, this.near_ = C, this.far_ = Q, this.transform.setTranslation(E), this.updateProjectionMatrix();
|
|
14102
14863
|
}
|
|
14864
|
+
/**
|
|
14865
|
+
* Sets the aspect ratio (width / height) of the viewport the camera
|
|
14866
|
+
* renders into. Called automatically by the owning viewport when it
|
|
14867
|
+
* resizes.
|
|
14868
|
+
*
|
|
14869
|
+
* @param aspectRatio - The viewport's width divided by its height.
|
|
14870
|
+
*/
|
|
14103
14871
|
setAspectRatio(A) {
|
|
14104
14872
|
this.aspectRatio_ = A, this.updateProjectionMatrix();
|
|
14105
14873
|
}
|
|
14874
|
+
/** Identifies the camera type as `PerspectiveCamera`. */
|
|
14106
14875
|
get type() {
|
|
14107
14876
|
return "PerspectiveCamera";
|
|
14108
14877
|
}
|
|
14878
|
+
/** The vertical field of view in degrees. */
|
|
14109
14879
|
get fov() {
|
|
14110
14880
|
return this.fov_;
|
|
14111
14881
|
}
|
|
14882
|
+
/**
|
|
14883
|
+
* Zooms the view by the given factor relative to the current zoom level.
|
|
14884
|
+
* Factors greater than `1` zoom in and factors between `0` and `1` zoom
|
|
14885
|
+
* out.
|
|
14886
|
+
*
|
|
14887
|
+
* Zooming narrows or widens the field of view rather than moving the
|
|
14888
|
+
* camera, and the result is clamped to valid angles.
|
|
14889
|
+
*
|
|
14890
|
+
* @param factor - The magnification factor to apply.
|
|
14891
|
+
*/
|
|
14112
14892
|
zoom(A) {
|
|
14113
14893
|
if (A <= 0)
|
|
14114
14894
|
throw new Error(`Invalid zoom factor: ${A}`);
|
|
14115
14895
|
this.fov_ = Math.max(oI, Math.min(XI, this.fov_ / A)), this.updateProjectionMatrix();
|
|
14116
14896
|
}
|
|
14897
|
+
/** @hidden */
|
|
14117
14898
|
updateProjectionMatrix() {
|
|
14118
14899
|
OC(
|
|
14119
14900
|
this.projectionMatrix_,
|
|
@@ -14126,7 +14907,11 @@ class Mo extends cC {
|
|
|
14126
14907
|
}
|
|
14127
14908
|
export {
|
|
14128
14909
|
Ro as AxesLayer,
|
|
14910
|
+
AA as Box2,
|
|
14911
|
+
SA as Box3,
|
|
14912
|
+
cC as Camera,
|
|
14129
14913
|
x as Color,
|
|
14914
|
+
Eo as Frustum,
|
|
14130
14915
|
no as Idetik,
|
|
14131
14916
|
rC as ImageLayer,
|
|
14132
14917
|
Ti as ImageRenderable,
|
|
@@ -14140,6 +14925,9 @@ export {
|
|
|
14140
14925
|
Mo as PerspectiveCamera,
|
|
14141
14926
|
ko as PointsRenderable,
|
|
14142
14927
|
pi as ProjectedLineRenderable,
|
|
14928
|
+
gI as RenderableObject,
|
|
14929
|
+
eC as TrsTransform,
|
|
14930
|
+
uQ as Viewport,
|
|
14143
14931
|
Uo as VolumeLayer,
|
|
14144
14932
|
bi as VolumeRenderable,
|
|
14145
14933
|
ug as createExplorationPolicy,
|