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 pieces; host applications keep
6//! control of 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, annotation, picking, and input.
72pub mod interaction;
73/// Main viewport renderer wrapping all GPU resources.
74pub mod renderer;
75/// GPU resource container (pipelines, buffers, bind groups).
76pub mod resources;
77/// Scene graph, material, traits, and AABB.
78pub mod scene;
79/// Axes orientation indicator.
80pub mod widgets;
81
82// ---------------------------------------------------------------------------
83// Module re-exports — preserve old `viewport_lib::foo::Bar` paths.
84// ---------------------------------------------------------------------------
85
86pub use geometry::bvh;
87pub use geometry::primitives;
88pub use interaction::annotation;
89pub use interaction::clip_plane;
90pub use interaction::gizmo;
91pub use interaction::input;
92pub use interaction::manipulation;
93pub use interaction::picking;
94pub use interaction::selection;
95pub use interaction::snap;
96pub use scene::aabb;
97pub use scene::material;
98pub use scene::traits;
99pub use widgets::axes_indicator;
100
101// ---------------------------------------------------------------------------
102// Flat re-exports — these form the public crate API.
103// ---------------------------------------------------------------------------
104
105pub use error::{ViewportError, ViewportResult};
106
107pub use camera::animator::{CameraAnimator, CameraDamping, Easing};
108pub use camera::camera::{Camera, CameraTarget, Projection};
109pub use camera::frustum::{CullStats, Frustum};
110pub use camera::view_preset::ViewPreset;
111
112pub use scene::aabb::Aabb;
113pub use scene::material::Material;
114pub use scene::scene::{Group, GroupId, Layer, LayerId, Scene, SceneNode};
115pub use scene::traits::{RenderMode, ViewportObject};
116
117pub use geometry::bvh::PickAccelerator;
118pub use geometry::isoline::{IsolineItem, extract_isolines};
119pub use geometry::marching_cubes::{VolumeData, extract_isosurface};
120
121pub use interaction::annotation::AnnotationLabel;
122#[cfg(feature = "egui")]
123pub use interaction::annotation::draw_annotation_labels;
124pub use interaction::annotation::{world_to_screen, world_to_screen_from_frame};
125pub use interaction::gizmo::{
126    Gizmo, GizmoAxis, GizmoMode, GizmoSpace, PivotMode, gizmo_center_for_pivot,
127};
128pub use interaction::input::{
129    Action, ActionState, Binding, FrameInput, InputMode, InputSystem, KeyCode, Modifiers,
130    MouseButton,
131};
132// New input pipeline — re-exported at crate root for convenience.
133pub use interaction::input::{
134    ActionFrame, BindingPreset, ButtonState, ModifiersMatch, NavigationActions,
135    OrbitCameraController, ResolvedActionState, ScrollUnits, ViewportBinding, ViewportContext,
136    ViewportEvent, ViewportGesture, ViewportInput, viewport_all_bindings,
137};
138pub use interaction::manipulation::solvers::{
139    angular_rotation_from_cursor, constrained_scale, constrained_translation,
140};
141pub use interaction::manipulation::{
142    GizmoInfo, ManipResult, ManipulationContext, ManipulationController, ManipulationKind,
143    ManipulationState, TransformDelta,
144};
145
146pub use interaction::clip_plane::{
147    ClipAxis, ClipPlaneContext, ClipPlaneController, ClipPlaneDelta, ClipPlaneHit,
148    ClipPlaneOverlay, ClipPlaneResult, ClipPlaneSessionKind, hit_test_normal_handle,
149    hit_test_plane_quad, plane_from_axis_preset, project_drag_onto_normal, ray_plane_intersection,
150    snap_plane_distance,
151};
152pub use interaction::picking::{
153    GpuPickHit, PickHit, ProbeBinding, RectPickResult, pick_rect,
154    pick_scene_accelerated_with_probe, pick_scene_nodes_with_probe, pick_scene_with_probe,
155};
156pub use interaction::selection::{NodeId, Selection};
157pub use interaction::snap::{ConstraintOverlay, SnapConfig};
158pub use interaction::sub_object;
159pub use interaction::sub_object::{SubObjectRef, SubSelection};
160
161pub use widgets::axes_indicator::AxisView;
162
163pub use renderer::shader_hashes::ShaderValidation;
164pub use renderer::stats::FrameStats;
165pub use renderer::{
166    CameraFrame, ClipPlane, ClipVolume, ComputeFilterItem, ComputeFilterKind, EffectsFrame,
167    EnvironmentMap, FilterMode, FrameData, GlyphItem, GlyphType, InteractionFrame, LightKind,
168    LightSource, LightingSettings, PointCloudItem, PointRenderMode, PolylineItem,
169    PostProcessSettings, RenderCamera, SceneEffects, SceneFrame, SceneRenderItem, ShadowFilter,
170    StreamtubeItem, SurfaceSubmission, ToneMapping, ViewportEffects, ViewportFrame, ViewportId,
171    ViewportRenderer, VolumeItem,
172};
173pub use renderer::{ScalarBar, ScalarBarAnchor, ScalarBarOrientation};
174
175pub use resources::colormap_data::{
176    export_paraview_xml_colormap, lerp_colormap_lut, parse_paraview_xml_colormap,
177};
178pub use resources::mesh_store::MeshId;
179pub use resources::{
180    AttributeData, AttributeKind, AttributeRef, BuiltinColormap, CameraUniform, ClipVolumeUniform,
181    ColormapId, ComputeFilterResult, LightUniform, LightsUniform, MeshData, SingleLightUniform,
182    ViewportGpuResources, VolumeId, lerp_attributes,
183};