### Quick Start: Basic Volume Rendering Setup Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/MTKCore.md Demonstrates the essential steps to set up basic volume rendering using MTKCore. It includes enforcing Metal runtime availability, creating a Metal device, preparing volume data, configuring the renderer for medical CT visualization, and rendering a frame. ```swift import MTKCore import Metal do { try MetalRuntimeAvailability.ensureAvailability() } catch { let status = MetalRuntimeAvailability.status() print("Metal runtime unsupported: \(status.missingFeatures)") throw error } // Create Metal device. guard let device = MTLCreateSystemDefaultDevice() else { throw MetalVolumeRenderingAdapter.InitializationError.metalDeviceUnavailable } // Create volume dataset from your voxel data let voxelCount = 256 * 256 * 128 let voxels = Data(repeating: 0, count: voxelCount * VolumePixelFormat.int16Signed.bytesPerVoxel) let dataset = VolumeDataset( data: voxels, dimensions: VolumeDimensions(width: 256, height: 256, depth: 128), spacing: VolumeSpacing(x: 1.0, y: 1.0, z: 1.5), pixelFormat: .int16Signed, intensityRange: (-1024)...3071 ) // Create rendering adapter let renderer = try MetalVolumeRenderingAdapter(device: device) // Configure for medical CT visualization try await renderer.setHuWindow(min: -500, max: 1200) try await renderer.setPreset(.softTissue) let request = VolumeRenderRequest( dataset: dataset, transferFunction: VolumeTransferFunction.defaultGrayscale(for: dataset), viewportSize: CGSize(width: 512, height: 512), camera: VolumeRenderRequest.Camera( position: SIMD3(0.5, 0.5, 2), target: SIMD3(0.5, 0.5, 0.5), up: SIMD3(0, 1, 0), fieldOfView: 45 ), samplingDistance: 0.002, compositing: .frontToBack, quality: .interactive ) let frame = try await renderer.renderFrame(using: request) let texture = frame.texture ``` -------------------------------- ### SwiftUI Volume Rendering Quick Start Source: https://github.com/thalesmms/mtk/blob/main/README.md A minimal SwiftUI view for applying and displaying a volume dataset using MTKCore. It demonstrates applying a dataset, setting window level, and applying a transfer function. ```swift import MTKCore import MTKUI import SwiftUI struct VolumePreview: View { @StateObject private var viewport = try! VolumeViewport3D() var body: some View { MetalViewportView(surface: viewport.surface) .task { let voxelCount = 256 * 256 * 128 let voxels = Data(repeating: 0, count: voxelCount * VolumePixelFormat.int16Signed.bytesPerVoxel) let dataset = VolumeDataset( data: voxels, dimensions: VolumeDimensions(width: 256, height: 256, depth: 128), spacing: VolumeSpacing(x: 1.0, y: 1.0, z: 1.5), pixelFormat: .int16Signed, intensityRange: (-1024)...3071 ) await viewport.applyDataset(dataset) await viewport.setWindowLevel(window: 1700, level: 350) try? await viewport.applyClinicalTransferFunctionPreset(.ctSoftTissue) } } } ``` -------------------------------- ### Clinical Viewport Grid Setup Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKUI/MTKUI.docc/MTKUI.md Sets up a clinical viewport session and displays it using ClinicalViewportGrid. Ensure you have a valid dataset available. ```swift import SwiftUI import MTKUI struct ClinicalGridView: View { @State private var session: ClinicalViewportSession? var body: some View { Group { if let session { ClinicalViewportGrid(session: session) } } .task { session = try? await ClinicalViewportSession.make(dataset: myDataset) } } } ``` -------------------------------- ### Initialize MetalMPRAdapter and Generate Slab Texture Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/MPRGuide.md Initializes the MetalMPRAdapter, generates a volume texture, and then creates an MPR slab texture. Handles potential Metal device unavailability and various Metal setup or rendering failures. ```swift guard let device = MTLCreateSystemDefaultDevice() else { // Present an explicit unsupported-runtime state. return } do { let adapter = try MetalMPRAdapter(device: device) let factory = VolumeTextureFactory(dataset: dataset) guard let volumeTexture = factory.generate(device: device) else { throw VolumeTextureFactory.TextureUploadError.textureCreationFailed } let frame = try await adapter.makeSlabTexture( dataset: dataset, volumeTexture: volumeTexture, plane: plane, thickness: 5, steps: 10, blend: .average ) print(frame.texture) } catch { // Present the Metal setup or rendering failure to the caller. throw error } ``` -------------------------------- ### Setup Direct Volume Rendering with Lighting Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/VolumeRenderingGuide.md This Swift code snippet shows how to set up the MetalVolumeRenderingAdapter for Direct Volume Rendering with lighting enabled. It configures the rendering mode, lighting, a soft tissue transfer function, and window/level settings for CT data. ```swift import MTKCore // Setup DVR with lighting enabled let adapter = try MetalVolumeRenderingAdapter() try await adapter.setRenderingMode(.directVolumeRendering) try await adapter.setLightingEnabled(true) // Apply soft tissue transfer function try await adapter.setPreset(.softTissue) // Set window/level for abdomen CT try await adapter.setHuWindow(min: -150, max: 250) ``` -------------------------------- ### Add MTKCore and MTKUI via Swift Package Manager Source: https://github.com/thalesmms/mtk/blob/main/README.md Integrate MTKCore and MTKUI into your application by adding the MTK Git repository as a package dependency. This snippet shows the basic setup for Xcode or SwiftPM. ```swift .package(url: "https://github.com/ThalesMMS/MTK.git", exact: "1.2.1"), .target( name: "YourApp", dependencies: [ .product(name: "MTKCore", package: "MTK"), .product(name: "MTKUI", package: "MTK") ] ) ``` -------------------------------- ### Programmatic Window/Level Adjustment for CT Visualization Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/TransferFunctionsGuide.md Provides examples of programmatically setting window/level ranges for common CT visualization scenarios like abdomen, lung, and bone imaging. ```swift // Abdomen CT visualization try await adapter.setHuWindow(min: -150, max: 250) // Lung window (emphasize air-tissue interface) try await adapter.setHuWindow(min: -1000, max: 200) // Bone window (suppress soft tissue) try await adapter.setHuWindow(min: -200, max: 1800) ``` -------------------------------- ### Send Blend Mode Command Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/MPRGuide.md Sends a command to change the blend mode for subsequent slab texture generation. This example sets the blend mode to minimum intensity projection. ```swift // Change blend mode for next slab try await adapter.send(.setBlend(.minimum)) ``` -------------------------------- ### Setup Average Intensity Projection (AIP) Rendering Mode Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/VolumeRenderingGuide.md This Swift code configures the rendering adapter to use the Average Intensity Projection mode. It also demonstrates how to set the HU gate for intensity filtering, or disable it to average all intensities. ```swift // Setup AIP for noise reduction try await adapter.setRenderingMode(.averageIntensityProjection) // No gating (average all intensities) try await adapter.setHuGate(min: -1024, max: 3071, enabled: false) ``` -------------------------------- ### Segmentation Surface Path Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/VolumeRenderingGuide.md Illustrates the data flow for rendering segmentation surfaces, starting from a LabelmapVolume and ending in a 3D viewport. ```text LabelmapVolume -> SurfaceMesh -> SurfaceMeshLayer -> volume3D viewport ``` -------------------------------- ### Apply Histogram-Driven Auto-Window Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/TransferFunctionsGuide.md Demonstrates loading a histogram from a volume and applying an auto-window preset to the tone curve. ```swift // Load histogram from volume let histogram = try await renderer.refreshHistogram( for: dataset, descriptor: VolumeHistogramDescriptor(binCount: 256, intensityRange: dataset.intensityRange), transferFunction: transferFunction ) toneCurve.setHistogram(histogram.bins) // Apply auto-window preset toneCurve.applyAutoWindow(.abdomen) ``` -------------------------------- ### Generate Project Documentation Source: https://github.com/thalesmms/mtk/blob/main/README.md Builds DocC documentation archives locally. These archives can be opened in Xcode or hosted as static HTML. ```bash bash Tooling/build_docs.sh ``` -------------------------------- ### Create and Edit Tone Curves Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/TransferFunctionsGuide.md Demonstrates how to create a default S-curve, insert, update, and remove control points, and generate sampled values for GPU upload. ```swift import MTKCore // Create tone curve with default S-curve let toneCurve = AdvancedToneCurveModel() // Get default control points (6-point S-curve) let defaultPoints = toneCurve.currentControlPoints() // [(0, 0), (32, 0.05), (96, 0.3), (160, 0.7), (224, 0.95), (255, 1)] // Insert custom control point toneCurve.insertPoint(AdvancedToneCurvePoint(x: 100, y: 0.5)) // Update existing point toneCurve.updatePoint(at: 2, to: AdvancedToneCurvePoint(x: 96, y: 0.4)) // Remove interior point (cannot remove endpoints) toneCurve.removePoint(at: 3) // Generate sampled values for GPU upload let samples = toneCurve.sampledValues() // 2551 samples (255 × 10 + 1) ``` -------------------------------- ### Apply Standard Window/Level Preset Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/TransferFunctionsGuide.md Shows how to retrieve and apply a clinically validated window/level preset, such as 'Soft Tissues', to a renderer using MTKCore. ```swift import MTKCore // CT soft tissue window (W:400, L:40) let softTissue = WindowLevelPresetLibrary.ct.first { $0.name == "Soft Tissues" }! let minHU = softTissue.minValue // -160 HU let maxHU = softTissue.maxValue // 240 HU // Apply to renderer try await renderer.setHuWindow(min: Int32(minHU), max: Int32(maxHU)) ``` -------------------------------- ### Public Viewports Source: https://github.com/thalesmms/mtk/blob/main/Architecture/PublicAPI.md Recommended UI entry points for creating volume-backed stack viewports, MPR viewports, and 3D volume viewports. ```APIDOC ## Public Viewports ### Description These are the recommended UI entry points. They let external apps create a volume-backed stack viewport, an MPR viewport, a 3D volume viewport, the reference 2x2 clinical layout, and drawable-backed `MTKView`/`CAMetalLayer` presentation. Applications should route normal viewer workflows through these wrappers instead of instantiating internal rendering components directly. ### Types - `StackViewport` - `VolumeViewport` - `VolumeViewport3D` - `ClinicalViewportSession` - `ClinicalViewportGrid(session:)` - `MedicalViewport` - `MedicalViewportState` - `MedicalViewportType` - `MedicalViewportRenderMode` - `MedicalViewportDatasetSummary` - `MedicalViewportSliceState` - `MedicalViewportPresentationState` - `MetalViewportSurface` - `MetalViewportView` - `ViewportPresenting` ``` -------------------------------- ### Build and Analyze a Volume Pipeline Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/VolumePipelineGuide.md Constructs a volume pipeline with a dataset source, crop and threshold filters, and a default mapper. It then analyzes the pipeline to compute a histogram and prepares the mapped volume for display in a viewport. ```swift import MTKCore import MTKUI import simd let pipeline = VolumePipeline( source: VolumeDatasetSource(dataset), filters: [ try VolumeCropFilter(inclusiveVoxelMin: SIMD3(1, 1, 0), inclusiveVoxelMax: SIMD3(4, 4, 2)), VolumeThresholdFilter(range: -200...1200, replacementValue: -1024) ], mapper: DefaultVolumeMapper() ) let histogram = try await pipeline.analyze( VolumeHistogramFilter(descriptor: .init(binCount: 256, intensityRange: -1024...3071, normalize: false)) ) let mapped = try await pipeline.mappedVolume() await viewport.applyDataset(mapped.dataset) try await viewport.setTransferFunction(mapped.transferFunction) ``` -------------------------------- ### MTK v1 Multi-Volume Contract Overview Source: https://github.com/thalesmms/mtk/blob/main/Architecture/MultiVolumeRegistration.md Illustrates the current MTK v1 workflow for scalar layer fusion, involving optional CPU resampling before per-layer raycasting and 2D compositing. ```text base VolumeDataset + [registered scalar VolumeLayer] -> optional CPU resample -> per-layer raycast -> 2D composite ``` -------------------------------- ### Combine Window/Level with Tone Curves Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/TransferFunctionsGuide.md Applies a coarse window/level range first, then refines visualization with an auto-windowed tone curve, and allows for further manual customization of control points. ```swift // 1. Set coarse window range try await adapter.setHuWindow(min: -500, max: 1200) // 2. Apply fine-grained tone curve within that range let toneCurve = AdvancedToneCurveModel() toneCurve.setHistogram(histogram) toneCurve.applyAutoWindow(.abdomen) // 3. Further customize control points toneCurve.insertPoint(AdvancedToneCurvePoint(x: 120, y: 0.6)) // 4. Upload to GPU let samples = toneCurve.sampledValues() // Apply samples to shader (implementation-specific) ``` -------------------------------- ### Swift Code for Setting Up MinIP Rendering Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/VolumeRenderingGuide.md Configure MTKCore for Minimum Intensity Projection, setting the rendering mode and HU window for airway visualization. ```swift // Setup MinIP for airway visualization try await adapter.setRenderingMode(.minimumIntensityProjection) // Window to air/lung tissue range try await adapter.setHuWindow(min: -1000, max: -400) ``` -------------------------------- ### Bone Survey Workflow Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/TransferFunctionsGuide.md Configures visualization for bone structures using the bone preset, MIP rendering, and a specific window/level setting for bone density. ```swift // 1. Apply bone preset try await adapter.setPreset(.ctBone) // 2. Use MIP for skeletal overview try await adapter.setRenderingMode(.maximumIntensityProjection) // 3. Set bone window (W:2000, L:300) try await adapter.setHuWindow(min: -700, max: 1300) // 4. Disable transfer function for grayscale intensity try await adapter.setTransferFunctionEnabled(false) ``` -------------------------------- ### 3D Volume Rendering with VolumeViewport3D Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKUI/MTKUI.docc/MTKUI.md Illustrates setting up a VolumeViewport3D for 3D volume rendering. It applies a dataset and configures the rendering method and preset for visualization. ```swift import SwiftUI import MTKUI import MTKCore struct Volume3DView: View { @StateObject private var viewport = try! VolumeViewport3D() var body: some View { MetalViewportView(surface: viewport.surface) .task { await viewport.applyDataset(myDataset) await viewport.setRenderMethod(.dvr) await viewport.setPreset(.ctSoftTissue) } } } ``` -------------------------------- ### MPR or Projection Viewport with MetalViewportView Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKUI/MTKUI.docc/MTKUI.md Shows how to set up a VolumeViewport for MPR or projection rendering. It applies a dataset, sets a slice position, and can switch between MIP projection and MPR modes. ```swift import SwiftUI import MTKUI import MTKCore struct MPRViewportView: View { @StateObject private var viewport = try! VolumeViewport(axis: .coronal) var body: some View { MetalViewportView(surface: viewport.surface) .task { await viewport.applyDataset(myDataset) await viewport.setSlicePosition(0.5) await viewport.setProjectionMode(.mip) // pass nil to return to MPR } } } ``` -------------------------------- ### Generate Slab with Overridden Parameters Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/MPRGuide.md Generates a slab texture using parameters that were previously overridden via the setSlab command. The actual thickness and steps used are 15 and 30, respectively. ```swift // Next makeSlabTexture call uses overridden parameters let thickSlab = try await adapter.makeSlabTexture( dataset: dataset, volumeTexture: volumeTexture, plane: plane, thickness: 5, // Overridden to 15 steps: 10, // Overridden to 30 blend: .maximum ) // Overrides are cleared after makeSlabTexture returns ``` -------------------------------- ### Basic MPRView with MPRGridComposer Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/MPRGuide.md Sets up a SwiftUI view using MPRGridComposer to display synchronized MPR views. Loads a dataset using DicomVolumeDatasetImporter and applies it to multiple viewport controllers. ```swift import MTKCore import MTKDicomBridge import MTKUI import SwiftUI struct MPRView: View { @StateObject private var volumeController = VolumeViewportController() @StateObject private var axialController = VolumeViewportController() @StateObject private var coronalController = VolumeViewportController() @StateObject private var sagittalController = VolumeViewportController() var body: some View { MPRGridComposer( volumeController: volumeController, axialController: axialController, coronalController: coronalController, sagittalController: sagittalController ) .task { // Load a renderer-ready dataset. Import MTKDicomBridge when using DICOM-Decoder. let importer = DicomVolumeDatasetImporter() let dataset = try await importDataset(from: dicomDirectory, using: importer) // Apply dataset to all controllers await volumeController.loadDataset(dataset) await axialController.loadDataset(dataset) await coronalController.loadDataset(dataset) await sagittalController.loadDataset(dataset) } } } ``` -------------------------------- ### Shader-level ZSKIP Heuristic Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/VolumeRenderingGuide.md This Metal shader snippet demonstrates the ZSKIP heuristic, which skips consecutive transparent samples during ray marching to optimize performance. It's active in DVR mode and helps reduce computation in low-density regions. ```metal // Metal shader snippet from direct_volume_rendering if (src.a < 0.001f) { zeroCount++; if (zeroCount >= ZRUN) { iStep += ZSKIP; // Skip multiple transparent samples zeroCount = 0; continue; } } ``` -------------------------------- ### Convert Window/Level to Min/Max Intensity Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/TransferFunctionsGuide.md Demonstrates the conversion of standard window/level parameters to minimum and maximum intensity values for display range. ```swift let minHU = level - (window / 2.0) let maxHU = level + (window / 2.0) ``` -------------------------------- ### Apply Otsu Threshold Auto-Window Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/TransferFunctionsGuide.md Applies the Otsu auto-window preset, which uses Otsu's method to find an optimal threshold for separating foreground and background. ```swift // Apply Otsu auto-window toneCurve.applyAutoWindow(.otsu) ``` -------------------------------- ### Create and Apply Custom Auto-Window Preset Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/TransferFunctionsGuide.md Defines a custom auto-window preset for 'Chest CT' with specific percentile and smoothing parameters, then applies it to the tone curve. ```swift // Create custom preset let customPreset = ToneCurveAutoWindowPreset( id: "custom.chest", title: "Chest CT", lowerPercentile: 0.05, upperPercentile: 0.95, smoothingRadius: 4 ) toneCurve.applyAutoWindow(customPreset) ``` -------------------------------- ### Check Metal Runtime Availability and Create Viewport Source: https://github.com/thalesmms/mtk/blob/main/README.md Ensures Metal rendering is available and retrieves its status, including Metal Performance Shaders support. It then attempts to create a 3D volume viewport. This is crucial for initializing Metal-based rendering components. ```swift func makeVolumeViewport() throws -> VolumeViewport3D { try MetalRuntimeAvailability.ensureAvailability() let status = MetalRuntimeAvailability.status() print("MPS available: \(status.supportsMetalPerformanceShaders)") return try VolumeViewport3D() } do { let viewport = try makeVolumeViewport() print(viewport.state.presentation) } catch { let status = MetalRuntimeAvailability.status() print("Metal requirement failed: \(status.missingFeatures)") print("MPS available: \(status.supportsMetalPerformanceShaders)") } ``` -------------------------------- ### Stack Slice Scrolling with MetalViewportView Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKUI/MTKUI.docc/MTKUI.md Demonstrates how to use StackViewport for stack slice scrolling. It applies a dataset and sets a specific slice index, with tap gestures to scroll through slices. ```swift import SwiftUI import MTKUI import MTKCore struct StackSliceView: View { @StateObject private var stack = try! StackViewport(axis: .axial) var body: some View { MetalViewportView(surface: stack.surface) .task { await stack.applyDataset(myDataset) await stack.setSliceIndex(32) } .onTapGesture { Task { await stack.scroll(by: 1) } } } } ``` -------------------------------- ### Maximum Intensity Projection (MIP) Algorithm Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/MPRGuide.md Illustrates the algorithm for MIP, which projects the brightest voxel encountered across all samples within a slab. Useful for visualizing high-density structures. ```pseudocode for each pixel (u, v): max_intensity = minimum_value for each step along normal: intensity = sample_volume(u, v, step) max_intensity = max(max_intensity, intensity) output[u, v] = max_intensity ``` -------------------------------- ### CT Abdomen Exploration Workflow Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/TransferFunctionsGuide.md Demonstrates loading a volume, applying soft tissue presets, enabling lighting, and using auto-windowing with manual adjustments for CT abdomen scans. ```swift // 1. Load volume and initialize renderer let adapter = try MetalVolumeRenderingAdapter() // 2. Apply soft tissue preset try await adapter.setPreset(.ctSoftTissue) try await adapter.setRenderingMode(.directVolumeRendering) // 3. Enable lighting for depth perception try await adapter.setLightingEnabled(true) // 4. Load histogram for auto-window let histogram = try await adapter.refreshHistogram( for: dataset, descriptor: VolumeHistogramDescriptor(binCount: 256, intensityRange: dataset.intensityRange), transferFunction: transferFunction ) let toneCurve = AdvancedToneCurveModel() toneCurve.setHistogram(histogram.bins) // 5. Apply abdomen auto-window toneCurve.applyAutoWindow(.abdomen) // 6. Fine-tune with manual window adjustment try await adapter.setHuWindow(min: -150, max: 250) ``` -------------------------------- ### Convert Window/Level to HU Min/Max Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/MPRGuide.md Converts window and level settings to the minimum and maximum HU values for intensity windowing. ```swift let min = level - (window / 2) let max = level + (window / 2) ``` -------------------------------- ### Swift Code for Setting Up MIP Rendering Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/VolumeRenderingGuide.md Configure MTKCore for Maximum Intensity Projection, including setting the rendering mode, HU gating for contrast-enhanced vessels, and applying an angiography transfer function. ```swift // Setup MIP for CT angiography try await adapter.setRenderingMode(.maximumIntensityProjection) // Gate to contrast-enhanced vessel range (150-400 HU) try await adapter.setHuGate(min: 150, max: 400, enabled: true) // Apply angiography transfer function with red colorization try await adapter.setPreset(.ctAngio) try await adapter.setTransferFunctionEnabled(true) ``` -------------------------------- ### Send Dynamic Slab Control Command Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/MPRGuide.md Sends a command to override slab thickness and steps for subsequent slab texture generation calls. Overrides are cleared after the call. ```swift // Override slab parameters via command try await adapter.send(.setSlab(thickness: 15, steps: 30)) ``` -------------------------------- ### 3D Volume Fusion with VolumeLayer Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKUI/MTKUI.docc/MTKUI.md Demonstrates how to fuse multiple volumes in a 3D viewport using VolumeLayer. It shows applying a secondary volume (PET) to a primary dataset (CT) with adjustable opacity and blend modes. ```swift let petLayer = VolumeLayer( id: "pet", dataset: petDataset, transferFunction: petTransferFunction, opacity: 0.5, blendMode: .additive ) await session.applyDataset(ctDataset) await session.setVolumeLayers([petLayer]) await session.setVolumeLayerOpacity(id: "pet", opacity: 0.35) await session.setVolumeLayerBlendMode(id: "pet", blendMode: .sourceOver) ``` -------------------------------- ### Fast MIP Slab Generation Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/MPRGuide.md Generates a Maximum Intensity Projection (MIP) slab with a thickness of 20 voxels but uses only 10 sampling steps for faster computation, potentially introducing slight noise. ```swift // Fast MIP: 20-voxel slab with only 10 samples let fastMIP = try await adapter.makeSlabTexture( dataset: dataset, volumeTexture: volumeTexture, plane: plane, thickness: 20, steps: 10, blend: .maximum ) ``` -------------------------------- ### Conceptual Ray Marching Pseudocode Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/VolumeRenderingGuide.md This pseudocode illustrates the fundamental steps involved in ray marching for volume rendering. It outlines ray generation, traversal, sample processing, and result accumulation for each pixel. ```pseudocode for each pixel in image: ray = generateRay(pixel, camera) result = initializeResult() for step in 0.. resampled VolumeDataset in base texture space -> current VolumeLayer fast path ``` -------------------------------- ### Generate Axial Slice with Metal Acceleration Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/MPRGuide.md Initializes a MetalMPRAdapter and generates a single axial slice from a dataset using specified plane geometry and blending. ```swift import MTKCore // Initialize adapter with Metal acceleration guard let device = MTLCreateSystemDefaultDevice() else { // Surface an app-level error or choose a non-Metal workflow. return } let adapter = try MetalMPRAdapter(device: device) let factory = VolumeTextureFactory(dataset: dataset) guard let volumeTexture = factory.generate(device: device) else { return } // Define an axial plane at the middle of the volume using the dataset geometry let plane = MPRPlaneGeometryFactory.makePlane(for: dataset, axis: .z, slicePosition: 0.5) // Generate single slice let frame = try await adapter.makeSlabTexture( dataset: dataset, volumeTexture: volumeTexture, plane: plane, thickness: 1, steps: 1, blend: .single ) // Access frame metadata print("Slice dimensions: \(frame.texture.width) × \(frame.texture.height)") print("Intensity range: \(frame.intensityRange)") ``` -------------------------------- ### Generate MinIP Slab with Overridden Blend Mode Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/MPRGuide.md Generates a slab texture using the overridden blend mode (.minimum), effectively creating a Minimum Intensity Projection (MinIP) slab. The blend parameter in the function call is ignored. ```swift // Generate MinIP slab (highlights airways) let minipSlab = try await adapter.makeSlabTexture( dataset: dataset, volumeTexture: volumeTexture, plane: plane, thickness: 10, steps: 20, blend: .maximum // Overridden to .minimum ) ``` -------------------------------- ### Direct Volume Rendering (DVR) Algorithm Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/VolumeRenderingGuide.md This Metal shader code implements the Direct Volume Rendering algorithm using front-to-back compositing and early ray termination. It accumulates color and opacity along viewing rays, supporting optional gradient lighting and transfer functions. ```metal // Metal shader: direct_volume_rendering float4 col = float4(0); // Accumulated color+alpha int zeroCount = 0; for (int iStep = 0; iStep < raymarch.numSteps; iStep++) { float3 currPos = lerp(ray.startPosition, ray.endPosition, t); short hu = getDensity(volume, currPos); // Map intensity to color via transfer function float densityDataset = normalize(hu, dataMin, dataMax); float4 src = getTfColour(tfTable, densityDataset); // Optional gradient lighting if (isLightingOn) { float3 gradient = calGradient(volume, currPos, dimension); float3 normal = normalize(gradient); src.rgb = calculateLighting(src.rgb, normal, lightDir, direction, 0.3f); } // Apply window-level opacity modulation if (densityWindow < 0.1f) src.a = 0.0f; else src.a *= densityWindow; // Front-to-back compositing src.rgb *= src.a; col = (1.0f - col.a) * src + col; // Early ray termination if (col.a > 1.0) break; } ``` -------------------------------- ### Apply CT and MR Presets Source: https://github.com/thalesmms/mtk/blob/main/Sources/MTKCore/MTKCore.docc/TransferFunctionsGuide.md Applies predefined CT and MR transfer function presets to the adapter. Can also combine CT presets with custom window settings. ```swift // Apply CT bone preset with lighting try await adapter.setPreset(.ctBone) try await adapter.setLightingEnabled(true) // Switch to MR angiography try await adapter.setPreset(.mrAngio) // Combine with custom window try await adapter.setPreset(.ctSoftTissue) try await adapter.setHuWindow(min: -100, max: 200) ```