leaflet-city-mapper 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -13
- package/cucumber.mjs +4 -0
- package/dist/leaflet-city-mapper.js +3 -1
- package/dist/leaflet-city-mapper.js.map +4 -4
- package/package.json +3 -4
- package/src/archives/decodeDirectory.js +32 -0
- package/src/archives/decodeHeader.js +19 -0
- package/src/archives/decompress.js +5 -0
- package/src/archives/getHeader.js +9 -0
- package/src/archives/getZxy.js +75 -0
- package/src/archives/loadDirectory.js +7 -0
- package/src/archives/loadSource.js +17 -0
- package/src/archives/read.js +29 -0
- package/src/archives/tileId.js +19 -0
- package/src/archives/varint.js +15 -0
- package/src/camera/angles.js +6 -0
- package/src/camera/animationPoint.js +8 -0
- package/src/camera/cameraMapReady.js +8 -0
- package/src/camera/cancelCameraAnimation.js +11 -0
- package/src/camera/cleanupCameraMap.js +11 -0
- package/src/camera/constrainCameraToBounds.js +3 -0
- package/src/camera/displayPoint.js +3 -0
- package/src/camera/fitCameraBounds.js +48 -0
- package/src/camera/groundBounds.js +11 -0
- package/src/camera/initializeCameraMap.js +25 -0
- package/src/camera/mapAnimateCamera.js +17 -0
- package/src/camera/mapCamera.js +123 -0
- package/src/camera/mapContainerPointToLayerPoint.js +7 -0
- package/src/camera/mapGetBearing.js +1 -0
- package/src/camera/mapGetBounds.js +14 -0
- package/src/camera/mapGetBoundsCenterZoom.js +7 -0
- package/src/camera/mapGetBoundsZoom.js +14 -0
- package/src/camera/mapGetCenterLayerPoint.js +5 -0
- package/src/camera/mapGetPitch.js +1 -0
- package/src/camera/mapLayerPointToContainerPoint.js +7 -0
- package/src/camera/mapLimitCenter.js +12 -0
- package/src/camera/mapLimitOffset.js +10 -0
- package/src/camera/mapPanBy.js +9 -0
- package/src/camera/mapPanInside.js +14 -0
- package/src/camera/mapResetNorth.js +1 -0
- package/src/camera/mapResetNorthPitch.js +1 -0
- package/src/camera/mapSetBearing.js +1 -0
- package/src/camera/mapSetPitch.js +1 -0
- package/src/camera/mapSetPitchAndBearing.js +14 -0
- package/src/camera/mapSetZoomAround.js +11 -0
- package/src/camera/mapStopPitchBearingAnimation.js +6 -0
- package/src/camera/mapTryAnimatedPan.js +9 -0
- package/src/camera/mapUpdateCameraOverlays.js +7 -0
- package/src/camera/pointOf.js +3 -0
- package/src/camera/project.js +20 -0
- package/src/camera/runCameraAnimations.js +28 -0
- package/src/camera/scheduleCameraAnimation.js +8 -0
- package/src/camera/updateSky.js +16 -0
- package/src/camera/verticalGroundY.js +4 -0
- package/src/collision/collectMeshes.js +5 -0
- package/src/collision/collider.js +63 -0
- package/src/collision/horizontalRay.js +12 -0
- package/src/collision/intersectMeshes.js +133 -0
- package/src/collision/sortHits.js +23 -0
- package/src/constants/CELL.js +4 -0
- package/src/constants/Compass.js +7 -0
- package/src/constants/ContainerResize.js +7 -0
- package/src/constants/HEIGHT.js +1 -0
- package/src/constants/PitchDrag.js +7 -0
- package/src/constants/ShiftRotate.js +7 -0
- package/src/constants/TILE_RADIUS.js +1 -0
- package/src/constants/TILE_SIZE.js +1 -0
- package/src/constants/TouchMode.js +6 -0
- package/src/constants/accessorSizes.js +1 -0
- package/src/constants/accessorTypes.js +8 -0
- package/src/constants/attachState.js +1 -0
- package/src/constants/cameraControlsState.js +1 -0
- package/src/constants/cityMapper.js +6 -0
- package/src/constants/colliders.js +2 -0
- package/src/constants/dark.js +1 -0
- package/src/constants/elevationWGSL.js +27 -0
- package/src/constants/glass.js +1 -0
- package/src/constants/headlight.js +1 -0
- package/src/constants/hull.js +1 -0
- package/src/constants/indexState.js +1 -0
- package/src/constants/limbs.js +9 -0
- package/src/constants/mapCameraState.js +1 -0
- package/src/constants/moves.js +11 -0
- package/src/constants/nativeEventMaps.js +1 -0
- package/src/constants/nativeLayerState.js +1 -0
- package/src/constants/nativeMethodHandlers.js +31 -0
- package/src/constants/onMapChangeState.js +1 -0
- package/src/constants/onZoomAnimState.js +1 -0
- package/src/constants/paints.js +10 -0
- package/src/constants/parts.js +19 -0
- package/src/constants/pendingUpdates.js +1 -0
- package/src/constants/pumpState.js +1 -0
- package/src/constants/renderers.js +2 -0
- package/src/constants/ringDirections.js +10 -0
- package/src/constants/roundProfile.js +1 -0
- package/src/constants/shirt.js +1 -0
- package/src/constants/skin.js +2 -0
- package/src/constants/speed.js +3 -0
- package/src/constants/taillight.js +1 -0
- package/src/constants/trafficShader.js +49 -0
- package/src/constants/trousers.js +1 -0
- package/src/constants/tyre.js +1 -0
- package/src/constants/underEntryState.js +1 -0
- package/src/constants/vehicles.js +40 -0
- package/src/constants/white.js +1 -0
- package/src/controls/acceptPitchDrag.js +4 -0
- package/src/controls/acceptRotateDrag.js +3 -0
- package/src/controls/adjustCameraDrag.js +10 -0
- package/src/controls/cameraControls.js +60 -0
- package/src/controls/cameraDragClick.js +9 -0
- package/src/controls/cameraDragContextMenu.js +8 -0
- package/src/controls/cameraDragDown.js +20 -0
- package/src/controls/cameraDragEnd.js +6 -0
- package/src/controls/cameraDragMove.js +23 -0
- package/src/controls/changeCameraTouch.js +14 -0
- package/src/controls/cleanupCameraTouch.js +24 -0
- package/src/controls/compassAddHooks.js +15 -0
- package/src/controls/compassOrientation.js +6 -0
- package/src/controls/compassRemoveHooks.js +5 -0
- package/src/controls/containerResizeAddHooks.js +8 -0
- package/src/controls/containerResizeRemoveHooks.js +5 -0
- package/src/controls/dragCamera.js +22 -0
- package/src/controls/editable.js +3 -0
- package/src/controls/endAllCameraDrags.js +7 -0
- package/src/controls/endAllCameraTouches.js +7 -0
- package/src/controls/endCameraTouch.js +11 -0
- package/src/controls/endCameraTouchEvent.js +5 -0
- package/src/controls/finishCameraDrag.js +9 -0
- package/src/controls/finishCompassPermission.js +16 -0
- package/src/controls/loadCameraControls.js +9 -0
- package/src/controls/moveCameraTouch.js +22 -0
- package/src/controls/notifyCameraTouchChange.js +1 -0
- package/src/controls/pitchDragAddHooks.js +6 -0
- package/src/controls/pitchDragRemoveHooks.js +5 -0
- package/src/controls/refreshRotateControl.js +7 -0
- package/src/controls/refreshRotateFocus.js +5 -0
- package/src/controls/removeCameraDrag.js +23 -0
- package/src/controls/resizeMap.js +3 -0
- package/src/controls/rotateButtonClick.js +7 -0
- package/src/controls/rotateButtonKeydown.js +11 -0
- package/src/controls/rotateControl.js +3 -0
- package/src/controls/rotateOnAdd.js +38 -0
- package/src/controls/rotateOnRemove.js +6 -0
- package/src/controls/shiftRotateAddHooks.js +8 -0
- package/src/controls/shiftRotateRemoveHooks.js +5 -0
- package/src/controls/shiftRotateWheel.js +9 -0
- package/src/controls/startCameraTouch.js +23 -0
- package/src/core/addImageState.js +7 -0
- package/src/core/addRasterImage.js +10 -0
- package/src/core/adjustCameraMarkerPan.js +22 -0
- package/src/core/beforeNativeRender.js +10 -0
- package/src/core/boundsQuad.js +11 -0
- package/src/core/bringNativeLayerToBack.js +3 -0
- package/src/core/bringNativeLayerToFront.js +3 -0
- package/src/core/cameraCircleBounds.js +6 -0
- package/src/core/cameraMarkerDrag.js +18 -0
- package/src/core/cameraMarkerOnDrag.js +8 -0
- package/src/core/cancelGridFade.js +10 -0
- package/src/core/closestCameraLayerPoint.js +7 -0
- package/src/core/compareNativeHits.js +3 -0
- package/src/core/current.js +3 -0
- package/src/core/disposeNativeLayer.js +35 -0
- package/src/core/fireRasterLoad.js +5 -0
- package/src/core/forwardNativeError.js +3 -0
- package/src/core/gridlayerGetEvents.js +7 -0
- package/src/core/gridlayerGetTiledPixelBounds.js +8 -0
- package/src/core/handleNativeMapEvent.js +47 -0
- package/src/core/hideTargets.js +16 -0
- package/src/core/initNativeGPU.js +21 -0
- package/src/core/initializeGridContainer.js +6 -0
- package/src/core/initializeNativeLayer.js +42 -0
- package/src/core/localPixel.js +5 -0
- package/src/core/localPixelForGeometry.js +6 -0
- package/src/core/localPosition.js +6 -0
- package/src/core/markerCameraIconPoint.js +9 -0
- package/src/core/markerGetEvents.js +5 -0
- package/src/core/markerInitInteraction.js +8 -0
- package/src/core/markerQuadCorners.js +31 -0
- package/src/core/markerSetIcon.js +9 -0
- package/src/core/markerSetPos.js +14 -0
- package/src/core/markerSetRotation.js +7 -0
- package/src/core/markerUpdateZIndex.js +8 -0
- package/src/core/nativeAddLatLng.js +3 -0
- package/src/core/nativeBringToBack.js +3 -0
- package/src/core/nativeBringToFront.js +3 -0
- package/src/core/nativeEvents.js +26 -0
- package/src/core/nativeImageError.js +8 -0
- package/src/core/nativeImageRefresh.js +7 -0
- package/src/core/nativeLayer.js +97 -0
- package/src/core/nativeLayerMethod.js +21 -0
- package/src/core/nativeRedraw.js +3 -0
- package/src/core/nativeSetBounds.js +3 -0
- package/src/core/nativeSetIcon.js +3 -0
- package/src/core/nativeSetLatLng.js +3 -0
- package/src/core/nativeSetLatLngs.js +3 -0
- package/src/core/nativeSetOpacity.js +3 -0
- package/src/core/nativeSetRadius.js +3 -0
- package/src/core/nativeSetStyle.js +3 -0
- package/src/core/nativeSetUrl.js +3 -0
- package/src/core/nativeSetZIndex.js +3 -0
- package/src/core/nativeSetZIndexOffset.js +3 -0
- package/src/core/popupAdjustPan.js +23 -0
- package/src/core/popupGetEvents.js +5 -0
- package/src/core/popupUpdatePosition.js +14 -0
- package/src/core/putNativeMesh.js +33 -0
- package/src/core/quadNativeMesh.js +15 -0
- package/src/core/readyNativeGPU.js +6 -0
- package/src/core/refreshNativeEvent.js +5 -0
- package/src/core/refreshNativeLayer.js +29 -0
- package/src/core/refreshNativeLayerContract.js +3 -0
- package/src/core/rejectNativeReady.js +3 -0
- package/src/core/removeImageState.js +8 -0
- package/src/core/removeNativeEvents.js +16 -0
- package/src/core/removeTargets.js +8 -0
- package/src/core/reorderNativeLayer.js +6 -0
- package/src/core/resolveNativeReady.js +3 -0
- package/src/core/restoreNativeEvents.js +6 -0
- package/src/core/runGridFades.js +14 -0
- package/src/core/runMarkerPanFrame.js +12 -0
- package/src/core/scheduleGridFade.js +9 -0
- package/src/core/scheduleMarkerPan.js +8 -0
- package/src/core/styleNativeMesh.js +10 -0
- package/src/core/syncGridLayer.js +22 -0
- package/src/core/syncImageOverlay.js +9 -0
- package/src/core/syncMarker.js +12 -0
- package/src/core/syncVectorLayer.js +26 -0
- package/src/core/synchronizeNativeLayer.js +35 -0
- package/src/core/textureFor.js +48 -0
- package/src/core/tooltipGetEvents.js +5 -0
- package/src/core/tooltipSetPosition.js +8 -0
- package/src/core/updateGridOpacity.js +23 -0
- package/src/core/updateNativeLayerView.js +6 -0
- package/src/core/uploadCanvasTexture.js +19 -0
- package/src/geometry/addBridges.js +88 -0
- package/src/geometry/below.js +3 -0
- package/src/geometry/box.js +3 -0
- package/src/geometry/bridgeElevation.js +19 -0
- package/src/geometry/bridgeLocal.js +4 -0
- package/src/geometry/build.js +19 -0
- package/src/geometry/circleAt.js +5 -0
- package/src/geometry/clipLine.js +23 -0
- package/src/geometry/clipSegment.js +19 -0
- package/src/geometry/computeBounds.js +33 -0
- package/src/geometry/conformModelToTerrain.js +67 -0
- package/src/geometry/cross.js +3 -0
- package/src/geometry/disk.js +11 -0
- package/src/geometry/diskAt.js +4 -0
- package/src/geometry/dot.js +6 -0
- package/src/geometry/emitter.js +8 -0
- package/src/geometry/lampPostGeometry.js +24 -0
- package/src/geometry/lampRing.js +11 -0
- package/src/geometry/lightGeometry.js +15 -0
- package/src/geometry/line.js +54 -0
- package/src/geometry/nativeGeometry.js +55 -0
- package/src/geometry/nativeTriangle.js +3 -0
- package/src/geometry/polygon.js +22 -0
- package/src/geometry/push.js +3 -0
- package/src/geometry/quad.js +4 -0
- package/src/geometry/roofCoverage.js +52 -0
- package/src/geometry/samePoint.js +3 -0
- package/src/geometry/segment.js +21 -0
- package/src/geometry/setVertexColor.js +15 -0
- package/src/geometry/sub.js +6 -0
- package/src/geometry/surface.js +17 -0
- package/src/geometry/treeGeometry.js +31 -0
- package/src/geometry/treeRing.js +14 -0
- package/src/geometry/triangle.js +12 -0
- package/src/geometry/vertexNormals.js +32 -0
- package/src/geometry/visit.js +9 -0
- package/src/index.js +98 -65
- package/src/lighting/cacheLightGrid.js +23 -0
- package/src/lighting/collectLightMeshes.js +6 -0
- package/src/lighting/lightGrid.js +42 -0
- package/src/lighting/updatePointLights.js +34 -0
- package/src/lighting/visitCells.js +15 -0
- package/src/lighting/worldLights.js +27 -0
- package/src/models/decodeModel.js +45 -0
- package/src/models/hasUnsupportedPrimitives.js +10 -0
- package/src/models/loadBuffer.js +6 -0
- package/src/models/loadImage.js +15 -0
- package/src/models/loadModel.js +69 -0
- package/src/models/materialFor.js +21 -0
- package/src/models/modelNode.js +93 -0
- package/src/models/nodeMatrix.js +22 -0
- package/src/models/readAccessor.js +53 -0
- package/src/models/readAccessorValues.js +16 -0
- package/src/models/textureFor.js +35 -0
- package/src/models/textureSampler.js +10 -0
- package/src/picking/collectVisibleMesh.js +4 -0
- package/src/picking/findFeature.js +49 -0
- package/src/picking/hit.js +23 -0
- package/src/picking/hitMesh.js +30 -0
- package/src/picking/onClick.js +13 -0
- package/src/picking/onPointerLeave.js +11 -0
- package/src/picking/onPointerMove.js +15 -0
- package/src/picking/pointerClick.js +5 -0
- package/src/picking/pointerLeave.js +5 -0
- package/src/picking/pointerMove.js +5 -0
- package/src/picking/raycast.js +59 -0
- package/src/picking/setHighlight.js +13 -0
- package/src/picking/shouldSkipOther.js +3 -0
- package/src/picking/showFeature.js +34 -0
- package/src/raster/addRasterTile.js +114 -0
- package/src/raster/comparePendingTiles.js +5 -0
- package/src/raster/createGeometry.js +22 -0
- package/src/raster/createRasterMesh.js +47 -0
- package/src/raster/finishAttachment.js +11 -0
- package/src/raster/finishRasterTile.js +47 -0
- package/src/raster/getRasterEvents.js +6 -0
- package/src/raster/getRasterTileSize.js +5 -0
- package/src/raster/initRaster.js +38 -0
- package/src/raster/isLoading.js +5 -0
- package/src/raster/loadRasterTile.js +10 -0
- package/src/raster/onPMTileAdd.js +10 -0
- package/src/raster/onPMTileRemove.js +8 -0
- package/src/raster/pruneRasterTiles.js +37 -0
- package/src/raster/pumpRasterTiles.js +22 -0
- package/src/raster/readyRaster.js +13 -0
- package/src/raster/registerTerrainTile.js +12 -0
- package/src/raster/releaseRasterTile.js +18 -0
- package/src/raster/releaseRasterTiles.js +15 -0
- package/src/raster/removeRasterTile.js +13 -0
- package/src/raster/reportError.js +6 -0
- package/src/raster/setPMTileOpacity.js +7 -0
- package/src/raster/setPMTileZIndex.js +7 -0
- package/src/raster/setRasterOpacity.js +11 -0
- package/src/raster/setRasterTerrain.js +21 -0
- package/src/raster/setRasterZIndex.js +11 -0
- package/src/raster/updateAttachedTiles.js +10 -0
- package/src/raster/updateRasterTiles.js +59 -0
- package/src/rendering/collectFrameMeshes.js +31 -0
- package/src/rendering/collectMeshes.js +36 -0
- package/src/rendering/compareMeshes.js +10 -0
- package/src/rendering/compareRoofTiles.js +4 -0
- package/src/rendering/composeRoofAtlas.js +52 -0
- package/src/rendering/createMesh.js +33 -0
- package/src/rendering/createProgram.js +92 -0
- package/src/rendering/destroyAfterSubmission.js +8 -0
- package/src/rendering/destroyTexture.js +6 -0
- package/src/rendering/disposeMesh.js +14 -0
- package/src/rendering/drawGeometry.js +129 -0
- package/src/rendering/drawSceneMeshes.js +51 -0
- package/src/rendering/ensureRoofBlit.js +40 -0
- package/src/rendering/prepareFrameMeshes.js +42 -0
- package/src/rendering/prepareFrameUniforms.js +49 -0
- package/src/rendering/rebuildRoofAtlas.js +67 -0
- package/src/rendering/render.js +57 -0
- package/src/rendering/reportCompilation.js +17 -0
- package/src/rendering/resizeRenderer.js +19 -0
- package/src/rendering/sortMeshes.js +6 -0
- package/src/rendering/synchronizeZoomView.js +34 -0
- package/src/rendering/textureBinding.js +7 -0
- package/src/rendering/updateMapCamera.js +32 -0
- package/src/rendering/updateRoofRaster.js +32 -0
- package/src/scene/attach.js +161 -0
- package/src/scene/attachLayer.js +10 -0
- package/src/scene/cancelUpdate.js +10 -0
- package/src/scene/emptyEvents.js +3 -0
- package/src/scene/emptyNode.js +11 -0
- package/src/scene/endZoom.js +16 -0
- package/src/scene/failAttachment.js +9 -0
- package/src/scene/get3DEvents.js +13 -0
- package/src/scene/init3D.js +30 -0
- package/src/scene/initializeLayer.js +16 -0
- package/src/scene/initializerFor.js +14 -0
- package/src/scene/layerInitialize.js +38 -0
- package/src/scene/layerLayerAdd.js +21 -0
- package/src/scene/onAdd3DLayer.js +35 -0
- package/src/scene/onMapChange.js +16 -0
- package/src/scene/onRemove3DLayer.js +69 -0
- package/src/scene/onZoomAnim.js +16 -0
- package/src/scene/placeEntry.js +11 -0
- package/src/scene/placeUnderEntry.js +8 -0
- package/src/scene/ready3D.js +25 -0
- package/src/scene/releaseRenderer.js +14 -0
- package/src/scene/removeEntry.js +6 -0
- package/src/scene/renderPendingMapChange.js +11 -0
- package/src/scene/renderPendingUpdates.js +19 -0
- package/src/scene/renderPendingZoomAnimation.js +7 -0
- package/src/scene/rendererDeviceError.js +10 -0
- package/src/scene/rendererDeviceLost.js +11 -0
- package/src/scene/replaceEntry.js +7 -0
- package/src/scene/reportError.js +3 -0
- package/src/scene/requestAdapter.js +12 -0
- package/src/scene/requestDevice.js +9 -0
- package/src/scene/resolveNextInitialization.js +12 -0
- package/src/scene/restoreObject.js +71 -0
- package/src/scene/runPlacements.js +7 -0
- package/src/scene/setParent.js +7 -0
- package/src/scene/showWebGPUWarning.js +16 -0
- package/src/scene/startZoom.js +5 -0
- package/src/scene/traverse.js +7 -0
- package/src/scene/underEntry.js +17 -0
- package/src/scene/update.js +19 -0
- package/src/scene/updateCamera.js +34 -0
- package/src/scene/updateWorldMatrix.js +48 -0
- package/src/{utils/shaders.js → shaders/materialShaders.js} +246 -237
- package/src/shadows/bindSunlight.js +12 -0
- package/src/shadows/drawShadowMeshes.js +48 -0
- package/src/shadows/ensureShadowPipeline.js +53 -0
- package/src/shadows/renderSunlight.js +46 -0
- package/src/shadows/resizeSunlight.js +15 -0
- package/src/shadows/shadowBounds.js +32 -0
- package/src/shadows/shadowCacheMatches.js +23 -0
- package/src/shadows/shadowMatrix.js +39 -0
- package/src/sources/addGeneratedTriangle.js +6 -0
- package/src/sources/addTriangle.js +17 -0
- package/src/sources/attachAreaMesh.js +58 -0
- package/src/sources/buildArea.js +42 -0
- package/src/sources/buildAreaFeature.js +41 -0
- package/src/sources/buildAreaPoint.js +25 -0
- package/src/sources/buildAreaPolygon.js +29 -0
- package/src/sources/compareAreaDistance.js +4 -0
- package/src/sources/generateTreeGeometry.js +11 -0
- package/src/sources/groundOffset.js +3 -0
- package/src/sources/initializeGeoJSON.js +8 -0
- package/src/sources/instanceAreaGeometry.js +29 -0
- package/src/sources/projectRing.js +20 -0
- package/src/sources/projectedTree.js +13 -0
- package/src/sources/pump.js +54 -0
- package/src/sources/releaseArea.js +22 -0
- package/src/sources/setGeoJSONData.js +12 -0
- package/src/sources/setGeoJSONLayerData.js +5 -0
- package/src/sources/sourceAreaContext.js +9 -0
- package/src/sources/updateArea.js +45 -0
- package/src/sources/updateStatus.js +12 -0
- package/src/sunlight/addTimeLayer.js +3 -0
- package/src/sunlight/addTo.js +10 -0
- package/src/sunlight/atmosphere.js +28 -0
- package/src/sunlight/horizontalPosition.js +16 -0
- package/src/sunlight/initSunlight.js +14 -0
- package/src/sunlight/initialize.js +11 -0
- package/src/sunlight/mix.js +6 -0
- package/src/sunlight/moonPosition.js +17 -0
- package/src/sunlight/onAdd.js +5 -0
- package/src/sunlight/onAddSun.js +66 -0
- package/src/sunlight/projectCelestialBody.js +13 -0
- package/src/sunlight/remove.js +7 -0
- package/src/sunlight/removeSun.js +15 -0
- package/src/sunlight/removeTimeLayer.js +3 -0
- package/src/sunlight/render.js +7 -0
- package/src/sunlight/rgb.js +6 -0
- package/src/sunlight/solarPosition.js +17 -0
- package/src/sunlight/styleTimeControl.js +7 -0
- package/src/sunlight/tickSun.js +5 -0
- package/src/sunlight/updateSky.js +20 -0
- package/src/sunlight/updateSun.js +34 -0
- package/src/sunlight/useLiveTime.js +6 -0
- package/src/sunlight/useSelectedTime.js +20 -0
- package/src/terrain/clearLayerTerrain.js +5 -0
- package/src/terrain/getElevation.js +10 -0
- package/src/terrain/initTerrain.js +20 -0
- package/src/terrain/loadReadyTerrain.js +5 -0
- package/src/terrain/loadTerrain.js +63 -0
- package/src/terrain/loadTerrainTiles.js +13 -0
- package/src/terrain/onTerrainAdd.js +21 -0
- package/src/terrain/onTerrainChange.js +14 -0
- package/src/terrain/onTerrainRemove.js +41 -0
- package/src/terrain/readBridges.js +4 -0
- package/src/terrain/sample.js +7 -0
- package/src/terrain/setLayerTerrain.js +5 -0
- package/src/terrain/setTerrainHeight.js +10 -0
- package/src/terrain/terrainAtlas.js +23 -0
- package/src/terrain/terrainElevation.js +20 -0
- package/src/terrain/terrainGrid.js +24 -0
- package/src/traffic/addTraffic.js +7 -0
- package/src/traffic/along.js +14 -0
- package/src/traffic/clockMinutes.js +6 -0
- package/src/traffic/compareDepartures.js +5 -0
- package/src/traffic/createTrafficMesh.js +7 -0
- package/src/traffic/destroyTrafficGpu.js +5 -0
- package/src/traffic/disposeTrafficObject.js +13 -0
- package/src/traffic/drawTrafficRoute.js +6 -0
- package/src/traffic/failTraffic.js +6 -0
- package/src/traffic/failedTrafficLoad.js +5 -0
- package/src/traffic/fetchTrafficLanes.js +10 -0
- package/src/traffic/groundTraffic.js +15 -0
- package/src/traffic/initTraffic.js +54 -0
- package/src/traffic/loadTraffic.js +15 -0
- package/src/traffic/loadedTrafficLanes.js +16 -0
- package/src/traffic/locateTraffic.js +9 -0
- package/src/traffic/moveTraffic.js +15 -0
- package/src/traffic/placeTraffic.js +21 -0
- package/src/traffic/prepareTraffic.js +25 -0
- package/src/traffic/readyTraffic.js +6 -0
- package/src/traffic/rebaseTraffic.js +58 -0
- package/src/traffic/rebuildTrafficMesh.js +28 -0
- package/src/traffic/removeTraffic.js +17 -0
- package/src/traffic/routeColor.js +6 -0
- package/src/traffic/routeGeometry.js +31 -0
- package/src/traffic/scheduledTrips.js +40 -0
- package/src/traffic/startTraffic.js +8 -0
- package/src/traffic/tickTraffic.js +57 -0
- package/src/traffic/toLanes.js +16 -0
- package/src/traffic/tooltip.js +11 -0
- package/src/traffic/trafficBounds.js +17 -0
- package/src/traffic/trafficNow.js +4 -0
- package/src/traffic/trafficStorage.js +5 -0
- package/src/traffic/tripsAt.js +27 -0
- package/src/traffic/updateTraffic.js +8 -0
- package/src/traffic/updateTrafficTerrain.js +12 -0
- package/src/traffic/vehicleOffsets.js +11 -0
- package/src/triangulation/area.js +9 -0
- package/src/triangulation/clean.js +18 -0
- package/src/triangulation/containsVertex.js +11 -0
- package/src/triangulation/cross.js +3 -0
- package/src/triangulation/crossesBoundary.js +8 -0
- package/src/triangulation/crossesRing.js +9 -0
- package/src/triangulation/equal.js +3 -0
- package/src/triangulation/inside.js +10 -0
- package/src/triangulation/insideHole.js +7 -0
- package/src/triangulation/intersects.js +11 -0
- package/src/triangulation/isClockWise.js +13 -0
- package/src/triangulation/minimumX.js +6 -0
- package/src/triangulation/on.js +4 -0
- package/src/triangulation/sortHoles.js +26 -0
- package/src/triangulation/triangulate.js +86 -0
- package/src/utils/channel.js +4 -0
- package/src/utils/compareDistance.js +3 -0
- package/src/utils/noOperation.js +1 -0
- package/src/utils/parseColor.js +42 -0
- package/src/utils/toSRGB.js +3 -0
- package/src/utils/wrap.js +3 -0
- package/src/vehicles/bicycleModel.js +23 -0
- package/src/vehicles/boatBenches.js +8 -0
- package/src/vehicles/boatModel.js +27 -0
- package/src/vehicles/busModel.js +6 -0
- package/src/vehicles/carModel.js +22 -0
- package/src/vehicles/carriage.js +19 -0
- package/src/vehicles/metroModel.js +9 -0
- package/src/vehicles/mirror.js +8 -0
- package/src/vehicles/pedestrianModel.js +17 -0
- package/src/vehicles/tramModel.js +9 -0
- package/src/walk/blocked.js +6 -0
- package/src/walk/createWalk.js +60 -0
- package/src/walk/initWalk.js +18 -0
- package/src/walk/initialize.js +6 -0
- package/src/walk/local.js +10 -0
- package/src/walk/onAdd.js +4 -0
- package/src/walk/onBlur.js +3 -0
- package/src/walk/onKey.js +12 -0
- package/src/walk/onPointer.js +13 -0
- package/src/walk/onRemove.js +4 -0
- package/src/walk/onTerrain.js +5 -0
- package/src/walk/place.js +18 -0
- package/src/walk/start.js +37 -0
- package/src/walk/step.js +53 -0
- package/src/walk/stop.js +27 -0
- package/src/walk/toggle.js +6 -0
- package/dist/scene/gpu.js +0 -3
- package/dist/scene/gpu.js.map +0 -7
- package/dist/scene/lighting.js +0 -9
- package/dist/scene/lighting.js.map +0 -7
- package/dist/scene/model.js +0 -2
- package/dist/scene/model.js.map +0 -7
- package/dist/scene/picking.js +0 -2
- package/dist/scene/picking.js.map +0 -7
- package/dist/scene/pmtiles.js +0 -2
- package/dist/scene/pmtiles.js.map +0 -7
- package/dist/scene/render.js +0 -15
- package/dist/scene/render.js.map +0 -7
- package/dist/scene/sources.js +0 -2
- package/dist/scene/sources.js.map +0 -7
- package/dist/types/3d.js +0 -2
- package/dist/types/3d.js.map +0 -7
- package/dist/types/geojson.js +0 -2
- package/dist/types/geojson.js.map +0 -7
- package/dist/types/pmtiles.js +0 -2
- package/dist/types/pmtiles.js.map +0 -7
- package/dist/types/sunlight.js +0 -2
- package/dist/types/sunlight.js.map +0 -7
- package/dist/types/terrain.js +0 -24
- package/dist/types/terrain.js.map +0 -7
- package/dist/types/traffic.js +0 -41
- package/dist/types/traffic.js.map +0 -7
- package/dist/types/walk.js +0 -2
- package/dist/types/walk.js.map +0 -7
- package/dist/utils/control.js +0 -2
- package/dist/utils/control.js.map +0 -7
- package/dist/utils/geometry.js +0 -2
- package/dist/utils/geometry.js.map +0 -7
- package/dist/utils/lighting.js +0 -2
- package/dist/utils/lighting.js.map +0 -7
- package/dist/utils/model.js +0 -2
- package/dist/utils/model.js.map +0 -7
- package/dist/utils/picking.js +0 -2
- package/dist/utils/picking.js.map +0 -7
- package/dist/utils/pmtiles.js +0 -2
- package/dist/utils/pmtiles.js.map +0 -7
- package/dist/utils/scene.js +0 -2
- package/dist/utils/scene.js.map +0 -7
- package/dist/utils/shaders.js +0 -203
- package/dist/utils/shaders.js.map +0 -7
- package/dist/utils/sun.js +0 -2
- package/dist/utils/sun.js.map +0 -7
- package/dist/utils/terrain.js +0 -2
- package/dist/utils/terrain.js.map +0 -7
- package/dist/utils/traffic.js +0 -2
- package/dist/utils/traffic.js.map +0 -7
- package/dist/utils/vehicles.js +0 -2
- package/dist/utils/vehicles.js.map +0 -7
- package/dist/utils/walk.js +0 -2
- package/dist/utils/walk.js.map +0 -7
- package/src/scene/gpu.js +0 -438
- package/src/scene/lighting.js +0 -193
- package/src/scene/model.js +0 -204
- package/src/scene/picking.js +0 -150
- package/src/scene/pmtiles.js +0 -94
- package/src/scene/render.js +0 -467
- package/src/scene/sources.js +0 -265
- package/src/types/3d.js +0 -337
- package/src/types/geojson.js +0 -42
- package/src/types/pmtiles.js +0 -143
- package/src/types/sunlight.js +0 -142
- package/src/types/terrain.js +0 -331
- package/src/types/traffic.js +0 -356
- package/src/types/walk.js +0 -219
- package/src/utils/control.js +0 -18
- package/src/utils/geometry.js +0 -256
- package/src/utils/lighting.js +0 -51
- package/src/utils/model.js +0 -178
- package/src/utils/picking.js +0 -119
- package/src/utils/pmtiles.js +0 -79
- package/src/utils/scene.js +0 -102
- package/src/utils/sun.js +0 -71
- package/src/utils/terrain.js +0 -78
- package/src/utils/traffic.js +0 -90
- package/src/utils/vehicles.js +0 -69
- package/src/utils/walk.js +0 -72
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/** Test the mesh's ground footprint against loaded imagery, including coarse parent tiles. */
|
|
2
|
+
export function roofCoverage(mesh, backend, rasters) {
|
|
3
|
+
const map = backend._map, bounds = mesh.geometry.bounds, world = mesh.worldMatrix;
|
|
4
|
+
let intersectsArchive = false;
|
|
5
|
+
let layer, zoom, origin, scale, min, max, i, x, y, z, px, py, nw, se, remaining, tile, size, left;
|
|
6
|
+
let top, pieces, x0, y0, x1, y1, l, t, r, b;
|
|
7
|
+
for (layer of rasters) {
|
|
8
|
+
zoom = layer._tileZoom, origin = map.project(backend._sceneOrigin, zoom);
|
|
9
|
+
scale = map.options.crs.scale(zoom) / (40075016.68557849 * Math.cos(backend._sceneOrigin.lat * Math.PI / 180));
|
|
10
|
+
min = [Infinity, Infinity], max = [-Infinity, -Infinity];
|
|
11
|
+
for (i = 0; i < 8; i++) {
|
|
12
|
+
x = i & 1 ? bounds.max[0] : bounds.min[0], y = i & 2 ? bounds.max[1] : bounds.min[1];
|
|
13
|
+
z = i & 4 ? bounds.max[2] : bounds.min[2];
|
|
14
|
+
px = origin.x + (world[0] * x + world[4] * y + world[8] * z + world[12]) * scale;
|
|
15
|
+
py = origin.y + (world[2] * x + world[6] * y + world[10] * z + world[14]) * scale;
|
|
16
|
+
min[0] = Math.min(min[0], px); min[1] = Math.min(min[1], py);
|
|
17
|
+
max[0] = Math.max(max[0], px); max[1] = Math.max(max[1], py);
|
|
18
|
+
}
|
|
19
|
+
if (layer.header.maxLat !== undefined && layer.header.minLon !== undefined &&
|
|
20
|
+
layer.header.minLat !== undefined && layer.header.maxLon !== undefined) {
|
|
21
|
+
nw = map.project([layer.header.maxLat, layer.header.minLon], zoom);
|
|
22
|
+
se = map.project([layer.header.minLat, layer.header.maxLon], zoom);
|
|
23
|
+
min[0] = Math.max(min[0], nw.x); min[1] = Math.max(min[1], nw.y);
|
|
24
|
+
max[0] = Math.min(max[0], se.x); max[1] = Math.min(max[1], se.y);
|
|
25
|
+
if (min[0] >= max[0] || min[1] >= max[1]) continue;
|
|
26
|
+
}
|
|
27
|
+
intersectsArchive = true;
|
|
28
|
+
remaining = [[min[0], min[1], max[0], max[1]]];
|
|
29
|
+
for (tile of layer._rasterTiles.values()) {
|
|
30
|
+
// Failed imagery already reports an error; do not hide the building indefinitely.
|
|
31
|
+
if (!tile.done && !tile.error) continue;
|
|
32
|
+
size = 256 * 2 ** (zoom - tile.coords.z);
|
|
33
|
+
left = tile.coords.x * size, top = tile.coords.y * size;
|
|
34
|
+
pieces = [];
|
|
35
|
+
for ([x0, y0, x1, y1] of remaining) {
|
|
36
|
+
l = Math.max(x0, left), t = Math.max(y0, top);
|
|
37
|
+
r = Math.min(x1, left + size), b = Math.min(y1, top + size);
|
|
38
|
+
if (l >= r || t >= b) {
|
|
39
|
+
pieces.push([x0, y0, x1, y1]);
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (y0 < t) pieces.push([x0, y0, x1, t]);
|
|
43
|
+
if (b < y1) pieces.push([x0, b, x1, y1]);
|
|
44
|
+
if (x0 < l) pieces.push([x0, t, l, b]);
|
|
45
|
+
if (r < x1) pieces.push([r, t, x1, b]);
|
|
46
|
+
}
|
|
47
|
+
remaining = pieces;
|
|
48
|
+
if (!remaining.length) return true;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return !intersectsArchive;
|
|
52
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { triangle } from './nativeTriangle.js';
|
|
2
|
+
import { disk } from './disk.js';
|
|
3
|
+
|
|
4
|
+
export function segment(context, a, b, startCap, endCap) {
|
|
5
|
+
const { options, width, stroke, point } = context;
|
|
6
|
+
const radius = width / 2;
|
|
7
|
+
const length = a.distanceTo(b);
|
|
8
|
+
if (!length) return;
|
|
9
|
+
const direction = b.subtract(a).divideBy(length);
|
|
10
|
+
const normal = new L.Point(-direction.y * radius, direction.x * radius);
|
|
11
|
+
if (options.lineCap === 'square') {
|
|
12
|
+
if (startCap) a = a.subtract(direction.multiplyBy(radius));
|
|
13
|
+
if (endCap) b = b.add(direction.multiplyBy(radius));
|
|
14
|
+
}
|
|
15
|
+
triangle(point, stroke, a.add(normal), a.subtract(normal), b.add(normal));
|
|
16
|
+
triangle(point, stroke, b.add(normal), a.subtract(normal), b.subtract(normal));
|
|
17
|
+
if (options.lineCap === 'round') {
|
|
18
|
+
if (startCap) disk(point, a, radius, stroke);
|
|
19
|
+
if (endCap) disk(point, b, radius, stroke);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Paints the vertices `[start, end)` of a mesh and marks its color buffer dirty.
|
|
3
|
+
* @param {Object} mesh Layer-created mesh with a color attribute.
|
|
4
|
+
* @param {number} start Inclusive vertex index, not an offset into the RGB array.
|
|
5
|
+
* @param {number} end Exclusive vertex index.
|
|
6
|
+
* @param {Object} color sRGB {r,g,b}, typically from parseColor().
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export function setVertexColor(mesh, start, end, color) {
|
|
10
|
+
let i;
|
|
11
|
+
for (i = start; i < end; i++) {
|
|
12
|
+
mesh.geometry.attributes.color.data.set([color.r, color.g, color.b], i * 3);
|
|
13
|
+
}
|
|
14
|
+
mesh.geometry.attributes.color.needsUpdate = true;
|
|
15
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ring } from './treeRing.js';
|
|
2
|
+
import { ringDirections } from '../constants/ringDirections.js';
|
|
3
|
+
|
|
4
|
+
export function surface(point, addTriangle, lowRadius, low, highRadius, high, color) {
|
|
5
|
+
const lower = ring(point, lowRadius), upper = ring(point, highRadius);
|
|
6
|
+
let i, next, slope, length, nx, nz, ny, normalX, normalZ;
|
|
7
|
+
for (i = 0; i < 8; i++) {
|
|
8
|
+
next = (i + 1) % 8;
|
|
9
|
+
slope = (lowRadius - highRadius) / (high - low);
|
|
10
|
+
length = Math.hypot(1, slope);
|
|
11
|
+
({ nx, nz } = ringDirections[i]);
|
|
12
|
+
ny = slope / length;
|
|
13
|
+
normalX = nx / length, normalZ = nz / length;
|
|
14
|
+
if (lowRadius) addTriangle(lower[i], low, lower[next], low, upper[next], high, normalX, ny, normalZ, color);
|
|
15
|
+
if (highRadius) addTriangle(lower[i], low, upper[next], high, upper[i], high, normalX, ny, normalZ, color);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { roundProfile } from '../constants/roundProfile.js';
|
|
2
|
+
import { parseColor } from "../utils/parseColor.js";
|
|
3
|
+
import { ring } from './treeRing.js';
|
|
4
|
+
import { surface } from './surface.js';
|
|
5
|
+
|
|
6
|
+
/** Low-poly tree, sharing the source block's buffers, picking and terrain offset. */
|
|
7
|
+
|
|
8
|
+
export function treeGeometry(point, style, addTriangle) {
|
|
9
|
+
const { top, bottom = 0, trunkRadius, crownRadius, crownBottom, crownShape = 'round' } = style;
|
|
10
|
+
if (!Number.isFinite(trunkRadius) || !Number.isFinite(crownRadius) || !Number.isFinite(crownBottom) ||
|
|
11
|
+
trunkRadius <= 0 || crownRadius < trunkRadius || crownBottom <= bottom || crownBottom >= top ||
|
|
12
|
+
!['round', 'cone'].includes(crownShape)) {
|
|
13
|
+
throw new Error('Invalid tree dimensions or crown shape');
|
|
14
|
+
}
|
|
15
|
+
const trunk = parseColor(style.trunkColor ?? 0x72513a);
|
|
16
|
+
const crown = parseColor(style.color ?? 0x4f823b);
|
|
17
|
+
surface(point, addTriangle, trunkRadius, bottom, trunkRadius, crownBottom + (top - crownBottom) * 0.25, trunk);
|
|
18
|
+
let i, low, lr, high, hr;
|
|
19
|
+
if (crownShape === 'cone') {
|
|
20
|
+
const base = ring(point, crownRadius);
|
|
21
|
+
for (i = 0; i < 8; i++) addTriangle(point, crownBottom, base[i], crownBottom,
|
|
22
|
+
base[(i + 1) % 8], crownBottom, 0, -1, 0, crown);
|
|
23
|
+
surface(point, addTriangle, crownRadius, crownBottom, 0, top, crown);
|
|
24
|
+
} else {
|
|
25
|
+
for (i = 1; i < roundProfile.length; i++) {
|
|
26
|
+
[low, lr] = roundProfile[i - 1], [high, hr] = roundProfile[i];
|
|
27
|
+
surface(point, addTriangle, lr * crownRadius, crownBottom + low * (top - crownBottom),
|
|
28
|
+
hr * crownRadius, crownBottom + high * (top - crownBottom), crown);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ringDirections } from '../constants/ringDirections.js';
|
|
2
|
+
|
|
3
|
+
export function ring(point, radius) {
|
|
4
|
+
const result = [];
|
|
5
|
+
let direction;
|
|
6
|
+
for (direction of ringDirections) {
|
|
7
|
+
result.push({
|
|
8
|
+
x: point.x + direction.x * radius,
|
|
9
|
+
y: point.y + direction.y * radius,
|
|
10
|
+
ground: point.ground,
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function triangle(position, normal, color, a, b, c, tint) {
|
|
2
|
+
const u = [], v = [];
|
|
3
|
+
let i, point, value;
|
|
4
|
+
for (i = 0; i < b.length; i++) u.push(b[i] - a[i]);
|
|
5
|
+
for (i = 0; i < c.length; i++) v.push(c[i] - a[i]);
|
|
6
|
+
const n = [u[1] * v[2] - u[2] * v[1], u[2] * v[0] - u[0] * v[2], u[0] * v[1] - u[1] * v[0]], length = Math.hypot(...n);
|
|
7
|
+
for (point of [a, b, c]) {
|
|
8
|
+
position.push(...point);
|
|
9
|
+
for (value of n) normal.push(value / length);
|
|
10
|
+
color.push(...tint);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** Area-weighted vertex normals, for indexed or non-indexed triangles. */
|
|
2
|
+
|
|
3
|
+
export function vertexNormals(p, indices) {
|
|
4
|
+
// Accumulate area-weighted face normals for shared vertices, then normalize.
|
|
5
|
+
const normals = new Float32Array(p.length);
|
|
6
|
+
let i, a, b, c, u, v, j, n, index, length;
|
|
7
|
+
for (i = 0; i < (indices?.length || p.length / 3); i += 3) {
|
|
8
|
+
a = indices ? indices[i] : i, b = indices ? indices[i + 1] : i + 1, c = indices ? indices[i + 2] : i + 2;
|
|
9
|
+
u = [], v = [];
|
|
10
|
+
for (j = 0; j < 3; j++) {
|
|
11
|
+
u.push(p[b * 3 + j] - p[a * 3 + j]);
|
|
12
|
+
v.push(p[c * 3 + j] - p[a * 3 + j]);
|
|
13
|
+
}
|
|
14
|
+
n = [
|
|
15
|
+
u[1] * v[2] - u[2] * v[1],
|
|
16
|
+
u[2] * v[0] - u[0] * v[2],
|
|
17
|
+
u[0] * v[1] - u[1] * v[0]
|
|
18
|
+
];
|
|
19
|
+
for (index of [a, b, c]) {
|
|
20
|
+
for (j = 0; j < 3; j++) {
|
|
21
|
+
normals[index * 3 + j] += n[j];
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
for (i = 0; i < normals.length; i += 3) {
|
|
26
|
+
length = Math.hypot(...normals.subarray(i, i + 3)) || 1;
|
|
27
|
+
for (j = 0; j < 3; j++) {
|
|
28
|
+
normals[i + j] /= length;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return normals;
|
|
32
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { polygon } from './polygon.js';
|
|
2
|
+
|
|
3
|
+
export function visit(context, coordinates, closed) {
|
|
4
|
+
if (!coordinates.length) return;
|
|
5
|
+
let child;
|
|
6
|
+
if (coordinates[0] instanceof L.LatLng) polygon(context, [coordinates], closed);
|
|
7
|
+
else if (closed && coordinates[0][0] instanceof L.LatLng) polygon(context, coordinates, closed);
|
|
8
|
+
else for (child of coordinates) visit(context, child, closed);
|
|
9
|
+
}
|
package/src/index.js
CHANGED
|
@@ -1,82 +1,115 @@
|
|
|
1
|
+
import './camera/mapCamera.js';
|
|
2
|
+
import { init3D } from './scene/init3D.js';
|
|
3
|
+
import { initNativeGPU } from './core/initNativeGPU.js';
|
|
4
|
+
import { initRaster } from './raster/initRaster.js';
|
|
5
|
+
import { setGeoJSONData } from './sources/setGeoJSONData.js';
|
|
6
|
+
import { initTerrain } from './terrain/initTerrain.js';
|
|
7
|
+
import './sunlight/initSunlight.js';
|
|
8
|
+
import { initTraffic } from './traffic/initTraffic.js';
|
|
9
|
+
import './walk/initWalk.js';
|
|
10
|
+
import { indexState } from './constants/indexState.js';
|
|
11
|
+
import { initializeNativeLayer } from './core/initializeNativeLayer.js';
|
|
12
|
+
import { layerLayerAdd } from './scene/layerLayerAdd.js';
|
|
13
|
+
import { layerInitialize } from './scene/layerInitialize.js';
|
|
14
|
+
|
|
1
15
|
/**
|
|
2
16
|
* `new L.Layer({ source: { type, url, ...settings }, pane, attribution })`: layers with a `source`
|
|
3
|
-
*
|
|
17
|
+
* initialize their specialized behavior on first use. Native map layers also join the WebGPU scene.
|
|
4
18
|
*/
|
|
5
19
|
|
|
6
20
|
/**
|
|
7
21
|
* Router for `new L.Layer({ source: { type, url, ...settings }, pane, attribution })`.
|
|
8
|
-
* It
|
|
9
|
-
*
|
|
22
|
+
* It initializes the existing instance from the bundled source modules;
|
|
23
|
+
* types receive flat options (`{ ...source, pane, attribution }`), so `layer.options.url` etc.
|
|
10
24
|
*
|
|
11
25
|
* Folder layout:
|
|
12
|
-
* -
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* and rendering. They receive the layer explicitly; types/3d.js declares its delegates, without mixins.
|
|
22
|
-
* - utils/: computations and scene-data helpers, independent of Leaflet layers and GPU devices.
|
|
23
|
-
* Geometry, decoders, lighting grids, terrain sampling, traffic and collisions can be tested in Node;
|
|
24
|
-
* scene transforms/picking use browser DOMMatrix/DOMPoint, and CSS colors use a canvas.
|
|
26
|
+
* - scene/: source routing, lifecycle and graph; initializers live in their domain folders.
|
|
27
|
+
* - core/: Leaflet layer integration; camera/ and controls/: camera and interaction.
|
|
28
|
+
* - sources/ and picking/: source geometry and feature interaction.
|
|
29
|
+
* - rendering/, shaders/, shadows/ and lighting/: WebGPU drawing and illumination.
|
|
30
|
+
* - geometry/, triangulation/ and collision/: mesh operations and spatial queries.
|
|
31
|
+
* - models/, archives/ and raster/: glTF loading, archive access and raster tiles.
|
|
32
|
+
* - constants/ and state/: exported module-level const and let bindings.
|
|
33
|
+
* - terrain/, sunlight/, traffic/ and walk/: feature-specific operations.
|
|
34
|
+
* Operations receive the layer explicitly, without subclasses or prototype replacement.
|
|
25
35
|
* Dataset-specific code and data (routes, timetables, API loaders) belong to the application, e.g. misc/.
|
|
26
36
|
*
|
|
27
|
-
* When `type` is omitted
|
|
37
|
+
* When `type` is omitted, inline FeatureCollections use 'geojson'; otherwise *.pmtiles URLs use
|
|
38
|
+
* 'pmtiles' and other sources use '3d'.
|
|
28
39
|
*/
|
|
29
40
|
|
|
30
|
-
|
|
41
|
+
indexState.layerProto = Object.defineProperties({}, Object.getOwnPropertyDescriptors(L.Layer.prototype));
|
|
31
42
|
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
43
|
+
// One chain for every pending layer: they become real layers in creation order.
|
|
44
|
+
indexState.loading = Promise.resolve();
|
|
45
|
+
|
|
46
|
+
indexState.pendingInitializations = [];
|
|
47
|
+
|
|
48
|
+
indexState.closestMethods = new WeakMap();
|
|
49
|
+
indexState.boundsMethods = new WeakMap();
|
|
50
|
+
indexState.gridInitializers = new WeakMap();
|
|
37
51
|
|
|
38
|
-
|
|
39
|
-
|
|
52
|
+
indexState.pendingGridFades = new Map();
|
|
53
|
+
indexState.gridFadeFrame = null;
|
|
40
54
|
|
|
41
|
-
|
|
42
|
-
|
|
55
|
+
indexState.pendingRasterLoads = [];
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* The '3d' layer type: native WebGPU scene synchronized with the map camera.
|
|
59
|
+
* Layers on one map share a canvas, scene and camera; each has its own root transform.
|
|
60
|
+
*
|
|
61
|
+
* @typedef {Object} Layer3DOptions Layer options; pane and attribution remain standard L.Layer options.
|
|
62
|
+
* @property {string} [type] '3d', 'geojson', 'pmtiles', 'terrain' or 'traffic'.
|
|
63
|
+
* @property {number[]} [center] Local origin [lat,lng]; defaults to the first map center.
|
|
64
|
+
* @property {number} [terrainOffset=0] Vertical offset in metres when terrain is enabled.
|
|
65
|
+
* @property {boolean} [terrainConform=false] Fit lower model geometry to local terrain elevation.
|
|
66
|
+
* @property {'OPAQUE'|'MASK'|'BLEND'} [alphaMode] Override every glTF material's alpha mode.
|
|
67
|
+
* @property {number[]} [rotation] Model Euler rotation [x,y,z] in radians, YXZ order.
|
|
68
|
+
* @property {number[]} [scale] Model scale [x,y,z].
|
|
69
|
+
* @property {string} [url] GLB/glTF model URL or PMTiles archive URL.
|
|
70
|
+
* @property {function(Object): (ExtrusionStyle|null)} [style] Source styling; null skips a feature.
|
|
71
|
+
* @property {function(PickedFeature): (Node|string)} [tooltip] Tooltip content; strings are text.
|
|
72
|
+
* @property {string} [ariaLabel='3D scene'] Shared canvas accessible name.
|
|
73
|
+
* @property {boolean} [nightLight=false] Point sources: emissive bulbs and local illumination.
|
|
74
|
+
* @property {boolean} [nightSparkle=false] Model: sparse luminous points at night.
|
|
75
|
+
*
|
|
76
|
+
* @typedef {Object} ExtrusionStyle
|
|
77
|
+
* @property {number} top Roof height in metres; must exceed bottom.
|
|
78
|
+
* @property {number} [bottom=0] Nonnegative base height.
|
|
79
|
+
* @property {number|string|Object} [color=0xd9b38c] RGB/CSS color or linear-space {h,s,l}.
|
|
80
|
+
* @property {number} [trunkRadius] Point tree trunk radius in metres.
|
|
81
|
+
* @property {number} [crownRadius] Point tree crown radius in metres.
|
|
82
|
+
* @property {number} [crownBottom] Point tree crown base in metres.
|
|
83
|
+
* @property {string} [crownShape='round'] Point tree crown shape.
|
|
84
|
+
* @property {number|string|Object} [trunkColor=0x72513a] Point tree bark color.
|
|
85
|
+
* @property {number} [lightRadius] Point light estimated ground reach in metres.
|
|
86
|
+
* @property {number} [lightFlux] Point light luminous flux in lumens.
|
|
87
|
+
*
|
|
88
|
+
* @typedef {Object} PickedFeature
|
|
89
|
+
* @property {string|number} id Source feature id or configured model URL.
|
|
90
|
+
* @property {Object} properties GeoJSON properties or model-level glTF extras.
|
|
91
|
+
* @property {Object} mesh Intersected mesh.
|
|
92
|
+
* @property {number[]} point Intersection [x,y,z] in shared scene metres.
|
|
93
|
+
* @property {Object} [model] Configured model root; absent for source polygons.
|
|
94
|
+
* @property {number} [vertexStart] First polygon vertex in the batched mesh.
|
|
95
|
+
* @property {number} [vertexEnd] Exclusive end of the polygon's vertex range.
|
|
96
|
+
*
|
|
97
|
+
* @typedef {Object} SourceArea
|
|
98
|
+
* @property {Object} coords Archive block {z,x,y}.
|
|
99
|
+
* @property {AbortController} request Cancellation prevents attaching obsolete results.
|
|
100
|
+
* @property {boolean} [done] Geometry built successfully, including empty blocks.
|
|
101
|
+
* @property {Object|null} [mesh] Batched GPU mesh.
|
|
102
|
+
* @property {number} [buildings] Emitted feature count.
|
|
103
|
+
* @property {number} [skipped] Features skipped by style.
|
|
104
|
+
* @property {string} [error] Failed load/build message.
|
|
105
|
+
*
|
|
106
|
+
* @param {L.Layer} backend
|
|
107
|
+
* @param {Layer3DOptions} [options] World origin comes from center or the first map centre.
|
|
108
|
+
*/
|
|
43
109
|
|
|
44
|
-
// Core L.Layer has no initialize and init hooks get no arguments: keep the options for the hook.
|
|
45
110
|
L.Layer.include({
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
const layer = this;
|
|
53
|
-
const { source: { type = /\.pmtiles(?:[?#]|$)/i.test(options.source.url) ? 'pmtiles' : '3d', ...source }, ...core } = options;
|
|
54
|
-
const settings = { ...source, ...core };
|
|
55
|
-
// A stand-in created by the entry point before this module loaded may already be on a map.
|
|
56
|
-
const map = layer._map;
|
|
57
|
-
map?.removeLayer(layer);
|
|
58
|
-
delete layer.onAdd;
|
|
59
|
-
delete layer.onRemove;
|
|
60
|
-
if (L.Layer.types[type]) {
|
|
61
|
-
Object.setPrototypeOf(layer, L.Layer.types[type].prototype);
|
|
62
|
-
layer.options = Object.create(L.Layer.types[type].prototype.options);
|
|
63
|
-
L.Layer.types[type].prototype.initialize.call(layer, settings);
|
|
64
|
-
map?.addLayer(layer);
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
Object.setPrototypeOf(layer, Pending.prototype);
|
|
68
|
-
L.Util.setOptions(layer, core);
|
|
69
|
-
map?.addLayer(layer);
|
|
70
|
-
// ponytail: type methods (setOpacity, add, ...) exist only once `ready` resolves.
|
|
71
|
-
loading = loading.catch(() => {}).then(() => import(`./types/${type}.js`));
|
|
72
|
-
const pending = layer.ready = loading.then(() => {
|
|
73
|
-
const map = layer._map;
|
|
74
|
-
map?.removeLayer(layer);
|
|
75
|
-
Object.setPrototypeOf(layer, L.Layer.types[type].prototype);
|
|
76
|
-
layer.options = Object.create(L.Layer.types[type].prototype.options);
|
|
77
|
-
L.Layer.types[type].prototype.initialize.call(layer, settings);
|
|
78
|
-
map?.addLayer(layer);
|
|
79
|
-
return layer.ready === pending ? layer : layer.ready;
|
|
80
|
-
});
|
|
81
|
-
},
|
|
82
|
-
});
|
|
111
|
+
_layerAdd: layerLayerAdd,
|
|
112
|
+
initialize: layerInitialize,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
L.Layer.addInitHook(initializeNativeLayer);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { lightGrid } from './lightGrid.js';
|
|
2
|
+
import { worldLights } from './worldLights.js';
|
|
3
|
+
|
|
4
|
+
/** Keep fixed lamps cached when moving headlights change. */
|
|
5
|
+
export function cacheLightGrid(meshes, previous, maxBytes) {
|
|
6
|
+
let unchanged = previous?.meshes.length === meshes.length;
|
|
7
|
+
const packed = [], snapshots = [];
|
|
8
|
+
let i, mesh, matrix, lights, cache, sameMatrix, j;
|
|
9
|
+
for (i = 0; i < meshes.length; i++) {
|
|
10
|
+
mesh = meshes[i], matrix = mesh.worldMatrix, lights = mesh.extras.lights;
|
|
11
|
+
cache = mesh._worldLights;
|
|
12
|
+
sameMatrix = Boolean(cache);
|
|
13
|
+
for (j = 0; j < matrix.length && sameMatrix; j++) sameMatrix = matrix[j] === cache.matrix[j];
|
|
14
|
+
if (!sameMatrix || cache.lights !== lights) {
|
|
15
|
+
cache = mesh._worldLights = { lights, matrix: [...matrix], data: worldLights(lights, matrix) };
|
|
16
|
+
}
|
|
17
|
+
unchanged &&= previous.meshes[i].mesh === mesh && previous.meshes[i].cache === cache;
|
|
18
|
+
packed.push(cache.data);
|
|
19
|
+
snapshots.push({ mesh, cache });
|
|
20
|
+
}
|
|
21
|
+
if (unchanged) return previous;
|
|
22
|
+
return { ...lightGrid(packed, maxBytes), meshes: snapshots };
|
|
23
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { visitCells } from './visitCells.js';
|
|
2
|
+
|
|
3
|
+
/** Pack world-space point lights into the shader's spatial grid. */
|
|
4
|
+
export function lightGrid(packed, maxBytes) {
|
|
5
|
+
let count = 0;
|
|
6
|
+
let values, i, value, key;
|
|
7
|
+
for (values of packed) count += values.length / 8;
|
|
8
|
+
const cellSize = 32;
|
|
9
|
+
let data = new Float32Array(8);
|
|
10
|
+
if (count) {
|
|
11
|
+
let minX = Infinity, minZ = Infinity, maxX = -Infinity, maxZ = -Infinity;
|
|
12
|
+
for (values of packed) for (i = 0; i < values.length; i += 8) {
|
|
13
|
+
minX = Math.min(minX, values[i] - values[i + 3]);
|
|
14
|
+
maxX = Math.max(maxX, values[i] + values[i + 3]);
|
|
15
|
+
minZ = Math.min(minZ, values[i + 2] - values[i + 3]);
|
|
16
|
+
maxZ = Math.max(maxZ, values[i + 2] + values[i + 3]);
|
|
17
|
+
}
|
|
18
|
+
const columns = Math.ceil((maxX - minX) / cellSize) + 1,
|
|
19
|
+
rows = Math.ceil((maxZ - minZ) / cellSize) + 1;
|
|
20
|
+
// Counting sort: count the lights of each cell, then fill each cell's slice.
|
|
21
|
+
const counts = new Uint32Array(columns * rows),
|
|
22
|
+
next = new Uint32Array(columns * rows);
|
|
23
|
+
visitCells(packed, minX, minZ, cellSize, columns, counts);
|
|
24
|
+
let entries = 0;
|
|
25
|
+
for (value of counts) entries += value;
|
|
26
|
+
const length = (2 + columns * rows + entries * 2) * 4;
|
|
27
|
+
if (length * 4 > maxBytes) {
|
|
28
|
+
throw new Error('Streetlight grid exceeds GPU storage limit');
|
|
29
|
+
}
|
|
30
|
+
data = new Float32Array(length);
|
|
31
|
+
data.set([minX, minZ, cellSize, columns, rows, count, 0, 0]);
|
|
32
|
+
let offset = 2 + columns * rows;
|
|
33
|
+
for (key = 0; key < counts.length; key++) if (counts[key]) {
|
|
34
|
+
data[(2 + key) * 4] = next[key] = offset;
|
|
35
|
+
data[(2 + key) * 4 + 1] = counts[key];
|
|
36
|
+
offset += counts[key] * 2;
|
|
37
|
+
}
|
|
38
|
+
visitCells(packed, minX, minZ, cellSize, columns, next, data);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return { data, count };
|
|
42
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { destroyTexture } from '../rendering/destroyTexture.js';
|
|
2
|
+
import { bindSunlight } from '../shadows/bindSunlight.js';
|
|
3
|
+
import { cacheLightGrid } from './cacheLightGrid.js';
|
|
4
|
+
import { collectLightMeshes } from './collectLightMeshes.js';
|
|
5
|
+
|
|
6
|
+
export function updatePointLights(backend) {
|
|
7
|
+
const { device, sunlight: sun } = backend.renderer;
|
|
8
|
+
const fixed = [], moving = [];
|
|
9
|
+
let layer;
|
|
10
|
+
for (layer of backend._layers) {
|
|
11
|
+
if (!layer.options.nightLight || !layer.root.visible) continue;
|
|
12
|
+
collectLightMeshes(layer.root, fixed, moving);
|
|
13
|
+
}
|
|
14
|
+
const maxBytes = device.limits.maxStorageBufferBindingSize;
|
|
15
|
+
const staticGrid = cacheLightGrid(fixed, sun.staticLightGrid, maxBytes);
|
|
16
|
+
const dynamicGrid = cacheLightGrid(moving, sun.dynamicLightGrid, maxBytes);
|
|
17
|
+
if (staticGrid === sun.staticLightGrid && dynamicGrid === sun.dynamicLightGrid) return;
|
|
18
|
+
const size = staticGrid.data.byteLength + dynamicGrid.data.byteLength;
|
|
19
|
+
if (size > maxBytes) throw new Error('Streetlight grid exceeds GPU storage limit');
|
|
20
|
+
let uploadStatic = staticGrid !== sun.staticLightGrid;
|
|
21
|
+
if (sun.lights.size < size) {
|
|
22
|
+
destroyTexture(backend, sun.lights);
|
|
23
|
+
sun.lights = device.createBuffer({ size, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST });
|
|
24
|
+
bindSunlight(backend);
|
|
25
|
+
uploadStatic = true;
|
|
26
|
+
}
|
|
27
|
+
// The spare header component points to a second grid in the same storage binding.
|
|
28
|
+
staticGrid.data[6] = staticGrid.data.length / 4;
|
|
29
|
+
if (uploadStatic) device.queue.writeBuffer(sun.lights, 0, staticGrid.data);
|
|
30
|
+
device.queue.writeBuffer(sun.lights, staticGrid.data.byteLength, dynamicGrid.data);
|
|
31
|
+
sun.lightCount = staticGrid.count + dynamicGrid.count;
|
|
32
|
+
sun.staticLightGrid = staticGrid;
|
|
33
|
+
sun.dynamicLightGrid = dynamicGrid;
|
|
34
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function visitCells(packed, minX, minZ, cellSize, columns, offsets, data) {
|
|
2
|
+
let values, i, radius, x, z, y, c, key, j, o;
|
|
3
|
+
for (values of packed) for (i = 0; i < values.length; i += 8) {
|
|
4
|
+
radius = values[i + 3], x = values[i] - minX, z = values[i + 2] - minZ;
|
|
5
|
+
for (y = Math.floor((z - radius) / cellSize); y <= Math.floor((z + radius) / cellSize); y++) {
|
|
6
|
+
for (c = Math.floor((x - radius) / cellSize); c <= Math.floor((x + radius) / cellSize); c++) {
|
|
7
|
+
key = y * columns + c;
|
|
8
|
+
if (data) {
|
|
9
|
+
for (j = 0, o = offsets[key] * 4; j < 8; j++) data[o + j] = values[i + j];
|
|
10
|
+
offsets[key] += 2;
|
|
11
|
+
} else offsets[key]++;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
|
|
2
|
+
/** World-space [x, y, z, radius, r, g, b, intensity] for one mesh's point lights. */
|
|
3
|
+
export function worldLights(lights, m) {
|
|
4
|
+
const values = new Float32Array(lights.length * 8);
|
|
5
|
+
let i, x, y, z, radius, color, flux, w;
|
|
6
|
+
for (i = 0; i < lights.length; i++) {
|
|
7
|
+
({
|
|
8
|
+
position: [x, y, z],
|
|
9
|
+
radius,
|
|
10
|
+
color,
|
|
11
|
+
flux
|
|
12
|
+
} = lights[i]);
|
|
13
|
+
w = m[3] * x + m[7] * y + m[11] * z + m[15];
|
|
14
|
+
values.set(
|
|
15
|
+
[
|
|
16
|
+
(m[0] * x + m[4] * y + m[8] * z + m[12]) / w,
|
|
17
|
+
(m[1] * x + m[5] * y + m[9] * z + m[13]) / w,
|
|
18
|
+
(m[2] * x + m[6] * y + m[10] * z + m[14]) / w,
|
|
19
|
+
radius,
|
|
20
|
+
...color,
|
|
21
|
+
flux / (4 * Math.PI) * 0.03
|
|
22
|
+
],
|
|
23
|
+
i * 8
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
return values;
|
|
27
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** Decode a static glTF JSON document or GLB v2 container. */
|
|
2
|
+
import { hasUnsupportedPrimitives } from './hasUnsupportedPrimitives.js';
|
|
3
|
+
|
|
4
|
+
export function decodeModel(data) {
|
|
5
|
+
const view = new DataView(data), decoder = new TextDecoder();
|
|
6
|
+
let description;
|
|
7
|
+
let offset, length, type, chunk;
|
|
8
|
+
if (view.getUint32(0, true) === 0x46546c67) {
|
|
9
|
+
// Decode GLB v2 chunks; unknown types are skipped.
|
|
10
|
+
if (view.getUint32(4, true) !== 2 || view.getUint32(8, true) !== data.byteLength) {
|
|
11
|
+
throw new Error('Invalid GLB header');
|
|
12
|
+
}
|
|
13
|
+
let binary;
|
|
14
|
+
for (offset = 12; offset < data.byteLength;) {
|
|
15
|
+
if (offset + 8 > data.byteLength) {
|
|
16
|
+
throw new Error('Truncated GLB chunk');
|
|
17
|
+
}
|
|
18
|
+
length = view.getUint32(offset, true), type = view.getUint32(offset + 4, true);
|
|
19
|
+
offset += 8;
|
|
20
|
+
if (offset + length > data.byteLength) {
|
|
21
|
+
throw new Error('Truncated GLB data');
|
|
22
|
+
}
|
|
23
|
+
chunk = data.slice(offset, offset + length);
|
|
24
|
+
if (type === 0x4e4f534a) {
|
|
25
|
+
description = JSON.parse(decoder.decode(chunk));
|
|
26
|
+
}
|
|
27
|
+
if (type === 0x004e4942) {
|
|
28
|
+
binary = chunk;
|
|
29
|
+
}
|
|
30
|
+
offset += length;
|
|
31
|
+
}
|
|
32
|
+
if (!description) {
|
|
33
|
+
throw new Error('Missing GLB JSON');
|
|
34
|
+
}
|
|
35
|
+
if (binary) {
|
|
36
|
+
description.buffers[0].binary = binary;
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
description = JSON.parse(decoder.decode(data));
|
|
40
|
+
}
|
|
41
|
+
if (description.skins?.length || description.animations?.length || description.extensionsRequired?.length || hasUnsupportedPrimitives(description.meshes)) {
|
|
42
|
+
throw new Error('Layer3D supports static triangle glTF models without required extensions');
|
|
43
|
+
}
|
|
44
|
+
return description;
|
|
45
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function hasUnsupportedPrimitives(meshes) {
|
|
2
|
+
if (!meshes) return false;
|
|
3
|
+
let mesh, primitive;
|
|
4
|
+
for (mesh of meshes) {
|
|
5
|
+
for (primitive of mesh.primitives) {
|
|
6
|
+
if (primitive.targets || (primitive.mode !== undefined && primitive.mode !== 4)) return true;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export async function loadBuffer(buffer, directory) {
|
|
2
|
+
if (buffer.binary) return;
|
|
3
|
+
const response = await fetch(new URL(buffer.uri, directory).href);
|
|
4
|
+
if (!response.ok) throw new Error(`Unable to load model buffer: HTTP ${response.status}`);
|
|
5
|
+
buffer.binary = await response.arrayBuffer();
|
|
6
|
+
}
|