Add 3D Model BabylonJS
Use a custom style layer with babylon.js to add a 3D model to the map. Requires Trimble Maps v4.0.0 or later.<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Add a 3D model with babylon.js</title> <link rel="stylesheet" href="https://maps-sdk.trimblemaps.com/v4/trimblemaps-4.2.1.css" /> <script src="https://maps-sdk.trimblemaps.com/v4/trimblemaps-4.2.1.js"></script> <style> body { margin: 0; padding: 0; } html, body, #map { height: 100%; } </style> </head> <body> <script src="https://unpkg.com/babylonjs@5.42.2/babylon.js"></script> <script src="https://unpkg.com/babylonjs-loaders@5.42.2/babylonjs.loaders.min.js"></script> <div id="map"></div> <script> const BABYLON = window.BABYLON; TrimbleMaps.setAPIKey("68B06901AF7DA34884CE5FB7A202A743"); const map = (window.map = new TrimbleMaps.Map({ container: "map", style: TrimbleMaps.Common.Style.TRANSPORTATION, zoom: 18, center: [148.9819, -35.3981], pitch: 60, antialias: true, // create the gl context with MSAA antialiasing, so custom layers are antialiased })); // World matrix parameters const worldOrigin = [148.9819, -35.39847]; const worldAltitude = 0; // Trimblemaps.js default coordinate system (no rotations) // +x east, -y north, +z up //var worldRotate = [0, 0, 0]; // Babylon.js default coordinate system // +x east, +y up, +z north const worldRotate = [Math.PI / 2, 0, 0]; // Calculate mercator coordinates and scale const worldOriginMercator = TrimbleMaps.MercatorCoordinate.fromLngLat(worldOrigin, worldAltitude); const worldScale = worldOriginMercator.meterInMercatorCoordinateUnits(); // Calculate world matrix const worldMatrix = BABYLON.Matrix.Compose( new BABYLON.Vector3(worldScale, worldScale, worldScale), BABYLON.Quaternion.FromEulerAngles(worldRotate[0], worldRotate[1], worldRotate[2]), new BABYLON.Vector3(worldOriginMercator.x, worldOriginMercator.y, worldOriginMercator.z), ); // configuration of the custom layer for a 3D model per the CustomLayerInterface const customLayer = { id: "3d-model", type: "custom", renderingMode: "3d", onAdd(map, gl) { this.engine = new BABYLON.Engine( gl, true, { useHighPrecisionMatrix: true, // Important to prevent jitter at mercator scale }, true, ); this.scene = new BABYLON.Scene(this.engine); this.scene.autoClear = false; this.scene.detachControl(); this.scene.beforeRender = () => { this.engine.wipeCaches(true); }; // create simple camera (will have its project matrix manually calculated) this.camera = new BABYLON.Camera("Camera", new BABYLON.Vector3(0, 0, 0), this.scene); // create simple light const light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 0, 100), this.scene); light.intensity = 0.7; // Add debug axes viewer, positioned at origin, 10 meter axis lengths new BABYLON.AxesViewer(this.scene, 10); // load GLTF model in to the scene BABYLON.SceneLoader.LoadAssetContainerAsync("/docs/assets/34M_17/34M_17.gltf", "", this.scene).then((modelContainer) => { modelContainer.addAllToScene(); const rootMesh = modelContainer.createRootMesh(); // If using trimblemaps.js coordinate system (+z up) //rootMesh.rotation.x = Math.PI/2 // Create a second mesh const rootMesh2 = rootMesh.clone(); // Position in babylon.js coordinate system rootMesh2.position.x = 25; // +east, meters rootMesh2.position.z = 25; // +north, meters }); this.map = map; }, render(gl, matrix) { const cameraMatrix = BABYLON.Matrix.FromArray(matrix); // world-view-projection matrix const wvpMatrix = worldMatrix.multiply(cameraMatrix); this.camera.freezeProjectionMatrix(wvpMatrix); this.scene.render(false); this.map.triggerRepaint(); }, }; map.on("style.load", () => { map.addLayer(customLayer); }); </script> </body> </html>
Add 3D Model BabylonJS
<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Add a 3D model with babylon.js</title> <link rel="stylesheet" href="https://maps-sdk.trimblemaps.com/v4/trimblemaps-4.2.1.css" /> <script src="https://maps-sdk.trimblemaps.com/v4/trimblemaps-4.2.1.js"></script> <style> body { margin: 0; padding: 0; } html, body, #map { height: 100%; } </style> </head> <body> <script src="https://unpkg.com/babylonjs@5.42.2/babylon.js"></script> <script src="https://unpkg.com/babylonjs-loaders@5.42.2/babylonjs.loaders.min.js"></script> <div id="map"></div> <script> const BABYLON = window.BABYLON; TrimbleMaps.setAPIKey("68B06901AF7DA34884CE5FB7A202A743"); const map = (window.map = new TrimbleMaps.Map({ container: "map", style: TrimbleMaps.Common.Style.TRANSPORTATION, zoom: 18, center: [148.9819, -35.3981], pitch: 60, antialias: true, // create the gl context with MSAA antialiasing, so custom layers are antialiased })); // World matrix parameters const worldOrigin = [148.9819, -35.39847]; const worldAltitude = 0; // Trimblemaps.js default coordinate system (no rotations) // +x east, -y north, +z up //var worldRotate = [0, 0, 0]; // Babylon.js default coordinate system // +x east, +y up, +z north const worldRotate = [Math.PI / 2, 0, 0]; // Calculate mercator coordinates and scale const worldOriginMercator = TrimbleMaps.MercatorCoordinate.fromLngLat(worldOrigin, worldAltitude); const worldScale = worldOriginMercator.meterInMercatorCoordinateUnits(); // Calculate world matrix const worldMatrix = BABYLON.Matrix.Compose( new BABYLON.Vector3(worldScale, worldScale, worldScale), BABYLON.Quaternion.FromEulerAngles(worldRotate[0], worldRotate[1], worldRotate[2]), new BABYLON.Vector3(worldOriginMercator.x, worldOriginMercator.y, worldOriginMercator.z), ); // configuration of the custom layer for a 3D model per the CustomLayerInterface const customLayer = { id: "3d-model", type: "custom", renderingMode: "3d", onAdd(map, gl) { this.engine = new BABYLON.Engine( gl, true, { useHighPrecisionMatrix: true, // Important to prevent jitter at mercator scale }, true, ); this.scene = new BABYLON.Scene(this.engine); this.scene.autoClear = false; this.scene.detachControl(); this.scene.beforeRender = () => { this.engine.wipeCaches(true); }; // create simple camera (will have its project matrix manually calculated) this.camera = new BABYLON.Camera("Camera", new BABYLON.Vector3(0, 0, 0), this.scene); // create simple light const light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 0, 100), this.scene); light.intensity = 0.7; // Add debug axes viewer, positioned at origin, 10 meter axis lengths new BABYLON.AxesViewer(this.scene, 10); // load GLTF model in to the scene BABYLON.SceneLoader.LoadAssetContainerAsync("/docs/assets/34M_17/34M_17.gltf", "", this.scene).then((modelContainer) => { modelContainer.addAllToScene(); const rootMesh = modelContainer.createRootMesh(); // If using trimblemaps.js coordinate system (+z up) //rootMesh.rotation.x = Math.PI/2 // Create a second mesh const rootMesh2 = rootMesh.clone(); // Position in babylon.js coordinate system rootMesh2.position.x = 25; // +east, meters rootMesh2.position.z = 25; // +north, meters }); this.map = map; }, render(gl, matrix) { const cameraMatrix = BABYLON.Matrix.FromArray(matrix); // world-view-projection matrix const wvpMatrix = worldMatrix.multiply(cameraMatrix); this.camera.freezeProjectionMatrix(wvpMatrix); this.scene.render(false); this.map.triggerRepaint(); }, }; map.on("style.load", () => { map.addLayer(customLayer); }); </script> </body> </html>