Skip to content

Commit

Permalink
feat: incremental volume loading
Browse files Browse the repository at this point in the history
  • Loading branch information
floryst committed Jun 18, 2024
1 parent 151da34 commit 6f27ecc
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 30 deletions.
27 changes: 25 additions & 2 deletions src/components/vtk/VtkBaseVolumeRepresentation.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { toRefs, computed, inject, watchEffect } from 'vue';
import { toRefs, computed, inject, watchEffect, watch, shallowRef } from 'vue';
import { useImage } from '@/src/composables/useCurrentImage';
import { useVolumeRepresentation } from '@/src/core/vtk/useVolumeRepresentation';
import { Maybe } from '@/src/types';
Expand Down Expand Up @@ -27,6 +27,8 @@ import type { vtkObject } from '@kitware/vtk.js/interfaces';
import { onVTKEvent } from '@/src/composables/onVTKEvent';
import { useCroppingEffect } from '@/src/composables/useCroppingEffect';
import { useCropStore } from '@/src/store/tools/crop';
import { useEventListener } from '@vueuse/core';
import { type ChunkLoadedInfo } from '@/src/core/streaming/chunkImage';
interface Props {
viewId: string;
Expand All @@ -43,6 +45,7 @@ const {
imageData,
metadata: imageMetadata,
isLoading: isImageStreaming,
chunkImage,
} = useImage(imageID);
const coloringConfig = computed(() =>
useVolumeColoringStore().getConfig(viewID.value, imageID.value)
Expand All @@ -65,6 +68,21 @@ rep.property.setSpecular(DEFAULT_SPECULAR);
onVTKEvent(obj, 'onModified', view.requestRender);
});
// watch for updated extents
const updatedExtents = shallowRef<Array<ChunkLoadedInfo['updatedExtent']>>([]);
useEventListener(chunkImage, 'chunkLoaded', (info: ChunkLoadedInfo) => {
updatedExtents.value = [...updatedExtents.value, info.updatedExtent];
});
watch(updatedExtents, (current, old) => {
const startOffset = old.length;
rep.mapper.setUpdatedExtents([
...rep.mapper.getUpdatedExtents(),
...current.slice(startOffset),
]);
view.requestRender();
});
// cinematic volume rendering
const cvrParams = computed(() => coloringConfig.value?.cvr);
const center = computed(() =>
Expand Down Expand Up @@ -124,7 +142,6 @@ watchEffect(() => {
image,
mapper,
quality: volumeQuality,
isAnimating: isAnimating.value,
});
setCinematicLocalAmbientOcclusion({
Expand All @@ -134,6 +151,12 @@ watchEffect(() => {
mapper,
});
if (isImageStreaming.value) {
// reduce the quality of the volume until the entire volume is loaded
const sampleDistance = mapper.getSampleDistance();
mapper.setSampleDistance(sampleDistance * 15);
}
view.requestRender();
});
Expand Down
47 changes: 19 additions & 28 deletions src/utils/volumeProperties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,44 +106,35 @@ export interface SetCinematicVolumeSamplingParameters {
enabled: boolean;
mapper: vtkVolumeMapper;
quality: number;
isAnimating: boolean;
image: vtkImageData;
}

export function setCinematicVolumeSampling({
enabled,
mapper,
quality,
isAnimating,
image,
}: SetCinematicVolumeSamplingParameters) {
if (isAnimating) {
mapper.setSampleDistance(0.75);
mapper.setMaximumSamplesPerRay(1000);
mapper.setGlobalIlluminationReach(0);
mapper.setComputeNormalFromOpacity(false);
} else {
const dims = image.getDimensions();
const spacing = image.getSpacing();
const spatialDiagonal = vec3.length(
vec3.fromValues(
dims[0] * spacing[0],
dims[1] * spacing[1],
dims[2] * spacing[2]
)
);
const dims = image.getDimensions();
const spacing = image.getSpacing();
const spatialDiagonal = vec3.length(
vec3.fromValues(
dims[0] * spacing[0],
dims[1] * spacing[1],
dims[2] * spacing[2]
)
);

// Use the average spacing for sampling by default
let sampleDistance = spacing.reduce((a, b) => a + b) / 3.0;
// Adjust the volume sampling by the quality slider value
sampleDistance /= quality > 1 ? 0.5 * quality ** 2 : 1.0;
const samplesPerRay = spatialDiagonal / sampleDistance + 1;
mapper.setMaximumSamplesPerRay(samplesPerRay);
mapper.setSampleDistance(sampleDistance);
// Adjust the global illumination reach by volume quality slider
mapper.setGlobalIlluminationReach(enabled ? 0.25 * quality : 0);
mapper.setComputeNormalFromOpacity(!enabled && quality > 2);
}
// Use the average spacing for sampling by default
let sampleDistance = spacing.reduce((a, b) => a + b) / 3.0;
// Adjust the volume sampling by the quality slider value
sampleDistance /= quality > 1 ? 0.5 * quality ** 2 : 1.0;
const samplesPerRay = spatialDiagonal / sampleDistance + 1;
mapper.setMaximumSamplesPerRay(samplesPerRay);
mapper.setSampleDistance(sampleDistance);
// Adjust the global illumination reach by volume quality slider
mapper.setGlobalIlluminationReach(enabled ? 0.25 * quality : 0);
mapper.setComputeNormalFromOpacity(!enabled && quality > 2);
}

export interface SetCinematicVolumeShadingParameters {
Expand Down

0 comments on commit 6f27ecc

Please sign in to comment.