Back to home page

EIC code displayed by LXR

 
 

    


Warning, /firebird/packages/firebird-ng/api/src/lib/views.ts is written in an unsupported language. File is not indexed.

0001 /**
0002  * The render view contracts: what an extension sees of the views that draw
0003  * the shared scene, the options for adding one, view overlays, and the
0004  * camera-layer routing.
0005  *
0006  * Interfaces and plain constants only: this module is part of the initial
0007  * bundle and imports three.js types, never three.js values.
0008  */
0009 
0010 import type { OrthographicCamera, PerspectiveCamera, Plane, Raycaster, Vector2, Vector3 } from 'three';
0011 import type { ClippingGroup } from 'three/webgpu';
0012 import type { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
0013 import type { CameraLimits, Vec3Tuple } from './tokens';
0014 
0015 // ---------------------------------------------------------------------------
0016 // Camera-layer routing
0017 // ---------------------------------------------------------------------------
0018 //
0019 // Every camera renders layer 0 (helpers, lights) and EVENT_DATA_LAYER. The
0020 // detector geometry stays on layer 0 until a geometry slice exists; then the
0021 // original geometry moves to GEOMETRY_MAIN_LAYER (the main view enables it)
0022 // and the slice copy sits on GEOMETRY_SLICE_LAYER (views created with
0023 // `geometrySlice` enable it).
0024 
0025 /** Original detector geometry while a geometry slice exists: rendered by the main view. */
0026 export const GEOMETRY_MAIN_LAYER = 1;
0027 /** The geometry slice copy: rendered by views created with `geometrySlice`. */
0028 export const GEOMETRY_SLICE_LAYER = 2;
0029 /**
0030  * Event data: everything under `sceneEvent`. Every view renders it; a
0031  * tracks-on-top view renders it in a second pass over a cleared depth
0032  * buffer. Painted objects are routed here by the display; objects an
0033  * extension adds go through `SceneContext.addEventObject()`. The lights
0034  * carry this layer too: both passes must collect the same light set, or
0035  * every shared render object rebuilds each frame.
0036  */
0037 export const EVENT_DATA_LAYER = 3;
0038 
0039 // ---------------------------------------------------------------------------
0040 // Views
0041 // ---------------------------------------------------------------------------
0042 
0043 /** A camera pose: where the camera is, what it orbits, and its screen up. */
0044 export interface CameraPose {
0045   position: Vec3Tuple;
0046   target: Vec3Tuple;
0047   up: Vec3Tuple;
0048 }
0049 
0050 /** Viewport rectangle in CSS pixels, top-left origin, as three's WebGPURenderer takes it. */
0051 export interface ViewportRect {
0052   /** Left edge relative to the canvas. */
0053   x: number;
0054   /** Top edge relative to the canvas; pass to `renderer.setViewport`/`setScissor` as is. */
0055   y: number;
0056   width: number;
0057   height: number;
0058 }
0059 
0060 /**
0061  * The independently clipped copy of the detector geometry that projection
0062  * views cut (see `SceneContext.createGeometrySlice()`).
0063  *
0064  * @experimental Edits to the original geometry after a load (visibility,
0065  * materials) do not reach the copy until `rebuildGeometrySlice()`.
0066  */
0067 export interface GeometrySlice {
0068   /** The clipping group holding the copy; the display adds it to the scene. */
0069   readonly group: ClippingGroup;
0070   /** The one clip plane, written by each view with its own `clipPlane` before it renders. */
0071   readonly plane: Plane;
0072 }
0073 
0074 /**
0075  * One view of the shared scene: a DOM container, a perspective and an
0076  * orthographic camera, orbit controls on that container, and a rectangle
0077  * of the shared canvas. The display's own view is `SceneContext.mainView`;
0078  * `SceneContext.addView()` adds more.
0079  */
0080 export interface RenderView {
0081   /** The name given at creation ('main' for the display's view). */
0082   readonly name: string;
0083   /**
0084    * The element the view fills. Pointer input (controls, picking) arrives
0085    * here, never on the shared canvas; the element changes when the view
0086    * moves to another page (`ViewOverlay.onViewContainerChange`).
0087    */
0088   readonly container: HTMLElement;
0089   /** The active camera (perspective or orthographic). */
0090   readonly camera: PerspectiveCamera | OrthographicCamera;
0091   readonly perspectiveCamera: PerspectiveCamera;
0092   readonly orthographicCamera: OrthographicCamera;
0093   /** Orbit controls bound to `container`. */
0094   readonly controls: OrbitControls;
0095   /** True for a view created with `fixedDirection`: it pans and zooms, never rotates. */
0096   readonly isRotationLocked: boolean;
0097   /**
0098    * This view's geometry cut in world space, or null. Mutate its normal and
0099    * constant to move the cut, then set `dirty`.
0100    *
0101    * @experimental Works only on a view created with `geometrySlice`.
0102    */
0103   readonly clipPlane: Plane | null;
0104   /** Draws event data over geometry regardless of depth (two render passes). */
0105   tracksOnTop: boolean;
0106   /**
0107    * True when this view needs a new frame. Set it after changing a per-view
0108    * setting; the render loop clears it. `SceneContext.invalidate()` marks
0109    * every view.
0110    */
0111   dirty: boolean;
0112   /** The view's rectangle inside the canvas, y ready for `renderer.setViewport`. */
0113   readonly viewportRect: Readonly<ViewportRect>;
0114   /** CSS-pixel size of the view container. */
0115   readonly size: Readonly<{ width: number; height: number }>;
0116   /** Adds an overlay drawn after this view's scene render. */
0117   addOverlay(overlay: ViewOverlay): void;
0118   /** Removes an overlay and calls its `dispose()`. */
0119   removeOverlay(overlay: ViewOverlay): void;
0120   /**
0121    * Sets the screen up vector of both cameras and resyncs the orbit
0122    * controls, which capture the up axis once at construction.
0123    */
0124   setCameraUp(up: Vector3): void;
0125   /** Normalized device coordinates of a pointer event inside this view; null outside it. */
0126   ndcFromEvent(event: { clientX: number; clientY: number }): Vector2 | null;
0127   /** A raycaster through the pointer position for this view's camera; null outside the view. */
0128   raycasterFromEvent(event: { clientX: number; clientY: number }): Raycaster | null;
0129 }
0130 
0131 /**
0132  * Something drawn on top of a view after its scene render: an orientation
0133  * cube, axes, 2D annotations. Overlays render into the shared canvas and set
0134  * their own viewport (`RenderView.viewportRect`); restore what you change.
0135  * A render that throws removes the overlay.
0136  */
0137 export interface ViewOverlay {
0138   /** Called every rendered frame, after the view's scene render. */
0139   render(view: RenderView): void;
0140   /** Called when the view's size or position changed. */
0141   onViewResize?(view: RenderView): void;
0142   /** Called when the view moved to another DOM container (page switches). */
0143   onViewContainerChange?(view: RenderView): void;
0144   /** Called when the view or the overlay is removed. */
0145   dispose?(): void;
0146 }
0147 
0148 /** Options of `SceneContext.addView()`. */
0149 export interface RenderViewOptions {
0150   /** Shown in debug output and used to find views. */
0151   name: string;
0152   /**
0153    * The element this view fills. It must sit above the shared canvas;
0154    * pointer input is listened on it and the viewport rectangle tracks it.
0155    */
0156   container: HTMLElement;
0157   /** Start with the orthographic camera instead of the perspective one. */
0158   orthographic?: boolean;
0159   /**
0160    * Initial visible world height [mm] of an orthographic view. Zooming and
0161    * resizing keep the height/zoom relation.
0162    */
0163   orthoWorldHeight?: number;
0164   /**
0165    * Fixed view direction (unit vector from the target toward the camera)
0166    * and screen up, for projection views. The controls pan and zoom but do
0167    * not rotate.
0168    */
0169   fixedDirection?: { direction: [number, number, number]; up: [number, number, number] };
0170   /** Extra camera layers this view renders, besides layer 0 and EVENT_DATA_LAYER. */
0171   extraLayers?: number[];
0172   /**
0173    * The geometry slice this view renders instead of the original geometry
0174    * (its camera gets GEOMETRY_SLICE_LAYER). Views sharing the slice each
0175    * write their own `clipPlane` into it before they render.
0176    *
0177    * @experimental See `GeometrySlice`.
0178    */
0179   geometrySlice?: GeometrySlice;
0180   /**
0181    * This view's geometry cut in world space; requires `geometrySlice`. The
0182    * visible side is `normal . p + constant >= 0`.
0183    *
0184    * @experimental See `GeometrySlice`.
0185    */
0186   clipPlane?: { normal: [number, number, number]; constant: number };
0187   /** Draw event data over geometry regardless of depth (see `RenderView.tracksOnTop`). */
0188   tracksOnTop?: boolean;
0189   /** The camera pose at construction. Default: the top view, 7 m above the origin. */
0190   startPose?: CameraPose;
0191   /** Orbit distance limits [mm]. Default: the display's current limits. */
0192   distanceLimits?: CameraLimits;
0193 }