3D models intersections
Use the MapTiler 3D JS module test whether a 3D model intersects another 3D model.
NPM module setup
npm install --save @maptiler/sdk @maptiler/3d three
import { Map, MapStyle, config } from '@maptiler/sdk';
import '@maptiler/sdk/dist/maptiler-sdk.css';
import { Layer3D, AltitudeReference } from '@maptiler/3d';
import * as THREE from 'three';
config.apiKey = 'YOUR_MAPTILER_API_KEY_HERE';
const center = [-11.40318, 21.12953];
const map = new Map({
container: document.getElementById('map'),
hash: true,
style: MapStyle.SATELLITE,
zoom: 12.63,
center: center,
pitch: 47,
maxPitch: 85,
terrainControl: true,
terrain: true,
maptilerLogo: true,
});
(async () => {
await map.onReadyAsync();
const layer3D = new Layer3D("item3d-intersections");
map.addLayer(layer3D);
// Adding a point light
layer3D.addPointLight("light", {
lngLat: [
center[0],
center[1],
],
intensity: 10,
decay: 0.1,
color: "#ffffff",
altitude: 6000,
});
// Adding a mesh.
const leftCubeMesh = new THREE.Mesh(new THREE.BoxGeometry(400, 400, 400), new THREE.MeshStandardMaterial({ color: "red", metalness: 0.25, roughness: 0.5 }));
leftCubeMesh.name = "static-cube-1";
const leftCubeItem3D = layer3D.addMesh("mesh1", leftCubeMesh, {
altitudeReference: AltitudeReference.MEAN_SEA_LEVEL,
lngLat: [
center[0] - 0.02,
center[1],
],
});
leftCubeItem3D.modify({
heading: 45,
altitude: 1000,
});
const movingItem3D = await layer3D.addMeshFromURL("duck", "https://docs-media.maptiler.com/docs/models/duck.glb", {
lngLat: center,
heading: 0,
scale: 180,
altitude: 950,
altitudeReference: AltitudeReference.MEAN_SEA_LEVEL,
});
const sphereRightMesh = new THREE.Mesh(new THREE.SphereGeometry(250, 32, 32), new THREE.MeshStandardMaterial({ color: "red", roughness: 0.5 }));
sphereRightMesh.name = "static-sphere";
const sphereRightItem3D = layer3D.addMesh("sphere", sphereRightMesh, {
lngLat: [
center[0] + 0.02,
center[1],
],
altitude: 1000,
altitudeReference: AltitudeReference.MEAN_SEA_LEVEL,
});
const itemLngLat = movingItem3D.lngLat;
let progress = 0;
addDebugCheckBox([leftCubeItem3D, movingItem3D, sphereRightItem3D]);
function loop() {
requestAnimationFrame(loop);
progress += 0.0005;
leftCubeItem3D.modify({
heading: 45,
altitude: 1000,
});
movingItem3D.modify({
lngLat: [
itemLngLat.lng + Math.sin(progress * Math.PI * 2) * 0.025,
itemLngLat.lat,
],
heading: progress * Math.PI * 100,
});
const mesh2IntersectsMesh1 = movingItem3D.intersects(leftCubeItem3D, "low");
const mesh2IntersectsMesh3 = movingItem3D.intersects(sphereRightItem3D, "low");
if (mesh2IntersectsMesh1) {
recursivelySetMaterialColor(leftCubeMesh, "green");
} else if (mesh2IntersectsMesh3) {
recursivelySetMaterialColor(sphereRightMesh, "blue");
} else {
recursivelySetMaterialColor(leftCubeMesh, "red");
recursivelySetMaterialColor(sphereRightMesh, "red");
}
}
loop();
})()
function recursivelySetMaterialColor(mesh, color) {
if (mesh instanceof THREE.Mesh) {
mesh.material.userData.oldMap = mesh.material.map;
mesh.material.map = null;
mesh.material.color.set(color);
} else if (mesh instanceof Group) {
mesh.traverse((node) => {
if (node instanceof THREE.Mesh) {
console.log(node);
node.material.userData.oldMap = node.material.map;
node.material.map = null;
node.material.color.set(color);
}
});
}
}
function addDebugCheckBox(objects) {
const checkbox = document.createElement("input");
checkbox.type = "checkbox";
const label = document.createElement("label");
label.style.position = "absolute";
label.style.top = "10px";
label.style.left = "10px";
label.style.zIndex = "1000";
label.style.background = "rgba(255,255,255,0.7)";
label.style.padding = "4px 8px";
label.style.borderRadius = "3px";
label.style.fontSize = "14px";
label.appendChild(checkbox);
label.appendChild(document.createTextNode(" Show debug bounds"));
checkbox.addEventListener("change", () => {
objects.forEach((object) => {
object.debug = checkbox.checked;
});
});
document.body.appendChild(label);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="robots" content="noindex">
<title>MapTiler 3D | Item3D Intersections</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div id="map"></div>
<script type="module" src="./main.js"></script>
</body>
</html>
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
COLLADA duck One texture Credit: © 2006, Sony. SCEA Shared Source License, Version 1.0 ↩