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, pass-based)
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 [`PassPath::prepare`] then [`PassPath::paint`] via `renderer.pass()`.
16//!
17//! # Quick start (single viewport, owned-encoder)
18//!
19//! Use `renderer.owned().render(device, queue, &output_view, &frame)` when you
20//! own the wgpu encoder (winit, raw wgpu). The call handles prepare and draw
21//! internally and returns a [`wgpu::CommandBuffer`] to submit.
22//!
23//! # Rendering paths
24//!
25//! [`ViewportRenderer::pass`] returns a [`PassPath`] for framework callbacks
26//! that hand you a render pass (eframe, iced). [`ViewportRenderer::owned`]
27//! returns an [`OwnedPath`] for setups where you own the encoder (winit, raw wgpu).
28//!
29//! # Multi-viewport rendering
30//!
31//! To render the same scene from multiple independent cameras (e.g. a CAD
32//! quad-view layout):
33//!
34//! ```rust,ignore
35//! // --- Setup (once at startup) ---
36//! let vp_persp = renderer.create_viewport(&device);   // ViewportId(0)
37//! let vp_top   = renderer.create_viewport(&device);   // ViewportId(1)
38//! let vp_front = renderer.create_viewport(&device);   // ViewportId(2)
39//!
40//! // --- Each frame ---
41//! // 1. Build per-viewport FrameData (shared scene, independent cameras).
42//! let frame_persp = FrameData {
43//!     camera: CameraFrame::from_camera(&cam_persp, vp_size).with_viewport_index(vp_persp.0),
44//!     scene: shared_scene.clone(),
45//!     ..FrameData::default()
46//! };
47//! // ... similarly for vp_top, vp_front ...
48//!
49//! // 2. Prepare scene data once (lighting, shadows, batching).
50//! let (scene_fx, _) = frame_persp.effects.split();
51//! renderer.pass().prepare_scene(&device, &queue, &frame_persp, &scene_fx);
52//!
53//! // 3. Prepare per-viewport state (camera uniforms, clip planes, overlays).
54//! renderer.pass().prepare_viewport(&device, &queue, vp_persp, &frame_persp);
55//! renderer.pass().prepare_viewport(&device, &queue, vp_top,   &frame_top);
56//! renderer.pass().prepare_viewport(&device, &queue, vp_front, &frame_front);
57//!
58//! // 4a. LDR path : single render pass with viewport/scissor rects.
59//! let mut rp = encoder.begin_render_pass(...);
60//! rp.set_viewport(0.0, 0.0, half_w, half_h, 0.0, 1.0);
61//! renderer.pass().paint_viewport(&mut rp, vp_persp, &frame_persp);
62//! rp.set_viewport(half_w, 0.0, half_w, half_h, 0.0, 1.0);
63//! renderer.pass().paint_viewport(&mut rp, vp_top, &frame_top);
64//! // ...
65//!
66//! // 4b. HDR path : one command buffer per viewport, each into its own texture.
67//! let cmd0 = renderer.owned().render_viewport(&device, &queue, &view0, vp_persp, &frame_persp);
68//! let cmd1 = renderer.owned().render_viewport(&device, &queue, &view1, vp_top,   &frame_top);
69//! queue.submit([cmd0, cmd1]);
70//! ```
71
72/// Error types for the viewport library.
73pub mod error;
74
75/// Arcball camera, frustum, view presets, and animator.
76pub mod camera;
77/// BVH picking, marching cubes, isolines, and cap geometry.
78pub mod geometry;
79/// Gizmo, snap, selection, picking, and input.
80pub mod interaction;
81/// On-surface vector quantities (intrinsic vectors, Whitney one-forms).
82pub mod quantities;
83/// Main viewport renderer wrapping all GPU resources.
84pub mod renderer;
85/// Scene runtime: per-frame orchestration, plugin system, and physics hooks.
86pub mod runtime;
87/// GPU resource container (pipelines, buffers, bind groups).
88pub mod resources;
89/// Scene graph, material, traits, and AABB.
90pub mod scene;
91/// Axes orientation indicator.
92pub mod widgets;
93
94// ---------------------------------------------------------------------------
95// Module re-exports : preserve old `viewport_lib::foo::Bar` paths.
96// ---------------------------------------------------------------------------
97
98pub use geometry::bvh;
99pub use geometry::primitives;
100pub use interaction::clip_plane;
101pub use interaction::gizmo;
102pub use interaction::input;
103pub use interaction::manipulation;
104pub use interaction::picking;
105pub use interaction::selection;
106pub use interaction::snap;
107pub use scene::aabb;
108pub use scene::material;
109pub use scene::scatter_volume;
110pub use scene::traits;
111pub use scene::scatter_volume::{
112    ColourSource, DensityRemap, Emission, EmissionCurve, NoiseDriver, ScatterShape, ScatterVolume,
113};
114pub use widgets::axes_indicator;
115
116// ---------------------------------------------------------------------------
117// Flat re-exports : these form the public crate API.
118// ---------------------------------------------------------------------------
119
120pub use error::{ViewportError, ViewportResult};
121
122pub use camera::animator::{CameraAnimator, CameraDamping, Easing};
123pub use camera::camera::{Camera, CameraTarget, Projection};
124pub use camera::frustum::{CullStats, Frustum};
125pub use camera::track::{CameraTrack, interpolate_camera};
126pub use camera::turntable::TurntableController;
127pub use camera::view_preset::ViewPreset;
128
129pub use scene::aabb::Aabb;
130pub use scene::material::{
131    ItemSettings, BackfacePattern, BackfacePolicy, Material, ParamVis, ParamVisMode,
132    PatternConfig, ShadingModel,
133};
134pub use scene::scene::{DecalHandle, Group, GroupId, Layer, LayerId, LiveDecal, Scene, SceneNode, SceneStats};
135pub use scene::traits::{RenderMode, ViewportObject};
136
137pub use geometry::bvh::PickAccelerator;
138pub use geometry::implicit::{
139    ImplicitRenderOptions, march_implicit_surface, march_implicit_surface_colour,
140};
141pub use geometry::isoline::{IsolineItem, extract_isolines};
142pub use geometry::marching_cubes::{VolumeData, extract_isosurface};
143
144pub use interaction::gizmo::{
145    Gizmo, GizmoAxis, GizmoMode, GizmoSpace, PivotMode, gizmo_center_for_pivot,
146};
147pub use interaction::input::{
148    Action, ActionState, Binding, FrameInput, InputMode, InputSystem, KeyCode, Modifiers,
149    MouseButton, NavigationMode,
150};
151// New input pipeline : re-exported at crate root for convenience.
152pub use interaction::input::{
153    ActionFrame, BindingPreset, ButtonState, ModifiersMatch, NavigationActions,
154    OrbitCameraController, ResolvedActionState, ScrollUnits, ViewportBinding, ViewportContext,
155    ViewportEvent, ViewportGesture, ViewportInput, viewport_all_bindings,
156};
157pub use interaction::manipulation::solvers::{
158    angular_rotation_from_cursor, constrained_scale, constrained_translation,
159};
160pub use interaction::manipulation::{
161    GizmoInfo, ManipResult, ManipulationContext, ManipulationController, ManipulationKind,
162    ManipulationState, TransformDelta,
163};
164
165pub use interaction::widgets::{
166    BoxWidget, CylinderWidget, DiskWidget, LineProbeWidget, PlaneWidget, PolylineWidget,
167    SphereWidget, SplineWidget, WidgetContext, WidgetResult,
168};
169
170pub use interaction::clip_plane::{
171    ClipAxis, ClipPlaneContext, ClipPlaneController, ClipPlaneDelta, ClipPlaneHit, ClipPlaneResult,
172    ClipPlaneSessionKind, hit_test_normal_handle, hit_test_plane_quad, plane_from_axis_preset,
173    project_drag_onto_normal, ray_plane_intersection, snap_plane_distance,
174};
175pub use interaction::pick_mask::PickMask;
176pub use interaction::picking::{
177    GpuPickHit, PickHit, ProbeBinding, RectPickResult, nearest_vertex_on_hit,
178    pick_gaussian_splat_cpu, pick_gaussian_splat_rect, pick_point_cloud_cpu, pick_rect,
179    pick_scene_accelerated_with_probe_cpu, pick_scene_nodes_with_probe_cpu,
180    pick_scene_with_probe_cpu, pick_transparent_volume_mesh_cpu, pick_transparent_volume_mesh_rect,
181    pick_volume_cpu, pick_volume_rect, voxel_world_aabb,
182};
183pub use interaction::selection::{NodeId, Selection};
184pub use interaction::snap::{ConstraintOverlay, SnapConfig};
185pub use interaction::sub_object;
186pub use interaction::sub_object::{
187    CellSelectionInfo, PolylineSelectionInfo, SubObjectRef, SubSelection, SubSelectionRef,
188    VolumeSelectionInfo,
189};
190
191pub use widgets::axes_indicator::AxisView;
192
193pub use renderer::shader_hashes::ShaderValidation;
194pub use renderer::stats::{FrameStats, PerformancePolicy, QualityPreset, RuntimeMode};
195pub use renderer::ShadowDebugStats;
196pub use renderer::{
197    AtlasViewerCorner,
198    CameraFrame, ClipObject, ClipShape, ComputeFilterItem, ComputeFilterKind,
199    CylindricalFacing, DecalAnimation, DecalBlendMode, DecalItem, DecalProjection,
200    DebugOutputMode, DebugQuantity, DebugVis,
201    EffectsFrame, EnvironmentMap, FilterMode, FrameData, GaussianSplatData, GaussianSplatId,
202    GaussianSplatItem, GlyphItem, GlyphType, GroundPlane, GroundPlaneMode, ImageAnchor,
203    ImageSliceItem, InteractionFrame, LabelAnchor, LabelItem, LightKind, LightSource,
204    LightingSettings, LoadingBarAnchor, LoadingBarItem, OwnedPath, PassPath, PassView, OverlayFrame, OverlayImageItem,
205    OverlayAnimation, OverlayFill, OverlayRectItem, OverlayShape, OverlayShapeItem,
206    OverlayTextureId, BorderMode, LineCap, PickId, TriangleDirection,
207    PickRectResult, PointCloudItem, PointRenderMode, PolylineItem, PostProcessSettings,
208    RenderCamera, RibbonItem, RulerItem, ScalarBarAnchor, ScalarBarItem, ScalarBarOrientation,
209    LicOverlay, SceneEffects, SceneFrame, SceneRenderItem, ScreenImageItem, ShDegree, ShadowFilter,
210    SliceAxis, SpriteItem, SpriteSizeMode, StreamtubeItem, SurfaceLICConfig,
211    ScatterQuality, ScatterSettings, ScatterVolumeItem,
212    SurfaceSubmission, TensorGlyphItem, ToneMapping, TransparentVolumeMeshItem, TubeItem,
213    ViewportEffects, ViewportFrame, ViewportId, ViewportRenderer, VolumeItem, VolumeMeshItem,
214    VolumeSurfaceSliceItem, aabb_wireframe_polyline, sphere_wireframe_polyline,
215};
216
217pub use quantities::{
218    edge_one_form_to_glyphs, face_intrinsic_to_glyphs, polyline_edge_vectors_to_glyphs,
219    polyline_node_vectors_to_glyphs, vertex_intrinsic_to_glyphs,
220    volume_mesh_cell_vectors_to_glyphs, volume_mesh_vertex_vectors_to_glyphs,
221};
222
223pub use resources::colourmap_data::{
224    export_paraview_xml_colourmap, lerp_colourmap_lut, parse_paraview_xml_colourmap,
225};
226pub use resources::mesh_store::MeshId;
227pub use resources::sparse_volume::SparseVolumeGridData;
228pub use resources::volume_mesh::{
229    CELL_SENTINEL, VolumeMeshData, extract_clipped_volume_faces,
230};
231pub use resources::{
232    AttributeData, AttributeKind, AttributeRef, BuiltinColourmap, BuiltinMatcap, CLIP_VOLUME_MAX,
233    CameraUniform, ClipVolumeEntry, ClipVolumesUniform, ColourmapId, ComputeFilterResult, FontError,
234    FontHandle, GpuImplicitItem, GpuImplicitOptions, GpuMarchingCubesJob, ImplicitBlendMode,
235    ImplicitPrimitive, LightUniform, LightsUniform, MatcapId, MeshData, PendingTextureId,
236    ProjectedTetId, SingleLightUniform, SkinWeights, TextureMemoryStats, ViewportGpuResources,
237    VolumeGpuId, VolumeId, lerp_attributes,
238};
239
240pub use runtime::{
241    AnimationClip, AnimationPlugin, AnimationTrack, CameraFollow, Channel, ClipPlayerPlugin,
242    Constraint, ConstraintPlugin, ContactEvent, DebugDraw, DebugLayer, DebugPrim, FixedStepIter,
243    FixedTimestep, Interpolation, Joint, JointMatrices, Keyframe, ManipulationSystem,
244    NodeTransformOp, PhysicsBody, PhysicsLitePlugin, Pose, RuntimeFrameContext, RuntimeOutput,
245    RuntimePhase, RuntimePlugin, RuntimeStepContext, Sampler, SceneRuntimeMode, SelectionOp,
246    SelectionSystem, SimulationStepContext, Skeleton, SkeletonPlugin, SkinnedActor,
247    SkinnedActorPart, SkinnedActorPlugin, SkinnedMeshUpdate, SkinnedPoseUpdate, SkinningPath, Track, TrackValue, TrackValues,
248    TransformSnapshot, TransformSnapshotTable, TransformWriteback, ViewportRuntime, apply_skin,
249};