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/// Built-in plugins: skinning, animation, constraints, physics, skeleton.
85pub mod plugins;
86/// On-surface vector quantities (intrinsic vectors, Whitney one-forms).
87pub mod quantities;
88/// Main viewport renderer wrapping all GPU resources.
89pub mod renderer;
90/// GPU resource container (pipelines, buffers, bind groups).
91pub mod resources;
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, FirstPersonCameraController, ModifiersMatch,
162    NavigationActions, OrbitCameraController, ResolvedActionState, ScrollUnits,
163    ThirdPersonCameraController, ViewportBinding, ViewportContext, ViewportEvent, ViewportGesture,
164    ViewportInput, viewport_all_bindings, wish_xy_from_actions,
165};
166pub use interaction::manipulation::solvers::{
167    angular_rotation_from_cursor, constrained_scale, constrained_translation,
168};
169pub use interaction::manipulation::{
170    GizmoInfo, ManipResult, ManipulationContext, ManipulationController, ManipulationKind,
171    ManipulationState, TransformDelta,
172};
173
174pub use interaction::widgets::{
175    BoxWidget, CylinderWidget, DiskWidget, LineProbeWidget, PlaneWidget, PolylineWidget,
176    SphereWidget, SplineWidget, WidgetContext, WidgetResult,
177};
178
179pub use interaction::clip_plane::{
180    ClipAxis, ClipPlaneContext, ClipPlaneController, ClipPlaneDelta, ClipPlaneHit, ClipPlaneResult,
181    ClipPlaneSessionKind, hit_test_normal_handle, hit_test_plane_quad, plane_from_axis_preset,
182    project_drag_onto_normal, ray_plane_intersection, snap_plane_distance,
183};
184pub use interaction::pick_mask::PickMask;
185pub use interaction::picking::{
186    GpuPickHit, PickHit, ProbeBinding, RectPickResult, nearest_vertex_on_hit,
187    pick_gaussian_splat_cpu, pick_gaussian_splat_rect, pick_point_cloud_cpu,
188    pick_scene_accelerated_with_probe_cpu, pick_scene_nodes_with_probe_cpu,
189    pick_scene_with_probe_cpu, pick_transparent_volume_mesh_cpu, pick_transparent_volume_mesh_rect,
190    pick_volume_cpu, pick_volume_rect, voxel_world_aabb,
191};
192pub use interaction::selection::{NodeId, Selection};
193pub use interaction::snap::{ConstraintOverlay, SnapConfig};
194pub use interaction::sub_object;
195pub use interaction::sub_object::{
196    CellSelectionInfo, PolylineSelectionInfo, SubObjectRef, SubSelection, SubSelectionRef,
197    VolumeSelectionInfo,
198};
199
200pub use widgets::axes_indicator::AxisView;
201
202pub use renderer::ShadowDebugStats;
203pub use renderer::shader_hashes::ShaderValidation;
204pub use renderer::stats::{
205    FrameStats, GpuBreakdown, PerformancePolicy, PrepareBreakdown, QualityPreset, RuntimeMode,
206};
207pub use renderer::{
208    AnimTrack, AtlasViewerCorner, BorderMode, CameraFrame, ClipObject, ClipShape,
209    ComputeFilterItem, ComputeFilterKind, CylindricalFacing, DebugOutputMode, DebugQuantity,
210    DebugVis, DecalAnimation, DecalBlendMode, DecalItem, DecalProjection, EffectsFrame,
211    EmitterConfig, EnvironmentMap, FilterMode, ForceField, FrameData, GaussianSplatData,
212    GaussianSplatId, GaussianSplatItem, GlyphItem, GlyphSetRefItem, GlyphType,
213    GpuParticleSystemItem, GradientStop, GroundPlane, GroundPlaneMode, ImageAnchor, ImageSliceItem,
214    InteractionFrame, LabelAnchor, LabelItem, LerpAnim, LicOverlay, LightKind, LightSource,
215    LightingSettings, LineCap, LineJoin, LoadingBarAnchor, LoadingBarItem, MeshInstanceItem,
216    NineSlice, OVERLAY_MAX_GRADIENT_STOPS, OverlayAnimation, OverlayAnimations, OverlayEasing,
217    OverlayFill, OverlayFrame, OverlayImageItem, OverlayPolylineItem, OverlayRectItem,
218    OverlayShape, OverlayShapeItem, OverlayTextureId, OwnedPath, ParticleMeshAlign, PassPath,
219    PassView, PathTrack, PickId, PickRectResult, PointCloudItem, PointCloudRefItem,
220    PointRenderMode, PolylineItem, PolylineRefItem, PostProcessSettings, RenderCamera, RepeatMode,
221    RibbonItem, RibbonRefItem, RulerItem, ScalarBarAnchor, ScalarBarItem, ScalarBarOrientation,
222    ScatterQuality, ScatterSettings, ScatterVolumeItem, SceneEffects, SceneFrame, SceneRenderItem,
223    ScreenImageItem, ShDegree, ShadowFilter, SliceAxis, SpawnShape, SpriteBlend,
224    SpriteInstanceSetRefItem, SpriteItem, SpriteOrientation, SpriteSetRefItem, SpriteSizeMode,
225    StreamtubeItem, StreamtubeRefItem, SurfaceLICConfig, SurfaceSubmission, TensorGlyphItem,
226    TensorGlyphSetRefItem, TextureTransform, TileMode, ToneMapping, TriangleDirection, TubeItem,
227    TubeRefItem, VelocityDist, ViewportEffects, ViewportFrame, ViewportId, ViewportRenderer,
228    VolumeItem, VolumeMeshItem, VolumeSurfaceSliceItem, VolumeTransparency,
229    aabb_wireframe_polyline, sphere_wireframe_polyline,
230};
231
232pub use quantities::{
233    edge_one_form_to_glyphs, face_intrinsic_to_glyphs, polyline_edge_vectors_to_glyphs,
234    polyline_node_vectors_to_glyphs, vertex_intrinsic_to_glyphs,
235    volume_mesh_cell_vectors_to_glyphs, volume_mesh_vertex_vectors_to_glyphs,
236};
237
238pub use resources::colourmap_data::{
239    export_paraview_xml_colourmap, lerp_colourmap_lut, parse_paraview_xml_colourmap,
240};
241pub use resources::lod::{LodGroup, LodGroupId, LodLevel, LodTransition, projected_screen_size};
242pub use resources::mesh_store::MeshId;
243pub use resources::sparse_volume::SparseVolumeGridData;
244pub use resources::tetmesh::{TetMesh, TetMeshAttributes};
245pub use resources::volume_mesh::{
246    CELL_SENTINEL, ConversionReport, ToTetMeshError, VolumeMeshData, extract_clipped_volume_faces,
247};
248pub use resources::{
249    AttributeData, AttributeKind, AttributeRef, BuiltinColourmap, BuiltinMatcap, CLIP_VOLUME_MAX,
250    CameraUniform, ClipVolumeEntry, ClipVolumesUniform, ColourmapId, ComputeFilterResult,
251    FontError, FontHandle, GpuImplicitItem, GpuImplicitOptions, GpuMarchingCubesJob,
252    ImplicitBlendMode, ImplicitPrimitive, JobId, LightUniform, LightsUniform, MatcapId, MeshData,
253    ProgressHandle, SingleLightUniform, TextureMemoryStats, UploadStatus, ViewportGpuResources,
254    VolumeGpuId, VolumeId, lerp_attributes,
255};
256pub use resources::{
257    DEFORM_PARAMS_PER_SLOT_PUB as DEFORM_PARAMS_PER_SLOT,
258    DEFORM_SLOT_COUNT_PUB as DEFORM_SLOT_COUNT, DEFORM_SLOT_PARAMS_BYTES, DeformSlotHandle,
259    DeformStage, DeformerDesc, DeformerId, deform_slot_params_byte_offset,
260};
261pub use resources::{
262    GlyphSetId, GpuParticleSystemConfig, GpuParticleSystemId, ParticleRender, PointCloudId,
263    PolylineId, RibbonId, SpriteInstanceSetId, SpriteSetId, StreamtubeId, TensorGlyphSetId, TubeId,
264};
265
266pub use runtime::{
267    CameraFollow, DebugDraw, DebugLayer, DebugPrim, FixedStepIter, FixedTimestep,
268    ManipulationSystem, NodeTransformOp, RuntimeFrameContext, RuntimeOutput, RuntimePhase,
269    RuntimePlugin, RuntimeStepContext, SceneRuntimeMode, SelectionOp, SelectionSystem,
270    SimulationStepContext, TransformSnapshot, TransformSnapshotTable, TransformWriteback,
271    ViewportRuntime,
272};