copper3d 3.2.0 → 3.2.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.
Files changed (31) hide show
  1. package/dist/Utils/segmentation/DragOperator.d.ts +2 -1
  2. package/dist/Utils/segmentation/DragOperator.js +3 -1
  3. package/dist/Utils/segmentation/DragOperator.js.map +1 -1
  4. package/dist/Utils/segmentation/NrrdTools.d.ts +3 -1
  5. package/dist/Utils/segmentation/NrrdTools.js +46 -2
  6. package/dist/Utils/segmentation/NrrdTools.js.map +1 -1
  7. package/dist/Utils/segmentation/core/GaussianSmoother.d.ts +55 -0
  8. package/dist/Utils/segmentation/core/GaussianSmoother.js +210 -0
  9. package/dist/Utils/segmentation/core/GaussianSmoother.js.map +1 -0
  10. package/dist/Utils/segmentation/core/MaskVolume.d.ts +9 -0
  11. package/dist/Utils/segmentation/core/MaskVolume.js +11 -0
  12. package/dist/Utils/segmentation/core/MaskVolume.js.map +1 -1
  13. package/dist/Utils/segmentation/tools/DragSliceTool.d.ts +0 -4
  14. package/dist/Utils/segmentation/tools/DragSliceTool.js +2 -19
  15. package/dist/Utils/segmentation/tools/DragSliceTool.js.map +1 -1
  16. package/dist/Utils/segmentation/tools/SliceRenderPipeline.js +8 -1
  17. package/dist/Utils/segmentation/tools/SliceRenderPipeline.js.map +1 -1
  18. package/dist/Utils/segmentation/tools/ToolHost.d.ts +1 -1
  19. package/dist/bundle.esm.js +281 -25
  20. package/dist/bundle.umd.js +281 -24
  21. package/dist/index.d.ts +3 -2
  22. package/dist/index.js +3 -3
  23. package/dist/index.js.map +1 -1
  24. package/dist/types/Utils/segmentation/DragOperator.d.ts +2 -1
  25. package/dist/types/Utils/segmentation/NrrdTools.d.ts +3 -1
  26. package/dist/types/Utils/segmentation/core/GaussianSmoother.d.ts +55 -0
  27. package/dist/types/Utils/segmentation/core/MaskVolume.d.ts +9 -0
  28. package/dist/types/Utils/segmentation/tools/DragSliceTool.d.ts +0 -4
  29. package/dist/types/Utils/segmentation/tools/ToolHost.d.ts +1 -1
  30. package/dist/types/index.d.ts +3 -2
  31. package/package.json +1 -1
