diff --git a/_posts/2025-01-25-volume-rendering.md b/_posts/2025-01-25-volume-rendering.md index d4c93d3..08599a4 100644 --- a/_posts/2025-01-25-volume-rendering.md +++ b/_posts/2025-01-25-volume-rendering.md @@ -6,6 +6,7 @@ assets: /assets/blog/volume_rendering thumbnail: /assets/blog/volume_rendering/thumbnail.png social_image: /assets/blog/volume_rendering/thumbnail.png +image_class: invertable alt: A volumetric render of a CT scan of my jaw. diff --git a/assets/js/outline-model-viewer/PointCloudViewer.js b/assets/js/outline-model-viewer/PointCloudViewer.js index d231f49..33d27fb 100644 --- a/assets/js/outline-model-viewer/PointCloudViewer.js +++ b/assets/js/outline-model-viewer/PointCloudViewer.js @@ -67,7 +67,7 @@ export class PointCloudViewer extends HTMLElement { this.onWindowResize = () => { this.camera.aspect = canvas.clientWidth / canvas.clientHeight; this.camera.updateProjectionMatrix(); - renderer.setSize(canvas.clientWidth, canvas.clientHeight); + renderer.setSize(canvas.clientWidth, canvas.clientHeight, false); }; const timer = new Timer(); diff --git a/assets/js/outline-model-viewer/VolumeViewer.js b/assets/js/outline-model-viewer/VolumeViewer.js index 05adb47..7d0f903 100644 --- a/assets/js/outline-model-viewer/VolumeViewer.js +++ b/assets/js/outline-model-viewer/VolumeViewer.js @@ -146,7 +146,8 @@ export class VolumeViewer extends HTMLElement { } connectedCallback() { - const { container, canvas, scene, renderer, gui } = setupThreeJS(this); + const { container, canvas, scene, renderer, gui, gui_buttons } = + setupThreeJS(this); const model = this.getAttribute("model"); const model_metadata = this.getAttribute("model-metadata"); @@ -215,7 +216,7 @@ export class VolumeViewer extends HTMLElement { }; // Add a button to print the current settings to the console - gui + gui_buttons .add( { printSettings: () => @@ -238,6 +239,7 @@ export class VolumeViewer extends HTMLElement { }; gui .add(renderProps, "preset", presets) + .setValue("Default") .onChange((preset) => { Object.keys(preset).forEach((key) => { if (material.uniforms[key]) { @@ -277,7 +279,7 @@ export class VolumeViewer extends HTMLElement { this.onWindowResize = () => { this.camera.aspect = canvas.clientWidth / canvas.clientHeight; this.camera.updateProjectionMatrix(); - renderer.setSize(canvas.clientWidth, canvas.clientHeight); + renderer.setSize(canvas.clientWidth, canvas.clientHeight, false); }; this.onWindowResize(); diff --git a/assets/js/outline-model-viewer/helpers.js b/assets/js/outline-model-viewer/helpers.js index cd9996f..657ed90 100644 --- a/assets/js/outline-model-viewer/helpers.js +++ b/assets/js/outline-model-viewer/helpers.js @@ -117,9 +117,10 @@ function componentHTML(component_rect) { color: var(--theme-subtle-outline); } - .lil-gui .title {height: 2em;} - .lil-gui.root { - margin-top: calc(${height}px - 2em); + .lil-gui .title {height: 2em;} + .lil-gui.root { + --height: 3em; + margin-top: calc(${height}px - var(--height)); width: 100%; z-index: 1; --background-color: none; @@ -132,6 +133,16 @@ function componentHTML(component_rect) { --number-color: #2cc9ff; --string-color: #a2db3c; } + .lil-gui.root.closed { + height: var(--height); + } + + #container.fullscreen > .lil-gui { + background-color: rgba(1,1,1, 0.5); + } + #container.fullscreen > .lil-gui.closed { + background-color: unset; + } .lil-gui div.title { margin: 0.5em; @@ -161,15 +172,32 @@ function componentHTML(component_rect) { height: 100%; z-index: 1; background: var(--theme-bg-color); - } + } #container.fullscreen canvas { + position: fixed; + top: 0; + left: 0; + width: 100%; height: 100%; } #container.fullscreen .lil-gui.root { + padding: 0.7em; margin-top: 0; - width: 50%; + } + + #container.fullscreen .lil-gui.root > div.title { + margin: 0 + } + + .common-lil-gui-buttons .children { + display: flex; + flex-wrap: wrap; + justify-content: center; + button { + padding: 0.2em; + } } `; @@ -223,9 +251,14 @@ function setupThreeJS(component) { }, }; - component.gui.add(params, "printCamera").name("Print Viewport State"); - component.gui.add(params, "screenshot").name("Take Screenshot"); - component.gui.add(params, "resetCamera").name("Reset Viewport"); + let buttons = component.gui.addFolder("Actions"); + buttons.open(); + buttons.$title.style.display = "none"; + buttons.domElement.classList.add("common-lil-gui-buttons"); + buttons.add(params, "printCamera").name("Print Viewport State"); + buttons.add(params, "screenshot").name("Take Screenshot"); + buttons.add(params, "resetCamera").name("Reset Viewport"); + component.gui_buttons = buttons; component.full_screen = false; // clone of original rect @@ -235,16 +268,21 @@ function setupThreeJS(component) { }; component.toggleFullScreen = () => { + if (!component.container.requestFullscreen) { + console.log("Fullscreen not supported"); + return; + } component.full_screen = !component.full_screen; + if (component.full_screen) { component.container.classList.add("fullscreen"); + component.container.requestFullscreen(); } else { component.container.classList.remove("fullscreen"); - component.canvas.height = component.original_rect.height; + component.canvas.style.height = component.original_rect.height + "px"; + component.canvas.style.width = component.original_rect.width + "px"; + document.exitFullscreen(); } - component.canvas.removeAttribute("style"); - component.canvas.removeAttribute("width"); - component.canvas.removeAttribute("height"); component.onWindowResize(); };