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::traits;
110pub use widgets::axes_indicator;
111
112// ---------------------------------------------------------------------------
113// Flat re-exports : these form the public crate API.
114// ---------------------------------------------------------------------------
115
116pub use error::{ViewportError, ViewportResult};
117
118pub use camera::animator::{CameraAnimator, CameraDamping, Easing};
119pub use camera::camera::{Camera, CameraTarget, Projection};
120pub use camera::frustum::{CullStats, Frustum};
121pub use camera::track::{CameraTrack, interpolate_camera};
122pub use camera::turntable::TurntableController;
123pub use camera::view_preset::ViewPreset;
124
125pub use scene::aabb::Aabb;
126pub use scene::material::{
127    AppearanceSettings, BackfacePattern, BackfacePolicy, Material, ParamVis, ParamVisMode,
128    PatternConfig,
129};
130pub use scene::scene::{Group, GroupId, Layer, LayerId, Scene, SceneNode, SceneStats};
131pub use scene::traits::{RenderMode, ViewportObject};
132
133pub use geometry::bvh::PickAccelerator;
134pub use geometry::implicit::{
135    ImplicitRenderOptions, march_implicit_surface, march_implicit_surface_colour,
136};
137pub use geometry::isoline::{IsolineItem, extract_isolines};
138pub use geometry::marching_cubes::{VolumeData, extract_isosurface};
139
140pub use interaction::gizmo::{
141    Gizmo, GizmoAxis, GizmoMode, GizmoSpace, PivotMode, gizmo_center_for_pivot,
142};
143pub use interaction::input::{
144    Action, ActionState, Binding, FrameInput, InputMode, InputSystem, KeyCode, Modifiers,
145    MouseButton, NavigationMode,
146};
147// New input pipeline : re-exported at crate root for convenience.
148pub use interaction::input::{
149    ActionFrame, BindingPreset, ButtonState, ModifiersMatch, NavigationActions,
150    OrbitCameraController, ResolvedActionState, ScrollUnits, ViewportBinding, ViewportContext,
151    ViewportEvent, ViewportGesture, ViewportInput, viewport_all_bindings,
152};
153pub use interaction::manipulation::solvers::{
154    angular_rotation_from_cursor, constrained_scale, constrained_translation,
155};
156pub use interaction::manipulation::{
157    GizmoInfo, ManipResult, ManipulationContext, ManipulationController, ManipulationKind,
158    ManipulationState, TransformDelta,
159};
160
161pub use interaction::widgets::{
162    BoxWidget, CylinderWidget, DiskWidget, LineProbeWidget, PlaneWidget, PolylineWidget,
163    SphereWidget, SplineWidget, WidgetContext, WidgetResult,
164};
165
166pub use interaction::clip_plane::{
167    ClipAxis, ClipPlaneContext, ClipPlaneController, ClipPlaneDelta, ClipPlaneHit, ClipPlaneResult,
168    ClipPlaneSessionKind, hit_test_normal_handle, hit_test_plane_quad, plane_from_axis_preset,
169    project_drag_onto_normal, ray_plane_intersection, snap_plane_distance,
170};
171pub use interaction::pick_mask::PickMask;
172pub use interaction::picking::{
173    GpuPickHit, PickHit, ProbeBinding, RectPickResult, nearest_vertex_on_hit,
174    pick_gaussian_splat_cpu, pick_gaussian_splat_rect, pick_point_cloud_cpu, pick_rect,
175    pick_scene_accelerated_with_probe_cpu, pick_scene_nodes_with_probe_cpu,
176    pick_scene_with_probe_cpu, pick_transparent_volume_mesh_cpu, pick_transparent_volume_mesh_rect,
177    pick_volume_cpu, pick_volume_rect, voxel_world_aabb,
178};
179pub use interaction::selection::{NodeId, Selection};
180pub use interaction::snap::{ConstraintOverlay, SnapConfig};
181pub use interaction::sub_object;
182pub use interaction::sub_object::{
183    CellSelectionInfo, PolylineSelectionInfo, SubObjectRef, SubSelection, SubSelectionRef,
184    VolumeSelectionInfo,
185};
186
187pub use widgets::axes_indicator::AxisView;
188
189pub use renderer::shader_hashes::ShaderValidation;
190pub use renderer::stats::{FrameStats, PerformancePolicy, QualityPreset, RuntimeMode};
191pub use renderer::{
192    CameraFrame, CameraFrustumItem, ClipObject, ClipShape, ComputeFilterItem, ComputeFilterKind,
193    EffectsFrame, EnvironmentMap, FilterMode, FrameData, GaussianSplatData, GaussianSplatId,
194    GaussianSplatItem, GlyphItem, GlyphType, GroundPlane, GroundPlaneMode, ImageAnchor,
195    ImageSliceItem, InteractionFrame, LabelAnchor, LabelItem, LightKind, LightSource,
196    LightingSettings, LoadingBarAnchor, LoadingBarItem, OwnedPath, PassPath, PassView, OverlayFrame, OverlayImageItem,
197    OverlayAnimation, OverlayFill, OverlayRectItem, OverlayShape, OverlayShapeItem,
198    OverlayTextureId, BorderMode, LineCap, PickId, TriangleDirection,
199    PickRectResult, PointCloudItem, PointRenderMode, PolylineItem, PostProcessSettings,
200    RenderCamera, RibbonItem, RulerItem, ScalarBarAnchor, ScalarBarItem, ScalarBarOrientation,
201    SceneEffects, SceneFrame, SceneRenderItem, ScreenImageItem, ShDegree, ShadowFilter, SliceAxis,
202    SpriteItem, SpriteSizeMode, StreamtubeItem, SurfaceLICConfig, SurfaceLICItem,
203    SurfaceSubmission, TensorGlyphItem, ToneMapping, TransparentVolumeMeshItem, TubeItem,
204    ViewportEffects, ViewportFrame, ViewportId, ViewportRenderer, VolumeItem, VolumeMeshItem,
205    VolumeSurfaceSliceItem, aabb_wireframe_polyline,
206};
207
208pub use quantities::{
209    edge_one_form_to_glyphs, face_intrinsic_to_glyphs, polyline_edge_vectors_to_glyphs,
210    polyline_node_vectors_to_glyphs, vertex_intrinsic_to_glyphs,
211    volume_mesh_cell_vectors_to_glyphs, volume_mesh_vertex_vectors_to_glyphs,
212};
213
214#[allow(deprecated)]
215pub use resources::ClipVolumeUniform;
216pub use resources::colourmap_data::{
217    export_paraview_xml_colourmap, lerp_colourmap_lut, parse_paraview_xml_colourmap,
218};
219pub use resources::mesh_store::MeshId;
220pub use resources::sparse_volume::SparseVolumeGridData;
221#[allow(deprecated)]
222pub use resources::volume_mesh::{
223    CELL_SENTINEL, TET_SENTINEL, VolumeMeshData, extract_clipped_volume_faces,
224};
225pub use resources::{
226    AttributeData, AttributeKind, AttributeRef, BuiltinColourmap, BuiltinMatcap, CLIP_VOLUME_MAX,
227    CameraUniform, ClipVolumeEntry, ClipVolumesUniform, ColourmapId, ComputeFilterResult, FontError,
228    FontHandle, GpuImplicitItem, GpuImplicitOptions, GpuMarchingCubesJob, ImplicitBlendMode,
229    ImplicitPrimitive, LightUniform, LightsUniform, MatcapId, MeshData, PendingTextureId,
230    ProjectedTetId, SingleLightUniform, SkinWeights, TextureMemoryStats, ViewportGpuResources,
231    VolumeGpuId, VolumeId, lerp_attributes,
232};
233
234pub use runtime::{
235    AnimationClip, AnimationPlugin, AnimationTrack, CameraFollow, Channel, ClipPlayerPlugin,
236    Constraint, ConstraintPlugin, ContactEvent, DebugDraw, DebugLayer, DebugPrim, FixedStepIter,
237    FixedTimestep, Interpolation, Joint, JointMatrices, Keyframe, ManipulationSystem,
238    NodeTransformOp, PhysicsBody, PhysicsLitePlugin, Pose, RuntimeFrameContext, RuntimeOutput,
239    RuntimePhase, RuntimePlugin, RuntimeStepContext, Sampler, SceneRuntimeMode, SelectionOp,
240    SelectionSystem, SimulationStepContext, Skeleton, SkeletonPlugin, SkinnedActor,
241    SkinnedActorPart, SkinnedActorPlugin, SkinnedMeshUpdate, SkinnedPoseUpdate, SkinningPath, Track, TrackValue, TrackValues,
242    TransformSnapshot, TransformSnapshotTable, TransformWriteback, ViewportRuntime, apply_skin,
243};