viewof mapboxMap = {
const container = html`<div style="height:500px; width: 800px">`;
yield container;
const floormaterial = new THREE.MeshPhongMaterial({
color: 0xffff00,
opacity: 1,
side: THREE.DoubleSide
});
const shadowmaterial = new THREE.ShadowMaterial({
side: THREE.DoubleSide
});
shadowmaterial.opacity = 1;
const meshCache = {};
viewof elevationOffset.addEventListener("input", () => {
tb.world.children.forEach((model) => {
if (model.userData.name !== "terrain") return;
const newOffset = viewof elevationOffset.value;
const slippyTile = model.userData.slippyTile;
const coords = meshCache[slippyTile].tileStartingCoord;
const newElevation =
coords[2] - meshCache[slippyTile].originalElevationOffset + newOffset;
model.setCoords([coords[0], coords[1], newElevation]);
});
tb.update();
});
const map = new mapboxgl.Map({
container: container,
style: "mapbox://styles/mapbox/satellite-v9",
zoom: 18,
center: [148.9819, -35.39847],
pitch: 60,
transformRequest: (url, resourceType) => {
if (url.includes("mapbox.mapbox-terrain-dem-v1/")) {
const slippyTile = url.split("mapbox-terrain-dem-v1/")[1].split(".")[0];
if (meshCache[slippyTile]) return;
const curMaxMeshError = maxMeshError === -1 ? undefined : maxMeshError;
createMeshForSlippyTile({
slippyTile,
maxMeshError: curMaxMeshError,
elevationOffset: viewof elevationOffset.value,
terrainExaggeration: terrainExaggeration,
mapboxAccessToken: mapboxgl.accessToken
}).then((res) => {
const { geometry, tileStartingCoord } = res;
meshCache[slippyTile] = {
slippyTile,
tileStartingCoord,
originalElevationOffset: viewof elevationOffset.value
};
const selectedMaterial =
shadowMeshMaterial === "Transparent"
? shadowmaterial
: floormaterial;
let threeMesh = new THREE.Mesh(geometry, selectedMaterial);
threeMesh = tb.Object3D({
obj: threeMesh,
units: "meters",
name: "terrain",
slippyTile: slippyTile
});
threeMesh.setRotation({ y: 0, x: 0, z: 90 });
threeMesh.receiveShadow = true;
threeMesh.castShadow = false;
threeMesh.setCoords(tileStartingCoord);
tb.add(threeMesh);
tb.update();
});
}
},
antialias: true
});
map.addControl(new mapboxgl.NavigationControl());
const tb = (window.tb = new Threebox.Threebox(
map,
map.getCanvas().getContext("webgl"),
{
realSunlight: true,
sky: true,
terrain: true
}
));
let model;
const modelOrigin = [148.9819, -35.39847, 659];
let date = new Date("04-27-2023");
let time =
date.getHours() * 3600 + date.getMinutes() * 60 + date.getSeconds();
container.value = date;
viewof timeSlider.addEventListener("input", () => {
time = +viewof timeSlider.value;
date.setHours(Math.floor(time / 60 / 60));
date.setMinutes(Math.floor(time / 60) % 60);
date.setSeconds(time % 60);
container.value = date;
container.dispatchEvent(new Event("input", { bubbles: true }));
map.triggerRepaint();
});
async function createCustomLayer(layerName, origin) {
const url = await FileAttachment("34M_17.glb").url();
let model;
let customLayer3D = {
id: layerName,
type: "custom",
renderingMode: "3d",
onAdd: function (map, gl) {
let options = {
type: "gltf",
mtl: "https://cdn.jsdelivr.net/npm/threebox-plugin@2.2.7/examples/models/radar/",
obj: url,
units: "meters",
scale: 333.22,
rotation: { x: 90, y: 180, z: 0 },
anchor: "center"
};
tb.loadObj(options, function (model) {
model.setCoords(origin);
model.addTooltip("A radar in the middle of nowhere", true);
tb.add(model);
model.castShadow = true;
tb.lights.dirLight.target = model;
});
},
render: function (gl, matrix) {
tb.setSunlight(date, origin);
tb.update();
}
};
return customLayer3D;
}
map.on("load", async function () {
const customLayer = await createCustomLayer("3d-model", modelOrigin);
map.addLayer(customLayer);
});
invalidation.then(() => map.remove());
}