react-babylon-map 0.0.1
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/.claude/settings.local.json +78 -0
- package/demo.html +161 -0
- package/dist/cjs/main.js +520 -0
- package/dist/es/main.mjs +20 -0
- package/dist/es/main.mjs.map +1 -0
- package/dist/es/main10.mjs +33 -0
- package/dist/es/main10.mjs.map +1 -0
- package/dist/es/main11.mjs +12 -0
- package/dist/es/main11.mjs.map +1 -0
- package/dist/es/main12.mjs +14 -0
- package/dist/es/main12.mjs.map +1 -0
- package/dist/es/main13.mjs +12 -0
- package/dist/es/main13.mjs.map +1 -0
- package/dist/es/main14.mjs +5 -0
- package/dist/es/main14.mjs.map +1 -0
- package/dist/es/main15.mjs +12 -0
- package/dist/es/main15.mjs.map +1 -0
- package/dist/es/main16.mjs +25 -0
- package/dist/es/main16.mjs.map +1 -0
- package/dist/es/main17.mjs +54 -0
- package/dist/es/main17.mjs.map +1 -0
- package/dist/es/main18.mjs +88 -0
- package/dist/es/main18.mjs.map +1 -0
- package/dist/es/main19.mjs +18 -0
- package/dist/es/main19.mjs.map +1 -0
- package/dist/es/main2.mjs +9 -0
- package/dist/es/main2.mjs.map +1 -0
- package/dist/es/main20.mjs +21 -0
- package/dist/es/main20.mjs.map +1 -0
- package/dist/es/main21.mjs +61 -0
- package/dist/es/main21.mjs.map +1 -0
- package/dist/es/main3.mjs +46 -0
- package/dist/es/main3.mjs.map +1 -0
- package/dist/es/main4.mjs +23 -0
- package/dist/es/main4.mjs.map +1 -0
- package/dist/es/main5.mjs +69 -0
- package/dist/es/main5.mjs.map +1 -0
- package/dist/es/main6.mjs +35 -0
- package/dist/es/main6.mjs.map +1 -0
- package/dist/es/main7.mjs +65 -0
- package/dist/es/main7.mjs.map +1 -0
- package/dist/es/main8.mjs +14 -0
- package/dist/es/main8.mjs.map +1 -0
- package/dist/es/main9.mjs +26 -0
- package/dist/es/main9.mjs.map +1 -0
- package/dist/maplibre/cjs/main.js +520 -0
- package/dist/maplibre/es/main.mjs +20 -0
- package/dist/maplibre/es/main.mjs.map +1 -0
- package/dist/maplibre/es/main10.mjs +33 -0
- package/dist/maplibre/es/main10.mjs.map +1 -0
- package/dist/maplibre/es/main11.mjs +12 -0
- package/dist/maplibre/es/main11.mjs.map +1 -0
- package/dist/maplibre/es/main12.mjs +14 -0
- package/dist/maplibre/es/main12.mjs.map +1 -0
- package/dist/maplibre/es/main13.mjs +12 -0
- package/dist/maplibre/es/main13.mjs.map +1 -0
- package/dist/maplibre/es/main14.mjs +5 -0
- package/dist/maplibre/es/main14.mjs.map +1 -0
- package/dist/maplibre/es/main15.mjs +12 -0
- package/dist/maplibre/es/main15.mjs.map +1 -0
- package/dist/maplibre/es/main16.mjs +25 -0
- package/dist/maplibre/es/main16.mjs.map +1 -0
- package/dist/maplibre/es/main17.mjs +54 -0
- package/dist/maplibre/es/main17.mjs.map +1 -0
- package/dist/maplibre/es/main18.mjs +88 -0
- package/dist/maplibre/es/main18.mjs.map +1 -0
- package/dist/maplibre/es/main19.mjs +18 -0
- package/dist/maplibre/es/main19.mjs.map +1 -0
- package/dist/maplibre/es/main2.mjs +9 -0
- package/dist/maplibre/es/main2.mjs.map +1 -0
- package/dist/maplibre/es/main20.mjs +61 -0
- package/dist/maplibre/es/main20.mjs.map +1 -0
- package/dist/maplibre/es/main21.mjs +21 -0
- package/dist/maplibre/es/main21.mjs.map +1 -0
- package/dist/maplibre/es/main3.mjs +46 -0
- package/dist/maplibre/es/main3.mjs.map +1 -0
- package/dist/maplibre/es/main4.mjs +23 -0
- package/dist/maplibre/es/main4.mjs.map +1 -0
- package/dist/maplibre/es/main5.mjs +69 -0
- package/dist/maplibre/es/main5.mjs.map +1 -0
- package/dist/maplibre/es/main6.mjs +35 -0
- package/dist/maplibre/es/main6.mjs.map +1 -0
- package/dist/maplibre/es/main7.mjs +65 -0
- package/dist/maplibre/es/main7.mjs.map +1 -0
- package/dist/maplibre/es/main8.mjs +14 -0
- package/dist/maplibre/es/main8.mjs.map +1 -0
- package/dist/maplibre/es/main9.mjs +26 -0
- package/dist/maplibre/es/main9.mjs.map +1 -0
- package/dist/maplibre/types/api/canvas-props.d.ts +9 -0
- package/dist/maplibre/types/api/coordinates.d.ts +13 -0
- package/dist/maplibre/types/api/coords-to-vector-3.d.ts +3 -0
- package/dist/maplibre/types/api/coords.d.ts +5 -0
- package/dist/maplibre/types/api/index.d.ts +7 -0
- package/dist/maplibre/types/api/near-coordinates.d.ts +13 -0
- package/dist/maplibre/types/api/use-map.d.ts +3 -0
- package/dist/maplibre/types/api/vector-3-to-coords.d.ts +2 -0
- package/dist/maplibre/types/core/canvas-in-layer/use-canvas-in-layer.d.ts +15 -0
- package/dist/maplibre/types/core/canvas-in-layer/use-render.d.ts +15 -0
- package/dist/maplibre/types/core/canvas-in-layer/use-root.d.ts +11 -0
- package/dist/maplibre/types/core/canvas-overlay/canvas-portal.d.ts +10 -0
- package/dist/maplibre/types/core/canvas-overlay/init-canvas-fc.d.ts +11 -0
- package/dist/maplibre/types/core/canvas-overlay/render.d.ts +1 -0
- package/dist/maplibre/types/core/canvas-overlay/sync-camera-fc.d.ts +12 -0
- package/dist/maplibre/types/core/coords-to-matrix.d.ts +9 -0
- package/dist/maplibre/types/core/earth-radius.d.ts +1 -0
- package/dist/maplibre/types/core/generic-map.d.ts +49 -0
- package/dist/maplibre/types/core/matrix-utils.d.ts +7 -0
- package/dist/maplibre/types/core/sync-camera.d.ts +7 -0
- package/dist/maplibre/types/core/use-babylon-map.d.ts +32 -0
- package/dist/maplibre/types/core/use-coords-to-matrix.d.ts +6 -0
- package/dist/maplibre/types/core/use-coords.d.ts +5 -0
- package/dist/maplibre/types/core/use-function.d.ts +1 -0
- package/dist/maplibre/types/maplibre/canvas.d.ts +4 -0
- package/dist/maplibre/types/maplibre.index.d.ts +4 -0
- package/dist/types/api/canvas-props.d.ts +9 -0
- package/dist/types/api/coordinates.d.ts +13 -0
- package/dist/types/api/coords-to-vector-3.d.ts +3 -0
- package/dist/types/api/coords.d.ts +5 -0
- package/dist/types/api/index.d.ts +7 -0
- package/dist/types/api/near-coordinates.d.ts +13 -0
- package/dist/types/api/use-map.d.ts +3 -0
- package/dist/types/api/vector-3-to-coords.d.ts +2 -0
- package/dist/types/core/canvas-in-layer/use-canvas-in-layer.d.ts +15 -0
- package/dist/types/core/canvas-in-layer/use-render.d.ts +15 -0
- package/dist/types/core/canvas-in-layer/use-root.d.ts +11 -0
- package/dist/types/core/canvas-overlay/canvas-portal.d.ts +10 -0
- package/dist/types/core/canvas-overlay/init-canvas-fc.d.ts +11 -0
- package/dist/types/core/canvas-overlay/render.d.ts +1 -0
- package/dist/types/core/canvas-overlay/sync-camera-fc.d.ts +12 -0
- package/dist/types/core/coords-to-matrix.d.ts +9 -0
- package/dist/types/core/earth-radius.d.ts +1 -0
- package/dist/types/core/generic-map.d.ts +49 -0
- package/dist/types/core/matrix-utils.d.ts +7 -0
- package/dist/types/core/sync-camera.d.ts +7 -0
- package/dist/types/core/use-babylon-map.d.ts +32 -0
- package/dist/types/core/use-coords-to-matrix.d.ts +6 -0
- package/dist/types/core/use-coords.d.ts +5 -0
- package/dist/types/core/use-function.d.ts +1 -0
- package/dist/types/mapbox/canvas.d.ts +4 -0
- package/dist/types/mapbox.index.d.ts +4 -0
- package/package.json +58 -0
- package/plan.md +719 -0
- package/src/api/canvas-props.ts +10 -0
- package/src/api/coordinates.tsx +83 -0
- package/src/api/coords-to-vector-3.ts +39 -0
- package/src/api/coords.tsx +6 -0
- package/src/api/index.ts +7 -0
- package/src/api/near-coordinates.tsx +87 -0
- package/src/api/use-map.ts +8 -0
- package/src/api/vector-3-to-coords.ts +13 -0
- package/src/core/canvas-in-layer/use-canvas-in-layer.tsx +27 -0
- package/src/core/canvas-in-layer/use-render.ts +43 -0
- package/src/core/canvas-in-layer/use-root.tsx +82 -0
- package/src/core/canvas-overlay/canvas-portal.tsx +98 -0
- package/src/core/canvas-overlay/init-canvas-fc.tsx +45 -0
- package/src/core/canvas-overlay/render.tsx +1 -0
- package/src/core/canvas-overlay/sync-camera-fc.tsx +83 -0
- package/src/core/coords-to-matrix.ts +21 -0
- package/src/core/earth-radius.ts +1 -0
- package/src/core/events.ts +55 -0
- package/src/core/generic-map.ts +59 -0
- package/src/core/map-engine.tsx +70 -0
- package/src/core/matrix-utils.ts +22 -0
- package/src/core/sync-camera.ts +29 -0
- package/src/core/use-babylon-map.ts +46 -0
- package/src/core/use-coords-to-matrix.ts +13 -0
- package/src/core/use-coords.tsx +22 -0
- package/src/core/use-function.ts +10 -0
- package/src/mapbox/canvas.tsx +59 -0
- package/src/mapbox.index.ts +7 -0
- package/src/maplibre/canvas.tsx +59 -0
- package/src/maplibre.index.ts +7 -0
- package/src/vite-env.d.ts +1 -0
- package/stories/.ladle/components.tsx +50 -0
- package/stories/.ladle/style.css +63 -0
- package/stories/package.json +31 -0
- package/stories/pnpm-lock.yaml +5450 -0
- package/stories/sandbox.config.json +3 -0
- package/stories/src/adaptive-dpr.tsx +34 -0
- package/stories/src/billboard.stories.tsx +111 -0
- package/stories/src/buildings-3d.stories.tsx +280 -0
- package/stories/src/canvas/mapbox.stories.tsx +113 -0
- package/stories/src/canvas/maplibre.stories.tsx +93 -0
- package/stories/src/comparison.stories.tsx +161 -0
- package/stories/src/extrude/chaillot.ts +8 -0
- package/stories/src/exude-coordinates.stories.tsx +139 -0
- package/stories/src/free-3d-buildings/get-buildings-data.ts +49 -0
- package/stories/src/html-on-top.stories.tsx +156 -0
- package/stories/src/ifc/ifc-to-babylon.ts +97 -0
- package/stories/src/ifc/ifc.main.ts +904 -0
- package/stories/src/ifc/ifc2bb.ts +343 -0
- package/stories/src/ifc/model.ifc +14155 -0
- package/stories/src/ifc.stories.tsx +276 -0
- package/stories/src/mapbox/story-mapbox.tsx +97 -0
- package/stories/src/maplibre/story-maplibre.tsx +36 -0
- package/stories/src/multi-coordinates.stories.tsx +115 -0
- package/stories/src/pivot-controls.stories.tsx +148 -0
- package/stories/src/postprocessing.stories.tsx +125 -0
- package/stories/src/render-on-demand.stories.tsx +76 -0
- package/stories/src/story-map.tsx +44 -0
- package/stories/src/sunlight.stories.tsx +215 -0
- package/stories/src/vite-env.d.ts +1 -0
- package/stories/tsconfig.json +32 -0
- package/stories/tsconfig.node.json +10 -0
- package/stories/vite.config.ts +27 -0
- package/tsconfig.json +31 -0
- package/tsconfig.mapbox.json +7 -0
- package/tsconfig.maplibre.json +7 -0
- package/tsconfig.node.json +10 -0
- package/tsconfig.types.json +25 -0
- package/vite.config.ts +65 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { syncCamera } from "./main12.mjs";
|
|
2
|
+
import { useFunction } from "./main11.mjs";
|
|
3
|
+
function useRender({
|
|
4
|
+
map,
|
|
5
|
+
origin,
|
|
6
|
+
scene,
|
|
7
|
+
camera,
|
|
8
|
+
frameloop,
|
|
9
|
+
babylonMap
|
|
10
|
+
}) {
|
|
11
|
+
const render = useFunction((_gl, projViewMx) => {
|
|
12
|
+
const pVMx = "defaultProjectionData" in projViewMx ? Object.values(projViewMx.defaultProjectionData.mainMatrix) : projViewMx;
|
|
13
|
+
babylonMap.viewProjMx = pVMx;
|
|
14
|
+
syncCamera(camera, origin, pVMx);
|
|
15
|
+
scene.getEngine().wipeCaches(true);
|
|
16
|
+
scene.render(false);
|
|
17
|
+
if (!frameloop || frameloop === "always")
|
|
18
|
+
map.triggerRepaint();
|
|
19
|
+
});
|
|
20
|
+
return render;
|
|
21
|
+
}
|
|
22
|
+
export {
|
|
23
|
+
useRender
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=main16.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main16.mjs","sources":["../../src/core/canvas-in-layer/use-render.ts"],"sourcesContent":["import { FreeCamera, Matrix, Scene } from '@babylonjs/core';\nimport { MapInstance } from '../generic-map';\nimport { syncCamera } from '../sync-camera';\nimport { useFunction } from '../use-function';\nimport { BabylonMap } from '../use-babylon-map';\n\nexport function useRender({\n map, origin, scene, camera, frameloop, babylonMap,\n}: {\n map: MapInstance;\n origin: Matrix;\n scene: Scene;\n camera: FreeCamera;\n frameloop?: 'always' | 'demand';\n babylonMap: BabylonMap;\n}) {\n const render = useFunction((\n _gl: WebGL2RenderingContext,\n projViewMx: number[] | { defaultProjectionData: { mainMatrix: Record<string, number> } },\n ) => {\n const pVMx = 'defaultProjectionData' in projViewMx\n ? Object.values(projViewMx.defaultProjectionData.mainMatrix)\n : projViewMx;\n\n // Update shared context\n babylonMap.viewProjMx = pVMx as number[];\n\n // Sync camera\n syncCamera(camera, origin, pVMx as number[]);\n\n // Wipe Babylon's internal GL state caches so the next render\n // re-applies everything from scratch. This is critical when\n // sharing a GL context with MapLibre.\n scene.getEngine().wipeCaches(true);\n\n // Render the Babylon scene into the shared GL context.\n scene.render(false);\n\n if (!frameloop || frameloop === 'always') map.triggerRepaint();\n });\n\n return render;\n}\n"],"names":[],"mappings":";;AAMO,SAAS,UAAU;AAAA,EACxB;AAAA,EAAK;AAAA,EAAQ;AAAA,EAAO;AAAA,EAAQ;AAAA,EAAW;AACzC,GAOG;AACD,QAAM,SAAS,YAAY,CACzB,KACA,eACG;AACG,UAAA,OAAO,2BAA2B,aACpC,OAAO,OAAO,WAAW,sBAAsB,UAAU,IACzD;AAGJ,eAAW,aAAa;AAGb,eAAA,QAAQ,QAAQ,IAAgB;AAKrC,UAAA,UAAA,EAAY,WAAW,IAAI;AAGjC,UAAM,OAAO,KAAK;AAEd,QAAA,CAAC,aAAa,cAAc;AAAU,UAAI,eAAe;AAAA,EAAA,CAC9D;AAEM,SAAA;AACT;"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Engine, Scene, Color4, FreeCamera, Vector3 } from "@babylonjs/core";
|
|
3
|
+
import { createRoot } from "./main20.mjs";
|
|
4
|
+
import { useState, useEffect } from "react";
|
|
5
|
+
import { createBabylonMap, BabylonMapContext } from "./main4.mjs";
|
|
6
|
+
import { useFunction } from "./main11.mjs";
|
|
7
|
+
function useRoot(fromLngLat, map, { longitude, latitude, altitude, frameloop, ...props }) {
|
|
8
|
+
const [{ engine, scene, camera, reactRoot, babylonMap }] = useState(() => {
|
|
9
|
+
const canvas = map.getCanvas();
|
|
10
|
+
const gl = canvas.getContext("webgl2") || canvas.getContext("webgl");
|
|
11
|
+
const engine2 = new Engine(
|
|
12
|
+
gl,
|
|
13
|
+
true,
|
|
14
|
+
{ useHighPrecisionMatrix: true },
|
|
15
|
+
true
|
|
16
|
+
);
|
|
17
|
+
const scene2 = new Scene(engine2);
|
|
18
|
+
scene2.autoClear = false;
|
|
19
|
+
scene2.clearColor = new Color4(0, 0, 0, 0);
|
|
20
|
+
scene2.detachControl();
|
|
21
|
+
const camera2 = new FreeCamera("cam", Vector3.Zero(), scene2);
|
|
22
|
+
camera2.inputs.clear();
|
|
23
|
+
camera2.minZ = 0;
|
|
24
|
+
const babylonMap2 = createBabylonMap({ map, fromLngLat, engine: engine2, scene: scene2 });
|
|
25
|
+
const container = document.createElement("div");
|
|
26
|
+
const reactRoot2 = createRoot(container);
|
|
27
|
+
return { engine: engine2, scene: scene2, camera: camera2, reactRoot: reactRoot2, container, babylonMap: babylonMap2 };
|
|
28
|
+
});
|
|
29
|
+
const onResize = useFunction(() => {
|
|
30
|
+
engine.resize();
|
|
31
|
+
});
|
|
32
|
+
const onRemove = useFunction(() => {
|
|
33
|
+
reactRoot.unmount();
|
|
34
|
+
scene.dispose();
|
|
35
|
+
engine.dispose();
|
|
36
|
+
});
|
|
37
|
+
babylonMap.coords = { longitude, latitude, altitude };
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
map.on("resize", onResize);
|
|
40
|
+
return () => {
|
|
41
|
+
map.off("resize", onResize);
|
|
42
|
+
};
|
|
43
|
+
}, []);
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
reactRoot.render(
|
|
46
|
+
/* @__PURE__ */ jsx(BabylonMapContext.Provider, { value: babylonMap, children: props.children })
|
|
47
|
+
);
|
|
48
|
+
}, [props.children]);
|
|
49
|
+
return { onRemove, engine, scene, camera, babylonMap };
|
|
50
|
+
}
|
|
51
|
+
export {
|
|
52
|
+
useRoot
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=main17.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main17.mjs","sources":["../../src/core/canvas-in-layer/use-root.tsx"],"sourcesContent":["import { Color4, Engine, FreeCamera, Scene, Vector3 } from '@babylonjs/core';\nimport { createRoot, Root } from 'react-dom/client';\nimport { useEffect, useState } from 'react';\nimport { CanvasProps } from '../../api/canvas-props';\nimport { BabylonMap, BabylonMapContext, createBabylonMap } from '../use-babylon-map';\nimport { FromLngLat, MapInstance } from '../generic-map';\nimport { useFunction } from '../use-function';\n\ninterface RootState {\n engine: Engine;\n scene: Scene;\n camera: FreeCamera;\n reactRoot: Root;\n container: HTMLDivElement;\n babylonMap: BabylonMap;\n}\n\nexport function useRoot(\n fromLngLat: FromLngLat,\n map: MapInstance,\n { longitude, latitude, altitude, frameloop, ...props }: CanvasProps,\n) {\n const [{ engine, scene, camera, reactRoot, babylonMap }] = useState<RootState>(() => {\n const canvas = map.getCanvas();\n const gl = (canvas.getContext('webgl2') || canvas.getContext('webgl')) as WebGLRenderingContext;\n\n // Create Babylon Engine from MapLibre's GL context (same pattern as demo.html)\n const engine = new Engine(\n gl as WebGL2RenderingContext,\n true,\n { useHighPrecisionMatrix: true },\n true,\n );\n\n const scene = new Scene(engine);\n scene.autoClear = false;\n scene.clearColor = new Color4(0, 0, 0, 0);\n scene.detachControl(); // let MapLibre handle pointer events\n\n const camera = new FreeCamera('cam', Vector3.Zero(), scene);\n camera.inputs.clear();\n camera.minZ = 0;\n\n const babylonMap = createBabylonMap({ map, fromLngLat, engine, scene });\n\n // Separate React root for children\n const container = document.createElement('div');\n const reactRoot = createRoot(container);\n\n return { engine, scene, camera, reactRoot, container, babylonMap };\n });\n\n const onResize = useFunction(() => {\n engine.resize();\n });\n\n const onRemove = useFunction(() => {\n reactRoot.unmount();\n scene.dispose();\n engine.dispose();\n });\n\n // Update coords on babylonMap\n babylonMap.coords = { longitude, latitude, altitude };\n\n // Resize listener\n useEffect(() => {\n map.on('resize', onResize);\n return () => { map.off('resize', onResize); };\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Render children into the separate React root\n useEffect(() => {\n reactRoot.render(\n <BabylonMapContext.Provider value={babylonMap}>\n {props.children}\n </BabylonMapContext.Provider>,\n );\n }, [props.children]); // eslint-disable-line react-hooks/exhaustive-deps\n\n return { onRemove, engine, scene, camera, babylonMap };\n}\n"],"names":["engine","scene","camera","babylonMap","reactRoot"],"mappings":";;;;;;AAiBgB,SAAA,QACd,YACA,KACA,EAAE,WAAW,UAAU,UAAU,WAAW,GAAG,SAC/C;AACM,QAAA,CAAC,EAAE,QAAQ,OAAO,QAAQ,WAAW,WAAW,CAAC,IAAI,SAAoB,MAAM;AAC7E,UAAA,SAAS,IAAI;AACnB,UAAM,KAAM,OAAO,WAAW,QAAQ,KAAK,OAAO,WAAW,OAAO;AAGpE,UAAMA,UAAS,IAAI;AAAA,MACjB;AAAA,MACA;AAAA,MACA,EAAE,wBAAwB,KAAK;AAAA,MAC/B;AAAA,IAAA;AAGIC,UAAAA,SAAQ,IAAI,MAAMD,OAAM;AAC9BC,WAAM,YAAY;AAClBA,WAAM,aAAa,IAAI,OAAO,GAAG,GAAG,GAAG,CAAC;AACxCA,WAAM,cAAc;AAEpB,UAAMC,UAAS,IAAI,WAAW,OAAO,QAAQ,KAAA,GAAQD,MAAK;AAC1DC,YAAO,OAAO;AACdA,YAAO,OAAO;AAERC,UAAAA,cAAa,iBAAiB,EAAE,KAAK,YAAY,QAAAH,SAAQ,OAAAC,OAAAA,CAAO;AAGhE,UAAA,YAAY,SAAS,cAAc,KAAK;AACxCG,UAAAA,aAAY,WAAW,SAAS;AAE/B,WAAA,EAAE,QAAAJ,SAAQ,OAAAC,QAAO,QAAAC,SAAQ,WAAAE,YAAW,WAAW,YAAAD,YAAW;AAAA,EAAA,CAClE;AAEK,QAAA,WAAW,YAAY,MAAM;AACjC,WAAO,OAAO;AAAA,EAAA,CACf;AAEK,QAAA,WAAW,YAAY,MAAM;AACjC,cAAU,QAAQ;AAClB,UAAM,QAAQ;AACd,WAAO,QAAQ;AAAA,EAAA,CAChB;AAGD,aAAW,SAAS,EAAE,WAAW,UAAU,SAAS;AAGpD,YAAU,MAAM;AACV,QAAA,GAAG,UAAU,QAAQ;AACzB,WAAO,MAAM;AAAM,UAAA,IAAI,UAAU,QAAQ;AAAA,IAAA;AAAA,EAC3C,GAAG,CAAE,CAAA;AAGL,YAAU,MAAM;AACJ,cAAA;AAAA,0BACP,kBAAkB,UAAlB,EAA2B,OAAO,YAChC,gBAAM,UACT;AAAA,IAAA;AAAA,EACF,GACC,CAAC,MAAM,QAAQ,CAAC;AAEnB,SAAO,EAAE,UAAU,QAAQ,OAAO,QAAQ,WAAW;AACvD;"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { jsxs, Fragment, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Engine, Scene, Color4, FreeCamera, Vector3 } from "@babylonjs/core";
|
|
3
|
+
import { memo, useRef, useState, useEffect } from "react";
|
|
4
|
+
import { createBabylonMap, BabylonMapContext } from "./main4.mjs";
|
|
5
|
+
import { useFunction } from "./main11.mjs";
|
|
6
|
+
import { SyncCameraFC } from "./main21.mjs";
|
|
7
|
+
const canvasStyle = {
|
|
8
|
+
position: "absolute",
|
|
9
|
+
top: 0,
|
|
10
|
+
left: 0,
|
|
11
|
+
width: "100%",
|
|
12
|
+
height: "100%",
|
|
13
|
+
pointerEvents: "none"
|
|
14
|
+
};
|
|
15
|
+
const CanvasPortal = memo(({
|
|
16
|
+
children,
|
|
17
|
+
latitude,
|
|
18
|
+
longitude,
|
|
19
|
+
altitude,
|
|
20
|
+
setOnRender,
|
|
21
|
+
map,
|
|
22
|
+
fromLngLat
|
|
23
|
+
}) => {
|
|
24
|
+
const canvasRef = useRef(null);
|
|
25
|
+
const mapCanvas = map.getCanvas();
|
|
26
|
+
const [babylonMap, setBabylonMap] = useState(null);
|
|
27
|
+
const [ready, setReady] = useState(false);
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
const canvas = canvasRef.current;
|
|
30
|
+
const engine = new Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true, useHighPrecisionMatrix: true });
|
|
31
|
+
const scene = new Scene(engine);
|
|
32
|
+
scene.clearColor = new Color4(0, 0, 0, 0);
|
|
33
|
+
const camera = new FreeCamera("cam", Vector3.Zero(), scene);
|
|
34
|
+
camera.inputs.clear();
|
|
35
|
+
camera.minZ = 0;
|
|
36
|
+
setBabylonMap(createBabylonMap({ map, fromLngLat, engine, scene }));
|
|
37
|
+
return () => {
|
|
38
|
+
scene.dispose();
|
|
39
|
+
engine.dispose();
|
|
40
|
+
};
|
|
41
|
+
}, []);
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (!(babylonMap == null ? void 0 : babylonMap.engine))
|
|
44
|
+
return;
|
|
45
|
+
const engine = babylonMap.engine;
|
|
46
|
+
const onResize = () => {
|
|
47
|
+
const c = canvasRef.current;
|
|
48
|
+
if (!c)
|
|
49
|
+
return;
|
|
50
|
+
c.width = mapCanvas.clientWidth * window.devicePixelRatio;
|
|
51
|
+
c.height = mapCanvas.clientHeight * window.devicePixelRatio;
|
|
52
|
+
c.style.width = `${mapCanvas.clientWidth}px`;
|
|
53
|
+
c.style.height = `${mapCanvas.clientHeight}px`;
|
|
54
|
+
engine.resize();
|
|
55
|
+
};
|
|
56
|
+
onResize();
|
|
57
|
+
map.on("resize", onResize);
|
|
58
|
+
return () => {
|
|
59
|
+
map.off("resize", onResize);
|
|
60
|
+
};
|
|
61
|
+
}, [babylonMap, map, mapCanvas]);
|
|
62
|
+
const onReady = useFunction(() => {
|
|
63
|
+
setReady(true);
|
|
64
|
+
});
|
|
65
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
66
|
+
/* @__PURE__ */ jsx("canvas", { ref: canvasRef, style: canvasStyle }),
|
|
67
|
+
babylonMap && /* @__PURE__ */ jsxs(BabylonMapContext.Provider, { value: babylonMap, children: [
|
|
68
|
+
/* @__PURE__ */ jsx(
|
|
69
|
+
SyncCameraFC,
|
|
70
|
+
{
|
|
71
|
+
latitude,
|
|
72
|
+
longitude,
|
|
73
|
+
altitude,
|
|
74
|
+
setOnRender,
|
|
75
|
+
onReady,
|
|
76
|
+
map,
|
|
77
|
+
canvasRef
|
|
78
|
+
}
|
|
79
|
+
),
|
|
80
|
+
ready && children
|
|
81
|
+
] })
|
|
82
|
+
] });
|
|
83
|
+
});
|
|
84
|
+
CanvasPortal.displayName = "CanvasPortal";
|
|
85
|
+
export {
|
|
86
|
+
CanvasPortal
|
|
87
|
+
};
|
|
88
|
+
//# sourceMappingURL=main18.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main18.mjs","sources":["../../src/core/canvas-overlay/canvas-portal.tsx"],"sourcesContent":["import { Color4, Engine, FreeCamera, Scene, Vector3 } from '@babylonjs/core';\nimport { memo, useEffect, useRef, useState } from 'react';\nimport { CanvasProps } from '../../api/canvas-props';\nimport { BabylonMap, BabylonMapContext, createBabylonMap } from '../use-babylon-map';\nimport { FromLngLat, MapInstance } from '../generic-map';\nimport { useFunction } from '../use-function';\nimport { SyncCameraFC } from './sync-camera-fc';\n\ninterface CanvasPortalProps extends CanvasProps {\n setOnRender: (callback: () => (mx: number[]) => void) => void;\n map: MapInstance;\n fromLngLat: FromLngLat;\n}\n\nconst canvasStyle: React.CSSProperties = {\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n pointerEvents: 'none',\n};\n\nexport const CanvasPortal = memo<CanvasPortalProps>(({\n children, latitude, longitude, altitude,\n setOnRender, map, fromLngLat,\n}) => {\n\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const mapCanvas = map.getCanvas();\n\n const [babylonMap, setBabylonMap] = useState<BabylonMap | null>(null);\n const [ready, setReady] = useState(false);\n\n // Create Engine + Scene on mount\n useEffect(() => {\n const canvas = canvasRef.current!;\n const engine = new Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true, useHighPrecisionMatrix: true });\n const scene = new Scene(engine);\n scene.clearColor = new Color4(0, 0, 0, 0);\n\n const camera = new FreeCamera('cam', Vector3.Zero(), scene);\n camera.inputs.clear();\n camera.minZ = 0;\n\n setBabylonMap(createBabylonMap({ map, fromLngLat, engine, scene }));\n\n return () => {\n scene.dispose();\n engine.dispose();\n };\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Resize handling\n useEffect(() => {\n if (!babylonMap?.engine) return;\n const engine = babylonMap.engine;\n\n const onResize = () => {\n const c = canvasRef.current;\n if (!c) return;\n c.width = mapCanvas.clientWidth * window.devicePixelRatio;\n c.height = mapCanvas.clientHeight * window.devicePixelRatio;\n c.style.width = `${mapCanvas.clientWidth}px`;\n c.style.height = `${mapCanvas.clientHeight}px`;\n engine.resize();\n };\n\n onResize();\n map.on('resize', onResize);\n return () => { map.off('resize', onResize); };\n }, [babylonMap, map, mapCanvas]);\n\n const onReady = useFunction(() => {\n setReady(true);\n });\n\n return (\n <>\n <canvas ref={canvasRef} style={canvasStyle} />\n {babylonMap && (\n <BabylonMapContext.Provider value={babylonMap}>\n <SyncCameraFC\n latitude={latitude}\n longitude={longitude}\n altitude={altitude}\n setOnRender={setOnRender}\n onReady={onReady}\n map={map}\n canvasRef={canvasRef}\n />\n {ready && children}\n </BabylonMapContext.Provider>\n )}\n </>\n );\n});\nCanvasPortal.displayName = 'CanvasPortal';\n"],"names":[],"mappings":";;;;;;AAcA,MAAM,cAAmC;AAAA,EACvC,UAAU;AAAA,EACV,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,eAAe;AACjB;AAEa,MAAA,eAAe,KAAwB,CAAC;AAAA,EACnD;AAAA,EAAU;AAAA,EAAU;AAAA,EAAW;AAAA,EAC/B;AAAA,EAAa;AAAA,EAAK;AACpB,MAAM;AAEE,QAAA,YAAY,OAA0B,IAAI;AAC1C,QAAA,YAAY,IAAI;AAEtB,QAAM,CAAC,YAAY,aAAa,IAAI,SAA4B,IAAI;AACpE,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,KAAK;AAGxC,YAAU,MAAM;AACd,UAAM,SAAS,UAAU;AACzB,UAAM,SAAS,IAAI,OAAO,QAAQ,MAAM,EAAE,uBAAuB,MAAM,SAAS,MAAM,wBAAwB,KAAM,CAAA;AAC9G,UAAA,QAAQ,IAAI,MAAM,MAAM;AAC9B,UAAM,aAAa,IAAI,OAAO,GAAG,GAAG,GAAG,CAAC;AAExC,UAAM,SAAS,IAAI,WAAW,OAAO,QAAQ,KAAA,GAAQ,KAAK;AAC1D,WAAO,OAAO;AACd,WAAO,OAAO;AAEd,kBAAc,iBAAiB,EAAE,KAAK,YAAY,QAAQ,MAAO,CAAA,CAAC;AAElE,WAAO,MAAM;AACX,YAAM,QAAQ;AACd,aAAO,QAAQ;AAAA,IAAA;AAAA,EAEnB,GAAG,CAAE,CAAA;AAGL,YAAU,MAAM;AACd,QAAI,EAAC,yCAAY;AAAQ;AACzB,UAAM,SAAS,WAAW;AAE1B,UAAM,WAAW,MAAM;AACrB,YAAM,IAAI,UAAU;AACpB,UAAI,CAAC;AAAG;AACN,QAAA,QAAQ,UAAU,cAAc,OAAO;AACvC,QAAA,SAAS,UAAU,eAAe,OAAO;AAC3C,QAAE,MAAM,QAAQ,GAAG,UAAU,WAAW;AACxC,QAAE,MAAM,SAAS,GAAG,UAAU,YAAY;AAC1C,aAAO,OAAO;AAAA,IAAA;AAGP;AACL,QAAA,GAAG,UAAU,QAAQ;AACzB,WAAO,MAAM;AAAM,UAAA,IAAI,UAAU,QAAQ;AAAA,IAAA;AAAA,EACxC,GAAA,CAAC,YAAY,KAAK,SAAS,CAAC;AAEzB,QAAA,UAAU,YAAY,MAAM;AAChC,aAAS,IAAI;AAAA,EAAA,CACd;AAED,SAEI,qBAAA,UAAA,EAAA,UAAA;AAAA,IAAA,oBAAC,UAAO,EAAA,KAAK,WAAW,OAAO,aAAa;AAAA,IAC3C,cACE,qBAAA,kBAAkB,UAAlB,EAA2B,OAAO,YACjC,UAAA;AAAA,MAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QAAA;AAAA,MACF;AAAA,MACC,SAAS;AAAA,IAAA,GACZ;AAAA,EAEJ,EAAA,CAAA;AAEJ,CAAC;AACD,aAAa,cAAc;"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Vector3, Quaternion, Matrix } from "@babylonjs/core";
|
|
2
|
+
function coordsToMatrix({
|
|
3
|
+
longitude,
|
|
4
|
+
latitude,
|
|
5
|
+
altitude,
|
|
6
|
+
fromLngLat
|
|
7
|
+
}) {
|
|
8
|
+
const center = fromLngLat([longitude, latitude], altitude);
|
|
9
|
+
const scaleUnit = center.meterInMercatorCoordinateUnits();
|
|
10
|
+
const position = new Vector3(center.x, center.y, center.z || 0);
|
|
11
|
+
const scaling = new Vector3(scaleUnit, scaleUnit, scaleUnit);
|
|
12
|
+
const rotation = Quaternion.FromEulerAngles(Math.PI / 2, 0, 0);
|
|
13
|
+
return Matrix.Compose(scaling, rotation, position);
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
coordsToMatrix
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=main19.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main19.mjs","sources":["../../src/core/coords-to-matrix.ts"],"sourcesContent":["import { Matrix, Quaternion, Vector3 } from '@babylonjs/core';\nimport { FromLngLat } from './generic-map';\nimport { Coords } from '../api/coords';\n\n/** Calculate Babylon.js Matrix from coordinates.\n * Returns a Babylon Matrix (world transform at the given geo coord).\n * Matches the pattern from MapLibre + Babylon.js integration demo. */\nexport function coordsToMatrix({\n longitude, latitude, altitude, fromLngLat\n}: Coords & { fromLngLat: FromLngLat }): Matrix {\n const center = fromLngLat([longitude, latitude], altitude);\n const scaleUnit = center.meterInMercatorCoordinateUnits();\n\n const position = new Vector3(center.x, center.y, center.z || 0);\n const scaling = new Vector3(scaleUnit, scaleUnit, scaleUnit);\n // Babylon default: +x east, +y up, +z north\n // MapLibre default: +x east, -y north, +z up\n const rotation = Quaternion.FromEulerAngles(Math.PI / 2, 0, 0);\n\n return Matrix.Compose(scaling, rotation, position);\n}\n"],"names":[],"mappings":";AAOO,SAAS,eAAe;AAAA,EAC7B;AAAA,EAAW;AAAA,EAAU;AAAA,EAAU;AACjC,GAAgD;AAC9C,QAAM,SAAS,WAAW,CAAC,WAAW,QAAQ,GAAG,QAAQ;AACnD,QAAA,YAAY,OAAO;AAEnB,QAAA,WAAW,IAAI,QAAQ,OAAO,GAAG,OAAO,GAAG,OAAO,KAAK,CAAC;AAC9D,QAAM,UAAU,IAAI,QAAQ,WAAW,WAAW,SAAS;AAG3D,QAAM,WAAW,WAAW,gBAAgB,KAAK,KAAK,GAAG,GAAG,CAAC;AAE7D,SAAO,OAAO,QAAQ,SAAS,UAAU,QAAQ;AACnD;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main2.mjs","sources":["../../src/api/use-map.ts"],"sourcesContent":["import { MapInstance } from '../core/generic-map';\nimport { useBabylonMap } from '../core/use-babylon-map';\n\n/** Access the underlying map instance from inside a `<Canvas>`. */\nexport const useMap = <T extends MapInstance = MapInstance>(): T => {\n const ctx = useBabylonMap();\n return ctx.map as T;\n};\n"],"names":[],"mappings":";AAIO,MAAM,SAAS,MAA8C;AAClE,QAAM,MAAM;AACZ,SAAO,IAAI;AACb;"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import require$$0 from "react-dom";
|
|
2
|
+
var createRoot;
|
|
3
|
+
var m = require$$0;
|
|
4
|
+
if (process.env.NODE_ENV === "production") {
|
|
5
|
+
createRoot = m.createRoot;
|
|
6
|
+
m.hydrateRoot;
|
|
7
|
+
} else {
|
|
8
|
+
var i = m.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
|
|
9
|
+
createRoot = function(c, o) {
|
|
10
|
+
i.usingClientEntryPoint = true;
|
|
11
|
+
try {
|
|
12
|
+
return m.createRoot(c, o);
|
|
13
|
+
} finally {
|
|
14
|
+
i.usingClientEntryPoint = false;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export {
|
|
19
|
+
createRoot
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=main20.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main20.mjs","sources":["../../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/client.js"],"sourcesContent":["'use strict';\n\nvar m = require('react-dom');\nif (process.env.NODE_ENV === 'production') {\n exports.createRoot = m.createRoot;\n exports.hydrateRoot = m.hydrateRoot;\n} else {\n var i = m.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n exports.createRoot = function(c, o) {\n i.usingClientEntryPoint = true;\n try {\n return m.createRoot(c, o);\n } finally {\n i.usingClientEntryPoint = false;\n }\n };\n exports.hydrateRoot = function(c, h, o) {\n i.usingClientEntryPoint = true;\n try {\n return m.hydrateRoot(c, h, o);\n } finally {\n i.usingClientEntryPoint = false;\n }\n };\n}\n"],"names":[],"mappings":";;AAEA,IAAI,IAAI;AACR,IAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,eAAqB,EAAE;AACD,IAAE;AAC1B,OAAO;AACL,MAAI,IAAI,EAAE;AACV,eAAqB,SAAS,GAAG,GAAG;AAClC,MAAE,wBAAwB;AAC1B,QAAI;AACF,aAAO,EAAE,WAAW,GAAG,CAAC;AAAA,IAC9B,UAAc;AACR,QAAE,wBAAwB;AAAA,IAC3B;AAAA,EACL;AASA;","x_google_ignoreList":[0]}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { memo, useRef, useMemo, useEffect } from "react";
|
|
2
|
+
import { syncCamera } from "./main12.mjs";
|
|
3
|
+
import { useCoordsToMatrix } from "./main13.mjs";
|
|
4
|
+
import { useFunction } from "./main11.mjs";
|
|
5
|
+
import { useBabylonMap } from "./main4.mjs";
|
|
6
|
+
const SyncCameraFC = memo(({
|
|
7
|
+
latitude,
|
|
8
|
+
longitude,
|
|
9
|
+
altitude = 0,
|
|
10
|
+
setOnRender,
|
|
11
|
+
onReady,
|
|
12
|
+
map,
|
|
13
|
+
canvasRef
|
|
14
|
+
}) => {
|
|
15
|
+
const mapCanvas = map.getCanvas();
|
|
16
|
+
const babylonMap = useBabylonMap();
|
|
17
|
+
const scene = babylonMap.scene;
|
|
18
|
+
const engine = babylonMap.engine;
|
|
19
|
+
const origin = useCoordsToMatrix({ latitude, longitude, altitude, fromLngLat: babylonMap.fromLngLat });
|
|
20
|
+
const ready = useRef(false);
|
|
21
|
+
const triggerRepaint = useMemo(() => map.triggerRepaint, [map]);
|
|
22
|
+
const mapPaintRequests = useRef(0);
|
|
23
|
+
const triggerRepaintOff = useFunction(() => {
|
|
24
|
+
mapPaintRequests.current++;
|
|
25
|
+
});
|
|
26
|
+
const onRender = useFunction((viewProjMx) => {
|
|
27
|
+
map.triggerRepaint = triggerRepaintOff;
|
|
28
|
+
if (canvasRef.current && engine) {
|
|
29
|
+
if (canvasRef.current.width !== mapCanvas.width || canvasRef.current.height !== mapCanvas.height) {
|
|
30
|
+
canvasRef.current.width = mapCanvas.clientWidth * window.devicePixelRatio;
|
|
31
|
+
canvasRef.current.height = mapCanvas.clientHeight * window.devicePixelRatio;
|
|
32
|
+
canvasRef.current.style.width = `${mapCanvas.clientWidth}px`;
|
|
33
|
+
canvasRef.current.style.height = `${mapCanvas.clientHeight}px`;
|
|
34
|
+
engine.resize();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const pVMx = "defaultProjectionData" in viewProjMx ? Object.values(viewProjMx.defaultProjectionData.mainMatrix) : viewProjMx;
|
|
38
|
+
babylonMap.viewProjMx = pVMx;
|
|
39
|
+
syncCamera(scene.activeCamera, origin, babylonMap.viewProjMx);
|
|
40
|
+
engine.wipeCaches(true);
|
|
41
|
+
scene.render(false);
|
|
42
|
+
if (!ready.current && onReady) {
|
|
43
|
+
ready.current = true;
|
|
44
|
+
onReady();
|
|
45
|
+
}
|
|
46
|
+
map.triggerRepaint = triggerRepaint;
|
|
47
|
+
if (mapPaintRequests.current > 0) {
|
|
48
|
+
mapPaintRequests.current = 0;
|
|
49
|
+
map.triggerRepaint();
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
setOnRender && setOnRender(() => onRender);
|
|
54
|
+
}, [setOnRender, onRender]);
|
|
55
|
+
return null;
|
|
56
|
+
});
|
|
57
|
+
SyncCameraFC.displayName = "SyncCameraFC";
|
|
58
|
+
export {
|
|
59
|
+
SyncCameraFC
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=main21.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main21.mjs","sources":["../../src/core/canvas-overlay/sync-camera-fc.tsx"],"sourcesContent":["import { FreeCamera } from '@babylonjs/core';\nimport { memo, RefObject, useEffect, useRef, useMemo } from 'react';\nimport { Coords } from '../../api/coords';\nimport { MapInstance } from '../generic-map';\nimport { syncCamera } from '../sync-camera';\nimport { useCoordsToMatrix } from '../use-coords-to-matrix';\nimport { useFunction } from '../use-function';\nimport { useBabylonMap } from '../use-babylon-map';\n\ninterface SyncCameraFCProps extends Coords {\n setOnRender?: (callback: () => (mx: number[]) => void) => void;\n onReady?: () => void;\n map: MapInstance;\n canvasRef: RefObject<HTMLCanvasElement | null>;\n}\n\n/** React component to sync the Babylon camera with the map provider on each render. */\nexport const SyncCameraFC = memo<SyncCameraFCProps>(({\n latitude, longitude, altitude = 0, setOnRender, onReady, map, canvasRef,\n}) => {\n\n const mapCanvas = map.getCanvas();\n const babylonMap = useBabylonMap();\n const scene = babylonMap.scene!;\n const engine = babylonMap.engine!;\n\n const origin = useCoordsToMatrix({ latitude, longitude, altitude, fromLngLat: babylonMap.fromLngLat });\n\n const ready = useRef(false);\n\n const triggerRepaint = useMemo(() => map.triggerRepaint, [map]);\n const mapPaintRequests = useRef(0);\n const triggerRepaintOff = useFunction(() => {\n mapPaintRequests.current++;\n });\n\n // Render callback — called by MapLibre on each paint frame\n const onRender = useFunction((viewProjMx: number[] | { defaultProjectionData: { mainMatrix: Record<string, number> } }) => {\n map.triggerRepaint = triggerRepaintOff;\n\n // Resize if needed\n if (canvasRef.current && engine) {\n if (canvasRef.current.width !== mapCanvas.width || canvasRef.current.height !== mapCanvas.height) {\n canvasRef.current.width = mapCanvas.clientWidth * window.devicePixelRatio;\n canvasRef.current.height = mapCanvas.clientHeight * window.devicePixelRatio;\n canvasRef.current.style.width = `${mapCanvas.clientWidth}px`;\n canvasRef.current.style.height = `${mapCanvas.clientHeight}px`;\n engine.resize();\n }\n }\n\n const pVMx = 'defaultProjectionData' in viewProjMx\n ? Object.values(viewProjMx.defaultProjectionData.mainMatrix)\n : viewProjMx;\n babylonMap.viewProjMx = pVMx as number[];\n\n // Sync camera\n syncCamera(scene.activeCamera as FreeCamera, origin, babylonMap.viewProjMx);\n\n // Wipe caches and render one frame\n engine.wipeCaches(true);\n scene.render(false);\n\n if (!ready.current && onReady) {\n ready.current = true;\n onReady();\n }\n\n // Restore triggerRepaint for demand-based rendering\n map.triggerRepaint = triggerRepaint;\n if (mapPaintRequests.current > 0) {\n mapPaintRequests.current = 0;\n map.triggerRepaint();\n }\n });\n\n useEffect(() => {\n setOnRender && setOnRender(() => onRender);\n }, [setOnRender, onRender]);\n\n return null;\n});\nSyncCameraFC.displayName = 'SyncCameraFC';\n"],"names":[],"mappings":";;;;;AAiBa,MAAA,eAAe,KAAwB,CAAC;AAAA,EACnD;AAAA,EAAU;AAAA,EAAW,WAAW;AAAA,EAAG;AAAA,EAAa;AAAA,EAAS;AAAA,EAAK;AAChE,MAAM;AAEE,QAAA,YAAY,IAAI;AACtB,QAAM,aAAa;AACnB,QAAM,QAAQ,WAAW;AACzB,QAAM,SAAS,WAAW;AAEpB,QAAA,SAAS,kBAAkB,EAAE,UAAU,WAAW,UAAU,YAAY,WAAW,WAAA,CAAY;AAE/F,QAAA,QAAQ,OAAO,KAAK;AAE1B,QAAM,iBAAiB,QAAQ,MAAM,IAAI,gBAAgB,CAAC,GAAG,CAAC;AACxD,QAAA,mBAAmB,OAAO,CAAC;AAC3B,QAAA,oBAAoB,YAAY,MAAM;AACzB,qBAAA;AAAA,EAAA,CAClB;AAGK,QAAA,WAAW,YAAY,CAAC,eAA6F;AACzH,QAAI,iBAAiB;AAGjB,QAAA,UAAU,WAAW,QAAQ;AAC3B,UAAA,UAAU,QAAQ,UAAU,UAAU,SAAS,UAAU,QAAQ,WAAW,UAAU,QAAQ;AAChG,kBAAU,QAAQ,QAAQ,UAAU,cAAc,OAAO;AACzD,kBAAU,QAAQ,SAAS,UAAU,eAAe,OAAO;AAC3D,kBAAU,QAAQ,MAAM,QAAQ,GAAG,UAAU,WAAW;AACxD,kBAAU,QAAQ,MAAM,SAAS,GAAG,UAAU,YAAY;AAC1D,eAAO,OAAO;AAAA,MAChB;AAAA,IACF;AAEM,UAAA,OAAO,2BAA2B,aACpC,OAAO,OAAO,WAAW,sBAAsB,UAAU,IACzD;AACJ,eAAW,aAAa;AAGxB,eAAW,MAAM,cAA4B,QAAQ,WAAW,UAAU;AAG1E,WAAO,WAAW,IAAI;AACtB,UAAM,OAAO,KAAK;AAEd,QAAA,CAAC,MAAM,WAAW,SAAS;AAC7B,YAAM,UAAU;AACR;IACV;AAGA,QAAI,iBAAiB;AACjB,QAAA,iBAAiB,UAAU,GAAG;AAChC,uBAAiB,UAAU;AAC3B,UAAI,eAAe;AAAA,IACrB;AAAA,EAAA,CACD;AAED,YAAU,MAAM;AACC,mBAAA,YAAY,MAAM,QAAQ;AAAA,EAAA,GACxC,CAAC,aAAa,QAAQ,CAAC;AAEnB,SAAA;AACT,CAAC;AACD,aAAa,cAAc;"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { jsxs, Fragment, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { MercatorCoordinate } from "mapbox-gl";
|
|
3
|
+
import { memo, useState } from "react";
|
|
4
|
+
import { useMap, Layer } from "react-map-gl/mapbox";
|
|
5
|
+
import { useCanvasInLayer } from "./main9.mjs";
|
|
6
|
+
import { InitCanvasFC } from "./main10.mjs";
|
|
7
|
+
import { useFunction } from "./main11.mjs";
|
|
8
|
+
const fromLngLat = MercatorCoordinate.fromLngLat;
|
|
9
|
+
const Canvas = memo(({ overlay, ...props }) => {
|
|
10
|
+
const map = useMap().current.getMap();
|
|
11
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
12
|
+
overlay && /* @__PURE__ */ jsx(CanvasOverlay, { map, ...props }),
|
|
13
|
+
!overlay && /* @__PURE__ */ jsx(CanvasInLayer, { map, ...props })
|
|
14
|
+
] });
|
|
15
|
+
});
|
|
16
|
+
Canvas.displayName = "Canvas";
|
|
17
|
+
const CanvasInLayer = memo(({ map, ...props }) => {
|
|
18
|
+
const layerProps = useCanvasInLayer(props, fromLngLat, map);
|
|
19
|
+
return /* @__PURE__ */ jsx(Layer, { ...layerProps });
|
|
20
|
+
});
|
|
21
|
+
CanvasInLayer.displayName = "CanvasInLayer";
|
|
22
|
+
const CanvasOverlay = memo(({ map, id, beforeId, ...props }) => {
|
|
23
|
+
const [onRender, setOnRender] = useState();
|
|
24
|
+
const render = useFunction((_gl, mx) => {
|
|
25
|
+
if (!onRender)
|
|
26
|
+
return;
|
|
27
|
+
onRender(mx);
|
|
28
|
+
});
|
|
29
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
30
|
+
/* @__PURE__ */ jsx(Layer, { id, beforeId, type: "custom", render }),
|
|
31
|
+
/* @__PURE__ */ jsx(
|
|
32
|
+
InitCanvasFC,
|
|
33
|
+
{
|
|
34
|
+
...props,
|
|
35
|
+
setOnRender,
|
|
36
|
+
map,
|
|
37
|
+
fromLngLat
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
] });
|
|
41
|
+
});
|
|
42
|
+
CanvasOverlay.displayName = "CanvasOverlay";
|
|
43
|
+
export {
|
|
44
|
+
Canvas
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=main3.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main3.mjs","sources":["../../src/mapbox/canvas.tsx"],"sourcesContent":["/* eslint-disable @typescript-eslint/ban-ts-comment */\nimport { MercatorCoordinate } from 'mapbox-gl';\nimport { memo, useState } from 'react';\nimport { Layer, useMap } from 'react-map-gl/mapbox';\nimport { CanvasProps } from '../api/canvas-props';\nimport { useCanvasInLayer } from '../core/canvas-in-layer/use-canvas-in-layer';\nimport { InitCanvasFC } from '../core/canvas-overlay/init-canvas-fc';\nimport { Render } from '../core/canvas-overlay/render';\nimport { MapInstance } from '../core/generic-map';\nimport { useFunction } from '../core/use-function';\n\nconst fromLngLat = MercatorCoordinate.fromLngLat;\n\n/** `react-babylon-map` canvas inside `Mapbox` */\nexport const Canvas = memo<CanvasProps>(({ overlay, ...props }) => {\n const map = useMap().current!.getMap(); // eslint-disable-line @typescript-eslint/no-non-null-assertion\n\n return (\n <>\n {overlay && <CanvasOverlay map={map} {...props} />}\n {!overlay && <CanvasInLayer map={map} {...props} />}\n </>\n );\n});\nCanvas.displayName = 'Canvas';\n\ninterface CanvasPropsAndMap extends CanvasProps {\n map: MapInstance;\n}\n\nconst CanvasInLayer = memo<CanvasPropsAndMap>(({ map, ...props }) => {\n const layerProps = useCanvasInLayer(props, fromLngLat, map);\n /* @ts-ignore */\n return <Layer {...layerProps} />;\n});\nCanvasInLayer.displayName = 'CanvasInLayer';\n\nconst CanvasOverlay = memo<CanvasPropsAndMap>(({ map, id, beforeId, ...props }) => {\n const [onRender, setOnRender] = useState<(mx: number[]) => void>();\n\n const render = useFunction<Render>((_gl, mx) => {\n if (!onRender) return;\n onRender(mx as number[]);\n });\n\n return (\n <>\n {/* @ts-ignore */}\n <Layer id={id} beforeId={beforeId} type=\"custom\" render={render} />\n <InitCanvasFC\n {...props}\n setOnRender={setOnRender}\n map={map}\n fromLngLat={fromLngLat}\n />\n </>\n );\n});\nCanvasOverlay.displayName = 'CanvasOverlay';\n"],"names":[],"mappings":";;;;;;;AAWA,MAAM,aAAa,mBAAmB;AAG/B,MAAM,SAAS,KAAkB,CAAC,EAAE,SAAS,GAAG,YAAY;AACjE,QAAM,MAAM,OAAA,EAAS,QAAS,OAAO;AAErC,SAEK,qBAAA,UAAA,EAAA,UAAA;AAAA,IAAA,WAAY,oBAAA,eAAA,EAAc,KAAW,GAAG,MAAO,CAAA;AAAA,IAC/C,CAAC,WAAW,oBAAC,eAAc,EAAA,KAAW,GAAG,OAAO;AAAA,EACnD,EAAA,CAAA;AAEJ,CAAC;AACD,OAAO,cAAc;AAMrB,MAAM,gBAAgB,KAAwB,CAAC,EAAE,KAAK,GAAG,YAAY;AACnE,QAAM,aAAa,iBAAiB,OAAO,YAAY,GAAG;AAEnD,SAAA,oBAAC,OAAO,EAAA,GAAG,WAAY,CAAA;AAChC,CAAC;AACD,cAAc,cAAc;AAE5B,MAAM,gBAAgB,KAAwB,CAAC,EAAE,KAAK,IAAI,UAAU,GAAG,YAAY;AACjF,QAAM,CAAC,UAAU,WAAW,IAAI,SAAiC;AAEjE,QAAM,SAAS,YAAoB,CAAC,KAAK,OAAO;AAC9C,QAAI,CAAC;AAAU;AACf,aAAS,EAAc;AAAA,EAAA,CACxB;AAED,SAGI,qBAAA,UAAA,EAAA,UAAA;AAAA,IAAA,oBAAC,OAAM,EAAA,IAAQ,UAAoB,MAAK,UAAS,QAAgB;AAAA,IACjE;AAAA,MAAC;AAAA,MAAA;AAAA,QACE,GAAG;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,IACF;AAAA,EACF,EAAA,CAAA;AAEJ,CAAC;AACD,cAAc,cAAc;"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { createContext, useContext } from "react";
|
|
2
|
+
const BabylonMapContext = createContext(null);
|
|
3
|
+
function useBabylonMap() {
|
|
4
|
+
const ctx = useContext(BabylonMapContext);
|
|
5
|
+
if (!ctx)
|
|
6
|
+
throw new Error("useBabylonMap must be used inside a <Canvas>");
|
|
7
|
+
return ctx;
|
|
8
|
+
}
|
|
9
|
+
function createBabylonMap(opts) {
|
|
10
|
+
return {
|
|
11
|
+
map: opts.map,
|
|
12
|
+
viewProjMx: new Array(16).fill(0),
|
|
13
|
+
fromLngLat: opts.fromLngLat,
|
|
14
|
+
engine: opts.engine,
|
|
15
|
+
scene: opts.scene
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export {
|
|
19
|
+
BabylonMapContext,
|
|
20
|
+
createBabylonMap,
|
|
21
|
+
useBabylonMap
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=main4.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main4.mjs","sources":["../../src/core/use-babylon-map.ts"],"sourcesContent":["import { createContext, useContext } from 'react';\nimport { Engine, Scene } from '@babylonjs/core';\nimport { FromLngLat, MapInstance } from './generic-map';\n\n/** Context object shared between both rendering modes. */\nexport interface BabylonMap<T extends MapInstance = MapInstance> {\n /** Map provider instance */\n map: T;\n /** Column-major view-projection matrix from the map provider */\n viewProjMx: number[];\n /** Mercator coordinate factory */\n fromLngLat: FromLngLat;\n /** Babylon Engine (may be null during init) */\n engine?: Engine;\n /** Babylon Scene (may be null during init) */\n scene?: Scene;\n /** Current origin coordinates (set by Canvas) */\n coords?: { longitude: number; latitude: number; altitude?: number };\n}\n\n// ── React context ──────────────────────────────────────────────────────\n\nexport const BabylonMapContext = createContext<BabylonMap | null>(null);\n\n/** Access the current BabylonMap context (map, scene, engine, viewProjMx). */\nexport function useBabylonMap<T extends MapInstance = MapInstance>(): BabylonMap<T> {\n const ctx = useContext(BabylonMapContext);\n if (!ctx) throw new Error('useBabylonMap must be used inside a <Canvas>');\n return ctx as BabylonMap<T>;\n}\n\n/** Initialise / update the BabylonMap context value. */\nexport function createBabylonMap<T extends MapInstance>(opts: {\n map: T;\n fromLngLat: FromLngLat;\n engine?: Engine;\n scene?: Scene;\n}): BabylonMap<T> {\n return {\n map: opts.map,\n viewProjMx: new Array(16).fill(0) as number[],\n fromLngLat: opts.fromLngLat,\n engine: opts.engine,\n scene: opts.scene,\n };\n}\n"],"names":[],"mappings":";AAsBa,MAAA,oBAAoB,cAAiC,IAAI;AAG/D,SAAS,gBAAoE;AAC5E,QAAA,MAAM,WAAW,iBAAiB;AACxC,MAAI,CAAC;AAAW,UAAA,IAAI,MAAM,8CAA8C;AACjE,SAAA;AACT;AAGO,SAAS,iBAAwC,MAKtC;AACT,SAAA;AAAA,IACL,KAAK,KAAK;AAAA,IACV,YAAY,IAAI,MAAM,EAAE,EAAE,KAAK,CAAC;AAAA,IAChC,YAAY,KAAK;AAAA,IACjB,QAAQ,KAAK;AAAA,IACb,OAAO,KAAK;AAAA,EAAA;AAEhB;"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Scene, Color4, FreeCamera, Vector3, HemisphericLight } from "@babylonjs/core";
|
|
3
|
+
import { memo, useState, useRef, useEffect } from "react";
|
|
4
|
+
import { syncCamera } from "./main12.mjs";
|
|
5
|
+
import { useCoordsToMatrix } from "./main13.mjs";
|
|
6
|
+
import { useBabylonMap, BabylonMapContext } from "./main4.mjs";
|
|
7
|
+
const Coordinates = memo(({
|
|
8
|
+
latitude,
|
|
9
|
+
longitude,
|
|
10
|
+
altitude = 0,
|
|
11
|
+
children
|
|
12
|
+
}) => {
|
|
13
|
+
const babylonMap = useBabylonMap();
|
|
14
|
+
const origin = useCoordsToMatrix({
|
|
15
|
+
latitude,
|
|
16
|
+
longitude,
|
|
17
|
+
altitude,
|
|
18
|
+
fromLngLat: babylonMap.fromLngLat
|
|
19
|
+
});
|
|
20
|
+
const [subScene] = useState(() => {
|
|
21
|
+
if (!babylonMap.engine)
|
|
22
|
+
return null;
|
|
23
|
+
const sub = new Scene(babylonMap.engine);
|
|
24
|
+
sub.autoClear = false;
|
|
25
|
+
sub.clearColor = new Color4(0, 0, 0, 0);
|
|
26
|
+
return sub;
|
|
27
|
+
});
|
|
28
|
+
const cameraRef = useRef(null);
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (!subScene)
|
|
31
|
+
return;
|
|
32
|
+
const cam = new FreeCamera("coordsCam", Vector3.Zero(), subScene);
|
|
33
|
+
cam.inputs.clear();
|
|
34
|
+
cam.minZ = 0;
|
|
35
|
+
cameraRef.current = cam;
|
|
36
|
+
const light = new HemisphericLight("coordsLight", new Vector3(0, 1, 0), subScene);
|
|
37
|
+
light.intensity = 1;
|
|
38
|
+
return () => {
|
|
39
|
+
cam.dispose();
|
|
40
|
+
light.dispose();
|
|
41
|
+
};
|
|
42
|
+
}, [subScene]);
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
if (!subScene || !babylonMap.scene)
|
|
45
|
+
return;
|
|
46
|
+
const mainScene = babylonMap.scene;
|
|
47
|
+
const observer = mainScene.onBeforeRenderObservable.add(() => {
|
|
48
|
+
var _a;
|
|
49
|
+
if (!cameraRef.current)
|
|
50
|
+
return;
|
|
51
|
+
syncCamera(cameraRef.current, origin, babylonMap.viewProjMx);
|
|
52
|
+
(_a = babylonMap.engine) == null ? void 0 : _a.wipeCaches(true);
|
|
53
|
+
subScene.render(false);
|
|
54
|
+
});
|
|
55
|
+
return () => {
|
|
56
|
+
mainScene.onBeforeRenderObservable.remove(observer);
|
|
57
|
+
};
|
|
58
|
+
}, [subScene, babylonMap.scene, origin, babylonMap]);
|
|
59
|
+
const childMap = {
|
|
60
|
+
...babylonMap,
|
|
61
|
+
scene: subScene || void 0
|
|
62
|
+
};
|
|
63
|
+
return /* @__PURE__ */ jsx(BabylonMapContext.Provider, { value: childMap, children });
|
|
64
|
+
});
|
|
65
|
+
Coordinates.displayName = "Coordinates";
|
|
66
|
+
export {
|
|
67
|
+
Coordinates
|
|
68
|
+
};
|
|
69
|
+
//# sourceMappingURL=main5.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main5.mjs","sources":["../../src/api/coordinates.tsx"],"sourcesContent":["import { Color4, FreeCamera, HemisphericLight, Scene, Vector3 } from '@babylonjs/core';\nimport { memo, useEffect, useRef, useState } from 'react';\nimport { syncCamera } from '../core/sync-camera';\nimport { useCoordsToMatrix } from '../core/use-coords-to-matrix';\nimport { useBabylonMap, BabylonMapContext } from '../core/use-babylon-map';\nimport type { BabylonMap } from '../core/use-babylon-map';\n\nexport interface CoordinatesProps {\n longitude: number;\n latitude: number;\n altitude?: number;\n children?: React.ReactNode;\n}\n\n/**\n * Place 3D content at specific geographic coordinates inside a `<Canvas>`.\n * Creates a sub-scene with its own camera synced to the given geo position,\n * mirroring react-three-map's createPortal approach.\n */\nexport const Coordinates = memo<CoordinatesProps>(({\n latitude, longitude, altitude = 0, children,\n}) => {\n const babylonMap = useBabylonMap();\n const origin = useCoordsToMatrix({\n latitude, longitude, altitude, fromLngLat: babylonMap.fromLngLat,\n });\n\n // Create a sub-scene for this coordinate portal\n const [subScene] = useState(() => {\n if (!babylonMap.engine) return null;\n const sub = new Scene(babylonMap.engine);\n sub.autoClear = false;\n sub.clearColor = new Color4(0, 0, 0, 0);\n return sub;\n });\n\n const cameraRef = useRef<FreeCamera | null>(null);\n\n // Create camera + default light in sub-scene\n useEffect(() => {\n if (!subScene) return;\n const cam = new FreeCamera('coordsCam', Vector3.Zero(), subScene);\n cam.inputs.clear();\n cam.minZ = 0;\n cameraRef.current = cam;\n\n // Add a default light so StandardMaterial isn't black\n const light = new HemisphericLight('coordsLight', new Vector3(0, 1, 0), subScene);\n light.intensity = 1;\n\n return () => { cam.dispose(); light.dispose(); };\n }, [subScene]);\n\n // Render the sub-scene each frame, synced to its geographic position\n useEffect(() => {\n if (!subScene || !babylonMap.scene) return;\n const mainScene = babylonMap.scene;\n\n const observer = mainScene.onBeforeRenderObservable.add(() => {\n if (!cameraRef.current) return;\n syncCamera(cameraRef.current, origin, babylonMap.viewProjMx);\n babylonMap.engine?.wipeCaches(true);\n subScene.render(false);\n });\n\n return () => {\n mainScene.onBeforeRenderObservable.remove(observer);\n };\n }, [subScene, babylonMap.scene, origin, babylonMap]);\n\n // Provide child context pointing at the sub-scene\n const childMap: BabylonMap = {\n ...babylonMap,\n scene: subScene || undefined,\n };\n\n return (\n <BabylonMapContext.Provider value={childMap}>\n {children}\n </BabylonMapContext.Provider>\n );\n});\nCoordinates.displayName = 'Coordinates';\n"],"names":[],"mappings":";;;;;;AAmBa,MAAA,cAAc,KAAuB,CAAC;AAAA,EACjD;AAAA,EAAU;AAAA,EAAW,WAAW;AAAA,EAAG;AACrC,MAAM;AACJ,QAAM,aAAa;AACnB,QAAM,SAAS,kBAAkB;AAAA,IAC/B;AAAA,IAAU;AAAA,IAAW;AAAA,IAAU,YAAY,WAAW;AAAA,EAAA,CACvD;AAGD,QAAM,CAAC,QAAQ,IAAI,SAAS,MAAM;AAChC,QAAI,CAAC,WAAW;AAAe,aAAA;AAC/B,UAAM,MAAM,IAAI,MAAM,WAAW,MAAM;AACvC,QAAI,YAAY;AAChB,QAAI,aAAa,IAAI,OAAO,GAAG,GAAG,GAAG,CAAC;AAC/B,WAAA;AAAA,EAAA,CACR;AAEK,QAAA,YAAY,OAA0B,IAAI;AAGhD,YAAU,MAAM;AACd,QAAI,CAAC;AAAU;AACf,UAAM,MAAM,IAAI,WAAW,aAAa,QAAQ,KAAA,GAAQ,QAAQ;AAChE,QAAI,OAAO;AACX,QAAI,OAAO;AACX,cAAU,UAAU;AAGd,UAAA,QAAQ,IAAI,iBAAiB,eAAe,IAAI,QAAQ,GAAG,GAAG,CAAC,GAAG,QAAQ;AAChF,UAAM,YAAY;AAElB,WAAO,MAAM;AAAE,UAAI,QAAQ;AAAG,YAAM,QAAQ;AAAA,IAAA;AAAA,EAAG,GAC9C,CAAC,QAAQ,CAAC;AAGb,YAAU,MAAM;AACV,QAAA,CAAC,YAAY,CAAC,WAAW;AAAO;AACpC,UAAM,YAAY,WAAW;AAE7B,UAAM,WAAW,UAAU,yBAAyB,IAAI,MAAM;;AAC5D,UAAI,CAAC,UAAU;AAAS;AACxB,iBAAW,UAAU,SAAS,QAAQ,WAAW,UAAU;AAChD,uBAAA,WAAA,mBAAQ,WAAW;AAC9B,eAAS,OAAO,KAAK;AAAA,IAAA,CACtB;AAED,WAAO,MAAM;AACD,gBAAA,yBAAyB,OAAO,QAAQ;AAAA,IAAA;AAAA,EACpD,GACC,CAAC,UAAU,WAAW,OAAO,QAAQ,UAAU,CAAC;AAGnD,QAAM,WAAuB;AAAA,IAC3B,GAAG;AAAA,IACH,OAAO,YAAY;AAAA,EAAA;AAGrB,6BACG,kBAAkB,UAAlB,EAA2B,OAAO,UAChC,SACH,CAAA;AAEJ,CAAC;AACD,YAAY,cAAc;"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { earthRadius } from "./main14.mjs";
|
|
2
|
+
const DEG2RAD = Math.PI / 180;
|
|
3
|
+
const mercatorScaleLookup = {};
|
|
4
|
+
function getMercatorScale(lat) {
|
|
5
|
+
const index = Math.round(lat * 1e3);
|
|
6
|
+
if (mercatorScaleLookup[index] === void 0) {
|
|
7
|
+
mercatorScaleLookup[index] = 1 / Math.cos(lat * DEG2RAD);
|
|
8
|
+
}
|
|
9
|
+
return mercatorScaleLookup[index];
|
|
10
|
+
}
|
|
11
|
+
function averageMercatorScale(originLat, pointLat, steps = 10) {
|
|
12
|
+
let totalScale = 0;
|
|
13
|
+
const latStep = (pointLat - originLat) / steps;
|
|
14
|
+
for (let i = 0; i <= steps; i++) {
|
|
15
|
+
const lat = originLat + latStep * i;
|
|
16
|
+
totalScale += getMercatorScale(lat);
|
|
17
|
+
}
|
|
18
|
+
return totalScale / (steps + 1);
|
|
19
|
+
}
|
|
20
|
+
function coordsToVector3(point, origin) {
|
|
21
|
+
const latitudeDiff = (point.latitude - origin.latitude) * DEG2RAD;
|
|
22
|
+
const longitudeDiff = (point.longitude - origin.longitude) * DEG2RAD;
|
|
23
|
+
const altitudeDiff = (point.altitude || 0) - (origin.altitude || 0);
|
|
24
|
+
const x = longitudeDiff * earthRadius * Math.cos(origin.latitude * DEG2RAD);
|
|
25
|
+
const y = altitudeDiff;
|
|
26
|
+
const steps = Math.ceil(Math.abs(point.latitude - origin.latitude)) * 100 + 1;
|
|
27
|
+
const avgScale = averageMercatorScale(origin.latitude, point.latitude, steps);
|
|
28
|
+
const z = -latitudeDiff * earthRadius / getMercatorScale(origin.latitude) * avgScale;
|
|
29
|
+
return [x, y, z];
|
|
30
|
+
}
|
|
31
|
+
export {
|
|
32
|
+
averageMercatorScale,
|
|
33
|
+
coordsToVector3
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=main6.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main6.mjs","sources":["../../src/api/coords-to-vector-3.ts"],"sourcesContent":["import { earthRadius } from '../core/earth-radius';\nimport { Coords } from './coords';\n\nconst DEG2RAD = Math.PI / 180;\n\nconst mercatorScaleLookup: { [key: number]: number } = {};\n\nfunction getMercatorScale(lat: number): number {\n const index = Math.round(lat * 1000);\n if (mercatorScaleLookup[index] === undefined) {\n mercatorScaleLookup[index] = 1 / Math.cos(lat * DEG2RAD);\n }\n return mercatorScaleLookup[index];\n}\n\nexport function averageMercatorScale(originLat: number, pointLat: number, steps = 10): number {\n let totalScale = 0;\n const latStep = (pointLat - originLat) / steps;\n for (let i = 0; i <= steps; i++) {\n const lat = originLat + latStep * i;\n totalScale += getMercatorScale(lat);\n }\n return totalScale / (steps + 1);\n}\n\nexport function coordsToVector3(point: Coords, origin: Coords): [number, number, number] {\n const latitudeDiff = (point.latitude - origin.latitude) * DEG2RAD;\n const longitudeDiff = (point.longitude - origin.longitude) * DEG2RAD;\n const altitudeDiff = (point.altitude || 0) - (origin.altitude || 0);\n\n const x = longitudeDiff * earthRadius * Math.cos(origin.latitude * DEG2RAD);\n const y = altitudeDiff;\n\n const steps = Math.ceil(Math.abs(point.latitude - origin.latitude)) * 100 + 1;\n const avgScale = averageMercatorScale(origin.latitude, point.latitude, steps);\n\n const z = ((-latitudeDiff * earthRadius) / getMercatorScale(origin.latitude)) * avgScale;\n return [x, y, z];\n}\n"],"names":[],"mappings":";AAGA,MAAM,UAAU,KAAK,KAAK;AAE1B,MAAM,sBAAiD,CAAA;AAEvD,SAAS,iBAAiB,KAAqB;AAC7C,QAAM,QAAQ,KAAK,MAAM,MAAM,GAAI;AAC/B,MAAA,oBAAoB,KAAK,MAAM,QAAW;AAC5C,wBAAoB,KAAK,IAAI,IAAI,KAAK,IAAI,MAAM,OAAO;AAAA,EACzD;AACA,SAAO,oBAAoB,KAAK;AAClC;AAEO,SAAS,qBAAqB,WAAmB,UAAkB,QAAQ,IAAY;AAC5F,MAAI,aAAa;AACX,QAAA,WAAW,WAAW,aAAa;AACzC,WAAS,IAAI,GAAG,KAAK,OAAO,KAAK;AACzB,UAAA,MAAM,YAAY,UAAU;AAClC,kBAAc,iBAAiB,GAAG;AAAA,EACpC;AACA,SAAO,cAAc,QAAQ;AAC/B;AAEgB,SAAA,gBAAgB,OAAe,QAA0C;AACvF,QAAM,gBAAgB,MAAM,WAAW,OAAO,YAAY;AAC1D,QAAM,iBAAiB,MAAM,YAAY,OAAO,aAAa;AAC7D,QAAM,gBAAgB,MAAM,YAAY,MAAM,OAAO,YAAY;AAEjE,QAAM,IAAI,gBAAgB,cAAc,KAAK,IAAI,OAAO,WAAW,OAAO;AAC1E,QAAM,IAAI;AAEJ,QAAA,QAAQ,KAAK,KAAK,KAAK,IAAI,MAAM,WAAW,OAAO,QAAQ,CAAC,IAAI,MAAM;AAC5E,QAAM,WAAW,qBAAqB,OAAO,UAAU,MAAM,UAAU,KAAK;AAE5E,QAAM,IAAM,CAAC,eAAe,cAAe,iBAAiB,OAAO,QAAQ,IAAK;AACzE,SAAA,CAAC,GAAG,GAAG,CAAC;AACjB;"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Scene, Color4, FreeCamera, Vector3, HemisphericLight } from "@babylonjs/core";
|
|
3
|
+
import { memo, useState, useRef, useEffect } from "react";
|
|
4
|
+
import { useBabylonMap, BabylonMapContext } from "./main4.mjs";
|
|
5
|
+
import { useCoords } from "./main15.mjs";
|
|
6
|
+
import { coordsToVector3 } from "./main6.mjs";
|
|
7
|
+
const NearCoordinates = memo(({ children, ...coords }) => {
|
|
8
|
+
const { latitude, longitude, altitude } = useCoords();
|
|
9
|
+
const babylonMap = useBabylonMap();
|
|
10
|
+
const pos = coordsToVector3(coords, { latitude, longitude, altitude });
|
|
11
|
+
const [subScene] = useState(() => {
|
|
12
|
+
if (!babylonMap.engine)
|
|
13
|
+
return null;
|
|
14
|
+
const sub = new Scene(babylonMap.engine);
|
|
15
|
+
sub.autoClear = false;
|
|
16
|
+
sub.clearColor = new Color4(0, 0, 0, 0);
|
|
17
|
+
return sub;
|
|
18
|
+
});
|
|
19
|
+
const cameraRef = useRef(null);
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
if (!subScene)
|
|
22
|
+
return;
|
|
23
|
+
const cam = new FreeCamera("nearCoordsCam", new Vector3(pos[0], pos[1], pos[2]), subScene);
|
|
24
|
+
cam.inputs.clear();
|
|
25
|
+
cam.minZ = 0;
|
|
26
|
+
cameraRef.current = cam;
|
|
27
|
+
const light = new HemisphericLight("nearCoordsLight", new Vector3(0, 1, 0), subScene);
|
|
28
|
+
light.intensity = 1;
|
|
29
|
+
return () => {
|
|
30
|
+
cam.dispose();
|
|
31
|
+
light.dispose();
|
|
32
|
+
};
|
|
33
|
+
}, [subScene]);
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
if (!cameraRef.current)
|
|
36
|
+
return;
|
|
37
|
+
cameraRef.current.position.set(pos[0], pos[1], pos[2]);
|
|
38
|
+
}, [pos]);
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (!subScene || !babylonMap.scene)
|
|
41
|
+
return;
|
|
42
|
+
const mainScene = babylonMap.scene;
|
|
43
|
+
const observer = mainScene.onBeforeRenderObservable.add(() => {
|
|
44
|
+
var _a;
|
|
45
|
+
if (!cameraRef.current)
|
|
46
|
+
return;
|
|
47
|
+
cameraRef.current.freezeProjectionMatrix(babylonMap.scene.activeCamera.getProjectionMatrix());
|
|
48
|
+
(_a = babylonMap.engine) == null ? void 0 : _a.wipeCaches(true);
|
|
49
|
+
subScene.render(false);
|
|
50
|
+
});
|
|
51
|
+
return () => {
|
|
52
|
+
mainScene.onBeforeRenderObservable.remove(observer);
|
|
53
|
+
};
|
|
54
|
+
}, [subScene, babylonMap.scene, babylonMap]);
|
|
55
|
+
const childMap = {
|
|
56
|
+
...babylonMap,
|
|
57
|
+
scene: subScene || void 0
|
|
58
|
+
};
|
|
59
|
+
return /* @__PURE__ */ jsx(BabylonMapContext.Provider, { value: childMap, children });
|
|
60
|
+
});
|
|
61
|
+
NearCoordinates.displayName = "NearCoordinates";
|
|
62
|
+
export {
|
|
63
|
+
NearCoordinates
|
|
64
|
+
};
|
|
65
|
+
//# sourceMappingURL=main7.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main7.mjs","sources":["../../src/api/near-coordinates.tsx"],"sourcesContent":["import { Color4, FreeCamera, HemisphericLight, Scene, Vector3 } from '@babylonjs/core';\nimport { memo, useEffect, useRef, useState } from 'react';\nimport { useBabylonMap, BabylonMapContext } from '../core/use-babylon-map';\nimport type { BabylonMap } from '../core/use-babylon-map';\nimport { useCoords } from '../core/use-coords';\nimport { coordsToVector3 } from './coords-to-vector-3';\n\nexport interface NearCoordinatesProps {\n longitude: number;\n latitude: number;\n altitude?: number;\n children?: React.ReactNode;\n}\n\n/**\n * Place 3D content at a nearby coordinate (relative to the Canvas origin).\n * Uses the sub-scene approach like Coordinates but computes a relative offset\n * for the camera's world matrix.\n */\nexport const NearCoordinates = memo<NearCoordinatesProps>(({ children, ...coords }) => {\n const { latitude, longitude, altitude } = useCoords();\n const babylonMap = useBabylonMap();\n\n const pos = coordsToVector3(coords, { latitude, longitude, altitude });\n\n // Create a sub-scene for this coordinate portal\n const [subScene] = useState(() => {\n if (!babylonMap.engine) return null;\n const sub = new Scene(babylonMap.engine);\n sub.autoClear = false;\n sub.clearColor = new Color4(0, 0, 0, 0);\n return sub;\n });\n\n const cameraRef = useRef<FreeCamera | null>(null);\n\n // Create camera + default light in sub-scene\n useEffect(() => {\n if (!subScene) return;\n const cam = new FreeCamera('nearCoordsCam', new Vector3(pos[0], pos[1], pos[2]), subScene);\n cam.inputs.clear();\n cam.minZ = 0;\n cameraRef.current = cam;\n\n const light = new HemisphericLight('nearCoordsLight', new Vector3(0, 1, 0), subScene);\n light.intensity = 1;\n\n return () => { cam.dispose(); light.dispose(); };\n }, [subScene]);\n\n // Update camera position when offset changes\n useEffect(() => {\n if (!cameraRef.current) return;\n cameraRef.current.position.set(pos[0], pos[1], pos[2]);\n }, [pos]);\n\n // Render the sub-scene each frame\n useEffect(() => {\n if (!subScene || !babylonMap.scene) return;\n const mainScene = babylonMap.scene;\n\n const observer = mainScene.onBeforeRenderObservable.add(() => {\n if (!cameraRef.current) return;\n // Use the same projection as the main scene but offset by local position\n cameraRef.current.freezeProjectionMatrix(babylonMap.scene!.activeCamera!.getProjectionMatrix());\n babylonMap.engine?.wipeCaches(true);\n subScene.render(false);\n });\n\n return () => {\n mainScene.onBeforeRenderObservable.remove(observer);\n };\n }, [subScene, babylonMap.scene, babylonMap]);\n\n // Provide child context pointing at the sub-scene\n const childMap: BabylonMap = {\n ...babylonMap,\n scene: subScene || undefined,\n };\n\n return (\n <BabylonMapContext.Provider value={childMap}>\n {children}\n </BabylonMapContext.Provider>\n );\n});\nNearCoordinates.displayName = 'NearCoordinates';\n"],"names":[],"mappings":";;;;;;AAmBO,MAAM,kBAAkB,KAA2B,CAAC,EAAE,UAAU,GAAG,aAAa;AACrF,QAAM,EAAE,UAAU,WAAW,aAAa,UAAU;AACpD,QAAM,aAAa;AAEnB,QAAM,MAAM,gBAAgB,QAAQ,EAAE,UAAU,WAAW,UAAU;AAGrE,QAAM,CAAC,QAAQ,IAAI,SAAS,MAAM;AAChC,QAAI,CAAC,WAAW;AAAe,aAAA;AAC/B,UAAM,MAAM,IAAI,MAAM,WAAW,MAAM;AACvC,QAAI,YAAY;AAChB,QAAI,aAAa,IAAI,OAAO,GAAG,GAAG,GAAG,CAAC;AAC/B,WAAA;AAAA,EAAA,CACR;AAEK,QAAA,YAAY,OAA0B,IAAI;AAGhD,YAAU,MAAM;AACd,QAAI,CAAC;AAAU;AACf,UAAM,MAAM,IAAI,WAAW,iBAAiB,IAAI,QAAQ,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,QAAQ;AACzF,QAAI,OAAO;AACX,QAAI,OAAO;AACX,cAAU,UAAU;AAEd,UAAA,QAAQ,IAAI,iBAAiB,mBAAmB,IAAI,QAAQ,GAAG,GAAG,CAAC,GAAG,QAAQ;AACpF,UAAM,YAAY;AAElB,WAAO,MAAM;AAAE,UAAI,QAAQ;AAAG,YAAM,QAAQ;AAAA,IAAA;AAAA,EAAG,GAC9C,CAAC,QAAQ,CAAC;AAGb,YAAU,MAAM;AACd,QAAI,CAAC,UAAU;AAAS;AACd,cAAA,QAAQ,SAAS,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;AAAA,EAAA,GACpD,CAAC,GAAG,CAAC;AAGR,YAAU,MAAM;AACV,QAAA,CAAC,YAAY,CAAC,WAAW;AAAO;AACpC,UAAM,YAAY,WAAW;AAE7B,UAAM,WAAW,UAAU,yBAAyB,IAAI,MAAM;;AAC5D,UAAI,CAAC,UAAU;AAAS;AAExB,gBAAU,QAAQ,uBAAuB,WAAW,MAAO,aAAc,qBAAqB;AACnF,uBAAA,WAAA,mBAAQ,WAAW;AAC9B,eAAS,OAAO,KAAK;AAAA,IAAA,CACtB;AAED,WAAO,MAAM;AACD,gBAAA,yBAAyB,OAAO,QAAQ;AAAA,IAAA;AAAA,KAEnD,CAAC,UAAU,WAAW,OAAO,UAAU,CAAC;AAG3C,QAAM,WAAuB;AAAA,IAC3B,GAAG;AAAA,IACH,OAAO,YAAY;AAAA,EAAA;AAGrB,6BACG,kBAAkB,UAAlB,EAA2B,OAAO,UAChC,SACH,CAAA;AAEJ,CAAC;AACD,gBAAgB,cAAc;"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { earthRadius } from "./main14.mjs";
|
|
2
|
+
const DEG2RAD = Math.PI / 180;
|
|
3
|
+
const RAD2DEG = 180 / Math.PI;
|
|
4
|
+
function vector3ToCoords(position, origin) {
|
|
5
|
+
const [x, y, z] = position;
|
|
6
|
+
const latitude = origin.latitude + -z / earthRadius * RAD2DEG;
|
|
7
|
+
const longitude = origin.longitude + x / earthRadius * RAD2DEG / Math.cos(origin.latitude * DEG2RAD);
|
|
8
|
+
const altitude = (origin.altitude || 0) + y;
|
|
9
|
+
return { latitude, longitude, altitude };
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
vector3ToCoords
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=main8.mjs.map
|