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::{BackfacePattern, BackfacePolicy, Material, ParamVis, ParamVisMode, PatternConfig};
117pub use scene::scene::{Group, GroupId, Layer, LayerId, Scene, SceneNode};
118pub use scene::traits::{RenderMode, ViewportObject};
119
120pub use geometry::bvh::PickAccelerator;
121pub use geometry::implicit::{ImplicitRenderOptions, march_implicit_surface, march_implicit_surface_color};
122pub use geometry::isoline::{IsolineItem, extract_isolines};
123pub use geometry::marching_cubes::{VolumeData, extract_isosurface};
124
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, NavigationMode,
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::widgets::{
147    BoxWidget, CylinderWidget, DiskWidget, LineProbeWidget, PlaneWidget, PolylineWidget,
148    SphereWidget, SplineWidget, WidgetContext, WidgetResult,
149};
150
151pub use interaction::clip_plane::{
152    ClipAxis, ClipPlaneContext, ClipPlaneController, ClipPlaneDelta, ClipPlaneHit, ClipPlaneResult,
153    ClipPlaneSessionKind, hit_test_normal_handle, hit_test_plane_quad, plane_from_axis_preset,
154    project_drag_onto_normal, ray_plane_intersection, snap_plane_distance,
155};
156pub use interaction::picking::{
157    GpuPickHit, PickHit, ProbeBinding, RectPickResult, pick_rect,
158    pick_scene_accelerated_with_probe_cpu, pick_scene_nodes_with_probe_cpu, pick_scene_with_probe_cpu,
159    nearest_vertex_on_hit, pick_gaussian_splat_cpu, pick_gaussian_splat_rect,
160    pick_point_cloud_cpu, pick_volume_cpu, pick_volume_rect,
161    pick_transparent_volume_mesh_cpu, pick_transparent_volume_mesh_rect,
162    voxel_world_aabb,
163};
164pub use interaction::selection::{NodeId, Selection};
165pub use interaction::snap::{ConstraintOverlay, SnapConfig};
166pub use interaction::pick_mask::PickMask;
167pub use interaction::sub_object;
168pub use interaction::sub_object::{CellSelectionInfo, PolylineSelectionInfo, SubObjectRef, SubSelection, SubSelectionRef, VolumeSelectionInfo};
169
170pub use widgets::axes_indicator::AxisView;
171
172pub use renderer::shader_hashes::ShaderValidation;
173pub use renderer::stats::{FrameStats, PerformancePolicy, QualityPreset, RuntimeMode};
174pub use renderer::{
175    CameraFrame, CameraFrustumItem, ClipObject, ClipShape, ComputeFilterItem, ComputeFilterKind,
176    EffectsFrame, EnvironmentMap, FilterMode, FrameData, GlyphItem, GlyphType, GroundPlane,
177    TensorGlyphItem,
178    GroundPlaneMode, ImageAnchor, InteractionFrame, LabelAnchor, LabelItem, LightKind, LightSource,
179    LightingSettings, LoadingBarAnchor, LoadingBarItem, OverlayFrame, OverlayImageItem, PickId,
180    PointCloudItem, PointRenderMode,
181    aabb_wireframe_polyline, PolylineItem, PostProcessSettings, RenderCamera, RulerItem, ScalarBarAnchor, ScalarBarItem,
182    ScalarBarOrientation, SceneEffects,
183    RibbonItem, SceneFrame, SceneRenderItem, ScreenImageItem, VolumeMeshItem,
184    GaussianSplatData, GaussianSplatId, GaussianSplatItem, ShDegree,
185    ImageSliceItem, SliceAxis, ShadowFilter, SpriteItem, SpriteSizeMode, StreamtubeItem,
186    SurfaceLICConfig, SurfaceLICItem, SurfaceSubmission, ToneMapping, TubeItem,
187    TransparentVolumeMeshItem, VolumeSurfaceSliceItem,
188    PickRectResult,
189    ViewportEffects, ViewportFrame, ViewportId, ViewportRenderer, VolumeItem,
190};
191
192pub use quantities::{
193    edge_one_form_to_glyphs, face_intrinsic_to_glyphs,
194    polyline_edge_vectors_to_glyphs, polyline_node_vectors_to_glyphs,
195    vertex_intrinsic_to_glyphs,
196    volume_mesh_cell_vectors_to_glyphs, volume_mesh_vertex_vectors_to_glyphs,
197};
198
199pub use resources::colormap_data::{
200    export_paraview_xml_colormap, lerp_colormap_lut, parse_paraview_xml_colormap,
201};
202pub use resources::mesh_store::MeshId;
203pub use resources::sparse_volume::SparseVolumeGridData;
204#[allow(deprecated)]
205pub use resources::volume_mesh::{CELL_SENTINEL, TET_SENTINEL, VolumeMeshData, extract_clipped_volume_faces};
206#[allow(deprecated)]
207pub use resources::ClipVolumeUniform;
208pub use resources::{
209    AttributeData, AttributeKind, AttributeRef, BuiltinColormap, BuiltinMatcap, CameraUniform,
210    ClipVolumeEntry, ClipVolumesUniform, CLIP_VOLUME_MAX,
211    ColormapId, ComputeFilterResult, FontError, FontHandle, GpuImplicitItem,
212    GpuImplicitOptions, GpuMarchingCubesJob, ImplicitBlendMode, ImplicitPrimitive, LightUniform,
213    LightsUniform, MatcapId, MeshData, ProjectedTetId, SingleLightUniform, ViewportGpuResources,
214    VolumeGpuId, VolumeId, lerp_attributes,
215};