@micrio/client 7.0.7 → 7.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/micrio.min.d.ts CHANGED
@@ -1444,6 +1444,14 @@ declare module '@micrio/client' {
1444
1444
  #private;
1445
1445
  /** Possible .zoom() override for Book3D */
1446
1446
  _zoomOverride: ((n: number) => void) | undefined;
1447
+ /** Possible override for Book3D */
1448
+ _isZoomedInOverride: (() => boolean) | undefined;
1449
+ /** Possible override for `_getXYDirect` for Book3D */
1450
+ _getXYDirectOverride: ((x: number, y: number) => Float64Array) | undefined;
1451
+ /** getMatrix book3d override */
1452
+ _getMatrixOverride: ((x: number, y: number, scale: number, rotX?: number, rotY?: number, rotZ?: number, scaleX?: number, scaleY?: number,
1453
+ /** The element's content width in CSS pixels (used to convert `scale` to a world size). */
1454
+ width?: number) => Float32Array) | undefined;
1447
1455
  /**
1448
1456
  * Gets the current image view rectangle [x0, y0, width, height].
1449
1457
  */
@@ -1547,7 +1555,9 @@ declare module '@micrio/client' {
1547
1555
  * @param x The image X coordinate (0-1).
1548
1556
  * @param y The image Y coordinate (0-1).
1549
1557
  * @param scale The object scale multiplier.
1550
- * @param radius The object radius (distance from center, default 10).
1558
+ * @param radius The object radius (distance from center, default 10). For Book3D images
1559
+ * this is used as the element's content width in CSS pixels, so `scale` stays a fraction
1560
+ * of the page width.
1551
1561
  * @param rotX The object X rotation in radians.
1552
1562
  * @param rotY The object Y rotation in radians.
1553
1563
  * @param rotZ The object Z rotation in radians.
@@ -1771,6 +1781,490 @@ declare module '@micrio/client' {
1771
1781
  animateTo(idx: number): void;
1772
1782
  }
1773
1783
 
1784
+ export class Vec3 {
1785
+ #private;
1786
+ _x: number;
1787
+ _y: number;
1788
+ _z: number;
1789
+ constructor(_x?: number, _y?: number, _z?: number);
1790
+ _clone(): Vec3;
1791
+ _set(x: number, y: number, z: number): Vec3;
1792
+ _copy(v: Vec3): Vec3;
1793
+ _add(v: Vec3): Vec3;
1794
+ _sub(v: Vec3): Vec3;
1795
+ _length(): number;
1796
+ _normalize(): Vec3;
1797
+ _dot(v: Vec3): number;
1798
+ _cross(v: Vec3): Vec3;
1799
+ }
1800
+
1801
+ /** Thickness of a single paper page in world-space units */
1802
+ export const PAGE_THICKNESS = 0.0012;
1803
+ /** Default page aspect ratio (height / width) — √2 ≅ A4 paper */
1804
+ export const DEFAULT_ASPECT: number;
1805
+ /** Use each page's own aspect ratio from source images instead of the book-wide average */
1806
+ export const USE_INDIVIDUAL_ASPECTS = false;
1807
+ /** Whether the first/last pages are rendered as hard covers */
1808
+ export const HARD_COVER = false;
1809
+ /** Cover thickness relative to a regular paper page */
1810
+ export const COVER_THICKNESS_MULTIPLIER = 16;
1811
+ /** Cover face scale relative to paper face (1.04 = 4% larger on width) */
1812
+ export const COVER_SCALE_X = 1.04;
1813
+ /** Cover face scale relative to paper face on height axis (1.08 = 8% taller) */
1814
+ export const COVER_SCALE_Y = 1.08;
1815
+ /** Number of vertex columns in the paper/cover face grid */
1816
+ export const GRID_COLS = 10;
1817
+ /** Number of vertex rows in the paper/cover face grid */
1818
+ export const GRID_ROWS = 14;
1819
+ /** Total vertex count per face grid */
1820
+ export const VERTEX_COUNT: number;
1821
+ /** Flip speed multiplier (1.0 = baseline, higher = faster flip) */
1822
+ export const FLIP_SPEED = 0.6;
1823
+ /** How far from the top edge to grab the corner during a flip (0.0 = top, 1.0 = bottom) */
1824
+ export const GRAB_ROW = 0.35;
1825
+ /** Maximum random offset added to GRAB_ROW each flip, to make the transition more natural */
1826
+ export const GRAB_ROW_MAX_OFFSET = 0.12;
1827
+ /** Tighter max random offset used during rapid .goto() flips for a more uniform look */
1828
+ export const GOTO_GRAB_ROW_MAX_OFFSET = 0.02;
1829
+ /** Peak arc height of the flipped corner above the rest position */
1830
+ export const ARC_PEAK = 0.7;
1831
+ /** Base duration (seconds) for a full page flip at speed 1.0 */
1832
+ export const BASE_FLIP_DURATION = 0.6;
1833
+ /** Number of constraint solver iterations per substep */
1834
+ export const SOLVER_ITERATIONS = 64;
1835
+ /** Number of physics substeps per frame */
1836
+ export const SOLVER_SUBSTEPS = 3;
1837
+ /** Distance constraint compliance (0.0 = perfectly stiff) */
1838
+ export const DISTANCE_COMPLIANCE = 0;
1839
+ /** Bending constraint compliance (lower = stiffer) */
1840
+ export const BENDING_COMPLIANCE = 0.000041;
1841
+ /** Velocity damping per substep (0.92 = 8% velocity loss per substep) */
1842
+ export const DAMPING = 0.975;
1843
+ /** Damping used during rapid .goto() page-flip cascades (higher = faster settling) */
1844
+ export const GOTO_DAMPING = 0.995;
1845
+ /** Gravitational acceleration in world-space units */
1846
+ export const GRAVITY = 9.81;
1847
+ /** Whether gravity is active */
1848
+ export const GRAVITY_ENABLED = true;
1849
+ /** Minimum vertex position delta to consider a page still "active" — below this it goes idle */
1850
+ export const DELTA_IDLE_THRESHOLD = 0.000001;
1851
+ /** Margin around the book as a fraction of the smaller viewport dimension (0.05 = 5%) */
1852
+ export const VIEWPORT_MARGIN_PCT = 0.05;
1853
+ /** Default camera polar angle in radians (0 = side view, π/2 = directly overhead) */
1854
+ export const DEFAULT_CAMERA_PHI: number;
1855
+ /** RGB tint for the front face of each page */
1856
+ export const FRONT_COLOR: [number, number, number];
1857
+ /** RGB tint for the back face of each page */
1858
+ export const BACK_COLOR: [number, number, number];
1859
+ /** Base URL for IIIF image server */
1860
+ export const IIIF_BASE_URL = "https://iiif.micr.io";
1861
+ /** Base debounce before starting a download for the currently viewed spread (ms) */
1862
+ export const IIIF_DEBOUNCE_BASE_MS = 500;
1863
+ /** Additional debounce per page distance from the spread center (ms) */
1864
+ export const IIIF_DEBOUNCE_PER_DISTANCE_MS = 2000;
1865
+ /** Duration of the cross-fade from low-res to hi-res texture (ms) */
1866
+ export const IIIF_CROSSFADE_DURATION = 500;
1867
+ /** Spreads away from the current spread before hi-res textures are pre-loaded */
1868
+ export const IIIF_PRELOAD_DISTANCE = 1;
1869
+ /** Spreads away from the current spread before hi-res textures are evicted from GPU */
1870
+ export const IIIF_GPU_EVICT_DISTANCE = 5;
1871
+ /** Default camera radius (used as baseline for zoom-aware IIIF resolution choice) */
1872
+ export const DEFAULT_CAMERA_RADIUS = 2.2;
1873
+ /** Master toggle for the tilt-shift blur effect */
1874
+ export const TILT_SHIFT_ENABLED = true;
1875
+ /** Normalised screen-space Y coordinate of the in-focus band centre (0 = bottom, 1 = top) */
1876
+ export const TILT_SHIFT_FOCUS_CENTER = 0.55;
1877
+ /** Vertical height of the sharp in-focus band as a fraction of the viewport */
1878
+ export const TILT_SHIFT_FOCUS_WIDTH = 0.25;
1879
+ /** Maximum blur radius in screen pixels (applied at the furthest distance from the focus band) */
1880
+ export const TILT_SHIFT_BLUR_RADIUS = 4;
1881
+ /** Sharpness of the transition between in-focus and blurred regions (higher = sharper) */
1882
+ export const TILT_SHIFT_BLUR_FALLOFF = 1;
1883
+ /** Active lighting preset name. Available: 'daylight', 'incandescent', 'candlelight', 'rainy day', 'moonlight', 'fireplace', 'haunted' */
1884
+ export const LIGHTING_PRESET = "daylight";
1885
+
1886
+ export { GRID_COLS, GRID_ROWS, VERTEX_COUNT } from "book/core/settings";
1887
+ export interface EdgeConstraint {
1888
+ _i: number;
1889
+ _j: number;
1890
+ _restLength: number;
1891
+ }
1892
+ export interface BendingConstraint {
1893
+ _i: number;
1894
+ _j: number;
1895
+ _restLength: number;
1896
+ }
1897
+ export interface TriangleData {
1898
+ _indices: [number, number, number];
1899
+ }
1900
+ export function buildIndexBuffer(triangles: TriangleData[]): Uint32Array;
1901
+ export function computeVertexNormals(positions: Float32Array, triangles: TriangleData[], vertexCount: number): Float32Array;
1902
+ export function addEdgeConstraint(i: number, j: number, restPositions: Float32Array, added: Set<string>, constrs: EdgeConstraint[]): void;
1903
+ export function addGridConstraints(baseIdx: number, add: (i: number, j: number) => void): void;
1904
+
1905
+ export { GRID_COLS, GRID_ROWS, VERTEX_COUNT } from "book/core/settings";
1906
+ export type { EdgeConstraint, BendingConstraint, TriangleData };
1907
+ export class PaperMesh {
1908
+ _restPositions: Float32Array;
1909
+ _positions: Float32Array;
1910
+ _velocities: Float32Array;
1911
+ _invMasses: Float32Array;
1912
+ _texCoords: Float32Array;
1913
+ _triangles: TriangleData[];
1914
+ _indexBuffer: Uint32Array;
1915
+ _distanceConstraints: EdgeConstraint[];
1916
+ _bendingConstraints: BendingConstraint[];
1917
+ _boundLeft: number[];
1918
+ readonly _yOffset: number;
1919
+ readonly _paperWidth: number;
1920
+ readonly _paperHeight: number;
1921
+ constructor(yOffset?: number, paperWidth?: number, aspectRatio?: number);
1922
+ protected _generateGrid(paperHeight: number): void;
1923
+ protected _generateTexCoords(): void;
1924
+ protected _generateTriangles(): void;
1925
+ protected _generateDistanceConstraints(): void;
1926
+ protected _generateBendingConstraints(): void;
1927
+ protected _identifyBoundEdges(): void;
1928
+ _reset(): void;
1929
+ _setBinding(): void;
1930
+ _computeNormals(): Float32Array;
1931
+ }
1932
+
1933
+ export class CoverMesh extends PaperMesh {
1934
+ #private;
1935
+ readonly _coverThickness: number;
1936
+ readonly _coverScale: number;
1937
+ readonly _coverScaleY: number;
1938
+ constructor(yOffset?: number, paperWidth?: number, aspectRatio?: number, coverThickness?: number, coverScale?: number, coverScaleY?: number);
1939
+ protected _generateGrid(): void;
1940
+ protected _generateTexCoords(): void;
1941
+ protected _generateTriangles(): void;
1942
+ protected _generateDistanceConstraints(): void;
1943
+ protected _generateBendingConstraints(): void;
1944
+ protected _identifyBoundEdges(): void;
1945
+ _computeNormals(): Float32Array;
1946
+ }
1947
+
1948
+ export class OrbitCamera {
1949
+ #private;
1950
+ _theta: number;
1951
+ _phi: number;
1952
+ _radius: number;
1953
+ _target: Vec3;
1954
+ _rotateSpeed: number;
1955
+ _zoomSpeed: number;
1956
+ _minRadius: number;
1957
+ _maxRadius: number;
1958
+ _panBoundsMin: Vec3 | null;
1959
+ _panBoundsMax: Vec3 | null;
1960
+ _freeCamMode: boolean;
1961
+ _canPanLeft: boolean;
1962
+ _canPanRight: boolean;
1963
+ _canPanUp: boolean;
1964
+ _canPanDown: boolean;
1965
+ _manualZoomActive: boolean;
1966
+ _isZoomedIn(): boolean;
1967
+ _fov: number;
1968
+ _setCanvasSize(w: number, h: number): void;
1969
+ _initContainRadius(bounds: {
1970
+ minX: number;
1971
+ maxX: number;
1972
+ minZ: number;
1973
+ maxZ: number;
1974
+ }, margin: number): void;
1975
+ _snap(): void;
1976
+ _update(dt: number): void;
1977
+ _isMoving(): boolean;
1978
+ _getEye(): Vec3;
1979
+ _getViewMatrix(): Mat4;
1980
+ _setFreeCamMode(on: boolean): void;
1981
+ _rotate(deltaTheta: number, deltaPhi: number, clampPhi?: boolean): void;
1982
+ _getPickRay(screenX: number, screenY: number): {
1983
+ origin: Vec3;
1984
+ direction: Vec3;
1985
+ };
1986
+ _zoom(delta: number, hitPoint?: Vec3): void;
1987
+ _pan(deltaX: number, deltaY: number): void;
1988
+ _clampViewport(screenBounds: {
1989
+ minX: number;
1990
+ maxX: number;
1991
+ minY: number;
1992
+ maxY: number;
1993
+ }, viewportW: number, viewportH: number, margin: number): void;
1994
+ }
1995
+
1996
+ export interface LightingParam {
1997
+ key: string;
1998
+ default: number;
1999
+ }
2000
+ export interface LightingPreset {
2001
+ name: string;
2002
+ isAnimated: boolean;
2003
+ params: LightingParam[];
2004
+ }
2005
+ export interface LightingState {
2006
+ _lightDir: [number, number, number];
2007
+ _lightColor: [number, number, number];
2008
+ _ambientColor: [number, number, number];
2009
+ _numPointLights: number;
2010
+ _pointLightPos: Float32Array;
2011
+ _pointLightColor: Float32Array;
2012
+ _pointLightIntensity: Float32Array;
2013
+ _bumpStrength: number;
2014
+ }
2015
+ export function getPresets(): LightingPreset[];
2016
+ export function getPreset(name: string): LightingPreset | undefined;
2017
+ export function computeLighting(presetName: string, params: Record<string, number>, time: number): LightingState;
2018
+
2019
+ export function computeWeightFactor(progress: Float32Array, pageCount: number): number;
2020
+ export function computePageSpineY(pageIndex: number, progress: number, weightFactor: number, totalStackHeight: number, pageCount: number, pageThickness: number): number;
2021
+ export function computeAllPageFloors(progress: Float32Array, weightFactor: number, totalStackHeight: number, pageCount: number, pageThickness: number): Float32Array;
2022
+ export function applySpineDelta(positions: Float32Array, delta: number): void;
2023
+
2024
+ export function compileShader(gl: WebGL2RenderingContext, type: number, src: string): WebGLShader;
2025
+ export function createGLProgram(gl: WebGL2RenderingContext, vertSrc: string, fragSrc: string): WebGLProgram;
2026
+ export function setupTextureParams(gl: WebGL2RenderingContext, tex: WebGLTexture): void;
2027
+ export function createWhiteTexture(gl: WebGL2RenderingContext): WebGLTexture;
2028
+
2029
+ export class PaperRenderer {
2030
+ #private;
2031
+ _tiltShiftEnabled: boolean;
2032
+ constructor(gl: WebGL2RenderingContext);
2033
+ _initialize(meshes: PaperMesh[]): void;
2034
+ _setPageTextures(pageIndex: number, frontBitmap: TexImageSource, backBitmap: TexImageSource): void;
2035
+ _setPageHiResTexture(pageIdx: number, side: 0 | 1, slot: 0 | 1, bitmap: ImageBitmap): void;
2036
+ _setPageBlend(pageIdx: number, frontBlendA: number, frontBlendB: number, backBlendA: number, backBlendB: number): void;
2037
+ _evictPageHiRes(pageIdx: number, side: 0 | 1, slot: 0 | 1): void;
2038
+ _getCanvas(): HTMLCanvasElement;
2039
+ _setLightingPreset(name: string, params: Record<string, number>): void;
2040
+ _isLightingAnimated(): boolean;
2041
+ _resize(): void;
2042
+ _updateVertexBuffer(meshIndex: number, mesh: PaperMesh): void;
2043
+ _updateNormalBuffer(meshIndex: number, mesh: PaperMesh): void;
2044
+ _getBoundingBoxCorners(): Float32Array | null;
2045
+ _getCanvasSize(): {
2046
+ width: number;
2047
+ height: number;
2048
+ };
2049
+ /**
2050
+ * Projects the 8 bounding box corners to screen CSS pixel coordinates.
2051
+ * Returns { minX, maxX, minY, maxY } or null if no corners are visible.
2052
+ */
2053
+ _getBoundingBoxScreenBounds(viewProj: Mat4): {
2054
+ minX: number;
2055
+ maxX: number;
2056
+ minY: number;
2057
+ maxY: number;
2058
+ } | null;
2059
+ _setFlipProgress(progress: Float32Array): void;
2060
+ _setBoundingBox(min: {
2061
+ x: number;
2062
+ y: number;
2063
+ z: number;
2064
+ }, max: {
2065
+ x: number;
2066
+ y: number;
2067
+ z: number;
2068
+ }): void;
2069
+ _render(camera: OrbitCamera): void;
2070
+ }
2071
+
2072
+ export class InputHandler {
2073
+ #private;
2074
+ _onPrevPage: (() => void) | null;
2075
+ _onNextPage: (() => void) | null;
2076
+ _onPageClick: ((x: number, y: number) => {
2077
+ direction: 'prev' | 'next';
2078
+ grabRow: number;
2079
+ } | null) | null;
2080
+ _lastClickGrabRow: number | null;
2081
+ _onWheelZoom: ((screenX: number, screenY: number) => Vec3 | null) | null;
2082
+ /** Override for the zoomed-in check, e.g. wired to the viewer's own viewport-fit logic. */
2083
+ _isZoomedInFn: (() => boolean) | null;
2084
+ _onPageDragStart: ((startX: number, startY: number) => void) | null;
2085
+ _onPageDragMove: ((currentX: number, currentY: number) => void) | null;
2086
+ _onPageDragEnd: (() => void) | null;
2087
+ _operation: 'none' | 'orbit' | 'pan';
2088
+ constructor(canvas: HTMLCanvasElement, camera: OrbitCamera, onActivity: () => void);
2089
+ }
2090
+
2091
+ export class PageFlipAnimator {
2092
+ #private;
2093
+ _hardCoverPages: Set<number>;
2094
+ get _animating(): boolean;
2095
+ _isPageAnimating(pageIndex: number): boolean;
2096
+ /** -1 = flipping back (left→right), +1 = flipping forward (right→left), 0 = idle/dragging. */
2097
+ _getPageDirection(pageIndex: number): number;
2098
+ _getPageProgress(pageIndex: number): number;
2099
+ _setPageProgress(pageIndex: number, value: number): void;
2100
+ _instantFlip(mesh: PaperMesh, pageIndex: number): void;
2101
+ _initSlots(pageCount: number): void;
2102
+ _flipLeft(pageIndex?: number, grabRow?: number): void;
2103
+ _flipRight(pageIndex?: number, grabRow?: number): void;
2104
+ _beginDrag(pageIndex: number, grabRow: number): void;
2105
+ _setDragProgress(pageIndex: number, progress: number): void;
2106
+ _endDrag(pageIndex: number, direction: number): void;
2107
+ _isPageDragging(pageIndex: number): boolean;
2108
+ _reset(meshes: PaperMesh[]): void;
2109
+ _update(dt: number, meshes: PaperMesh[], selectedPage: number, totalStackHeight: number, pageCount: number, pageThickness: number): void;
2110
+ }
2111
+
2112
+ /** Structure-of-arrays constraint layout for cache-friendly iteration. */
2113
+ export interface ConstraintSet {
2114
+ count: number;
2115
+ i: Int32Array;
2116
+ j: Int32Array;
2117
+ restLength: Float32Array;
2118
+ }
2119
+ export interface SubstepParams {
2120
+ dt: number;
2121
+ solverIterations: number;
2122
+ distanceCompliance: number;
2123
+ bendingCompliance: number;
2124
+ damping: number;
2125
+ gravity: number;
2126
+ gravityEnabled: boolean;
2127
+ }
2128
+ /** Flatten a mesh's {_i, _j, _restLength} constraint list into SoA buffers. */
2129
+ export function buildConstraintSet(constraints: EdgeConstraint[] | BendingConstraint[]): ConstraintSet;
2130
+ /**
2131
+ * Run one XPBD substep over all vertices and constraints.
2132
+ * Mutates `positions` / `velocities` in place and writes the start-of-step
2133
+ * position backup into `prevPositions`.
2134
+ */
2135
+ export function runSubstep(positions: Float32Array, velocities: Float32Array, prevPositions: Float32Array, invMasses: Float32Array, N: number, distanceConstraints: ConstraintSet, bendingConstraints: ConstraintSet, distanceLambda: Float64Array, bendingLambda: Float64Array, params: SubstepParams, pageFloor: number): void;
2136
+
2137
+ export interface SolverSettings {
2138
+ _solverIterations: number;
2139
+ _substeps: number;
2140
+ _distanceCompliance: number;
2141
+ _bendingCompliance: number;
2142
+ _damping: number;
2143
+ _gravity: number;
2144
+ _gravityEnabled: boolean;
2145
+ }
2146
+ export function isWasmReady(): boolean;
2147
+ export function initWasmSolver(meshes: PaperMesh[], pageCount: number): Promise<void>;
2148
+ export function dispatchSolve(subDt: number, activeIndices: number[], substeps: number, solverSettings: SolverSettings, meshes: PaperMesh[], progress: Float32Array, totalStackHeight: number, pageCount: number, pageThickness: number): void;
2149
+
2150
+ export class IIIFTextureManager {
2151
+ #private;
2152
+ /** Set by the host so the manager can request a redraw when it has something new to show. */
2153
+ _onRequestFrame: (() => void) | null;
2154
+ constructor(renderer: PaperRenderer, baseUrl?: string);
2155
+ _init(images: Models.ImageInfo.ImageInfo[], pageCount: number, pageIdxes: number[][]): void;
2156
+ _onFrame(now: number, spreadCenter: number, cameraRadius: number): boolean;
2157
+ _hasPendingWork(): boolean;
2158
+ }
2159
+
2160
+ export interface PageClickResult {
2161
+ direction: 'prev' | 'next';
2162
+ grabRow: number;
2163
+ }
2164
+ export interface PageDragResult {
2165
+ pageIndex: number;
2166
+ grabRow: number;
2167
+ worldX: number;
2168
+ }
2169
+
2170
+ export interface RayHit {
2171
+ _t: number;
2172
+ _point: Vec3;
2173
+ _meshIndex: number;
2174
+ }
2175
+ export function rayIntersectMeshes(meshes: readonly PaperMesh[], origin: Vec3, direction: Vec3): RayHit | null;
2176
+
2177
+ export interface UvWorldResult {
2178
+ /** Interpolated world-space position on the deformed mesh. */
2179
+ _point: Vec3;
2180
+ /** Interpolated (normalized) world-space surface normal at that point. */
2181
+ _normal: Vec3;
2182
+ /** World-space direction of increasing image u (not normalized). */
2183
+ _tangentU: Vec3;
2184
+ /** World-space direction of increasing image v (not normalized). */
2185
+ _tangentV: Vec3;
2186
+ }
2187
+ /**
2188
+ * Returns the world-space position, surface normal and UV tangents of a
2189
+ * relative texture coordinate (u, v) on a page mesh, using the mesh's *current*
2190
+ * (possibly animated/displaced) positions.
2191
+ *
2192
+ * `side` is the page side the image is displayed on:
2193
+ * 0 = front face (sampled at uv directly),
2194
+ * 1 = back face (sampled with the U axis mirrored on a single-grid PaperMesh,
2195
+ * or on the separate back-face grid of a CoverMesh).
2196
+ *
2197
+ * Returns null when (u, v) falls outside [0, 1].
2198
+ */
2199
+ export function uvToWorldPosition(mesh: PaperMesh, u: number, v: number, side: 0 | 1): UvWorldResult | null;
2200
+ /**
2201
+ * Like `uvToWorldPosition` but returns only the interpolated world-space
2202
+ * position, skipping the surface normal and tangent computation.
2203
+ */
2204
+ export function sampleMeshPosition(mesh: PaperMesh, u: number, v: number, side: 0 | 1): Vec3 | null;
2205
+ /**
2206
+ * Projects a world-space point through the given view-projection matrix to CSS
2207
+ * pixel coordinates relative to the canvas top-left. Returns null when the point
2208
+ * is behind the camera.
2209
+ */
2210
+ export function projectWorldToScreen(point: Vec3, viewProj: Mat4, clientWidth: number, clientHeight: number): {
2211
+ x: number;
2212
+ y: number;
2213
+ } | null;
2214
+
2215
+ export interface DrawnImage {
2216
+ /** The micrio image id. */
2217
+ id: string;
2218
+ /**
2219
+ * A rough axis-aligned rectangle `[u, v, w, h]` in the image's texture UV
2220
+ * space (0..1) covering the part currently visible in the viewport. The
2221
+ * full texture visible is `[0, 0, 1, 1]`.
2222
+ */
2223
+ bounds: [number, number, number, number];
2224
+ }
2225
+ export interface BookViewerOptions {
2226
+ /** The WebGL2 canvas to render into. Must be present in the document and sized by its host. */
2227
+ _canvas: HTMLCanvasElement;
2228
+ /** The already-loaded book index JSON. */
2229
+ _images: Models.ImageInfo.ImageInfo[];
2230
+ /** Called whenever the current reading position changes. */
2231
+ _onPageChange?: (pageIdx: number) => void;
2232
+ /** Called whenever the camera moves (rotate/zoom/pan, including smoothing). */
2233
+ _onViewChange?: (images: DrawnImage[]) => void;
2234
+ /** Called after every frame that is drawn to the canvas, with the micrioIds of the images visible in the current spread (plus any page mid-flip), each with a rough `[u, v, w, h]` rectangle (in texture UV space 0..1) of the part visible in the viewport. */
2235
+ _onDraw?: (images: DrawnImage[]) => void;
2236
+ _hardCover?: boolean;
2237
+ _tiltShift?: boolean;
2238
+ _lightingPreset?: string;
2239
+ _useIndividualAspects?: boolean;
2240
+ _startPageIdx?: number;
2241
+ /** Base URL for the IIIF image server (hi-res streaming). */
2242
+ _iiifBaseUrl?: string;
2243
+ }
2244
+ export class BookViewer {
2245
+ #private;
2246
+ static _getPresets: typeof getPresets;
2247
+ readonly _ready: Promise<void>;
2248
+ constructor(options: BookViewerOptions);
2249
+ goto(pageIdx: number): void;
2250
+ zoom(delta: number): void;
2251
+ /**
2252
+ * Returns whether the camera is zoomed in beyond the fit view. This is the
2253
+ * complement of "the whole spread fits the viewport": when every currently
2254
+ * visible image shows its full texture (`[0, 0, 1, 1]` bounds) the view is
2255
+ * zoomed out, and any image cut off by the viewport means it is zoomed in.
2256
+ * Based on the last rendered frame's on-screen bounds, so it stays accurate
2257
+ * after zooming back out.
2258
+ */
2259
+ isZoomedIn(): boolean;
2260
+ setLightingPreset(name: string): void;
2261
+ _getCurrentPage(): number;
2262
+ _getPageCount(): number;
2263
+ _nextPage(grabRow?: number): void;
2264
+ _prevPage(grabRow?: number): void;
2265
+ _hookImageBook3d(img: MicrioImage): void;
2266
+ }
2267
+
1774
2268
  /**
1775
2269
  * Manages the HTML `<canvas>` element used for WebGL rendering,
1776
2270
  * handles resizing, and provides viewport information.