From faa2a7c84665608f83438e152920f44d57571fcf Mon Sep 17 00:00:00 2001 From: Tom Date: Wed, 29 Jan 2025 18:04:34 +0000 Subject: [PATCH] update volume viewer --- _posts/2025-01-25-volume-rendering.md | 2 + .../after_quantisation_hist.svg | 538 ++++----- assets/blog/volume_rendering/hist.svg | 1026 ++++++++--------- .../blog/volume_rendering/volume_scan.data.gz | Bin 14171171 -> 14171171 bytes .../js/outline-model-viewer/VolumeShaders.js | 48 +- .../js/outline-model-viewer/VolumeViewer.js | 159 ++- assets/js/outline-model-viewer/helpers.js | 2 +- 7 files changed, 949 insertions(+), 826 deletions(-) diff --git a/_posts/2025-01-25-volume-rendering.md b/_posts/2025-01-25-volume-rendering.md index f834cb6..988d825 100644 --- a/_posts/2025-01-25-volume-rendering.md +++ b/_posts/2025-01-25-volume-rendering.md @@ -161,6 +161,8 @@ f.savefig("hist.svg") We could probably get away with clamping all the data from -1000 to -500 to one air value, which would free up a lot of our limited 0-225 for the more interesting stuff happening between -100 and 400. But I didn't really notice an issues with the quantisation so I didn't pursue this. +EDIT: After I implemented the iso-surface rendering mode and found that I could see interesting regions like my windpipe and inside my sinuses I wondered if having more density precision would help see them. So I using float16 or float32 textures but didn't see much improvement at the expense of doubling or quadrupling the file size, so I switched back to 8 bit values. + ## Viewing the Data For the viewer I mostly copied the code from [this excellent tutorial](https://observablehq.com/@mroehlig/3d-volume-rendering-with-webgl-three-js) and integrated it into my existing three.js helper methods. diff --git a/assets/blog/volume_rendering/after_quantisation_hist.svg b/assets/blog/volume_rendering/after_quantisation_hist.svg index fb63887..ff88f64 100644 --- a/assets/blog/volume_rendering/after_quantisation_hist.svg +++ b/assets/blog/volume_rendering/after_quantisation_hist.svg @@ -6,7 +6,7 @@ - 2025-01-26T14:41:38.494634 + 2025-01-29T13:46:28.639668 image/svg+xml @@ -45,7 +45,7 @@ L 37.148617 58.309559 L 37.148617 -83.935628 L 33.64 -83.935628 z -" clip-path="url(#p925f2d3785)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> +" clip-path="url(#pcdbbce7f8b)" style="fill: #1f77b4"/> - - + @@ -2208,7 +2208,7 @@ z - + @@ -2251,7 +2251,7 @@ z - + @@ -2340,7 +2340,7 @@ z - + @@ -2402,7 +2402,7 @@ z - + @@ -2567,7 +2567,7 @@ z - + @@ -2659,7 +2659,7 @@ z - + @@ -2708,12 +2708,12 @@ z - - + @@ -2726,7 +2726,7 @@ L -3.5 0 - + @@ -2826,7 +2826,7 @@ L 415.449081 21.72 - + diff --git a/assets/blog/volume_rendering/hist.svg b/assets/blog/volume_rendering/hist.svg index 6d7873a..7008f4a 100644 --- a/assets/blog/volume_rendering/hist.svg +++ b/assets/blog/volume_rendering/hist.svg @@ -6,7 +6,7 @@ - 2025-01-26T14:36:53.335495 + 2025-01-29T12:39:50.203168 image/svg+xml @@ -45,7 +45,7 @@ L 31.971137 58.309559 L 31.971137 -429.388434 L 30.158344 -429.388434 z -" clip-path="url(#pad778b0742)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> +" clip-path="url(#p5fdbfa6ad6)" style="fill: #1f77b4"/> - - + @@ -4160,7 +4160,7 @@ z - + @@ -4203,7 +4203,7 @@ z - + @@ -4292,7 +4292,7 @@ z - + @@ -4354,7 +4354,7 @@ z - + @@ -4519,7 +4519,7 @@ z - + @@ -4611,7 +4611,7 @@ z - + @@ -4660,12 +4660,12 @@ z - - + @@ -4689,7 +4689,7 @@ z - + @@ -4791,7 +4791,7 @@ L 415.449081 21.72 - + diff --git a/assets/blog/volume_rendering/volume_scan.data.gz b/assets/blog/volume_rendering/volume_scan.data.gz index 4728460d8c13953b206572e949b8ec25d77a40fc..4d9a693c27c2c7d97809ab797e8e04f2af91bce8 100644 GIT binary patch delta 668 zcmWN_S3?c}06u|>{KL3N=hjSmeLX;#ThDLQbx*3IVmp{BwQ*=C8;b`Btoi6HK{H& zq^8u8+7c;sBub*CuGEwI(m)zYBWWy6q^UHM<`N?lSlFhP3Qe~@blkKAHke#wicFP_~lfAM}_R9e|DCu%Y4oik)$`Ls#S#nIW z<+z-XlX6OOMVx*BYmL}3vnn`nMAuT0VT1jhZBWu6tCdcK3 clampMax ? 0. : value; - - // Keep track of the maximum value. - if (value > density) { - // Store the value if it is greater than the previous values. - density = value; + if (value > max_density) { + max_density = value; + } + if (value < min_density && value > 0.0) { + min_density = value; + } + if (value > 0.0) { + mean_density += value; + mean_samples += 1; + } + if (abs(value - iso_threshold) < iso_width && iso_depth == 0.0) { + iso_depth = 1.; } - // Early exit the loop when the maximum possible value is found or the exit point is reached. - if (density >= 1.0 || t > tEnd) { + // Early exit if the exit point is reached. + if (t > tEnd) { break; } } + // Compute the final density value based on the selected rendering mode. + mean_density = mean_samples > 0 ? mean_density / float(mean_samples) : 0.0; + float density = 0.0; + if (renderMode == 0) { + density = max_density; + } else if (renderMode == 1) { + density = mean_density; + } else if (renderMode == 2) { + density = min_density; + } else if (renderMode == 3) { + density = iso_depth; + } + // Convert the found value to a color by sampling the color palette texture. color.rgb = sampleColor(density).rgb; // Modify the alpha value of the color to make lower values more transparent. diff --git a/assets/js/outline-model-viewer/VolumeViewer.js b/assets/js/outline-model-viewer/VolumeViewer.js index d241f2e..05adb47 100644 --- a/assets/js/outline-model-viewer/VolumeViewer.js +++ b/assets/js/outline-model-viewer/VolumeViewer.js @@ -11,56 +11,81 @@ import { deserialiseControls, } from "./helpers.js"; +// See https://stackoverflow.com/questions/62003464/what-is-relation-between-type-and-format-of-texture +// https://webgl2fundamentals.org/webgl/lessons/webgl-data-textures.html +const dtypes = { + uint8: { + internalFormat: "R8", + format: THREE.RedFormat, + type: THREE.UnsignedByteType, + array_type: Uint8Array, + }, + float16: { + internalFormat: "R16F", + format: THREE.RedFormat, + type: THREE.HalfFloatType, + array_type: Uint16Array, + }, + float32: { + internalFormat: "R32F", + format: THREE.RedFormat, + type: THREE.FloatType, + array_type: Float32Array, + }, +}; + async function load_metadata(metadata_path) { console.log("Loading metadata from", metadata_path); const metadata_res = await fetch(metadata_path); return await metadata_res.json(); } -async function load_model_bytes(model_path) { - console.log("Loading model from", model_path); - const res = await fetch(model_path); - const buffer = await res.arrayBuffer(); - return new Uint8Array(buffer); // Create an uint8-array-view from the file buffer. -} - -async function load_model_bytes_gzip(model_path, metadata_path, scene) { +async function load_model_compressed_bytes(model_path) { + const model_response = await fetch(model_path); const ds = new DecompressionStream("gzip"); - const response = await fetch(model_path); - const blob_in = await response.blob(); + const blob_in = await model_response.blob(); console.log("Compressed Model size", blob_in.size); const stream_in = blob_in.stream().pipeThrough(ds); const buffer = await new Response(stream_in).arrayBuffer(); console.log("Decompressed Model size", buffer.byteLength); - return new Uint8Array(buffer); + return buffer; +} + +async function load_model_bytes_gzip(model_path, metadata_path) { + const [metadata, model_buffer] = await Promise.all([ + load_metadata(metadata_path), + load_model_compressed_bytes(model_path), + ]); + + const array_type = dtypes[metadata.dtype].array_type; + return [metadata, new array_type(model_buffer)]; } async function load_model(model_path, metadata_path, scene) { // If the model path ends in ".gz", we assume that the model is compressed. - const model_promise = model_path.endsWith(".gz") - ? load_model_bytes_gzip(model_path, metadata_path, scene) - : load_model_bytes(model_path); - - const [byteArray, metadata] = await Promise.all([ - model_promise, - load_metadata(metadata_path), - ]); + const [metadata, model_data] = await load_model_bytes_gzip( + model_path, + metadata_path + ); console.log("Loaded model with metadata", metadata); console.log("Model shape", metadata.shape); console.log("Model dtype", metadata.dtype); const texture = new THREE.Data3DTexture( - byteArray, // The data values stored in the pixels of the texture. + model_data, // The data values stored in the pixels of the texture. metadata.shape[2], // Width of texture. metadata.shape[1], // Height of texture. metadata.shape[0] // Depth of texture. ); + texture.internalFormat = dtypes[metadata.dtype].internalFormat; + texture.format = dtypes[metadata.dtype].format; + texture.type = dtypes[metadata.dtype].type; - texture.format = THREE.RedFormat; // Our texture has only one channel (red). - texture.type = THREE.UnsignedByteType; // The data type is 8 bit unsighed integer. texture.minFilter = THREE.LinearFilter; // Linear filter for minification. texture.magFilter = THREE.LinearFilter; // Linear filter for maximization. + // texture.minFilter = THREE.NearestFilter; // Nearest filter for minification. + // texture.magFilter = THREE.NearestFilter; // Nearest filter for maximization. // Repeat edge values when sampling outside of texture boundaries. texture.wrapS = THREE.ClampToEdgeWrapping; @@ -93,13 +118,16 @@ function volumeMaterial(texture, renderProps) { uniforms: { dataTexture: { value: texture }, // Volume data texture. // colorTexture: { value: colorTexture }, // Color palette texture. + renderMode: { value: renderProps.renderMode }, // Rendering mode. cameraPosition: { value: new THREE.Vector3() }, // Current camera position. samplingRate: { value: renderProps.samplingRate }, // Sampling rate of the volume. clampMin: { value: renderProps.clampMin }, // Clamp values below this value to 0. clampMax: { value: renderProps.clampMax }, // Clamp values above this value to 1. - threshold: { value: renderProps.threshold }, // Threshold for adjusting volume rendering. + iso_threshold: { value: renderProps.iso_threshold }, // Threshold for adjusting volume rendering. + iso_width: { value: renderProps.iso_width }, // Threshold for adjusting volume rendering. + alphaScale: { value: renderProps.alphaScale }, // Alpha scale of volume rendering. invertColor: { value: renderProps.invertColor }, // Invert color palette. }, @@ -127,11 +155,21 @@ export class VolumeViewer extends HTMLElement { const box = make_box(); scene.add(box); + const renderModes = { + "Max Intensity": 0, + "Mean Intensity": 1, + "Min Intensity": 2, + Isosurface: 3, + }; + let material = null; load_model(model, model_metadata, scene).then(({ texture, metadata }) => { // Create the custom material with attached shaders. - material = volumeMaterial(texture, renderProps); + material = volumeMaterial(texture, presets.Default); box.material = material; + gui + .add(material.uniforms.renderMode, "value", renderModes) + .name("Render Mode"); gui .add(material.uniforms.samplingRate, "value", 0.1, 2.0, 0.1) .name("Sampling Rate"); @@ -142,23 +180,76 @@ export class VolumeViewer extends HTMLElement { .add(material.uniforms.clampMax, "value", 0.0, 1.0, 0.01) .name("Clamp Max"); gui - .add(material.uniforms.threshold, "value", 0.0, 1.0, 0.01) - .name("Threshold"); + .add(material.uniforms.iso_threshold, "value", 0.0, 1.0, 0.01) + .name("Isosurface Threshold"); + gui + .add(material.uniforms.iso_width, "value", 0.0, 0.05, 0.001) + .name("Isosurface Width"); gui .add(material.uniforms.alphaScale, "value", 0.1, 2.0, 0.1) .name("Alpha Scale"); gui.add(material.uniforms.invertColor, "value").name("Invert Color"); }); - const renderProps = { - samplingRate: 1.0, - clampMin: 0.0, - clampMax: 1.0, - threshold: 0.1, - alphaScale: 1.0, - invertColor: false, + const presets = { + Default: { + renderMode: 0, + samplingRate: 1.0, + clampMin: 0.0, + clampMax: 1.0, + iso_threshold: 0.1, + iso_width: 0.01, + alphaScale: 1.0, + invertColor: false, + }, + "Air Pockets": { + alphaScale: 2, + clampMax: 1, + clampMin: 0, + invertColor: false, + iso_threshold: 0.06, + iso_width: 0.002, + renderMode: 3, + samplingRate: 1, + }, }; + // Add a button to print the current settings to the console + gui + .add( + { + printSettings: () => + console.log( + Object.fromEntries( + Object.keys(presets.Default).map((key) => [ + key, + material?.uniforms[key]?.value, + ]) + ) + ), + }, + "printSettings" + ) + .name("Print Current Settings"); + + // Add a dropdown to select a preset + let renderProps = { + presets: "Default", + }; + gui + .add(renderProps, "preset", presets) + .onChange((preset) => { + Object.keys(preset).forEach((key) => { + if (material.uniforms[key]) { + material.uniforms[key].value = preset[key]; + } else { + console.warn(`No uniform found for ${key}`); + } + }); + gui.controllers.forEach((control) => control.updateDisplay()); + }) + .name("Presets"); + const render = () => renderer.render(scene, this.camera); this.render = render; @@ -188,6 +279,8 @@ export class VolumeViewer extends HTMLElement { this.camera.updateProjectionMatrix(); renderer.setSize(canvas.clientWidth, canvas.clientHeight); }; + this.onWindowResize(); + const timer = new Timer(); const update = () => { diff --git a/assets/js/outline-model-viewer/helpers.js b/assets/js/outline-model-viewer/helpers.js index bcabdd2..cd9996f 100644 --- a/assets/js/outline-model-viewer/helpers.js +++ b/assets/js/outline-model-viewer/helpers.js @@ -169,7 +169,7 @@ function componentHTML(component_rect) { #container.fullscreen .lil-gui.root { margin-top: 0; - width: 200px; + width: 50%; } `;