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