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/// 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::annotation;
91pub use interaction::clip_plane;
92pub use interaction::gizmo;
93pub use interaction::input;
94pub use interaction::manipulation;
95pub use interaction::picking;
96pub use interaction::selection;
97pub use interaction::snap;
98pub use scene::aabb;
99pub use scene::material;
100pub use scene::traits;
101pub use widgets::axes_indicator;
102
103// ---------------------------------------------------------------------------
104// Flat re-exports : these form the public crate API.
105// ---------------------------------------------------------------------------
106
107pub use error::{ViewportError, ViewportResult};
108
109pub use camera::animator::{CameraAnimator, CameraDamping, Easing};
110pub use camera::camera::{Camera, CameraTarget, Projection};
111pub use camera::frustum::{CullStats, Frustum};
112pub use camera::view_preset::ViewPreset;
113
114pub use scene::aabb::Aabb;
115pub use scene::material::{BackfacePattern, BackfacePolicy, Material, ParamVis, ParamVisMode};
116pub use scene::scene::{Group, GroupId, Layer, LayerId, Scene, SceneNode};
117pub use scene::traits::{RenderMode, ViewportObject};
118
119pub use geometry::bvh::PickAccelerator;
120pub use geometry::implicit::{ImplicitRenderOptions, march_implicit_surface, march_implicit_surface_color};
121pub use geometry::isoline::{IsolineItem, extract_isolines};
122pub use geometry::marching_cubes::{VolumeData, extract_isosurface};
123
124pub use interaction::annotation::AnnotationLabel;
125#[cfg(feature = "egui")]
126pub use interaction::annotation::draw_annotation_labels;
127pub use interaction::annotation::{world_to_screen, world_to_screen_from_frame};
128pub use interaction::gizmo::{
129    Gizmo, GizmoAxis, GizmoMode, GizmoSpace, PivotMode, gizmo_center_for_pivot,
130};
131pub use interaction::input::{
132    Action, ActionState, Binding, FrameInput, InputMode, InputSystem, KeyCode, Modifiers,
133    MouseButton, NavigationMode,
134};
135// New input pipeline : re-exported at crate root for convenience.
136pub use interaction::input::{
137    ActionFrame, BindingPreset, ButtonState, ModifiersMatch, NavigationActions,
138    OrbitCameraController, ResolvedActionState, ScrollUnits, ViewportBinding, ViewportContext,
139    ViewportEvent, ViewportGesture, ViewportInput, viewport_all_bindings,
140};
141pub use interaction::manipulation::solvers::{
142    angular_rotation_from_cursor, constrained_scale, constrained_translation,
143};
144pub use interaction::manipulation::{
145    GizmoInfo, ManipResult, ManipulationContext, ManipulationController, ManipulationKind,
146    ManipulationState, TransformDelta,
147};
148
149pub use interaction::clip_plane::{
150    ClipAxis, ClipPlaneContext, ClipPlaneController, ClipPlaneDelta, ClipPlaneHit, ClipPlaneResult,
151    ClipPlaneSessionKind, hit_test_normal_handle, hit_test_plane_quad, plane_from_axis_preset,
152    project_drag_onto_normal, ray_plane_intersection, snap_plane_distance,
153};
154pub use interaction::picking::{
155    GpuPickHit, PickHit, ProbeBinding, RectPickResult, pick_rect,
156    pick_scene_accelerated_with_probe_cpu, pick_scene_nodes_with_probe_cpu, pick_scene_with_probe_cpu,
157    pick_volume_cpu, voxel_world_aabb,
158};
159pub use interaction::selection::{NodeId, Selection};
160pub use interaction::snap::{ConstraintOverlay, SnapConfig};
161pub use interaction::sub_object;
162pub use interaction::sub_object::{SubObjectRef, SubSelection, SubSelectionRef, VolumeSelectionInfo};
163
164pub use widgets::axes_indicator::AxisView;
165
166pub use renderer::shader_hashes::ShaderValidation;
167pub use renderer::stats::FrameStats;
168pub use renderer::{
169    CameraFrame, CameraFrustumItem, ClipObject, ClipShape, ComputeFilterItem, ComputeFilterKind,
170    EffectsFrame, EnvironmentMap, FilterMode, FrameData, GlyphItem, GlyphType, GroundPlane,
171    GroundPlaneMode, ImageAnchor, InteractionFrame, LabelItem, LightKind, LightSource,
172    LightingSettings, OverlayFrame, OverlayImageItem, PickId, PointCloudItem, PointRenderMode,
173    PolylineItem, PostProcessSettings, RenderCamera, RulerItem, ScalarBar, ScalarBarAnchor,
174    ScalarBarItem, ScalarBarOrientation, SceneEffects, SceneFrame, SceneRenderItem, ScreenImageItem,
175    ShadowFilter, StreamtubeItem, SurfaceSubmission, ToneMapping, ViewportEffects, ViewportFrame,
176    ViewportId, ViewportRenderer, VolumeItem,
177};
178
179pub use quantities::{
180    edge_one_form_to_glyphs, face_intrinsic_to_glyphs,
181    polyline_edge_vectors_to_glyphs, polyline_node_vectors_to_glyphs,
182    vertex_intrinsic_to_glyphs,
183    volume_mesh_cell_vectors_to_glyphs, volume_mesh_vertex_vectors_to_glyphs,
184};
185
186pub use resources::colormap_data::{
187    export_paraview_xml_colormap, lerp_colormap_lut, parse_paraview_xml_colormap,
188};
189pub use resources::mesh_store::MeshId;
190pub use resources::sparse_volume::SparseVolumeGridData;
191pub use resources::volume_mesh::{TET_SENTINEL, VolumeMeshData};
192pub use resources::{
193    AttributeData, AttributeKind, AttributeRef, BuiltinColormap, BuiltinMatcap, CameraUniform,
194    ClipVolumeUniform, ColormapId, ComputeFilterResult, FontError, FontHandle, GpuImplicitItem,
195    GpuImplicitOptions, GpuMarchingCubesJob, ImplicitBlendMode, ImplicitPrimitive, LightUniform,
196    LightsUniform, MatcapId, MeshData, SingleLightUniform, ViewportGpuResources, VolumeGpuId,
197    VolumeId, lerp_attributes,
198};