Skip to main content

viewport_lib/
lib.rs

1#![warn(missing_docs)]
2//! `viewport-lib` : a 3D viewport library for `wgpu` applications.
3//!
4//! Built on `wgpu` and `glam`, with no required UI toolkit. The crate provides
5//! the renderer, camera, picking, and interaction code; host applications keep
6//! their own windowing and event loop.
7//!
8//! # Quick start (single viewport)
9//!
10//! 1. Create a [`ViewportRenderer`] from a `wgpu::Device` and target format.
11//! 2. Upload meshes or volumes through [`ViewportGpuResources`].
12//! 3. Build a [`FrameData`] each frame (camera via [`CameraFrame`] and
13//!    [`RenderCamera`], scene content via [`SceneFrame`], viewport chrome via
14//!    [`ViewportFrame`], etc.).
15//! 4. Call [`ViewportRenderer::prepare`] and then [`ViewportRenderer::paint_to`].
16//!
17//! # Multi-viewport rendering
18//!
19//! To render the same scene from multiple independent cameras (e.g. a CAD
20//! quad-view layout), use the split prepare/paint API:
21//!
22//! ```rust,ignore
23//! // --- Setup (once at startup) ---
24//! let vp_persp = renderer.create_viewport(&device);   // ViewportId(0)
25//! let vp_top   = renderer.create_viewport(&device);   // ViewportId(1)
26//! let vp_front = renderer.create_viewport(&device);   // ViewportId(2)
27//!
28//! // --- Each frame ---
29//! // 1. Build per-viewport FrameData (shared scene, independent cameras).
30//! let frame_persp = FrameData {
31//!     camera: CameraFrame::from_camera(&cam_persp, vp_size).with_viewport_index(vp_persp.0),
32//!     scene: shared_scene.clone(),
33//!     ..FrameData::default()
34//! };
35//! // ... similarly for vp_top, vp_front ...
36//!
37//! // 2. Prepare scene data once (lighting, shadows, batching).
38//! let (scene_fx, _) = frame_persp.effects.split();
39//! renderer.prepare_scene(&device, &queue, &frame_persp, &scene_fx);
40//!
41//! // 3. Prepare per-viewport state (camera uniforms, clip planes, overlays).
42//! renderer.prepare_viewport(&device, &queue, vp_persp, &frame_persp);
43//! renderer.prepare_viewport(&device, &queue, vp_top,   &frame_top);
44//! renderer.prepare_viewport(&device, &queue, vp_front, &frame_front);
45//!
46//! // 4a. LDR path : single render pass with viewport/scissor rects.
47//! let mut rp = encoder.begin_render_pass(...);
48//! rp.set_viewport(0.0, 0.0, half_w, half_h, 0.0, 1.0);
49//! renderer.paint_viewport(&mut rp, vp_persp, &frame_persp);
50//! rp.set_viewport(half_w, 0.0, half_w, half_h, 0.0, 1.0);
51//! renderer.paint_viewport(&mut rp, vp_top, &frame_top);
52//! // ...
53//!
54//! // 4b. HDR path : one command buffer per viewport, each into its own texture.
55//! let cmd0 = renderer.render_viewport(&device, &queue, &view0, vp_persp, &frame_persp);
56//! let cmd1 = renderer.render_viewport(&device, &queue, &view1, vp_top,   &frame_top);
57//! queue.submit([cmd0, cmd1]);
58//! ```
59//!
60//! Single-viewport applications require zero code changes:
61//! [`prepare`](ViewportRenderer::prepare), [`paint_to`](ViewportRenderer::paint_to), and
62//! [`render`](ViewportRenderer::render) continue to work as before.
63
64/// Error types for the viewport library.
65pub mod error;
66
67/// Arcball camera, frustum, view presets, and animator.
68pub mod camera;
69/// BVH picking, marching cubes, isolines, and cap geometry.
70pub mod geometry;
71/// Gizmo, snap, selection, picking, and input.
72pub mod interaction;
73/// On-surface vector quantities (intrinsic vectors, Whitney one-forms).
74pub mod quantities;
75/// Main viewport renderer wrapping all GPU resources.
76pub mod renderer;
77/// GPU resource container (pipelines, buffers, bind groups).
78pub mod resources;
79/// Scene graph, material, traits, and AABB.
80pub mod scene;
81/// Axes orientation indicator.
82pub mod widgets;
83
84// ---------------------------------------------------------------------------
85// Module re-exports : preserve old `viewport_lib::foo::Bar` paths.
86// ---------------------------------------------------------------------------
87
88pub use geometry::bvh;
89pub use geometry::primitives;
90pub use interaction::clip_plane;
91pub use interaction::gizmo;
92pub use interaction::input;
93pub use interaction::manipulation;
94pub use interaction::picking;
95pub use interaction::selection;
96pub use interaction::snap;
97pub use scene::aabb;
98pub use scene::material;
99pub use scene::traits;
100pub use widgets::axes_indicator;
101
102// ---------------------------------------------------------------------------
103// Flat re-exports : these form the public crate API.
104// ---------------------------------------------------------------------------
105
106pub use error::{ViewportError, ViewportResult};
107
108pub use camera::animator::{CameraAnimator, CameraDamping, Easing};
109pub use camera::camera::{Camera, CameraTarget, Projection};
110pub use camera::frustum::{CullStats, Frustum};
111pub use camera::track::{CameraTrack, interpolate_camera};
112pub use camera::turntable::TurntableController;
113pub use camera::view_preset::ViewPreset;
114
115pub use scene::aabb::Aabb;
116pub use scene::material::{
117    AppearanceSettings, BackfacePattern, BackfacePolicy, Material, ParamVis, ParamVisMode,
118    PatternConfig,
119};
120pub use scene::scene::{Group, GroupId, Layer, LayerId, Scene, SceneNode};
121pub use scene::traits::{RenderMode, ViewportObject};
122
123pub use geometry::bvh::PickAccelerator;
124pub use geometry::implicit::{
125    ImplicitRenderOptions, march_implicit_surface, march_implicit_surface_colour,
126};
127pub use geometry::isoline::{IsolineItem, extract_isolines};
128pub use geometry::marching_cubes::{VolumeData, extract_isosurface};
129
130pub use interaction::gizmo::{
131    Gizmo, GizmoAxis, GizmoMode, GizmoSpace, PivotMode, gizmo_center_for_pivot,
132};
133pub use interaction::input::{
134    Action, ActionState, Binding, FrameInput, InputMode, InputSystem, KeyCode, Modifiers,
135    MouseButton, NavigationMode,
136};
137// New input pipeline : re-exported at crate root for convenience.
138pub use interaction::input::{
139    ActionFrame, BindingPreset, ButtonState, ModifiersMatch, NavigationActions,
140    OrbitCameraController, ResolvedActionState, ScrollUnits, ViewportBinding, ViewportContext,
141    ViewportEvent, ViewportGesture, ViewportInput, viewport_all_bindings,
142};
143pub use interaction::manipulation::solvers::{
144    angular_rotation_from_cursor, constrained_scale, constrained_translation,
145};
146pub use interaction::manipulation::{
147    GizmoInfo, ManipResult, ManipulationContext, ManipulationController, ManipulationKind,
148    ManipulationState, TransformDelta,
149};
150
151pub use interaction::widgets::{
152    BoxWidget, CylinderWidget, DiskWidget, LineProbeWidget, PlaneWidget, PolylineWidget,
153    SphereWidget, SplineWidget, WidgetContext, WidgetResult,
154};
155
156pub use interaction::clip_plane::{
157    ClipAxis, ClipPlaneContext, ClipPlaneController, ClipPlaneDelta, ClipPlaneHit, ClipPlaneResult,
158    ClipPlaneSessionKind, hit_test_normal_handle, hit_test_plane_quad, plane_from_axis_preset,
159    project_drag_onto_normal, ray_plane_intersection, snap_plane_distance,
160};
161pub use interaction::pick_mask::PickMask;
162pub use interaction::picking::{
163    GpuPickHit, PickHit, ProbeBinding, RectPickResult, nearest_vertex_on_hit,
164    pick_gaussian_splat_cpu, pick_gaussian_splat_rect, pick_point_cloud_cpu, pick_rect,
165    pick_scene_accelerated_with_probe_cpu, pick_scene_nodes_with_probe_cpu,
166    pick_scene_with_probe_cpu, pick_transparent_volume_mesh_cpu, pick_transparent_volume_mesh_rect,
167    pick_volume_cpu, pick_volume_rect, voxel_world_aabb,
168};
169pub use interaction::selection::{NodeId, Selection};
170pub use interaction::snap::{ConstraintOverlay, SnapConfig};
171pub use interaction::sub_object;
172pub use interaction::sub_object::{
173    CellSelectionInfo, PolylineSelectionInfo, SubObjectRef, SubSelection, SubSelectionRef,
174    VolumeSelectionInfo,
175};
176
177pub use widgets::axes_indicator::AxisView;
178
179pub use renderer::shader_hashes::ShaderValidation;
180pub use renderer::stats::{FrameStats, PerformancePolicy, QualityPreset, RuntimeMode};
181pub use renderer::{
182    CameraFrame, CameraFrustumItem, ClipObject, ClipShape, ComputeFilterItem, ComputeFilterKind,
183    EffectsFrame, EnvironmentMap, FilterMode, FrameData, GaussianSplatData, GaussianSplatId,
184    GaussianSplatItem, GlyphItem, GlyphType, GroundPlane, GroundPlaneMode, ImageAnchor,
185    ImageSliceItem, InteractionFrame, LabelAnchor, LabelItem, LightKind, LightSource,
186    LightingSettings, LoadingBarAnchor, LoadingBarItem, OverlayFrame, OverlayImageItem, PickId,
187    PickRectResult, PointCloudItem, PointRenderMode, PolylineItem, PostProcessSettings,
188    RenderCamera, RibbonItem, RulerItem, ScalarBarAnchor, ScalarBarItem, ScalarBarOrientation,
189    SceneEffects, SceneFrame, SceneRenderItem, ScreenImageItem, ShDegree, ShadowFilter, SliceAxis,
190    SpriteItem, SpriteSizeMode, StreamtubeItem, SurfaceLICConfig, SurfaceLICItem,
191    SurfaceSubmission, TensorGlyphItem, ToneMapping, TransparentVolumeMeshItem, TubeItem,
192    ViewportEffects, ViewportFrame, ViewportId, ViewportRenderer, VolumeItem, VolumeMeshItem,
193    VolumeSurfaceSliceItem, aabb_wireframe_polyline,
194};
195
196pub use quantities::{
197    edge_one_form_to_glyphs, face_intrinsic_to_glyphs, polyline_edge_vectors_to_glyphs,
198    polyline_node_vectors_to_glyphs, vertex_intrinsic_to_glyphs,
199    volume_mesh_cell_vectors_to_glyphs, volume_mesh_vertex_vectors_to_glyphs,
200};
201
202#[allow(deprecated)]
203pub use resources::ClipVolumeUniform;
204pub use resources::colourmap_data::{
205    export_paraview_xml_colourmap, lerp_colourmap_lut, parse_paraview_xml_colourmap,
206};
207pub use resources::mesh_store::MeshId;
208pub use resources::sparse_volume::SparseVolumeGridData;
209#[allow(deprecated)]
210pub use resources::volume_mesh::{
211    CELL_SENTINEL, TET_SENTINEL, VolumeMeshData, extract_clipped_volume_faces,
212};
213pub use resources::{
214    AttributeData, AttributeKind, AttributeRef, BuiltinColourmap, BuiltinMatcap, CLIP_VOLUME_MAX,
215    CameraUniform, ClipVolumeEntry, ClipVolumesUniform, ColourmapId, ComputeFilterResult, FontError,
216    FontHandle, GpuImplicitItem, GpuImplicitOptions, GpuMarchingCubesJob, ImplicitBlendMode,
217    ImplicitPrimitive, LightUniform, LightsUniform, MatcapId, MeshData, ProjectedTetId,
218    SingleLightUniform, ViewportGpuResources, VolumeGpuId, VolumeId, lerp_attributes,
219};