@expofp/renderer 0.0.0-experimental.cf063fc
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/README.md +145 -0
- package/dist/Renderer.d.ts +102 -0
- package/dist/Renderer.js +96 -0
- package/dist/controls/CameraControls.d.ts +108 -0
- package/dist/controls/CameraControls.js +203 -0
- package/dist/controls/Controls.d.ts +53 -0
- package/dist/controls/Controls.js +54 -0
- package/dist/controls/camera-api.d.ts +226 -0
- package/dist/controls/camera-api.js +179 -0
- package/dist/controls/gestures.d.ts +71 -0
- package/dist/controls/gestures.js +98 -0
- package/dist/controls/handlers/DoubleTapZoom.d.ts +23 -0
- package/dist/controls/handlers/DoubleTapZoom.js +82 -0
- package/dist/controls/handlers/Inertia.d.ts +60 -0
- package/dist/controls/handlers/Inertia.js +222 -0
- package/dist/controls/handlers/Pan.d.ts +23 -0
- package/dist/controls/handlers/Pan.js +212 -0
- package/dist/controls/handlers/Pitch.d.ts +19 -0
- package/dist/controls/handlers/Pitch.js +200 -0
- package/dist/controls/handlers/Roll.d.ts +30 -0
- package/dist/controls/handlers/Roll.js +196 -0
- package/dist/controls/handlers/Zoom.d.ts +28 -0
- package/dist/controls/handlers/Zoom.js +34 -0
- package/dist/controls/hooks.d.ts +136 -0
- package/dist/controls/hooks.js +200 -0
- package/dist/controls/index.d.ts +9 -0
- package/dist/controls/index.js +7 -0
- package/dist/controls/zoom-to.d.ts +89 -0
- package/dist/controls/zoom-to.js +91 -0
- package/dist/core/InstanceUniforms.d.ts +108 -0
- package/dist/core/InstanceUniforms.js +298 -0
- package/dist/core/SquareDataTexture.d.ts +277 -0
- package/dist/core/SquareDataTexture.js +476 -0
- package/dist/core/batch/BatchedMesh.d.ts +74 -0
- package/dist/core/batch/BatchedMesh.js +155 -0
- package/dist/core/instanced/FrustumCulling.d.ts +141 -0
- package/dist/core/instanced/FrustumCulling.js +246 -0
- package/dist/core/instanced/InstancedMesh.d.ts +302 -0
- package/dist/core/instanced/InstancedMesh.js +497 -0
- package/dist/core/instanced/Instances.d.ts +119 -0
- package/dist/core/instanced/Instances.js +230 -0
- package/dist/core/instanced/Raycasting.d.ts +118 -0
- package/dist/core/instanced/Raycasting.js +134 -0
- package/dist/core/instanced/instanced-material.d.ts +77 -0
- package/dist/core/instanced/instanced-material.js +228 -0
- package/dist/core/lines/BatchedLines.d.ts +137 -0
- package/dist/core/lines/BatchedLines.js +215 -0
- package/dist/core/lines/FrustumCullingLines.d.ts +44 -0
- package/dist/core/lines/FrustumCullingLines.js +85 -0
- package/dist/core/lines/RaycastingLines.d.ts +45 -0
- package/dist/core/lines/RaycastingLines.js +91 -0
- package/dist/core/lines/lines-material.d.ts +47 -0
- package/dist/core/lines/lines-material.js +124 -0
- package/dist/core/shader-source.d.ts +70 -0
- package/dist/core/shader-source.js +110 -0
- package/dist/core/sprites/BatchedSprites.d.ts +115 -0
- package/dist/core/sprites/BatchedSprites.js +173 -0
- package/dist/core/sprites/RaycastingSprites.d.ts +41 -0
- package/dist/core/sprites/RaycastingSprites.js +71 -0
- package/dist/core/sprites/sprite-material.d.ts +59 -0
- package/dist/core/sprites/sprite-material.js +192 -0
- package/dist/core/text/BatchedText.d.ts +233 -0
- package/dist/core/text/BatchedText.js +473 -0
- package/dist/core/text/MemberTexture.d.ts +90 -0
- package/dist/core/text/MemberTexture.js +289 -0
- package/dist/core/text/Text.d.ts +88 -0
- package/dist/core/text/Text.js +230 -0
- package/dist/core/text/batched-text-material.d.ts +56 -0
- package/dist/core/text/batched-text-material.js +123 -0
- package/dist/core/text/glyph-packing.d.ts +17 -0
- package/dist/core/text/glyph-packing.js +61 -0
- package/dist/core/typed-array.d.ts +16 -0
- package/dist/core/typed-array.js +20 -0
- package/dist/debug/components/DebugPanelProvider.d.ts +20 -0
- package/dist/debug/components/DebugPanelProvider.js +50 -0
- package/dist/debug/components/DebugTools.d.ts +22 -0
- package/dist/debug/components/DebugTools.js +28 -0
- package/dist/debug/components/Gui.d.ts +22 -0
- package/dist/debug/components/Gui.js +42 -0
- package/dist/debug/components/MemoryInfo.d.ts +22 -0
- package/dist/debug/components/MemoryInfo.js +42 -0
- package/dist/debug/components/Panel.d.ts +31 -0
- package/dist/debug/components/Panel.js +104 -0
- package/dist/debug/components/Stats.d.ts +9 -0
- package/dist/debug/components/Stats.js +24 -0
- package/dist/debug/debug-chunk.d.ts +26 -0
- package/dist/debug/debug-chunk.js +32 -0
- package/dist/debug/debug-context.d.ts +41 -0
- package/dist/debug/debug-context.js +59 -0
- package/dist/debug/index.d.ts +41 -0
- package/dist/debug/index.js +43 -0
- package/dist/events/LayoutDriver.d.ts +36 -0
- package/dist/events/LayoutDriver.js +192 -0
- package/dist/events/PointerMissed.d.ts +23 -0
- package/dist/events/PointerMissed.js +58 -0
- package/dist/events/def-culling.d.ts +46 -0
- package/dist/events/def-culling.js +69 -0
- package/dist/events/layout-targets.d.ts +151 -0
- package/dist/events/layout-targets.js +397 -0
- package/dist/events/placement/box.d.ts +59 -0
- package/dist/events/placement/box.js +96 -0
- package/dist/events/placement/grid.d.ts +161 -0
- package/dist/events/placement/grid.js +235 -0
- package/dist/events/placement/index.d.ts +2 -0
- package/dist/events/placement/index.js +1 -0
- package/dist/events/placement/pass.d.ts +70 -0
- package/dist/events/placement/pass.js +617 -0
- package/dist/events/pointer.d.ts +194 -0
- package/dist/events/pointer.js +356 -0
- package/dist/external/ExternalCanvas.d.ts +56 -0
- package/dist/external/ExternalCanvas.js +177 -0
- package/dist/external/external-camera.d.ts +18 -0
- package/dist/external/external-camera.js +103 -0
- package/dist/external/external-events.d.ts +14 -0
- package/dist/external/external-events.js +33 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +14 -0
- package/dist/objects/Background.d.ts +31 -0
- package/dist/objects/Background.js +37 -0
- package/dist/objects/containers/SlotContainer.d.ts +312 -0
- package/dist/objects/containers/SlotContainer.js +311 -0
- package/dist/objects/containers/hooks.d.ts +61 -0
- package/dist/objects/containers/hooks.js +196 -0
- package/dist/objects/containers/index.d.ts +6 -0
- package/dist/objects/containers/index.js +4 -0
- package/dist/objects/containers/keys.d.ts +10 -0
- package/dist/objects/containers/keys.js +18 -0
- package/dist/objects/containers/mesh-writes.d.ts +106 -0
- package/dist/objects/containers/mesh-writes.js +97 -0
- package/dist/objects/containers/props.d.ts +33 -0
- package/dist/objects/containers/props.js +1 -0
- package/dist/objects/images/ImageInstance.d.ts +29 -0
- package/dist/objects/images/ImageInstance.js +152 -0
- package/dist/objects/images/Images.d.ts +49 -0
- package/dist/objects/images/Images.js +394 -0
- package/dist/objects/images/atlas-packer.d.ts +129 -0
- package/dist/objects/images/atlas-packer.js +287 -0
- package/dist/objects/images/image-container.d.ts +74 -0
- package/dist/objects/images/image-container.js +100 -0
- package/dist/objects/images/index.d.ts +2 -0
- package/dist/objects/images/index.js +1 -0
- package/dist/objects/images/pack-sources.d.ts +190 -0
- package/dist/objects/images/pack-sources.js +272 -0
- package/dist/objects/images/texture-budget.d.ts +120 -0
- package/dist/objects/images/texture-budget.js +215 -0
- package/dist/objects/images/worker/atlas-worker.d.ts +56 -0
- package/dist/objects/images/worker/atlas-worker.js +123 -0
- package/dist/objects/images/worker/client.d.ts +62 -0
- package/dist/objects/images/worker/client.js +249 -0
- package/dist/objects/images/worker/index.d.ts +10 -0
- package/dist/objects/images/worker/index.js +1 -0
- package/dist/objects/layer/Layer.d.ts +28 -0
- package/dist/objects/layer/Layer.js +134 -0
- package/dist/objects/layer/index.d.ts +2 -0
- package/dist/objects/layer/index.js +1 -0
- package/dist/objects/layer/layer-context.d.ts +74 -0
- package/dist/objects/layer/layer-context.js +82 -0
- package/dist/objects/layer/mount-scheduler.d.ts +131 -0
- package/dist/objects/layer/mount-scheduler.js +289 -0
- package/dist/objects/layer/visibility-gui.d.ts +19 -0
- package/dist/objects/layer/visibility-gui.js +93 -0
- package/dist/objects/lighting/Lighting.d.ts +92 -0
- package/dist/objects/lighting/Lighting.js +384 -0
- package/dist/objects/lighting/OcclusionPasses.d.ts +23 -0
- package/dist/objects/lighting/OcclusionPasses.js +271 -0
- package/dist/objects/lighting/index.d.ts +11 -0
- package/dist/objects/lighting/index.js +10 -0
- package/dist/objects/lighting/lighting-gui.d.ts +24 -0
- package/dist/objects/lighting/lighting-gui.js +114 -0
- package/dist/objects/lighting/occluder.d.ts +34 -0
- package/dist/objects/lighting/occluder.js +62 -0
- package/dist/objects/lighting/occlusion-targets.d.ts +143 -0
- package/dist/objects/lighting/occlusion-targets.js +276 -0
- package/dist/objects/lines/LineInstance.d.ts +21 -0
- package/dist/objects/lines/LineInstance.js +73 -0
- package/dist/objects/lines/Lines.d.ts +17 -0
- package/dist/objects/lines/Lines.js +31 -0
- package/dist/objects/lines/index.d.ts +2 -0
- package/dist/objects/lines/index.js +1 -0
- package/dist/objects/lines/line-container.d.ts +35 -0
- package/dist/objects/lines/line-container.js +40 -0
- package/dist/objects/materials/ColorMaterial.d.ts +92 -0
- package/dist/objects/materials/ColorMaterial.js +124 -0
- package/dist/objects/materials/LineMaterial.d.ts +44 -0
- package/dist/objects/materials/LineMaterial.js +74 -0
- package/dist/objects/materials/ModelMaterial.d.ts +53 -0
- package/dist/objects/materials/ModelMaterial.js +111 -0
- package/dist/objects/materials/TextureMaterial.d.ts +33 -0
- package/dist/objects/materials/TextureMaterial.js +48 -0
- package/dist/objects/materials/effects/ao/ambient-occlusion-pass.d.ts +77 -0
- package/dist/objects/materials/effects/ao/ambient-occlusion-pass.js +296 -0
- package/dist/objects/materials/effects/ao/ambient-occlusion-patch.d.ts +29 -0
- package/dist/objects/materials/effects/ao/ambient-occlusion-patch.js +115 -0
- package/dist/objects/materials/effects/ao/blur-pass.d.ts +61 -0
- package/dist/objects/materials/effects/ao/blur-pass.js +101 -0
- package/dist/objects/materials/effects/ao/index.d.ts +129 -0
- package/dist/objects/materials/effects/ao/index.js +72 -0
- package/dist/objects/materials/effects/color-dim.d.ts +115 -0
- package/dist/objects/materials/effects/color-dim.js +206 -0
- package/dist/objects/materials/effects/contact-shadow.d.ts +100 -0
- package/dist/objects/materials/effects/contact-shadow.js +167 -0
- package/dist/objects/materials/effects/effects-context.d.ts +53 -0
- package/dist/objects/materials/effects/effects-context.js +24 -0
- package/dist/objects/materials/shared.d.ts +24 -0
- package/dist/objects/materials/shared.js +72 -0
- package/dist/objects/models/ModelInstance.d.ts +22 -0
- package/dist/objects/models/ModelInstance.js +33 -0
- package/dist/objects/models/Models.d.ts +22 -0
- package/dist/objects/models/Models.js +186 -0
- package/dist/objects/models/gltf-cache.d.ts +17 -0
- package/dist/objects/models/gltf-cache.js +50 -0
- package/dist/objects/models/index.d.ts +2 -0
- package/dist/objects/models/index.js +1 -0
- package/dist/objects/models/model-asset.d.ts +48 -0
- package/dist/objects/models/model-asset.js +77 -0
- package/dist/objects/models/model-container.d.ts +123 -0
- package/dist/objects/models/model-container.js +207 -0
- package/dist/objects/shapes/ShapeInstance.d.ts +26 -0
- package/dist/objects/shapes/ShapeInstance.js +39 -0
- package/dist/objects/shapes/Shapes.d.ts +21 -0
- package/dist/objects/shapes/Shapes.js +131 -0
- package/dist/objects/shapes/index.d.ts +2 -0
- package/dist/objects/shapes/index.js +1 -0
- package/dist/objects/shapes/shape-container.d.ts +141 -0
- package/dist/objects/shapes/shape-container.js +242 -0
- package/dist/objects/shapes/shape-geometry.d.ts +27 -0
- package/dist/objects/shapes/shape-geometry.js +94 -0
- package/dist/objects/text/TextInstance.d.ts +22 -0
- package/dist/objects/text/TextInstance.js +95 -0
- package/dist/objects/text/Texts.d.ts +30 -0
- package/dist/objects/text/Texts.js +43 -0
- package/dist/objects/text/index.d.ts +2 -0
- package/dist/objects/text/index.js +1 -0
- package/dist/objects/text/text-container.d.ts +121 -0
- package/dist/objects/text/text-container.js +229 -0
- package/dist/objects/text/text-layout.d.ts +92 -0
- package/dist/objects/text/text-layout.js +180 -0
- package/dist/space/Camera.d.ts +103 -0
- package/dist/space/Camera.js +321 -0
- package/dist/space/Scene.d.ts +47 -0
- package/dist/space/Scene.js +127 -0
- package/dist/space/Space.d.ts +325 -0
- package/dist/space/Space.js +359 -0
- package/dist/space/VisibleRect.d.ts +45 -0
- package/dist/space/VisibleRect.js +129 -0
- package/dist/space/camera-handle.d.ts +67 -0
- package/dist/space/camera-handle.js +63 -0
- package/dist/space/camera-kind.d.ts +26 -0
- package/dist/space/camera-kind.js +30 -0
- package/dist/space/canvas-size.d.ts +24 -0
- package/dist/space/canvas-size.js +20 -0
- package/dist/space/clipping.d.ts +69 -0
- package/dist/space/clipping.js +130 -0
- package/dist/space/layout-measure.d.ts +67 -0
- package/dist/space/layout-measure.js +175 -0
- package/dist/space/viewport.d.ts +112 -0
- package/dist/space/viewport.js +67 -0
- package/dist/types/defs.d.ts +234 -0
- package/dist/types/defs.js +1 -0
- package/dist/types/events.d.ts +198 -0
- package/dist/types/events.js +1 -0
- package/dist/types/guards.d.ts +21 -0
- package/dist/types/guards.js +52 -0
- package/dist/update/index.d.ts +3 -0
- package/dist/update/index.js +2 -0
- package/dist/update/slot-writers.d.ts +30 -0
- package/dist/update/slot-writers.js +76 -0
- package/dist/update/store.d.ts +41 -0
- package/dist/update/store.js +104 -0
- package/dist/utils/arrays.d.ts +13 -0
- package/dist/utils/arrays.js +20 -0
- package/dist/utils/colors.d.ts +19 -0
- package/dist/utils/colors.js +27 -0
- package/dist/utils/hot-state.d.ts +41 -0
- package/dist/utils/hot-state.js +37 -0
- package/dist/utils/logging.d.ts +29 -0
- package/dist/utils/logging.js +55 -0
- package/dist/utils/math.d.ts +52 -0
- package/dist/utils/math.js +76 -0
- package/package.json +79 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { _roots, advance, createRoot, extend } from '@react-three/fiber';
|
|
3
|
+
import { StrictMode, useEffect, useEffectEvent, useRef } from 'react';
|
|
4
|
+
import * as THREE from 'three';
|
|
5
|
+
import { Camera, WebGLRenderer } from 'three';
|
|
6
|
+
import { createLogger } from '../utils/logging';
|
|
7
|
+
import { setExternalCameraProjection } from './external-camera';
|
|
8
|
+
import { externalEvents } from './external-events';
|
|
9
|
+
const logger = createLogger('external');
|
|
10
|
+
/**
|
|
11
|
+
* `<Canvas>`'s stand-in for a host that already owns the canvas: everything the Canvas component
|
|
12
|
+
* does — boot an R3F root, configure the renderer, the events, the size — minus the one thing it
|
|
13
|
+
* cannot share, creating the canvas element. It knows nothing of the scene: `children` render into
|
|
14
|
+
* the root verbatim, so `Renderer` composes one tree and only the mount differs.
|
|
15
|
+
*
|
|
16
|
+
* The bootstrap is imperative because the host's contract is: there is no React tree to mount into
|
|
17
|
+
* until a context exists. R3F's `<Canvas>` cannot serve here — it creates and owns its own canvas
|
|
18
|
+
* element inside a wrapper it renders, and has no way to adopt a foreign one — so this takes R3F's
|
|
19
|
+
* own escape hatch for exactly that, `createRoot(canvas)`, which is all `<Canvas>` wraps anyway.
|
|
20
|
+
* It is configured once per context, while the tree re-renders through props like any other.
|
|
21
|
+
*
|
|
22
|
+
* The camera half is the mount's as well, because the host owns it: one bare camera carries
|
|
23
|
+
* whatever matrix the host handed the frame hook, decomposed into a rigid view and a projection so
|
|
24
|
+
* that everything reading a camera's transform — culling, raycasts, lighting — works unchanged.
|
|
25
|
+
* There is no viewbox fit, no controls and no camera commands; the tree above simply mounts none
|
|
26
|
+
* of them.
|
|
27
|
+
*
|
|
28
|
+
* The demand loop inverts. R3F's own `invalidate` is a no-op under `frameloop: 'never'`, so the
|
|
29
|
+
* store's copy is replaced with the host's `requestFrame` — and every host frame redraws in full,
|
|
30
|
+
* as a shared canvas requires, starting from `resetState()` so three's GL-state tracking never
|
|
31
|
+
* trusts what the host's own drawing left behind.
|
|
32
|
+
* @param props - The host's hooks, and the tree to render into the root.
|
|
33
|
+
* @returns Nothing; the tree renders on the host's canvas, not in this one.
|
|
34
|
+
*/
|
|
35
|
+
export function ExternalCanvas(props) {
|
|
36
|
+
const { gl, requestFrame, onFrame, children } = props;
|
|
37
|
+
// A ref rather than state: nothing renders from the root — the tree renders *into* it — and the
|
|
38
|
+
// forwarding effect always runs after this one within a commit, so it never reads it stale.
|
|
39
|
+
const mountedRef = useRef(undefined);
|
|
40
|
+
// Effect events, so the host handing over a fresh function identity neither re-bootstraps the
|
|
41
|
+
// root nor goes stale: the bootstrap captures these two, and they read the latest props.
|
|
42
|
+
const askFrame = useEffectEvent(() => requestFrame());
|
|
43
|
+
const subscribeFrames = useEffectEvent((draw) => onFrame(draw));
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
const external = mountExternal(gl, askFrame, subscribeFrames);
|
|
46
|
+
mountedRef.current = external;
|
|
47
|
+
return () => {
|
|
48
|
+
mountedRef.current = undefined;
|
|
49
|
+
external?.dispose();
|
|
50
|
+
};
|
|
51
|
+
}, [gl]);
|
|
52
|
+
// The tree flows into the foreign root exactly as it would into a Canvas: every children change
|
|
53
|
+
// re-renders it, and only a context change re-bootstraps — `gl` is a dependency here for exactly
|
|
54
|
+
// that case, so a fresh root receives the tree the moment it exists.
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
mountedRef.current?.render(_jsx(StrictMode, { children: children }));
|
|
57
|
+
}, [gl, children]);
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Boots an R3F root on the host's canvas and wires it to the host's frame loop.
|
|
62
|
+
* @param context - The host's WebGL context.
|
|
63
|
+
* @param requestFrame - Asks the host for a frame.
|
|
64
|
+
* @param onFrame - Subscribes the per-frame draw to the host.
|
|
65
|
+
* @returns The root and its teardown, or `undefined` when the context has no usable canvas.
|
|
66
|
+
*/
|
|
67
|
+
function mountExternal(context, requestFrame, onFrame) {
|
|
68
|
+
const canvas = context.canvas;
|
|
69
|
+
if (!(canvas instanceof HTMLCanvasElement)) {
|
|
70
|
+
logger.warn('external mode needs a context bound to an HTMLCanvasElement');
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
// `<Canvas>` extends R3F's element catalog with the whole THREE namespace itself; a manual root
|
|
74
|
+
// has to do the same. Idempotent, and the namespace is a module the renderer already ships. The
|
|
75
|
+
// cast steps past the catalog's constructors-only typing — the namespace carries plain values
|
|
76
|
+
// too, which `extend` skips at runtime, exactly as the Canvas path relies on.
|
|
77
|
+
extend(THREE);
|
|
78
|
+
// Deliberately a bare camera: three's frustum cameras derive their projection, and this one's
|
|
79
|
+
// arrives whole from the host each frame. Marked manual so R3F's resize handling leaves it
|
|
80
|
+
// alone; both auto-updates are off because the decomposition writes every matrix by hand.
|
|
81
|
+
const camera = new Camera();
|
|
82
|
+
camera.matrixAutoUpdate = false;
|
|
83
|
+
camera.matrixWorldAutoUpdate = false;
|
|
84
|
+
camera.manual = true;
|
|
85
|
+
// Constructed bare on purpose: anything the renderer would opine on is left unset.
|
|
86
|
+
const glRenderer = new WebGLRenderer({ canvas, context });
|
|
87
|
+
// Never clear: the host's own layers are already on the canvas when this renderer draws.
|
|
88
|
+
glRenderer.autoClear = false;
|
|
89
|
+
// The canvas is the host's, twice over. Three would write the css style along with every resize
|
|
90
|
+
// unless told otherwise each time; and R3F's unmount forces a context loss on the renderer it
|
|
91
|
+
// tears down, which on a shared context would take the host's own drawing with it.
|
|
92
|
+
const applySize = glRenderer.setSize.bind(glRenderer);
|
|
93
|
+
glRenderer.setSize = (width, height) => applySize(width, height, false);
|
|
94
|
+
glRenderer.forceContextLoss = () => undefined;
|
|
95
|
+
const measure = () => {
|
|
96
|
+
const rect = canvas.getBoundingClientRect();
|
|
97
|
+
return { width: rect.width, height: rect.height, top: rect.top, left: rect.left };
|
|
98
|
+
};
|
|
99
|
+
const root = createRoot(canvas);
|
|
100
|
+
let disposed = false;
|
|
101
|
+
let configured = false;
|
|
102
|
+
let pending;
|
|
103
|
+
let unsubscribeFrame;
|
|
104
|
+
let observer;
|
|
105
|
+
void root
|
|
106
|
+
.configure({
|
|
107
|
+
gl: glRenderer,
|
|
108
|
+
// R3F force-writes ACES filmic tone mapping onto a fresh renderer unless `flat` is set, which
|
|
109
|
+
// is the one value landing on three's own default, `NoToneMapping`. This renderer does not
|
|
110
|
+
// tone map: `Lighting` keeps the rig's light sum in range by construction, rather than
|
|
111
|
+
// compressing an unbounded one back into range afterward.
|
|
112
|
+
flat: true,
|
|
113
|
+
// The cast widens past R3F's frustum-camera union; `manual` above is what keeps R3F's own
|
|
114
|
+
// camera handling off it.
|
|
115
|
+
camera: camera,
|
|
116
|
+
frameloop: 'never',
|
|
117
|
+
events: externalEvents,
|
|
118
|
+
size: measure(),
|
|
119
|
+
dpr: window.devicePixelRatio,
|
|
120
|
+
})
|
|
121
|
+
.then(() => {
|
|
122
|
+
if (disposed)
|
|
123
|
+
return;
|
|
124
|
+
const store = _roots.get(canvas)?.store;
|
|
125
|
+
if (!store)
|
|
126
|
+
return;
|
|
127
|
+
// R3F's invalidate no-ops under `frameloop: 'never'`; the host owns the frames, so demand
|
|
128
|
+
// becomes a repaint request. Replaced after configure, which is what wrote the original.
|
|
129
|
+
store.setState({
|
|
130
|
+
invalidate: () => {
|
|
131
|
+
if (!disposed)
|
|
132
|
+
requestFrame();
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
store.getState().events.connect?.(canvas);
|
|
136
|
+
unsubscribeFrame = onFrame((projectionMatrix) => {
|
|
137
|
+
if (disposed)
|
|
138
|
+
return;
|
|
139
|
+
setExternalCameraProjection(camera, projectionMatrix);
|
|
140
|
+
// Three tracks GL state it did not set; sharing a context means resetting that tracking
|
|
141
|
+
// at the start of every frame, or the host's own state reads as three's.
|
|
142
|
+
glRenderer.resetState();
|
|
143
|
+
advance(performance.now(), true, store.getState());
|
|
144
|
+
});
|
|
145
|
+
// The host resizes its own canvas; the root only has to notice. Watching the element beats a
|
|
146
|
+
// host-specific resize event, and a dpr change reaches the same handler through the resize
|
|
147
|
+
// the host performs for it. Feature-detected for the oldest WebViews the SDK still runs in —
|
|
148
|
+
// without the observer the plan still draws, at the size it mounted at.
|
|
149
|
+
if (typeof ResizeObserver === 'function') {
|
|
150
|
+
observer = new ResizeObserver(() => {
|
|
151
|
+
if (disposed)
|
|
152
|
+
return;
|
|
153
|
+
const next = measure();
|
|
154
|
+
store.getState().setSize(next.width, next.height, next.top, next.left);
|
|
155
|
+
store.getState().setDpr(window.devicePixelRatio);
|
|
156
|
+
});
|
|
157
|
+
observer.observe(canvas);
|
|
158
|
+
}
|
|
159
|
+
configured = true;
|
|
160
|
+
if (pending !== undefined)
|
|
161
|
+
root.render(pending);
|
|
162
|
+
requestFrame();
|
|
163
|
+
});
|
|
164
|
+
return {
|
|
165
|
+
render(node) {
|
|
166
|
+
pending = node;
|
|
167
|
+
if (configured)
|
|
168
|
+
root.render(node);
|
|
169
|
+
},
|
|
170
|
+
dispose() {
|
|
171
|
+
disposed = true;
|
|
172
|
+
observer?.disconnect();
|
|
173
|
+
unsubscribeFrame?.();
|
|
174
|
+
root.unmount();
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type Camera } from 'three';
|
|
2
|
+
/**
|
|
3
|
+
* Decomposes the host's combined world-to-clip matrix into a rigid view matrix and a projection
|
|
4
|
+
* matrix, publishing all four matrices (and their inverses) on the camera.
|
|
5
|
+
*
|
|
6
|
+
* Ported from the imperative renderer's `ExternalCameraSystem`. The split is not unique — many
|
|
7
|
+
* (P′, V′) pairs multiply to the same M — but the *rigid* split is the one three's `Camera` class
|
|
8
|
+
* assumes for `getWorldDirection`, frustum culling, raycasting and the lighting that reads the
|
|
9
|
+
* camera's world matrix. Any extra scale or skew in M (mercator-unit conversion, say) ends up
|
|
10
|
+
* absorbed into P, where it breaks none of those — a *reflection* being the exception, which is why
|
|
11
|
+
* the host's world is mirrored into three's before any of this runs.
|
|
12
|
+
* @param camera - The external camera to publish onto; `matrixAutoUpdate` and
|
|
13
|
+
* `matrixWorldAutoUpdate` must be off, since everything here is written by hand.
|
|
14
|
+
* @param mainMatrix - The combined matrix mapping world space directly to clip space, sixteen
|
|
15
|
+
* elements column-major.
|
|
16
|
+
*/
|
|
17
|
+
export declare function setExternalCameraProjection(camera: Camera, mainMatrix: ArrayLike<number>): void;
|
|
18
|
+
//# sourceMappingURL=external-camera.d.ts.map
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { Matrix3, Matrix4, Vector3 } from 'three';
|
|
2
|
+
import { HANDEDNESS_FLIP } from '../space/Space';
|
|
3
|
+
/**
|
|
4
|
+
* Decomposes the host's combined world-to-clip matrix into a rigid view matrix and a projection
|
|
5
|
+
* matrix, publishing all four matrices (and their inverses) on the camera.
|
|
6
|
+
*
|
|
7
|
+
* Ported from the imperative renderer's `ExternalCameraSystem`. The split is not unique — many
|
|
8
|
+
* (P′, V′) pairs multiply to the same M — but the *rigid* split is the one three's `Camera` class
|
|
9
|
+
* assumes for `getWorldDirection`, frustum culling, raycasting and the lighting that reads the
|
|
10
|
+
* camera's world matrix. Any extra scale or skew in M (mercator-unit conversion, say) ends up
|
|
11
|
+
* absorbed into P, where it breaks none of those — a *reflection* being the exception, which is why
|
|
12
|
+
* the host's world is mirrored into three's before any of this runs.
|
|
13
|
+
* @param camera - The external camera to publish onto; `matrixAutoUpdate` and
|
|
14
|
+
* `matrixWorldAutoUpdate` must be off, since everything here is written by hand.
|
|
15
|
+
* @param mainMatrix - The combined matrix mapping world space directly to clip space, sixteen
|
|
16
|
+
* elements column-major.
|
|
17
|
+
*/
|
|
18
|
+
export function setExternalCameraProjection(camera, mainMatrix) {
|
|
19
|
+
// The host's matrix reads the host's world; the space mirrors that world into three's, so undo
|
|
20
|
+
// the mirror here. The two cancel: the plan lands exactly where the host put it, and what is left
|
|
21
|
+
// is a plan → world matrix that reverses orientation, which is the whole point — see
|
|
22
|
+
// {@link HANDEDNESS_FLIP}.
|
|
23
|
+
const M = _main.fromArray(mainMatrix).multiply(HANDEDNESS_FLIP);
|
|
24
|
+
const e = M.elements; // column-major storage: M[row, col] = e[row + 4 * col]
|
|
25
|
+
// Step 1: camera world position c.
|
|
26
|
+
//
|
|
27
|
+
// A standard perspective projection P has its fourth column equal to (0, 0, ±f, 0), so
|
|
28
|
+
// P · [0; 0; 0; 1] is zero in rows 0, 1, and 3. The view matrix V maps the camera position to
|
|
29
|
+
// view-space origin: V · [c; 1] = [0; 0; 0; 1]. Composing these:
|
|
30
|
+
//
|
|
31
|
+
// M · [c; 1] = P · V · [c; 1] = P · [0; 0; 0; 1] = (0, 0, k, 0)
|
|
32
|
+
//
|
|
33
|
+
// so rows 0, 1, and 3 of M dotted with [c; 1] all equal zero. That is a 3×3 linear system for
|
|
34
|
+
// the three components of c, independent of NDC z conventions (standard OpenGL vs. reverse-z),
|
|
35
|
+
// so it works for both maplibre and a vanilla GL setup.
|
|
36
|
+
_system.set(e[0], e[4], e[8], e[1], e[5], e[9], e[3], e[7], e[11]);
|
|
37
|
+
_position.set(-e[12], -e[13], -e[15]).applyMatrix3(_system.invert());
|
|
38
|
+
// Step 2: view direction in world space.
|
|
39
|
+
//
|
|
40
|
+
// Unproject two world-space points along the central view ray and take their difference. The
|
|
41
|
+
// clip-space z boundaries (±1) are used rather than an interior NDC z because maplibre's
|
|
42
|
+
// projection has an infinite far plane in a reverse-z arrangement: an interior z (0 in
|
|
43
|
+
// particular) unprojects to a homogeneous direction at infinity and comes back as NaN after the
|
|
44
|
+
// w-divide. z = ±1 always produces finite points, so the subtraction is well-defined.
|
|
45
|
+
//
|
|
46
|
+
// Which of the two is the near plane depends on the projection's z convention — reverse-z under
|
|
47
|
+
// maplibre, standard under vanilla GL — so it is settled by distance to the eye recovered above:
|
|
48
|
+
// the near point is the closer one, and the view looks from it toward the other. (The imperative
|
|
49
|
+
// renderer hardcoded maplibre's ordering; measuring is what makes both conventions work.)
|
|
50
|
+
_mainInverse.copy(M).invert();
|
|
51
|
+
_near.set(0, 0, 1).applyMatrix4(_mainInverse);
|
|
52
|
+
_far.set(0, 0, -1).applyMatrix4(_mainInverse);
|
|
53
|
+
const nearZ = _near.distanceToSquared(_position) <= _far.distanceToSquared(_position) ? 1 : -1;
|
|
54
|
+
if (nearZ === 1) {
|
|
55
|
+
_direction.copy(_far).sub(_near).normalize();
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
_direction.copy(_near).sub(_far).normalize();
|
|
59
|
+
}
|
|
60
|
+
// Step 3: the camera's up axis, measured rather than chosen, and a rigid view matrix from it.
|
|
61
|
+
//
|
|
62
|
+
// Any up not parallel to the view direction gives a valid (P′, V′) pair for *drawing*, because P
|
|
63
|
+
// is recomputed from M · matrixWorld at the end and absorbs whatever roll V′ was given. The axis
|
|
64
|
+
// is also *read*, though: `Lighting` takes the plan's heading from the camera's up axis, so a
|
|
65
|
+
// chosen one aims the key light at an angle the host never had — a fixed world +z aimed it from
|
|
66
|
+
// the far side of the plan at every bearing, and every face turned toward the camera lost its
|
|
67
|
+
// direct light.
|
|
68
|
+
//
|
|
69
|
+
// Two points at one clip x and one clip z, one at the top of the screen and one at the bottom,
|
|
70
|
+
// differ by a vector along the camera's up axis alone: a constant clip z is a constant view-space
|
|
71
|
+
// z, so the forward components cancel and the difference is (0, Δy, 0) in view space. Clip y
|
|
72
|
+
// grows upward under every projection, maplibre's reverse-z included, so this reads none of the
|
|
73
|
+
// host's own conventions — and unlike a chosen axis it has no degenerate view to fall back from,
|
|
74
|
+
// since the axis it recovers is perpendicular to the view direction by construction.
|
|
75
|
+
//
|
|
76
|
+
// Unprojected at `nearZ`, the near plane's own clip z: a point there is finite under either z
|
|
77
|
+
// convention, which an interior z is not.
|
|
78
|
+
_screenTop.set(0, 1, nearZ).applyMatrix4(_mainInverse);
|
|
79
|
+
_screenBottom.set(0, -1, nearZ).applyMatrix4(_mainInverse);
|
|
80
|
+
_up.copy(_screenTop).sub(_screenBottom).normalize();
|
|
81
|
+
_target.copy(_position).add(_direction);
|
|
82
|
+
camera.matrixWorld.lookAt(_position, _target, _up);
|
|
83
|
+
camera.matrixWorld.setPosition(_position);
|
|
84
|
+
camera.matrixWorldInverse.copy(camera.matrixWorld).invert();
|
|
85
|
+
// Step 4: derive projection so that P · V = M exactly.
|
|
86
|
+
//
|
|
87
|
+
// P = M · matrixWorld, because matrixWorld = V⁻¹ and therefore P · V = (M · V⁻¹) · V = M. Any
|
|
88
|
+
// scale or skew that did not fit into the rigid V lives in P.
|
|
89
|
+
camera.projectionMatrix.multiplyMatrices(M, camera.matrixWorld);
|
|
90
|
+
camera.projectionMatrixInverse.copy(camera.projectionMatrix).invert();
|
|
91
|
+
}
|
|
92
|
+
// Scratch, reused across calls so a per-frame update allocates nothing.
|
|
93
|
+
const _main = new Matrix4();
|
|
94
|
+
const _mainInverse = new Matrix4();
|
|
95
|
+
const _system = new Matrix3();
|
|
96
|
+
const _position = new Vector3();
|
|
97
|
+
const _near = new Vector3();
|
|
98
|
+
const _far = new Vector3();
|
|
99
|
+
const _direction = new Vector3();
|
|
100
|
+
const _screenTop = new Vector3();
|
|
101
|
+
const _screenBottom = new Vector3();
|
|
102
|
+
const _target = new Vector3();
|
|
103
|
+
const _up = new Vector3();
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type EventManager, type RootStore } from '@react-three/fiber';
|
|
2
|
+
/**
|
|
3
|
+
* R3F's DOM event manager, aiming its rays through the hosted camera.
|
|
4
|
+
*
|
|
5
|
+
* The default manager computes its ray with three's `setFromCamera`, which refuses a camera that is
|
|
6
|
+
* neither perspective nor orthographic — and the external camera is deliberately neither, one folded
|
|
7
|
+
* matrix with no transform of its own. Only the computation changes: hit testing, hover tracking,
|
|
8
|
+
* capture and the missed-click path all stay R3F's, so picking under a host behaves exactly as it
|
|
9
|
+
* does under the renderer's own canvas.
|
|
10
|
+
* @param store - The root the manager serves.
|
|
11
|
+
* @returns The event manager.
|
|
12
|
+
*/
|
|
13
|
+
export declare function externalEvents(store: RootStore): EventManager<HTMLElement>;
|
|
14
|
+
//# sourceMappingURL=external-events.d.ts.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { events as createDomEvents } from '@react-three/fiber';
|
|
2
|
+
import { castRay } from '../space/Space';
|
|
3
|
+
/**
|
|
4
|
+
* R3F's DOM event manager, aiming its rays through the hosted camera.
|
|
5
|
+
*
|
|
6
|
+
* The default manager computes its ray with three's `setFromCamera`, which refuses a camera that is
|
|
7
|
+
* neither perspective nor orthographic — and the external camera is deliberately neither, one folded
|
|
8
|
+
* matrix with no transform of its own. Only the computation changes: hit testing, hover tracking,
|
|
9
|
+
* capture and the missed-click path all stay R3F's, so picking under a host behaves exactly as it
|
|
10
|
+
* does under the renderer's own canvas.
|
|
11
|
+
* @param store - The root the manager serves.
|
|
12
|
+
* @returns The event manager.
|
|
13
|
+
*/
|
|
14
|
+
export function externalEvents(store) {
|
|
15
|
+
const manager = createDomEvents(store);
|
|
16
|
+
return {
|
|
17
|
+
...manager,
|
|
18
|
+
// The canvas is the host's and carries the host's own pointer handling; listening one element
|
|
19
|
+
// up leaves it alone, while `offsetX` stays canvas-relative — the events still target the
|
|
20
|
+
// canvas, which sits alone in its container.
|
|
21
|
+
connect(target) {
|
|
22
|
+
manager.connect?.(target.parentElement ?? target);
|
|
23
|
+
},
|
|
24
|
+
compute(event, state) {
|
|
25
|
+
state.pointer.set((event.offsetX / state.size.width) * 2 - 1, -(event.offsetY / state.size.height) * 2 + 1);
|
|
26
|
+
// R3F's pointer is a bare Vector2; the set above is what put it in NDC.
|
|
27
|
+
castRay(state.raycaster, state.pointer, state.camera);
|
|
28
|
+
// Screen-space raycasts — a route line answering at its drawn width — read the camera off the
|
|
29
|
+
// raycaster; `setFromCamera` writes it and the general-camera path must too.
|
|
30
|
+
state.raycaster.camera = state.camera;
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { type CameraAPI, type CameraAxes, type CameraState, type ControlsConfig, type InertiaConfig, type PanConfig, type RollConfig, type TransitionOptions, useCameraAPI, useCameraGesture, useCameraMoveEnd, useCameraState, type ZoomConfig, type ZoomToOptions, } from './controls';
|
|
2
|
+
export { prepareDebug } from './debug/debug-chunk';
|
|
3
|
+
export { useDebugPanel } from './debug/debug-context';
|
|
4
|
+
export { type LightingProps, type ShadowProps } from './objects/lighting';
|
|
5
|
+
export * from './Renderer';
|
|
6
|
+
export { type CameraProps, type SmoothTime } from './space/Camera';
|
|
7
|
+
export { type CanvasPoint, type CanvasPointLike, type PlanPoint, type PlanPointLike, } from './space/Space';
|
|
8
|
+
export { useViewport, type ViewportAPI } from './space/viewport';
|
|
9
|
+
export * from './types/defs';
|
|
10
|
+
export * from './types/events';
|
|
11
|
+
export * from './types/guards';
|
|
12
|
+
export { update } from './update';
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// The camera's public surface: commands, a state reader, and the two movement events — the user's
|
|
2
|
+
// own hand on the camera, and any movement coming to rest. Deliberately not `useControlsEffect` or
|
|
3
|
+
// the controls themselves — those hand out `camera-controls`, which is this renderer's internals.
|
|
4
|
+
export { useCameraAPI, useCameraGesture, useCameraMoveEnd, useCameraState, } from './controls';
|
|
5
|
+
// The debug chunk's preload, for an external host that must create its context instrumented.
|
|
6
|
+
export { prepareDebug } from './debug/debug-chunk';
|
|
7
|
+
// Publishing a host's own values into the debug panel.
|
|
8
|
+
export { useDebugPanel } from './debug/debug-context';
|
|
9
|
+
export * from './Renderer';
|
|
10
|
+
export { useViewport } from './space/viewport';
|
|
11
|
+
export * from './types/defs';
|
|
12
|
+
export * from './types/events';
|
|
13
|
+
export * from './types/guards';
|
|
14
|
+
export { update } from './update';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type ColorInput } from '../types/defs';
|
|
3
|
+
/** Props for {@link Background}. */
|
|
4
|
+
export interface BackgroundProps {
|
|
5
|
+
/** The background color. */
|
|
6
|
+
color: ColorInput;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The scene's background: a screen-space quad drawn below every layer, replacing what a clear
|
|
10
|
+
* color would paint — and unlike one, dimmed with the venue. The root `Layer` renders it inside
|
|
11
|
+
* its own group, under the root layer's dim provider, so the dim reaches this material exactly as
|
|
12
|
+
* it reaches a layer's.
|
|
13
|
+
*
|
|
14
|
+
* **Screen-space in the vertex shader**, as the imperative renderer drew it: projection is
|
|
15
|
+
* replaced with the quad's own xy in clip space at the far plane, so it covers the canvas edge to
|
|
16
|
+
* edge under any camera — fit, zoom, roll, pitch — and no matrix above it is ever read.
|
|
17
|
+
*
|
|
18
|
+
* It draws through the same {@link ColorMaterial} as the layers, with one addition through the
|
|
19
|
+
* material's pre-dim hook: a quad has no batch prologue, so the per-instance dim uniform the
|
|
20
|
+
* unmodified dim patch looks for is declared here as a constant pinned to "inherit" — every
|
|
21
|
+
* fragment defers to the layer amount, which is the point.
|
|
22
|
+
*
|
|
23
|
+
* **Draw order**: `renderOrder` 0 puts it level with the first layer group, and the tie falls to
|
|
24
|
+
* `material.id` — this material is created as the root layer mounts, before the scheduler admits
|
|
25
|
+
* any leaf, so it draws first. That ordering is load-bearing: flat content writes no depth, so
|
|
26
|
+
* anything drawn after the quad simply paints over it.
|
|
27
|
+
* @param props - The color.
|
|
28
|
+
* @returns The quad.
|
|
29
|
+
*/
|
|
30
|
+
export declare function Background(props: BackgroundProps): ReactNode;
|
|
31
|
+
//# sourceMappingURL=Background.d.ts.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { declareBeforeMain } from '../core/shader-source';
|
|
4
|
+
import { ColorMaterial } from './materials/ColorMaterial';
|
|
5
|
+
import { DIM_INHERIT, DIM_UNIFORM } from './materials/effects/color-dim';
|
|
6
|
+
/**
|
|
7
|
+
* The scene's background: a screen-space quad drawn below every layer, replacing what a clear
|
|
8
|
+
* color would paint — and unlike one, dimmed with the venue. The root `Layer` renders it inside
|
|
9
|
+
* its own group, under the root layer's dim provider, so the dim reaches this material exactly as
|
|
10
|
+
* it reaches a layer's.
|
|
11
|
+
*
|
|
12
|
+
* **Screen-space in the vertex shader**, as the imperative renderer drew it: projection is
|
|
13
|
+
* replaced with the quad's own xy in clip space at the far plane, so it covers the canvas edge to
|
|
14
|
+
* edge under any camera — fit, zoom, roll, pitch — and no matrix above it is ever read.
|
|
15
|
+
*
|
|
16
|
+
* It draws through the same {@link ColorMaterial} as the layers, with one addition through the
|
|
17
|
+
* material's pre-dim hook: a quad has no batch prologue, so the per-instance dim uniform the
|
|
18
|
+
* unmodified dim patch looks for is declared here as a constant pinned to "inherit" — every
|
|
19
|
+
* fragment defers to the layer amount, which is the point.
|
|
20
|
+
*
|
|
21
|
+
* **Draw order**: `renderOrder` 0 puts it level with the first layer group, and the tie falls to
|
|
22
|
+
* `material.id` — this material is created as the root layer mounts, before the scheduler admits
|
|
23
|
+
* any leaf, so it draws first. That ordering is load-bearing: flat content writes no depth, so
|
|
24
|
+
* anything drawn after the quad simply paints over it.
|
|
25
|
+
* @param props - The color.
|
|
26
|
+
* @returns The quad.
|
|
27
|
+
*/
|
|
28
|
+
export function Background(props) {
|
|
29
|
+
// One handler for the material's life, per `ColorMaterial`'s contract for its pre-dim hook.
|
|
30
|
+
const [onBeforeCompile] = useState(() => (parameters) => {
|
|
31
|
+
parameters.vertexShader = parameters.vertexShader.replace('#include <project_vertex>',
|
|
32
|
+
/* glsl */ `gl_Position = vec4(transformed.xy, 1.0, 1.0);`);
|
|
33
|
+
parameters.fragmentShader = declareBeforeMain(parameters.fragmentShader,
|
|
34
|
+
/* glsl */ `const float ${DIM_UNIFORM} = ${DIM_INHERIT}.0;`);
|
|
35
|
+
});
|
|
36
|
+
return (_jsxs("mesh", { name: "background", renderOrder: 0, frustumCulled: false, children: [_jsx("planeGeometry", { args: [2, 2] }), _jsx(ColorMaterial, { color: props.color, onBeforeCompile: onBeforeCompile })] }));
|
|
37
|
+
}
|