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/// Plugin substrate: target descriptors, shared bind layouts, WGSL helpers,
82/// pipeline builders. See [`plugin_api`] for the published extension surface.
83pub mod plugin_api;
84/// On-surface vector quantities (intrinsic vectors, Whitney one-forms).
85pub mod quantities;
86/// Main viewport renderer wrapping all GPU resources.
87pub mod renderer;
88/// GPU resource container (pipelines, buffers, bind groups).
89pub mod resources;
90/// Built-in plugins: skinning, animation, constraints, physics, skeleton.
91pub mod plugins;
92/// Scene runtime: per-frame orchestration, plugin system, and physics hooks.
93pub mod runtime;
94/// Scene graph, material, traits, and AABB.
95pub mod scene;
96/// Axes orientation indicator.
97pub mod widgets;
98
99// ---------------------------------------------------------------------------
100// Module re-exports : preserve old `viewport_lib::foo::Bar` paths.
101// ---------------------------------------------------------------------------
102
103pub use geometry::bvh;
104pub use geometry::primitives;
105pub use interaction::clip_plane;
106pub use interaction::gizmo;
107pub use interaction::input;
108pub use interaction::manipulation;
109pub use interaction::picking;
110pub use interaction::selection;
111pub use interaction::snap;
112pub use scene::aabb;
113pub use scene::material;
114pub use scene::scatter_volume;
115pub use scene::scatter_volume::{
116    ColourSource, DensityRemap, Emission, EmissionCurve, NoiseDriver, RefractionParams,
117    ScatterShape, ScatterVolume,
118};
119pub use scene::traits;
120pub use widgets::axes_indicator;
121
122// ---------------------------------------------------------------------------
123// Flat re-exports : these form the public crate API.
124// ---------------------------------------------------------------------------
125
126pub use error::{ViewportError, ViewportResult};
127
128pub use camera::animator::{CameraAnimator, CameraDamping, Easing};
129pub use camera::camera::{Camera, CameraTarget, Projection};
130pub use camera::frustum::{CullStats, Frustum};
131pub use camera::track::{CameraTrack, interpolate_camera};
132pub use camera::turntable::TurntableController;
133pub use camera::view_preset::ViewPreset;
134
135pub use scene::aabb::Aabb;
136pub use scene::material::{
137    BackfacePattern, BackfacePolicy, ItemSettings, Material, ParamVis, ParamVisMode, PatternConfig,
138    ShadingModel,
139};
140pub use scene::scene::{
141    DecalHandle, Group, GroupId, Layer, LayerId, LiveDecal, Scene, SceneNode, SceneStats,
142};
143pub use scene::traits::{RenderMode, ViewportObject};
144
145pub use geometry::bvh::PickAccelerator;
146pub use geometry::implicit::{
147    ImplicitRenderOptions, march_implicit_surface, march_implicit_surface_colour,
148};
149pub use geometry::isoline::{IsolineItem, extract_isolines};
150pub use geometry::marching_cubes::{VolumeData, extract_isosurface};
151
152pub use interaction::gizmo::{
153    Gizmo, GizmoAxis, GizmoMode, GizmoSpace, PivotMode, gizmo_center_for_pivot,
154};
155pub use interaction::input::{
156    Action, ActionState, Binding, FrameInput, InputMode, InputSystem, KeyCode, Modifiers,
157    MouseButton, NavigationMode,
158};
159// New input pipeline : re-exported at crate root for convenience.
160pub use interaction::input::{
161    ActionFrame, BindingPreset, ButtonState, ModifiersMatch, NavigationActions,
162    OrbitCameraController, ResolvedActionState, ScrollUnits, ViewportBinding, ViewportContext,
163    ViewportEvent, ViewportGesture, ViewportInput, viewport_all_bindings,
164};
165pub use interaction::manipulation::solvers::{
166    angular_rotation_from_cursor, constrained_scale, constrained_translation,
167};
168pub use interaction::manipulation::{
169    GizmoInfo, ManipResult, ManipulationContext, ManipulationController, ManipulationKind,
170    ManipulationState, TransformDelta,
171};
172
173pub use interaction::widgets::{
174    BoxWidget, CylinderWidget, DiskWidget, LineProbeWidget, PlaneWidget, PolylineWidget,
175    SphereWidget, SplineWidget, WidgetContext, WidgetResult,
176};
177
178pub use interaction::clip_plane::{
179    ClipAxis, ClipPlaneContext, ClipPlaneController, ClipPlaneDelta, ClipPlaneHit, ClipPlaneResult,
180    ClipPlaneSessionKind, hit_test_normal_handle, hit_test_plane_quad, plane_from_axis_preset,
181    project_drag_onto_normal, ray_plane_intersection, snap_plane_distance,
182};
183pub use interaction::pick_mask::PickMask;
184pub use interaction::picking::{
185    GpuPickHit, PickHit, ProbeBinding, RectPickResult, nearest_vertex_on_hit,
186    pick_gaussian_splat_cpu, pick_gaussian_splat_rect, pick_point_cloud_cpu, pick_rect,
187    pick_scene_accelerated_with_probe_cpu, pick_scene_nodes_with_probe_cpu,
188    pick_scene_with_probe_cpu, pick_transparent_volume_mesh_cpu, pick_transparent_volume_mesh_rect,
189    pick_volume_cpu, pick_volume_rect, voxel_world_aabb,
190};
191pub use interaction::selection::{NodeId, Selection};
192pub use interaction::snap::{ConstraintOverlay, SnapConfig};
193pub use interaction::sub_object;
194pub use interaction::sub_object::{
195    CellSelectionInfo, PolylineSelectionInfo, SubObjectRef, SubSelection, SubSelectionRef,
196    VolumeSelectionInfo,
197};
198
199pub use widgets::axes_indicator::AxisView;
200
201pub use renderer::ShadowDebugStats;
202pub use renderer::shader_hashes::ShaderValidation;
203pub use renderer::stats::{FrameStats, PerformancePolicy, QualityPreset, RuntimeMode};
204pub use renderer::{
205    AnimTrack, AtlasViewerCorner, BorderMode, CameraFrame, ClipObject, ClipShape,
206    ComputeFilterItem, ComputeFilterKind, CylindricalFacing, DebugOutputMode, DebugQuantity,
207    DebugVis, DecalAnimation, DecalBlendMode, DecalItem, DecalProjection, EffectsFrame,
208    EmitterConfig, EnvironmentMap, FilterMode, ForceField, FrameData, GaussianSplatData,
209    GaussianSplatId, GaussianSplatItem, GlyphItem, GlyphSetRefItem, GlyphType,
210    GpuParticleSystemItem, GradientStop, GroundPlane, GroundPlaneMode, ImageAnchor, ImageSliceItem,
211    InteractionFrame, LabelAnchor, LabelItem, LerpAnim, LicOverlay, LightKind, LightSource,
212    LightingSettings, LineCap, LineJoin, LoadingBarAnchor, LoadingBarItem, MeshInstanceItem,
213    NineSlice, OVERLAY_MAX_GRADIENT_STOPS, OverlayAnimation, OverlayAnimations, OverlayEasing, ParticleMeshAlign,
214    OverlayFill, OverlayFrame, OverlayImageItem, OverlayPolylineItem, OverlayRectItem,
215    OverlayShape, OverlayShapeItem, OverlayTextureId, OwnedPath, PassPath, PassView, PathTrack,
216    PickId, PickRectResult, PointCloudItem, PointCloudRefItem, PointRenderMode, PolylineItem,
217    PolylineRefItem, PostProcessSettings, RenderCamera, RepeatMode, RibbonItem, RibbonRefItem,
218    RulerItem, ScalarBarAnchor, ScalarBarItem, ScalarBarOrientation, ScatterQuality,
219    ScatterSettings, ScatterVolumeItem, SceneEffects, SceneFrame, SceneRenderItem, ScreenImageItem,
220    ShDegree, ShadowFilter, SliceAxis, SpawnShape, SpriteBlend, SpriteInstanceSetRefItem,
221    SpriteItem, SpriteOrientation, SpriteSetRefItem, SpriteSizeMode, StreamtubeItem,
222    StreamtubeRefItem, SurfaceLICConfig, SurfaceSubmission, TensorGlyphItem, TensorGlyphSetRefItem,
223    TextureTransform, TileMode, ToneMapping, TriangleDirection, TubeItem, TubeRefItem,
224    VelocityDist, ViewportEffects, ViewportFrame, ViewportId, ViewportRenderer, VolumeItem,
225    VolumeMeshItem, VolumeSurfaceSliceItem, VolumeTransparency, aabb_wireframe_polyline,
226    sphere_wireframe_polyline,
227};
228
229pub use quantities::{
230    edge_one_form_to_glyphs, face_intrinsic_to_glyphs, polyline_edge_vectors_to_glyphs,
231    polyline_node_vectors_to_glyphs, vertex_intrinsic_to_glyphs,
232    volume_mesh_cell_vectors_to_glyphs, volume_mesh_vertex_vectors_to_glyphs,
233};
234
235pub use resources::colourmap_data::{
236    export_paraview_xml_colourmap, lerp_colourmap_lut, parse_paraview_xml_colourmap,
237};
238pub use resources::{
239    DEFORM_PARAMS_PER_SLOT_PUB as DEFORM_PARAMS_PER_SLOT,
240    DEFORM_SLOT_COUNT_PUB as DEFORM_SLOT_COUNT, DEFORM_SLOT_PARAMS_BYTES, DeformSlotHandle,
241    DeformStage, DeformerDesc, DeformerId, deform_slot_params_byte_offset,
242};
243pub use resources::mesh_store::MeshId;
244pub use resources::sparse_volume::SparseVolumeGridData;
245pub use resources::volume_mesh::{CELL_SENTINEL, VolumeMeshData, extract_clipped_volume_faces};
246pub use resources::{
247    AttributeData, AttributeKind, AttributeRef, BuiltinColourmap, BuiltinMatcap, CLIP_VOLUME_MAX,
248    CameraUniform, ClipVolumeEntry, ClipVolumesUniform, ColourmapId, ComputeFilterResult,
249    FontError, FontHandle, GpuImplicitItem, GpuImplicitOptions, GpuMarchingCubesJob,
250    ImplicitBlendMode, ImplicitPrimitive, JobId, LightUniform, LightsUniform, MatcapId, MeshData,
251    ProgressHandle, SingleLightUniform, TextureMemoryStats,
252    UploadStatus, ViewportGpuResources, VolumeGpuId, VolumeId, lerp_attributes,
253};
254pub use resources::{
255    GlyphSetId, GpuParticleSystemConfig, GpuParticleSystemId, ParticleRender, PointCloudId,
256    PolylineId, RibbonId, SpriteInstanceSetId, SpriteSetId, StreamtubeId, TensorGlyphSetId, TubeId,
257};
258
259pub use runtime::{
260    CameraFollow, DebugDraw, DebugLayer, DebugPrim, FixedStepIter, FixedTimestep,
261    ManipulationSystem, NodeTransformOp, RuntimeFrameContext, RuntimeOutput, RuntimePhase,
262    RuntimePlugin, RuntimeStepContext, SceneRuntimeMode, SelectionOp, SelectionSystem,
263    SimulationStepContext, TransformSnapshot,
264    TransformSnapshotTable, TransformWriteback, ViewportRuntime,
265};
266