leaflet-city-mapper 0.0.0-stage → 0.0.2
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/LICENSE +674 -0
- package/README.md +78 -2
- package/cucumber.mjs +9 -0
- package/dist/leaflet-city-mapper.js +2 -0
- package/dist/leaflet-city-mapper.js.map +7 -0
- package/dist/utils/CELL.js +2 -0
- package/dist/utils/CELL.js.map +7 -0
- package/dist/utils/addBridges.js +2 -0
- package/dist/utils/addBridges.js.map +7 -0
- package/dist/utils/addRasterTile.js +2 -0
- package/dist/utils/addRasterTile.js.map +7 -0
- package/dist/utils/along.js +2 -0
- package/dist/utils/along.js.map +7 -0
- package/dist/utils/atmosphere.js +2 -0
- package/dist/utils/atmosphere.js.map +7 -0
- package/dist/utils/attach.js +2 -0
- package/dist/utils/attach.js.map +7 -0
- package/dist/utils/bindSunlight.js +2 -0
- package/dist/utils/bindSunlight.js.map +7 -0
- package/dist/utils/box.js +2 -0
- package/dist/utils/box.js.map +7 -0
- package/dist/utils/bridgeElevation.js +2 -0
- package/dist/utils/bridgeElevation.js.map +7 -0
- package/dist/utils/build.js +2 -0
- package/dist/utils/build.js.map +7 -0
- package/dist/utils/cameraControls.js +2 -0
- package/dist/utils/cameraControls.js.map +7 -0
- package/dist/utils/channel.js +2 -0
- package/dist/utils/channel.js.map +7 -0
- package/dist/utils/collider.js +2 -0
- package/dist/utils/collider.js.map +7 -0
- package/dist/utils/colliders.js +2 -0
- package/dist/utils/colliders.js.map +7 -0
- package/dist/utils/computeBounds.js +2 -0
- package/dist/utils/computeBounds.js.map +7 -0
- package/dist/utils/conformModelToTerrain.js +2 -0
- package/dist/utils/conformModelToTerrain.js.map +7 -0
- package/dist/utils/createMesh.js +2 -0
- package/dist/utils/createMesh.js.map +7 -0
- package/dist/utils/createProgram.js +3 -0
- package/dist/utils/createProgram.js.map +7 -0
- package/dist/utils/decodeDirectory.js +2 -0
- package/dist/utils/decodeDirectory.js.map +7 -0
- package/dist/utils/decodeHeader.js +2 -0
- package/dist/utils/decodeHeader.js.map +7 -0
- package/dist/utils/decodeModel.js +2 -0
- package/dist/utils/decodeModel.js.map +7 -0
- package/dist/utils/decompress.js +2 -0
- package/dist/utils/decompress.js.map +7 -0
- package/dist/utils/destroyTexture.js +2 -0
- package/dist/utils/destroyTexture.js.map +7 -0
- package/dist/utils/disposeMesh.js +2 -0
- package/dist/utils/disposeMesh.js.map +7 -0
- package/dist/utils/drawGeometry.js +2 -0
- package/dist/utils/drawGeometry.js.map +7 -0
- package/dist/utils/elevationWGSL.js +24 -0
- package/dist/utils/elevationWGSL.js.map +7 -0
- package/dist/utils/emptyNode.js +2 -0
- package/dist/utils/emptyNode.js.map +7 -0
- package/dist/utils/endZoom.js +2 -0
- package/dist/utils/endZoom.js.map +7 -0
- package/dist/utils/findFeature.js +2 -0
- package/dist/utils/findFeature.js.map +7 -0
- package/dist/utils/geometry.js +1 -0
- package/dist/utils/geometry.js.map +7 -0
- package/dist/utils/getElevation.js +2 -0
- package/dist/utils/getElevation.js.map +7 -0
- package/dist/utils/getHeader.js +2 -0
- package/dist/utils/getHeader.js.map +7 -0
- package/dist/utils/getZxy.js +2 -0
- package/dist/utils/getZxy.js.map +7 -0
- package/dist/utils/glass.js +2 -0
- package/dist/utils/glass.js.map +7 -0
- package/dist/utils/headlight.js +2 -0
- package/dist/utils/headlight.js.map +7 -0
- package/dist/utils/hit.js +2 -0
- package/dist/utils/hit.js.map +7 -0
- package/dist/utils/horizontalPosition.js +2 -0
- package/dist/utils/horizontalPosition.js.map +7 -0
- package/dist/utils/horizontalRay.js +2 -0
- package/dist/utils/horizontalRay.js.map +7 -0
- package/dist/utils/hull.js +2 -0
- package/dist/utils/hull.js.map +7 -0
- package/dist/utils/initSunlight.js +2 -0
- package/dist/utils/initSunlight.js.map +7 -0
- package/dist/utils/initTerrain.js +2 -0
- package/dist/utils/initTerrain.js.map +7 -0
- package/dist/utils/initTraffic.js +40 -0
- package/dist/utils/initTraffic.js.map +7 -0
- package/dist/utils/initWalk.js +2 -0
- package/dist/utils/initWalk.js.map +7 -0
- package/dist/utils/intersectMeshes.js +2 -0
- package/dist/utils/intersectMeshes.js.map +7 -0
- package/dist/utils/isClockWise.js +2 -0
- package/dist/utils/isClockWise.js.map +7 -0
- package/dist/utils/lampPostGeometry.js +2 -0
- package/dist/utils/lampPostGeometry.js.map +7 -0
- package/dist/utils/lightGeometry.js +2 -0
- package/dist/utils/lightGeometry.js.map +7 -0
- package/dist/utils/lightGrid.js +2 -0
- package/dist/utils/lightGrid.js.map +7 -0
- package/dist/utils/limbs.js +2 -0
- package/dist/utils/limbs.js.map +7 -0
- package/dist/utils/loadModel.js +2 -0
- package/dist/utils/loadModel.js.map +7 -0
- package/dist/utils/loadSource.js +2 -0
- package/dist/utils/loadSource.js.map +7 -0
- package/dist/utils/loadTerrain.js +2 -0
- package/dist/utils/loadTerrain.js.map +7 -0
- package/dist/utils/mapCamera.js +2 -0
- package/dist/utils/mapCamera.js.map +7 -0
- package/dist/utils/materialShaders.js +211 -0
- package/dist/utils/materialShaders.js.map +7 -0
- package/dist/utils/mirror.js +2 -0
- package/dist/utils/mirror.js.map +7 -0
- package/dist/utils/moonPosition.js +2 -0
- package/dist/utils/moonPosition.js.map +7 -0
- package/dist/utils/moves.js +2 -0
- package/dist/utils/moves.js.map +7 -0
- package/dist/utils/nativeEvents.js +2 -0
- package/dist/utils/nativeEvents.js.map +7 -0
- package/dist/utils/nativeGeometry.js +2 -0
- package/dist/utils/nativeGeometry.js.map +7 -0
- package/dist/utils/nativeLayer.js +2 -0
- package/dist/utils/nativeLayer.js.map +7 -0
- package/dist/utils/nodeMatrix.js +2 -0
- package/dist/utils/nodeMatrix.js.map +7 -0
- package/dist/utils/onAdd3DLayer.js +2 -0
- package/dist/utils/onAdd3DLayer.js.map +7 -0
- package/dist/utils/onAddSun.js +2 -0
- package/dist/utils/onAddSun.js.map +7 -0
- package/dist/utils/onClick.js +2 -0
- package/dist/utils/onClick.js.map +7 -0
- package/dist/utils/onMapChange.js +2 -0
- package/dist/utils/onMapChange.js.map +7 -0
- package/dist/utils/onPMTileAdd.js +2 -0
- package/dist/utils/onPMTileAdd.js.map +7 -0
- package/dist/utils/onPMTileRemove.js +2 -0
- package/dist/utils/onPMTileRemove.js.map +7 -0
- package/dist/utils/onPointerLeave.js +2 -0
- package/dist/utils/onPointerLeave.js.map +7 -0
- package/dist/utils/onPointerMove.js +2 -0
- package/dist/utils/onPointerMove.js.map +7 -0
- package/dist/utils/onRemove3DLayer.js +2 -0
- package/dist/utils/onRemove3DLayer.js.map +7 -0
- package/dist/utils/onRemoveSun.js +2 -0
- package/dist/utils/onRemoveSun.js.map +7 -0
- package/dist/utils/onTerrainAdd.js +2 -0
- package/dist/utils/onTerrainAdd.js.map +7 -0
- package/dist/utils/onTerrainChange.js +2 -0
- package/dist/utils/onTerrainChange.js.map +7 -0
- package/dist/utils/onTerrainRemove.js +2 -0
- package/dist/utils/onTerrainRemove.js.map +7 -0
- package/dist/utils/onZoomAnim.js +2 -0
- package/dist/utils/onZoomAnim.js.map +7 -0
- package/dist/utils/paints.js +2 -0
- package/dist/utils/paints.js.map +7 -0
- package/dist/utils/parseColor.js +2 -0
- package/dist/utils/parseColor.js.map +7 -0
- package/dist/utils/parts.js +2 -0
- package/dist/utils/parts.js.map +7 -0
- package/dist/utils/projectCelestialBody.js +2 -0
- package/dist/utils/projectCelestialBody.js.map +7 -0
- package/dist/utils/pump.js +2 -0
- package/dist/utils/pump.js.map +7 -0
- package/dist/utils/rasterTiles.js +2 -0
- package/dist/utils/rasterTiles.js.map +7 -0
- package/dist/utils/raycast.js +2 -0
- package/dist/utils/raycast.js.map +7 -0
- package/dist/utils/read.js +2 -0
- package/dist/utils/read.js.map +7 -0
- package/dist/utils/readAccessor.js +2 -0
- package/dist/utils/readAccessor.js.map +7 -0
- package/dist/utils/releaseArea.js +2 -0
- package/dist/utils/releaseArea.js.map +7 -0
- package/dist/utils/removeRasterTile.js +2 -0
- package/dist/utils/removeRasterTile.js.map +7 -0
- package/dist/utils/render.js +15 -0
- package/dist/utils/render.js.map +7 -0
- package/dist/utils/renderSunlight.js +13 -0
- package/dist/utils/renderSunlight.js.map +7 -0
- package/dist/utils/renderers.js +2 -0
- package/dist/utils/renderers.js.map +7 -0
- package/dist/utils/resizeSunlight.js +2 -0
- package/dist/utils/resizeSunlight.js.map +7 -0
- package/dist/utils/roofCoverage.js +2 -0
- package/dist/utils/roofCoverage.js.map +7 -0
- package/dist/utils/routeGeometry.js +2 -0
- package/dist/utils/routeGeometry.js.map +7 -0
- package/dist/utils/scheduledTrips.js +2 -0
- package/dist/utils/scheduledTrips.js.map +7 -0
- package/dist/utils/setGeoJSONData.js +2 -0
- package/dist/utils/setGeoJSONData.js.map +7 -0
- package/dist/utils/setHighlight.js +2 -0
- package/dist/utils/setHighlight.js.map +7 -0
- package/dist/utils/setPMTileOpacity.js +2 -0
- package/dist/utils/setPMTileOpacity.js.map +7 -0
- package/dist/utils/setPMTileZIndex.js +2 -0
- package/dist/utils/setPMTileZIndex.js.map +7 -0
- package/dist/utils/setParent.js +2 -0
- package/dist/utils/setParent.js.map +7 -0
- package/dist/utils/setTerrainHeight.js +2 -0
- package/dist/utils/setTerrainHeight.js.map +7 -0
- package/dist/utils/setVertexColor.js +2 -0
- package/dist/utils/setVertexColor.js.map +7 -0
- package/dist/utils/showFeature.js +2 -0
- package/dist/utils/showFeature.js.map +7 -0
- package/dist/utils/sizes.js +2 -0
- package/dist/utils/sizes.js.map +7 -0
- package/dist/utils/skin.js +2 -0
- package/dist/utils/skin.js.map +7 -0
- package/dist/utils/solarPosition.js +2 -0
- package/dist/utils/solarPosition.js.map +7 -0
- package/dist/utils/sortMeshes.js +2 -0
- package/dist/utils/sortMeshes.js.map +7 -0
- package/dist/utils/speed.js +2 -0
- package/dist/utils/speed.js.map +7 -0
- package/dist/utils/startZoom.js +2 -0
- package/dist/utils/startZoom.js.map +7 -0
- package/dist/utils/taillight.js +2 -0
- package/dist/utils/taillight.js.map +7 -0
- package/dist/utils/terrainAtlas.js +2 -0
- package/dist/utils/terrainAtlas.js.map +7 -0
- package/dist/utils/terrainElevation.js +2 -0
- package/dist/utils/terrainElevation.js.map +7 -0
- package/dist/utils/terrainGrid.js +2 -0
- package/dist/utils/terrainGrid.js.map +7 -0
- package/dist/utils/textureSampler.js +2 -0
- package/dist/utils/textureSampler.js.map +7 -0
- package/dist/utils/tileId.js +2 -0
- package/dist/utils/tileId.js.map +7 -0
- package/dist/utils/toLanes.js +2 -0
- package/dist/utils/toLanes.js.map +7 -0
- package/dist/utils/toSRGB.js +2 -0
- package/dist/utils/toSRGB.js.map +7 -0
- package/dist/utils/tooltip.js +3 -0
- package/dist/utils/tooltip.js.map +7 -0
- package/dist/utils/traffic.js +2 -0
- package/dist/utils/traffic.js.map +7 -0
- package/dist/utils/traverse.js +2 -0
- package/dist/utils/traverse.js.map +7 -0
- package/dist/utils/treeGeometry.js +2 -0
- package/dist/utils/treeGeometry.js.map +7 -0
- package/dist/utils/triangulate.js +2 -0
- package/dist/utils/triangulate.js.map +7 -0
- package/dist/utils/tripsAt.js +2 -0
- package/dist/utils/tripsAt.js.map +7 -0
- package/dist/utils/types.js +2 -0
- package/dist/utils/types.js.map +7 -0
- package/dist/utils/underEntry.js +2 -0
- package/dist/utils/underEntry.js.map +7 -0
- package/dist/utils/update.js +2 -0
- package/dist/utils/update.js.map +7 -0
- package/dist/utils/updateArea.js +2 -0
- package/dist/utils/updateArea.js.map +7 -0
- package/dist/utils/updateCamera.js +2 -0
- package/dist/utils/updateCamera.js.map +7 -0
- package/dist/utils/updatePointLights.js +2 -0
- package/dist/utils/updatePointLights.js.map +7 -0
- package/dist/utils/updateWorldMatrix.js +2 -0
- package/dist/utils/updateWorldMatrix.js.map +7 -0
- package/dist/utils/vehicleOffsets.js +2 -0
- package/dist/utils/vehicleOffsets.js.map +7 -0
- package/dist/utils/vehicles.js +2 -0
- package/dist/utils/vehicles.js.map +7 -0
- package/dist/utils/vertexNormals.js +2 -0
- package/dist/utils/vertexNormals.js.map +7 -0
- package/dist/utils/walk.js +2 -0
- package/dist/utils/walk.js.map +7 -0
- package/dist/utils/white.js +2 -0
- package/dist/utils/white.js.map +7 -0
- package/dist/utils/worldLights.js +2 -0
- package/dist/utils/worldLights.js.map +7 -0
- package/dist/utils/wrap.js +2 -0
- package/dist/utils/wrap.js.map +7 -0
- package/package.json +43 -4
- package/src/index.js +397 -0
- package/src/utils/CELL.js +4 -0
- package/src/utils/addBridges.js +66 -0
- package/src/utils/addRasterTile.js +112 -0
- package/src/utils/along.js +9 -0
- package/src/utils/atmosphere.js +20 -0
- package/src/utils/attach.js +255 -0
- package/src/utils/bindSunlight.js +12 -0
- package/src/utils/box.js +1 -0
- package/src/utils/bridgeElevation.js +18 -0
- package/src/utils/build.js +20 -0
- package/src/utils/cameraControls.js +287 -0
- package/src/utils/channel.js +4 -0
- package/src/utils/collider.js +62 -0
- package/src/utils/colliders.js +2 -0
- package/src/utils/computeBounds.js +17 -0
- package/src/utils/conformModelToTerrain.js +69 -0
- package/src/utils/createMesh.js +31 -0
- package/src/utils/createProgram.js +92 -0
- package/src/utils/decodeDirectory.js +40 -0
- package/src/utils/decodeHeader.js +15 -0
- package/src/utils/decodeModel.js +43 -0
- package/src/utils/decompress.js +5 -0
- package/src/utils/destroyTexture.js +7 -0
- package/src/utils/disposeMesh.js +13 -0
- package/src/utils/drawGeometry.js +122 -0
- package/src/utils/elevationWGSL.js +27 -0
- package/src/utils/emptyNode.js +9 -0
- package/src/utils/endZoom.js +15 -0
- package/src/utils/findFeature.js +49 -0
- package/src/utils/geometry.js +2 -0
- package/src/utils/getElevation.js +10 -0
- package/src/utils/getHeader.js +9 -0
- package/src/utils/getZxy.js +76 -0
- package/src/utils/glass.js +1 -0
- package/src/utils/headlight.js +1 -0
- package/src/utils/hit.js +41 -0
- package/src/utils/horizontalPosition.js +16 -0
- package/src/utils/horizontalRay.js +12 -0
- package/src/utils/hull.js +1 -0
- package/src/utils/initSunlight.js +9 -0
- package/src/utils/initTerrain.js +19 -0
- package/src/utils/initTraffic.js +93 -0
- package/src/utils/initWalk.js +72 -0
- package/src/utils/intersectMeshes.js +121 -0
- package/src/utils/isClockWise.js +12 -0
- package/src/utils/lampPostGeometry.js +26 -0
- package/src/utils/lightGeometry.js +22 -0
- package/src/utils/lightGrid.js +50 -0
- package/src/utils/limbs.js +9 -0
- package/src/utils/loadModel.js +217 -0
- package/src/utils/loadSource.js +17 -0
- package/src/utils/loadTerrain.js +65 -0
- package/src/utils/mapCamera.js +432 -0
- package/src/utils/materialShaders.js +243 -0
- package/src/utils/mirror.js +6 -0
- package/src/utils/moonPosition.js +17 -0
- package/src/utils/moves.js +11 -0
- package/src/utils/nativeEvents.js +77 -0
- package/src/utils/nativeGeometry.js +131 -0
- package/src/utils/nativeLayer.js +317 -0
- package/src/utils/nodeMatrix.js +22 -0
- package/src/utils/onAdd3DLayer.js +31 -0
- package/src/utils/onAddSun.js +147 -0
- package/src/utils/onClick.js +13 -0
- package/src/utils/onMapChange.js +16 -0
- package/src/utils/onPMTileAdd.js +15 -0
- package/src/utils/onPMTileRemove.js +8 -0
- package/src/utils/onPointerLeave.js +11 -0
- package/src/utils/onPointerMove.js +15 -0
- package/src/utils/onRemove3DLayer.js +78 -0
- package/src/utils/onRemoveSun.js +3 -0
- package/src/utils/onTerrainAdd.js +18 -0
- package/src/utils/onTerrainChange.js +13 -0
- package/src/utils/onTerrainRemove.js +40 -0
- package/src/utils/onZoomAnim.js +14 -0
- package/src/utils/paints.js +10 -0
- package/src/utils/parseColor.js +42 -0
- package/src/utils/parts.js +16 -0
- package/src/utils/projectCelestialBody.js +13 -0
- package/src/utils/pump.js +226 -0
- package/src/utils/rasterTiles.js +285 -0
- package/src/utils/raycast.js +60 -0
- package/src/utils/read.js +29 -0
- package/src/utils/readAccessor.js +68 -0
- package/src/utils/releaseArea.js +34 -0
- package/src/utils/removeRasterTile.js +13 -0
- package/src/utils/render.js +406 -0
- package/src/utils/renderSunlight.js +170 -0
- package/src/utils/renderers.js +2 -0
- package/src/utils/resizeSunlight.js +15 -0
- package/src/utils/roofCoverage.js +47 -0
- package/src/utils/routeGeometry.js +22 -0
- package/src/utils/scheduledTrips.js +29 -0
- package/src/utils/setGeoJSONData.js +11 -0
- package/src/utils/setHighlight.js +13 -0
- package/src/utils/setPMTileOpacity.js +7 -0
- package/src/utils/setPMTileZIndex.js +7 -0
- package/src/utils/setParent.js +7 -0
- package/src/utils/setTerrainHeight.js +10 -0
- package/src/utils/setVertexColor.js +14 -0
- package/src/utils/showFeature.js +27 -0
- package/src/utils/sizes.js +1 -0
- package/src/utils/skin.js +2 -0
- package/src/utils/solarPosition.js +17 -0
- package/src/utils/sortMeshes.js +12 -0
- package/src/utils/speed.js +3 -0
- package/src/utils/startZoom.js +5 -0
- package/src/utils/taillight.js +1 -0
- package/src/utils/terrainAtlas.js +21 -0
- package/src/utils/terrainElevation.js +20 -0
- package/src/utils/terrainGrid.js +23 -0
- package/src/utils/textureSampler.js +10 -0
- package/src/utils/tileId.js +18 -0
- package/src/utils/toLanes.js +7 -0
- package/src/utils/toSRGB.js +1 -0
- package/src/utils/tooltip.js +6 -0
- package/src/utils/traffic.js +315 -0
- package/src/utils/traverse.js +6 -0
- package/src/utils/treeGeometry.js +45 -0
- package/src/utils/triangulate.js +100 -0
- package/src/utils/tripsAt.js +16 -0
- package/src/utils/types.js +8 -0
- package/src/utils/underEntry.js +17 -0
- package/src/utils/update.js +18 -0
- package/src/utils/updateArea.js +40 -0
- package/src/utils/updateCamera.js +32 -0
- package/src/utils/updatePointLights.js +38 -0
- package/src/utils/updateWorldMatrix.js +47 -0
- package/src/utils/vehicleOffsets.js +8 -0
- package/src/utils/vehicles.js +65 -0
- package/src/utils/vertexNormals.js +30 -0
- package/src/utils/walk.js +187 -0
- package/src/utils/white.js +1 -0
- package/src/utils/worldLights.js +25 -0
- package/src/utils/wrap.js +1 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { underEntry } from './underEntry.js';
|
|
2
|
+
import { update as updateScene } from "./update.js";
|
|
3
|
+
import { atmosphere } from './atmosphere.js';
|
|
4
|
+
import { moonPosition } from './moonPosition.js';
|
|
5
|
+
import { projectCelestialBody } from './projectCelestialBody.js';
|
|
6
|
+
import { solarPosition } from './solarPosition.js';
|
|
7
|
+
|
|
8
|
+
export function onAddSun(layer, map) {
|
|
9
|
+
if (!layer.control) {
|
|
10
|
+
const control = new L.Control({ position: 'bottomright' });
|
|
11
|
+
control.live = true;
|
|
12
|
+
let date, slider, output, status, timer;
|
|
13
|
+
const originalSky = map.getContainer().style.getPropertyValue('--leaflet-sky-background');
|
|
14
|
+
const disc = 'position:absolute;width:18px;height:18px;border-radius:50%;transform:translate(-50%,-50%);pointer-events:none;';
|
|
15
|
+
const sunDisc = L.DomUtil.create('div', 'sunlight-sun');
|
|
16
|
+
const moonDisc = L.DomUtil.create('div', 'sunlight-moon');
|
|
17
|
+
sunDisc.style.cssText = disc + 'background:#fff3bd;box-shadow:0 0 18px 7px #ffd27699;';
|
|
18
|
+
moonDisc.style.cssText = disc + 'background:#dce5f2;box-shadow:0 0 10px 2px #cbdcff55;';
|
|
19
|
+
sunDisc.setAttribute('role', 'img'); sunDisc.setAttribute('aria-label', 'Sun');
|
|
20
|
+
moonDisc.setAttribute('role', 'img'); moonDisc.setAttribute('aria-label', 'Moon');
|
|
21
|
+
const updateSky = () => {
|
|
22
|
+
const sun = map._sunlight, sky = map._pitchSky;
|
|
23
|
+
if (sun) map.getContainer().style.setProperty('--leaflet-sky-background', sun.background);
|
|
24
|
+
else if (originalSky) map.getContainer().style.setProperty('--leaflet-sky-background', originalSky);
|
|
25
|
+
else map.getContainer().style.removeProperty('--leaflet-sky-background');
|
|
26
|
+
const size = map.getSize(), pitch = map.getPitch() * Math.PI / 180, bearing = map.getBearing() * Math.PI / 180;
|
|
27
|
+
for (const [disc, body] of [[sunDisc, sun], [moonDisc, sun?.moon]]) {
|
|
28
|
+
disc.hidden = true;
|
|
29
|
+
if (!sky || !body || body.altitude <= 0 || !sun) continue;
|
|
30
|
+
if (disc.parentNode !== sky) sky.append(disc);
|
|
31
|
+
const point = projectCelestialBody(body.direction, size, pitch, bearing);
|
|
32
|
+
if (!point) continue;
|
|
33
|
+
const { left, top } = point;
|
|
34
|
+
disc.hidden = left < 0 || left > size.x || top < 0 || top > sky.clientHeight || sky.style.display === 'none';
|
|
35
|
+
disc.style.left = `${left}px`; disc.style.top = `${top}px`;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const render = () => {
|
|
39
|
+
const renderer = L.Layer._renderers.get(map);
|
|
40
|
+
if (renderer) updateScene(renderer);
|
|
41
|
+
};
|
|
42
|
+
const update = () => {
|
|
43
|
+
try {
|
|
44
|
+
if (control.live) control.time = new Date();
|
|
45
|
+
const time = control.time.toISOString();
|
|
46
|
+
date.value = time.slice(0, 10);
|
|
47
|
+
slider.value = String(control.time.getUTCHours() * 60 + control.time.getUTCMinutes());
|
|
48
|
+
output.textContent = `${time.slice(11, 16)} UTC${control.live ? ' · now' : ''}`;
|
|
49
|
+
const center = map.getCenter();
|
|
50
|
+
const sun = map._sunlight = solarPosition(control.time, center.lat, center.lng);
|
|
51
|
+
Object.assign(sun, atmosphere(sun.altitude));
|
|
52
|
+
sun.moon = moonPosition(control.time, center.lat, center.lng);
|
|
53
|
+
status.textContent = sun.altitude <= 0
|
|
54
|
+
? 'Night · no direct sunlight'
|
|
55
|
+
: sun.altitude < 3
|
|
56
|
+
? 'Low sun · shadows paused'
|
|
57
|
+
: `Sun altitude ${sun.altitude.toFixed(1)}°`;
|
|
58
|
+
map.fire('simulationtimechange', { time: new Date(control.time), live: control.live });
|
|
59
|
+
updateSky();
|
|
60
|
+
render();
|
|
61
|
+
} catch (error) {
|
|
62
|
+
delete map._sunlight;
|
|
63
|
+
updateSky();
|
|
64
|
+
render();
|
|
65
|
+
status.textContent = `Error: ${error.message}`;
|
|
66
|
+
console.error('Solar simulation', error);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
control.onAdd = () => {
|
|
70
|
+
const container = L.DomUtil.create('div', 'sunlight-control');
|
|
71
|
+
container.style.cssText = 'color:#222;width:min(200px,calc(100vw - 60px));font:12px/1.4 sans-serif;';
|
|
72
|
+
date = document.createElement('input');
|
|
73
|
+
date.type = 'date';
|
|
74
|
+
date.style.cssText = 'width:100%;box-sizing:border-box;';
|
|
75
|
+
date.setAttribute('aria-label', 'Solar date (UTC)');
|
|
76
|
+
slider = document.createElement('input');
|
|
77
|
+
slider.type = 'range';
|
|
78
|
+
slider.style.cssText = 'width:100%;box-sizing:border-box;margin:10px 0 4px;cursor:pointer;';
|
|
79
|
+
slider.min = '0'; slider.max = '1439'; slider.step = '1';
|
|
80
|
+
slider.setAttribute('aria-label', 'Time of day (UTC)');
|
|
81
|
+
output = document.createElement('output');
|
|
82
|
+
output.style.cssText = 'font-weight:bold;font-variant-numeric:tabular-nums;';
|
|
83
|
+
output.setAttribute('aria-live', 'off');
|
|
84
|
+
const now = document.createElement('button');
|
|
85
|
+
now.type = 'button'; now.textContent = 'Now';
|
|
86
|
+
now.onclick = () => { control.live = true; update(); };
|
|
87
|
+
const timeRow = document.createElement('div');
|
|
88
|
+
timeRow.className = 'sunlight-time';
|
|
89
|
+
timeRow.style.cssText = 'display:flex;justify-content:space-between;align-items:center;';
|
|
90
|
+
timeRow.append(output, now);
|
|
91
|
+
status = document.createElement('div');
|
|
92
|
+
status.className = 'sunlight-status';
|
|
93
|
+
status.style.marginTop = '5px';
|
|
94
|
+
status.setAttribute('role', 'status');
|
|
95
|
+
const note = document.createElement('small');
|
|
96
|
+
note.style.color = '#555';
|
|
97
|
+
note.textContent = 'Indicative · loaded geometry only. Streetlight illumination is estimated, not measured lux.';
|
|
98
|
+
container.append(date, slider, timeRow, status, note);
|
|
99
|
+
date.onchange = slider.oninput = () => {
|
|
100
|
+
control.live = false;
|
|
101
|
+
if (!date.value || !date.validity.valid) {
|
|
102
|
+
control.time = new Date(NaN);
|
|
103
|
+
map.fire('simulationtimechange', { time: null, live: false });
|
|
104
|
+
delete map._sunlight;
|
|
105
|
+
updateSky();
|
|
106
|
+
render();
|
|
107
|
+
status.textContent = 'Error: choose a valid solar date';
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
control.time = new Date(`${date.value}T00:00:00Z`);
|
|
111
|
+
control.time.setUTCMinutes(Number(slider.value));
|
|
112
|
+
update();
|
|
113
|
+
};
|
|
114
|
+
L.DomEvent.disableClickPropagation(container);
|
|
115
|
+
L.DomEvent.disableScrollPropagation(container);
|
|
116
|
+
update();
|
|
117
|
+
timer = setInterval(() => { if (control.live) update(); }, 60000);
|
|
118
|
+
map.on('moveend', update);
|
|
119
|
+
map.on('move rotate pitch resize', updateSky);
|
|
120
|
+
return container;
|
|
121
|
+
};
|
|
122
|
+
control.onRemove = () => {
|
|
123
|
+
clearInterval(timer);
|
|
124
|
+
map.fire('simulationtimechange', { time: null, live: false });
|
|
125
|
+
map.off('moveend', update);
|
|
126
|
+
map.off('move rotate pitch resize', updateSky);
|
|
127
|
+
delete map._sunlight;
|
|
128
|
+
updateSky();
|
|
129
|
+
sunDisc.remove(); moonDisc.remove();
|
|
130
|
+
render();
|
|
131
|
+
};
|
|
132
|
+
layer.control = control;
|
|
133
|
+
}
|
|
134
|
+
if (!layer.control._map) {
|
|
135
|
+
layer.control.addTo(map);
|
|
136
|
+
}
|
|
137
|
+
// Shown under this layer's entry in the layers control; a standalone control without one.
|
|
138
|
+
const container = layer.control.getContainer(), nested = underEntry(layer, container);
|
|
139
|
+
container.classList.toggle('leaflet-control', !nested);
|
|
140
|
+
container.classList.toggle('leaflet-bar', !nested);
|
|
141
|
+
Object.assign(
|
|
142
|
+
container.style,
|
|
143
|
+
nested
|
|
144
|
+
? { background: '', padding: '2px 0 6px 20px', margin: '0' }
|
|
145
|
+
: { background: '#fff', padding: '8px', margin: '' }
|
|
146
|
+
);
|
|
147
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { findFeature } from './findFeature.js';
|
|
2
|
+
import { setHighlight } from './setHighlight.js';
|
|
3
|
+
import { showFeature } from './showFeature.js';
|
|
4
|
+
|
|
5
|
+
/** Emit click without moving the map or pinning the tooltip. */
|
|
6
|
+
|
|
7
|
+
export function onClick(layer, event) {
|
|
8
|
+
const feature = findFeature(layer, event);
|
|
9
|
+
layer.hoveredFeature = feature;
|
|
10
|
+
setHighlight(layer, feature);
|
|
11
|
+
showFeature(layer, feature, event);
|
|
12
|
+
layer.fire('featureclick', { feature, originalEvent: event });
|
|
13
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { update } from "./update.js";
|
|
2
|
+
import { render } from "./render.js";
|
|
3
|
+
|
|
4
|
+
/** Map movement: render within the frame of Leaflet's CSS transforms, coalescing same-tick events. */
|
|
5
|
+
|
|
6
|
+
export function onMapChange() {
|
|
7
|
+
const layer = this;
|
|
8
|
+
if (layer._queued) return;
|
|
9
|
+
layer._queued = true;
|
|
10
|
+
queueMicrotask(() => {
|
|
11
|
+
layer._queued = false;
|
|
12
|
+
if (layer._shared !== layer || !layer.renderer) return;
|
|
13
|
+
if (layer._map._animatingZoom) update(layer);
|
|
14
|
+
else render(layer);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { attach } from './attach.js';
|
|
2
|
+
import { setRasterTerrain, updateRasterTiles } from './rasterTiles.js';
|
|
3
|
+
|
|
4
|
+
export function onPMTileAdd(backend, map) {
|
|
5
|
+
if (!backend.location) backend.location = map.getCenter();
|
|
6
|
+
const attached = attach(backend, map);
|
|
7
|
+
attached.then(() => {
|
|
8
|
+
backend._added.resolve();
|
|
9
|
+
setRasterTerrain(backend, map._terrain3D);
|
|
10
|
+
})
|
|
11
|
+
.catch(error => backend.fire('error', { error }));
|
|
12
|
+
Promise.all([attached, backend.ready]).then(() => {
|
|
13
|
+
if (backend._map === map && map.hasLayer(backend)) updateRasterTiles(backend);
|
|
14
|
+
}).catch(error => backend.fire('error', { error }));
|
|
15
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { setHighlight } from './setHighlight.js';
|
|
2
|
+
import { showFeature } from './showFeature.js';
|
|
3
|
+
|
|
4
|
+
/** Clear hover, highlight and tooltip without retaining a selected feature. */
|
|
5
|
+
|
|
6
|
+
export function onPointerLeave(layer) {
|
|
7
|
+
layer.hoveredFeature = null;
|
|
8
|
+
setHighlight(layer, null);
|
|
9
|
+
showFeature(layer, null);
|
|
10
|
+
layer.fire('featurehover', { feature: null });
|
|
11
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { findFeature } from './findFeature.js';
|
|
2
|
+
import { setHighlight } from './setHighlight.js';
|
|
3
|
+
import { showFeature } from './showFeature.js';
|
|
4
|
+
|
|
5
|
+
/** Hover is transient; featurehover also reports misses with feature:null. */
|
|
6
|
+
|
|
7
|
+
export function onPointerMove(layer, event) {
|
|
8
|
+
layer.hoveredFeature = findFeature(layer, event);
|
|
9
|
+
setHighlight(layer, layer.hoveredFeature);
|
|
10
|
+
showFeature(layer, layer.hoveredFeature, event);
|
|
11
|
+
layer.fire('featurehover', {
|
|
12
|
+
feature: layer.hoveredFeature,
|
|
13
|
+
originalEvent: event
|
|
14
|
+
});
|
|
15
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import * as destroyTexture from './destroyTexture.js';
|
|
2
|
+
import * as endZoom from './endZoom.js';
|
|
3
|
+
import * as onMapChange from './onMapChange.js';
|
|
4
|
+
import * as onPointerLeave from './onPointerLeave.js';
|
|
5
|
+
import * as onZoomAnim from './onZoomAnim.js';
|
|
6
|
+
import * as releaseArea from './releaseArea.js';
|
|
7
|
+
import { setParent } from './setParent.js';
|
|
8
|
+
import * as startZoom from './startZoom.js';
|
|
9
|
+
import * as update from './update.js';
|
|
10
|
+
|
|
11
|
+
/** Release source meshes/UI; retain manually added objects and model CPU data. */
|
|
12
|
+
export function onRemove3DLayer(backend, map) {
|
|
13
|
+
backend._added = Promise.withResolvers();
|
|
14
|
+
if (backend.container) {
|
|
15
|
+
onPointerLeave.onPointerLeave(backend);
|
|
16
|
+
L.DomEvent.off(backend.container, backend._pointerEvents);
|
|
17
|
+
backend.container = null;
|
|
18
|
+
}
|
|
19
|
+
for (const area of backend._areas.values()) releaseArea.releaseArea(backend, area);
|
|
20
|
+
backend._areas.clear();
|
|
21
|
+
backend._tooltip?.remove();
|
|
22
|
+
backend._tooltip = null;
|
|
23
|
+
if (backend.url || backend._geojson) releaseArea.updateStatus(backend, false);
|
|
24
|
+
const shared = backend._shared;
|
|
25
|
+
if (!shared) return;
|
|
26
|
+
setParent(backend.root, null);
|
|
27
|
+
shared._layers.delete(backend);
|
|
28
|
+
if (shared === backend) {
|
|
29
|
+
map.off('move zoom rotate pitch resize viewreset layeradd layerremove', onMapChange.onMapChange, backend);
|
|
30
|
+
map.off('zoomstart', startZoom.startZoom, backend);
|
|
31
|
+
map.off('zoomanim', onZoomAnim.onZoomAnim, backend);
|
|
32
|
+
map.off('zoomend', endZoom.endZoom, backend);
|
|
33
|
+
cancelAnimationFrame(backend._frame);
|
|
34
|
+
backend._frame = null;
|
|
35
|
+
backend._queued = false;
|
|
36
|
+
if (backend._layers.size) {
|
|
37
|
+
// Keep the original scene origin and GPU resources when ownership changes.
|
|
38
|
+
const next = backend._layers.values().next().value;
|
|
39
|
+
for (const key of ['_layers', '_sceneOrigin', '_size', '_zoomLevel', '_zoomTransitions', '_zoomView', '_cursor', '_roofRaster']) {
|
|
40
|
+
next[key] = backend[key];
|
|
41
|
+
delete backend[key];
|
|
42
|
+
}
|
|
43
|
+
for (const layer of next._layers) layer._shared = next;
|
|
44
|
+
L.Layer._renderers.set(map, next);
|
|
45
|
+
map.on('move zoom rotate pitch resize viewreset layeradd layerremove', onMapChange.onMapChange, next);
|
|
46
|
+
map.on('zoomstart', startZoom.startZoom, next);
|
|
47
|
+
map.on('zoomanim', onZoomAnim.onZoomAnim, next);
|
|
48
|
+
map.on('zoomend', endZoom.endZoom, next);
|
|
49
|
+
update.update(next);
|
|
50
|
+
} else {
|
|
51
|
+
if (backend._roofRaster) destroyTexture.destroyTexture(backend, backend._roofRaster.texture.texture);
|
|
52
|
+
backend._roofRaster = null;
|
|
53
|
+
for (const animation of backend._zoomTransitions?.keys() || []) animation.play();
|
|
54
|
+
backend._zoomTransitions = null;
|
|
55
|
+
backend._zoomView = null;
|
|
56
|
+
delete map._cameraView;
|
|
57
|
+
map.getContainer().classList.remove('leaflet-camera-zoom');
|
|
58
|
+
const renderer = backend.renderer;
|
|
59
|
+
renderer.canvas.remove();
|
|
60
|
+
renderer.device.queue.onSubmittedWorkDone()
|
|
61
|
+
.then(() => {
|
|
62
|
+
renderer.depthTexture?.destroy();
|
|
63
|
+
renderer.roofFallbackTexture?.texture?.destroy();
|
|
64
|
+
renderer.uniformBuffer?.destroy();
|
|
65
|
+
renderer.sunlight?.texture?.destroy();
|
|
66
|
+
renderer.sunlight?.buffer?.destroy();
|
|
67
|
+
renderer.sunlight?.lights?.destroy();
|
|
68
|
+
renderer.device.destroy();
|
|
69
|
+
}, error => {
|
|
70
|
+
backend.fire('error', { error });
|
|
71
|
+
renderer.device.destroy();
|
|
72
|
+
});
|
|
73
|
+
L.Layer._renderers.delete(map);
|
|
74
|
+
for (const key of ['_layers', '_sceneOrigin', '_size', '_zoomLevel', '_cursor']) delete backend[key];
|
|
75
|
+
}
|
|
76
|
+
} else update.update(shared);
|
|
77
|
+
backend._shared = backend.renderer = backend.scene = backend.camera = null;
|
|
78
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { loadTerrain } from "./loadTerrain.js";
|
|
2
|
+
import { setRasterTerrain } from "./rasterTiles.js";
|
|
3
|
+
import { onAdd3DLayer } from './onAdd3DLayer.js';
|
|
4
|
+
|
|
5
|
+
export function onTerrainAdd(backend, map) {
|
|
6
|
+
if (map._terrain3D && map._terrain3D !== backend) {
|
|
7
|
+
throw new Error('Only one terrain layer can be active per map');
|
|
8
|
+
}
|
|
9
|
+
map._terrain3D = backend;
|
|
10
|
+
onAdd3DLayer(backend, map);
|
|
11
|
+
backend._terrainPromise = backend.root
|
|
12
|
+
? loadTerrain(backend)
|
|
13
|
+
: new Promise(resolve => backend.once('ready', () => loadTerrain(backend).then(resolve), backend));
|
|
14
|
+
map.eachLayer(layer => {
|
|
15
|
+
if (layer._type === 'pmtiles') setRasterTerrain(layer, backend);
|
|
16
|
+
});
|
|
17
|
+
map.fire('terrainchange');
|
|
18
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { releaseArea } from "./releaseArea.js";
|
|
2
|
+
import { updateArea } from "./updateArea.js";
|
|
3
|
+
|
|
4
|
+
/** GeoJSON source areas: loading, building and releasing. */
|
|
5
|
+
|
|
6
|
+
export function onTerrainChange(layer) {
|
|
7
|
+
if (!layer._map) return;
|
|
8
|
+
for (const area of layer._areas.values()) {
|
|
9
|
+
releaseArea(layer, area);
|
|
10
|
+
}
|
|
11
|
+
layer._areas.clear();
|
|
12
|
+
updateArea(layer);
|
|
13
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { destroyTexture } from './destroyTexture.js';
|
|
2
|
+
import { conformModelToTerrain } from './conformModelToTerrain.js';
|
|
3
|
+
import { disposeMesh } from './disposeMesh.js';
|
|
4
|
+
import { setRasterTerrain } from './rasterTiles.js';
|
|
5
|
+
import { removeRasterTile } from './removeRasterTile.js';
|
|
6
|
+
import { setTerrainHeight } from './setTerrainHeight.js';
|
|
7
|
+
import { onRemove3DLayer } from './onRemove3DLayer.js';
|
|
8
|
+
|
|
9
|
+
export function onTerrainRemove(layer, map) {
|
|
10
|
+
layer._terrainController?.abort();
|
|
11
|
+
layer._terrainLoading = false;
|
|
12
|
+
layer._terrainReady = false;
|
|
13
|
+
map.eachLayer(layer => {
|
|
14
|
+
if (layer._type === 'pmtiles') setRasterTerrain(layer, null);
|
|
15
|
+
});
|
|
16
|
+
for (const tile of layer._rasterTiles.keys()) removeRasterTile(layer, tile);
|
|
17
|
+
if (map._terrain3D === layer) delete map._terrain3D;
|
|
18
|
+
for (const l of Object.values(map._layers)) {
|
|
19
|
+
conformModelToTerrain(l, null);
|
|
20
|
+
setTerrainHeight(l);
|
|
21
|
+
}
|
|
22
|
+
map.fire('terrainchange');
|
|
23
|
+
layer._terrainTiles.clear();
|
|
24
|
+
layer._terrainOriginElevation = 0;
|
|
25
|
+
layer._terrainPromise = null;
|
|
26
|
+
if (layer._rasterProgram) {
|
|
27
|
+
layer._rasterProgram.pipelineCache.clear();
|
|
28
|
+
}
|
|
29
|
+
layer._rasterProgram = null;
|
|
30
|
+
if (layer._dem) destroyTexture(layer, layer._dem.texture);
|
|
31
|
+
layer._dem = null;
|
|
32
|
+
for (const grid of layer._terrainGrids?.values() || []) {
|
|
33
|
+
for (const attribute of Object.values(grid)) destroyTexture(layer, attribute.buffer);
|
|
34
|
+
}
|
|
35
|
+
layer._terrainGrids = null;
|
|
36
|
+
layer._bridges = null;
|
|
37
|
+
disposeMesh(layer, layer._bridgeMesh);
|
|
38
|
+
layer._bridgeMesh = null;
|
|
39
|
+
onRemove3DLayer(layer, map);
|
|
40
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { render } from "./render.js";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export function onZoomAnim(event) {
|
|
5
|
+
const map = this._map;
|
|
6
|
+
if (event && !this._zoomView) {
|
|
7
|
+
this._zoomView = { from: map.getCenter(), zoom: map.getZoom(), to: event.center,
|
|
8
|
+
targetZoom: event.zoom, start: performance.now() };
|
|
9
|
+
map.getContainer().classList.add('leaflet-camera-zoom');
|
|
10
|
+
}
|
|
11
|
+
queueMicrotask(() => {
|
|
12
|
+
if (this._shared === this && this.renderer) render(this);
|
|
13
|
+
});
|
|
14
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Built-in vehicles for the 'traffic' type. Models are [ring of [x, z], bottom, top, rgb, topRing?] convex prisms in metres;
|
|
2
|
+
// forward is -z, right is +x. `topRing` (same length as `ring`) tapers the prism; rgb components above 1 are self-lit lamps.
|
|
3
|
+
export const paints = [
|
|
4
|
+
[0.86, 0.86, 0.88],
|
|
5
|
+
[0.1, 0.1, 0.12],
|
|
6
|
+
[0.5, 0.53, 0.57],
|
|
7
|
+
[0.65, 0.1, 0.08],
|
|
8
|
+
[0.12, 0.25, 0.55],
|
|
9
|
+
[0.85, 0.7, 0.15]
|
|
10
|
+
];
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { toSRGB } from "./toSRGB.js";
|
|
2
|
+
import { channel } from "./channel.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* HSL inputs are linear-space to preserve the original building styling.
|
|
6
|
+
* Numeric/CSS/RGB inputs are already sRGB; CSS alpha is not used for extrusion.
|
|
7
|
+
* @param {number|string|Object} value 0xRRGGBB, CSS color, {r,g,b}, or {h,s,l} in 0..1.
|
|
8
|
+
* @returns {Object} sRGB {r,g,b} components in 0..1.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export function parseColor(value) {
|
|
12
|
+
if (value && typeof value === 'object' && 'h' in value) {
|
|
13
|
+
const a = value.s * Math.min(value.l, 1 - value.l);
|
|
14
|
+
return {
|
|
15
|
+
r: toSRGB(channel(0, value.h, value.l, a)),
|
|
16
|
+
g: toSRGB(channel(8, value.h, value.l, a)),
|
|
17
|
+
b: toSRGB(channel(4, value.h, value.l, a))
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
if (value && typeof value === 'object' && 'r' in value) {
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
if (typeof value === 'number') {
|
|
24
|
+
return {
|
|
25
|
+
r: (value >> 16 & 255) / 255,
|
|
26
|
+
g: (value >> 8 & 255) / 255,
|
|
27
|
+
b: (value & 255) / 255,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
if (typeof value !== 'string' || !CSS.supports('color', value)) {
|
|
31
|
+
throw new Error('Invalid 3D color');
|
|
32
|
+
}
|
|
33
|
+
const context = document.createElement('canvas').getContext('2d');
|
|
34
|
+
context.fillStyle = value;
|
|
35
|
+
context.fillRect(0, 0, 1, 1);
|
|
36
|
+
const [r, g, b] = context.getImageData(0, 0, 1, 1).data;
|
|
37
|
+
return {
|
|
38
|
+
r: r / 255,
|
|
39
|
+
g: g / 255,
|
|
40
|
+
b: b / 255
|
|
41
|
+
};
|
|
42
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { box } from "./box.js";
|
|
2
|
+
import { trousers, shirt, skin, dark } from "./skin.js";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export const parts = {
|
|
6
|
+
body: [
|
|
7
|
+
[box(-0.17, 0.17, -0.1, 0.1), 0.82, 0.95, trousers],
|
|
8
|
+
[box(-0.19, 0.19, -0.11, 0.11), 0.95, 1.44, shirt],
|
|
9
|
+
[box(-0.05, 0.05, -0.05, 0.05), 1.44, 1.5, skin],
|
|
10
|
+
[box(-0.1, 0.1, -0.11, 0.1), 1.5, 1.72, skin],
|
|
11
|
+
[box(-0.105, 0.105, -0.06, 0.115), 1.58, 1.77, dark],
|
|
12
|
+
[box(-0.105, 0.105, -0.115, -0.06), 1.7, 1.77, dark],
|
|
13
|
+
],
|
|
14
|
+
leg: [[box(-0.07, 0.07, -0.07, 0.07), -0.82, 0, trousers], [box(-0.07, 0.07, -0.17, 0.07), -0.9, -0.82, dark]],
|
|
15
|
+
arm: [[box(-0.05, 0.05, -0.05, 0.05), -0.55, 0, shirt], [box(-0.045, 0.045, -0.045, 0.045), -0.66, -0.55, skin]],
|
|
16
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Perspective projection of a celestial direction; null when behind the camera. */
|
|
2
|
+
|
|
3
|
+
export function projectCelestialBody(dir, size, pitch, bearing) {
|
|
4
|
+
const [x, y, z] = dir;
|
|
5
|
+
const forward = -x * Math.sin(bearing) * Math.sin(pitch) - y * Math.cos(pitch) - z * Math.cos(bearing) * Math.sin(pitch);
|
|
6
|
+
if (forward > 0) {
|
|
7
|
+
return {
|
|
8
|
+
left: size.x / 2 + size.y * 1.5 * (x * Math.cos(bearing) - z * Math.sin(bearing)) / forward,
|
|
9
|
+
top: size.y / 2 - size.y * 1.5 * (-x * Math.sin(bearing) * Math.cos(pitch) + y * Math.sin(pitch) - z * Math.cos(bearing) * Math.cos(pitch)) / forward
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
return null;
|
|
13
|
+
}
|