@@ -71387,6 +71387,17 @@ class MaskVolume {
71387
71387
  getChannels() {
71388
71388
  return this.numChannels;
71389
71389
  }
71390
+ /**
71391
+ * Return the number of bytes in one complete z-slice.
71392
+ *
71393
+ * Equal to `width × height × channels`. Useful for direct buffer
71394
+ * index arithmetic in performance-critical code paths.
71395
+ *
71396
+ * @returns Bytes per z-slice.
71397
+ */
71398
+ getBytesPerSlice() {
71399
+ return this.bytesPerSlice;
71400
+ }
71390
71401
  /**
71391
71402
  * Return total memory used by the backing buffer, in bytes.
71392
71403
  *
@@ -73204,8 +73215,8 @@ class DragSliceTool extends BaseTool {
73204
73215
  }
73205
73216
  }
73206
73217
  }
73207
- // Composite all layers to master canvas
73208
- this.compositeAllLayers();
73218
+ // Composite all layers to master canvas (uses per-layer alpha)
73219
+ this.callbacks.compositeAllLayers();
73209
73220
  }
73210
73221
  // Refresh sphere overlay from volume for the new slice
73211
73222
  if (this.ctx.gui_states.mode.sphere) {
@@ -73214,23 +73225,6 @@ class DragSliceTool extends BaseTool {
73214
73225
  view.switchSliceFlag = false;
73215
73226
  }
73216
73227
  }
73217
- /**
73218
- * Composite all visible layer canvases to the master display canvas.
73219
- */
73220
- compositeAllLayers() {
73221
- const masterCtx = this.ctx.protectedData.ctxes.drawingLayerMasterCtx;
73222
- const width = this.ctx.nrrd_states.view.changedWidth;
73223
- const height = this.ctx.nrrd_states.view.changedHeight;
73224
- masterCtx.clearRect(0, 0, width, height);
73225
- // Master stores full-alpha composite; globalAlpha applied in start() render loop.
73226
- for (const layerId of this.ctx.nrrd_states.image.layers) {
73227
- if (!this.ctx.gui_states.layerChannel.layerVisibility[layerId])
73228
- continue;
73229
- const target = this.ctx.protectedData.layerTargets.get(layerId);
73230
- if (target)
73231
- masterCtx.drawImage(target.canvas, 0, 0, width, height);
73232
- }
73233
- }
73234
73228
  // ===== Canvas Cleanup =====
73235
73229
  cleanCanvases(flag) {
73236
73230
  if (flag) {
@@ -73272,7 +73266,7 @@ class DragSliceTool extends BaseTool {
73272
73266
  }
73273
73267
 
73274
73268
  class DragOperator {
73275
- constructor(container, nrrd_sates, gui_states, protectedData, drawingPrameters, setSyncsliceNum, setIsDrawFalse, flipDisplayImageByAxis, setEmptyCanvasSize, getOrCreateSliceBuffer, renderSliceToCanvas) {
73269
+ constructor(container, nrrd_sates, gui_states, protectedData, drawingPrameters, setSyncsliceNum, setIsDrawFalse, flipDisplayImageByAxis, setEmptyCanvasSize, getOrCreateSliceBuffer, renderSliceToCanvas, compositeAllLayers) {
73276
73270
  this.dragPrameters = {
73277
73271
  move: 0,
73278
73272
  y: 0,
@@ -73308,6 +73302,7 @@ class DragOperator {
73308
73302
  this.setEmptyCanvasSize = setEmptyCanvasSize;
73309
73303
  this.getOrCreateSliceBuffer = getOrCreateSliceBuffer;
73310
73304
  this.renderSliceToCanvas = renderSliceToCanvas;
73305
+ this.compositeAllLayers = compositeAllLayers;
73311
73306
  this.showDragNumberDiv = createShowSliceNumberDiv();
73312
73307
  this.init();
73313
73308
  }
@@ -73333,6 +73328,7 @@ class DragOperator {
73333
73328
  setEmptyCanvasSize: (axis) => this.setEmptyCanvasSize(axis),
73334
73329
  getOrCreateSliceBuffer: (axis) => this.getOrCreateSliceBuffer(axis),
73335
73330
  renderSliceToCanvas: (layer, axis, sliceIndex, buffer, targetCtx, w, h) => this.renderSliceToCanvas(layer, axis, sliceIndex, buffer, targetCtx, w, h),
73331
+ compositeAllLayers: () => this.compositeAllLayers(),
73336
73332
  refreshSphereOverlay: () => { var _a; return (_a = this.refreshSphereOverlayCb) === null || _a === void 0 ? void 0 : _a.call(this); },
73337
73333
  }, this.showDragNumberDiv, dragEffectCanvases);
73338
73334
  }
@@ -76460,6 +76456,216 @@ class CanvasState {
76460
76456
  }
76461
76457
  }
76462
76458
 
76459
+ /**
76460
+ * GaussianSmoother — 3D Gaussian smoothing for segmentation masks.
76461
+ *
76462
+ * Applies a separable 3D Gaussian blur to a single label channel within a
76463
+ * MaskVolume, then thresholds the result back to a binary mask. This smooths
76464
+ * jagged edges and fills small holes in segmentation annotations.
76465
+ *
76466
+ * Pure, stateless utility — no DOM/Canvas/GUI dependencies.
76467
+ *
76468
+ * Performance: uses direct typed-array access (bypassing getVoxel/setVoxel
76469
+ * boundary checks) and branch-free convolution for the interior region.
76470
+ */
76471
+ class GaussianSmoother {
76472
+ /**
76473
+ * Smooth a single label channel in-place using separable 3D Gaussian blur.
76474
+ *
76475
+ * Steps:
76476
+ * 1. Extract — create a Float32Array with 1.0 where voxel === channel, 0.0 elsewhere.
76477
+ * 2. Blur — apply separable Gaussian (X → Y → Z) on the float buffer.
76478
+ * 3. Threshold — binarize at 0.5.
76479
+ * 4. Write back — overwrite/erase voxels according to the thresholded result.
76480
+ *
76481
+ * @param volume The MaskVolume to operate on (modified in-place).
76482
+ * @param channel The label value to smooth (must be > 0).
76483
+ * @param sigma Base Gaussian sigma in voxel units (default 1.0).
76484
+ * @param spacing Optional voxel spacing [sx, sy, sz]. When provided, per-axis
76485
+ * sigma is computed as `sigma / spacing[axis]` so that the
76486
+ * physical smoothing radius is isotropic.
76487
+ */
76488
+ static gaussianSmooth3D(volume, channel, sigma = 1.0, spacing) {
76489
+ const dims = volume.getDimensions();
76490
+ const { width, height, depth } = dims;
76491
+ const totalVoxels = width * height * depth;
76492
+ // Direct access to underlying buffer — bypasses getVoxel/setVoxel
76493
+ // boundary checks for ~10x speedup in hot loops.
76494
+ const rawData = volume.getRawData();
76495
+ const channels = volume.getChannels();
76496
+ const bytesPerSlice = volume.getBytesPerSlice();
76497
+ const rowStride = width * channels;
76498
+ // Compute per-axis sigma (normalized to voxel units)
76499
+ const sigmaX = spacing ? sigma / spacing[0] : sigma;
76500
+ const sigmaY = spacing ? sigma / spacing[1] : sigma;
76501
+ const sigmaZ = spacing ? sigma / spacing[2] : sigma;
76502
+ // 1. Extract binary float buffer — direct array access
76503
+ const buffer = new Float32Array(totalVoxels);
76504
+ for (let z = 0; z < depth; z++) {
76505
+ const zOffset = z * bytesPerSlice;
76506
+ for (let y = 0; y < height; y++) {
76507
+ const zyOffset = zOffset + y * rowStride;
76508
+ for (let x = 0; x < width; x++) {
76509
+ const bufIdx = z * height * width + y * width + x;
76510
+ buffer[bufIdx] = rawData[zyOffset + x * channels] === channel ? 1.0 : 0.0;
76511
+ }
76512
+ }
76513
+ }
76514
+ // 2. Separable Gaussian blur: X → Y → Z
76515
+ const kernelX = GaussianSmoother.generateKernel1D(sigmaX);
76516
+ const kernelY = GaussianSmoother.generateKernel1D(sigmaY);
76517
+ const kernelZ = GaussianSmoother.generateKernel1D(sigmaZ);
76518
+ GaussianSmoother.convolve1D(buffer, width, height, depth, 0, kernelX); // X axis
76519
+ GaussianSmoother.convolve1D(buffer, width, height, depth, 1, kernelY); // Y axis
76520
+ GaussianSmoother.convolve1D(buffer, width, height, depth, 2, kernelZ); // Z axis
76521
+ // 3 & 4. Threshold and write back — direct array access
76522
+ for (let z = 0; z < depth; z++) {
76523
+ const zOffset = z * bytesPerSlice;
76524
+ for (let y = 0; y < height; y++) {
76525
+ const zyOffset = zOffset + y * rowStride;
76526
+ for (let x = 0; x < width; x++) {
76527
+ const bufIdx = z * height * width + y * width + x;
76528
+ const smoothed = buffer[bufIdx] >= 0.5 ? 1 : 0;
76529
+ const rawIdx = zyOffset + x * channels;
76530
+ const original = rawData[rawIdx];
76531
+ if (smoothed === 1 && original !== channel) {
76532
+ // Smoothed region expands into this voxel — overwrite
76533
+ rawData[rawIdx] = channel;
76534
+ }
76535
+ else if (smoothed === 0 && original === channel) {
76536
+ // Smoothed region retreats — erase
76537
+ rawData[rawIdx] = 0;
76538
+ }
76539
+ // Otherwise leave unchanged
76540
+ }
76541
+ }
76542
+ }
76543
+ }
76544
+ /**
76545
+ * Generate a normalized 1D Gaussian kernel truncated at ±3σ.
76546
+ *
76547
+ * @param sigma Standard deviation (in voxels). Must be > 0.
76548
+ * @returns Normalized Float32Array of odd length.
76549
+ */
76550
+ static generateKernel1D(sigma) {
76551
+ if (sigma <= 0) {
76552
+ return new Float32Array([1.0]);
76553
+ }
76554
+ const radius = Math.ceil(sigma * 3);
76555
+ const size = 2 * radius + 1;
76556
+ const kernel = new Float32Array(size);
76557
+ const twoSigmaSq = 2 * sigma * sigma;
76558
+ let sum = 0;
76559
+ for (let i = 0; i < size; i++) {
76560
+ const x = i - radius;
76561
+ kernel[i] = Math.exp(-(x * x) / twoSigmaSq);
76562
+ sum += kernel[i];
76563
+ }
76564
+ // Normalize
76565
+ for (let i = 0; i < size; i++) {
76566
+ kernel[i] /= sum;
76567
+ }
76568
+ return kernel;
76569
+ }
76570
+ /**
76571
+ * In-place single-axis convolution with zero-padding at boundaries.
76572
+ *
76573
+ * Uses a 3-segment approach: left boundary (with bounds check),
76574
+ * middle interior (branch-free, ~95% of work), right boundary
76575
+ * (with bounds check). This eliminates per-element branching
76576
+ * in the hot inner loop.
76577
+ *
76578
+ * @param data Flat float buffer (width × height × depth).
76579
+ * @param width X dimension.
76580
+ * @param height Y dimension.
76581
+ * @param depth Z dimension.
76582
+ * @param axis 0 = X, 1 = Y, 2 = Z.
76583
+ * @param kernel 1D convolution kernel (odd length).
76584
+ */
76585
+ static convolve1D(data, width, height, depth, axis, kernel) {
76586
+ const kLen = kernel.length;
76587
+ const radius = (kLen - 1) / 2;
76588
+ // Determine the dimension length along the convolution axis
76589
+ // and the stride between consecutive elements along that axis
76590
+ let axisLen;
76591
+ let stride;
76592
+ let outerCount;
76593
+ if (axis === 0) {
76594
+ // X axis: stride = 1, iterate over all (y, z) lines
76595
+ axisLen = width;
76596
+ stride = 1;
76597
+ outerCount = height * depth;
76598
+ }
76599
+ else if (axis === 1) {
76600
+ // Y axis: stride = width, iterate over all (x, z) lines
76601
+ axisLen = height;
76602
+ stride = width;
76603
+ outerCount = width * depth;
76604
+ }
76605
+ else {
76606
+ // Z axis: stride = width * height, iterate over all (x, y) lines
76607
+ axisLen = depth;
76608
+ stride = width * height;
76609
+ outerCount = width * height;
76610
+ }
76611
+ // Precompute middle segment bounds
76612
+ const midStart = radius;
76613
+ const midEnd = axisLen - radius;
76614
+ // Temporary line buffer to avoid read-after-write issues
76615
+ const line = new Float32Array(axisLen);
76616
+ for (let outer = 0; outer < outerCount; outer++) {
76617
+ // Compute the starting index for this line
76618
+ let lineStart;
76619
+ if (axis === 0) {
76620
+ lineStart = outer * width;
76621
+ }
76622
+ else if (axis === 1) {
76623
+ const z = Math.floor(outer / width);
76624
+ const x = outer % width;
76625
+ lineStart = z * width * height + x;
76626
+ }
76627
+ else {
76628
+ lineStart = outer;
76629
+ }
76630
+ // Read the line
76631
+ for (let i = 0; i < axisLen; i++) {
76632
+ line[i] = data[lineStart + i * stride];
76633
+ }
76634
+ // Left boundary segment (i = 0 .. radius-1): lower bound check
76635
+ for (let i = 0; i < midStart; i++) {
76636
+ let sum = 0;
76637
+ for (let k = 0; k < kLen; k++) {
76638
+ const j = i + k - radius;
76639
+ if (j >= 0) {
76640
+ sum += line[j] * kernel[k];
76641
+ }
76642
+ }
76643
+ data[lineStart + i * stride] = sum;
76644
+ }
76645
+ // Middle segment (i = radius .. axisLen-radius-1): NO bounds check
76646
+ for (let i = midStart; i < midEnd; i++) {
76647
+ let sum = 0;
76648
+ const lineOffset = i - radius;
76649
+ for (let k = 0; k < kLen; k++) {
76650
+ sum += line[lineOffset + k] * kernel[k];
76651
+ }
76652
+ data[lineStart + i * stride] = sum;
76653
+ }
76654
+ // Right boundary segment (i = axisLen-radius .. axisLen-1): upper bound check
76655
+ for (let i = midEnd; i < axisLen; i++) {
76656
+ let sum = 0;
76657
+ for (let k = 0; k < kLen; k++) {
76658
+ const j = i + k - radius;
76659
+ if (j < axisLen) {
76660
+ sum += line[j] * kernel[k];
76661
+ }
76662
+ }
76663
+ data[lineStart + i * stride] = sum;
76664
+ }
76665
+ }
76666
+ }
76667
+ }
76668
+
76463
76669
  /**
76464
76670
  * Manages layer/channel state: active selection, visibility, and channel colors.
76465
76671
  *
@@ -76976,6 +77182,8 @@ class SliceRenderPipeline extends BaseTool {
76976
77182
  * Then update the changedWidth and changedHeight based on the sizeFactor.
76977
77183
  */
76978
77184
  updateOriginAndChangedWH() {
77185
+ const prevW = this.ctx.nrrd_states.image.originWidth;
77186
+ const prevH = this.ctx.nrrd_states.image.originHeight;
76979
77187
  this.ctx.nrrd_states.image.originWidth =
76980
77188
  this.ctx.protectedData.canvases.originCanvas.width;
76981
77189
  this.ctx.nrrd_states.image.originHeight =
@@ -76984,7 +77192,12 @@ class SliceRenderPipeline extends BaseTool {
76984
77192
  // Setting them here would defeat the sizeChanged detection in resizePaintArea,
76985
77193
  // causing canvas elements to keep stale dimensions after axis switches.
76986
77194
  this.resizePaintArea(this.ctx.nrrd_states.view.sizeFactor);
76987
- this.resetPaintAreaUIPosition();
77195
+ // Only re-center when origin dimensions changed (e.g. axis switch).
77196
+ // Contrast toggle doesn't change origin size, so skip to preserve user's pan/zoom.
77197
+ if (prevW !== this.ctx.nrrd_states.image.originWidth ||
77198
+ prevH !== this.ctx.nrrd_states.image.originHeight) {
77199
+ this.resetPaintAreaUIPosition();
77200
+ }
76988
77201
  }
76989
77202
  /**
76990
77203
  * Keep all contrast slice index to same.
@@ -77198,7 +77411,7 @@ class NrrdTools {
77198
77411
  // Wire RenderingUtils' setEmptyCanvasSize callback
77199
77412
  this.drawCore.renderer.setEmptyCanvasSize = (axis) => this.setEmptyCanvasSize(axis);
77200
77413
  this.init();
77201
- this.dragOperator = new DragOperator(this.container, this.state.nrrd_states, this.state.gui_states, this.state.protectedData, this.drawCore.drawingPrameters, this.setSyncsliceNum.bind(this), this.setIsDrawFalse.bind(this), this.flipDisplayImageByAxis.bind(this), this.setEmptyCanvasSize.bind(this), this.drawCore.renderer.getOrCreateSliceBuffer.bind(this.drawCore.renderer), this.drawCore.renderer.renderSliceToCanvas.bind(this.drawCore.renderer));
77414
+ this.dragOperator = new DragOperator(this.container, this.state.nrrd_states, this.state.gui_states, this.state.protectedData, this.drawCore.drawingPrameters, this.setSyncsliceNum.bind(this), this.setIsDrawFalse.bind(this), this.flipDisplayImageByAxis.bind(this), this.setEmptyCanvasSize.bind(this), this.drawCore.renderer.getOrCreateSliceBuffer.bind(this.drawCore.renderer), this.drawCore.renderer.renderSliceToCanvas.bind(this.drawCore.renderer), this.drawCore.renderer.compositeAllLayers.bind(this.drawCore.renderer));
77202
77415
  // Inject EventRouter into DragOperator for centralized event handling
77203
77416
  if (this.drawCore.eventRouter) {
77204
77417
  this.dragOperator.setEventRouter(this.drawCore.eventRouter);
@@ -77517,7 +77730,8 @@ class NrrdTools {
77517
77730
  getPencilColor() {
77518
77731
  return this.state.gui_states.drawing.color;
77519
77732
  }
77520
- executeAction(action) {
77733
+ executeAction(action, opts) {
77734
+ var _a;
77521
77735
  switch (action) {
77522
77736
  case "undo":
77523
77737
  this.undo();
@@ -77555,6 +77769,48 @@ class NrrdTools {
77555
77769
  enableDownload(config);
77556
77770
  break;
77557
77771
  }
77772
+ case "gaussianSmooth": {
77773
+ const layerId = this.state.gui_states.layerChannel.layer;
77774
+ const channel = this.state.gui_states.layerChannel.activeChannel;
77775
+ const volume = this.drawCore.renderer.getVolumeForLayer(layerId);
77776
+ if (volume && channel > 0) {
77777
+ const dims = volume.getDimensions();
77778
+ // 1. Snapshot all Z-slices before mutation (undo support)
77779
+ const deltas = [];
77780
+ for (let z = 0; z < dims.depth; z++) {
77781
+ const sliceData = volume.getSliceUint8(z, "z").data;
77782
+ const hasChannel = sliceData.some((v) => v === channel);
77783
+ if (hasChannel) {
77784
+ deltas.push({
77785
+ layerId,
77786
+ axis: "z",
77787
+ sliceIndex: z,
77788
+ oldSlice: sliceData.slice(),
77789
+ newSlice: new Uint8Array(0), // placeholder, filled after smoothing
77790
+ });
77791
+ }
77792
+ }
77793
+ // 2. Apply smoothing with anisotropic spacing
77794
+ const spacing = this.state.nrrd_states.image.voxelSpacing;
77795
+ const spacingTuple = spacing.length >= 3 ? [spacing[0], spacing[1], spacing[2]] : undefined;
77796
+ const sigma = (_a = opts === null || opts === void 0 ? void 0 : opts.sigma) !== null && _a !== void 0 ? _a : 1.0;
77797
+ GaussianSmoother.gaussianSmooth3D(volume, channel, sigma, spacingTuple);
77798
+ // 3. Capture newSlice data after smoothing and push undo group
77799
+ for (const delta of deltas) {
77800
+ delta.newSlice = volume.getSliceUint8(delta.sliceIndex, "z").data.slice();
77801
+ }
77802
+ if (deltas.length > 0) {
77803
+ this.drawCore.undoManager.pushGroup(deltas);
77804
+ }
77805
+ // 4. Notify backend for each changed slice
77806
+ for (const delta of deltas) {
77807
+ const { data: sliceData, width, height } = volume.getSliceUint8(delta.sliceIndex, "z");
77808
+ this.state.annotationCallbacks.onMaskChanged(sliceData, layerId, channel, delta.sliceIndex, "z", width, height, false);
77809
+ }
77810
+ this.reloadMasksFromVolume();
77811
+ }
77812
+ break;
77813
+ }
77558
77814
  }
77559
77815
  }
77560
77816
  // ═══════════════════════════════════════════════════════════════════════════
@@ -78269,7 +78525,7 @@ function evaluateElement(element, weights) {
78269
78525
  }
78270
78526
 
78271
78527
  // import * as kiwrious from "copper3d_plugin_heart_k";
78272
- const REVISION = "v3.2.0-beta";
78528
+ const REVISION = "v3.2.1-beta";
78273
78529
  console.log(`%cCopper3D Visualisation %cBeta:${REVISION}`, "padding: 3px;color:white; background:#023047", "padding: 3px;color:white; background:#f50a25");
78274
78530
 
78275
- export { CHANNEL_COLORS, CHANNEL_HEX_COLORS, CameraViewPoint, Copper3dTrackballControls, MeshNodeTool, NrrdTools, REVISION, addBoxHelper, addLabelToScene, configKiwriousHeart, convert3DPostoScreenPos, convertScreenPosto3DPos, copperMScene, copperMSceneRenderer, copperRenderer, copperRendererOnDemond, copperScene, copperSceneOnDemond, createTexture2D_NRRD, fullScreenListenner, kiwrious, loading, removeGuiFolderChilden, rgbaToCss, rgbaToHex, setHDRFilePath, throttle };
78531
+ export { CHANNEL_COLORS, CHANNEL_HEX_COLORS, CameraViewPoint, Copper3dTrackballControls, GaussianSmoother, MeshNodeTool, NrrdTools, REVISION, addBoxHelper, addLabelToScene, configKiwriousHeart, convert3DPostoScreenPos, convertScreenPosto3DPos, copperMScene, copperMSceneRenderer, copperRenderer, copperRendererOnDemond, copperScene, copperSceneOnDemond, createTexture2D_NRRD, fullScreenListenner, kiwrious, loading, removeGuiFolderChilden, rgbaToCss, rgbaToHex, setHDRFilePath, throttle };