TrackAsiaTrackAsia GL JS DocsExamplesAdd a 3D model with babylon.js

Add a 3D model with babylon.js

Use a custom style layer with babylon.js to add a 3D model to the map.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Add a 3D model with babylon.js</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://unpkg.com/trackasia-gl@1.0.5/dist/trackasia-gl.js"></script>
<link href="https://unpkg.com/trackasia-gl@1.0.5/dist/trackasia-gl.css" rel="stylesheet" />
<style>
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 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>
var BABYLON = window.BABYLON;
var map = (window.map = new trackasiagl.Map({
container: 'map',
style: 'https://maps.track-asia.com/styles/v1/streets.json?key=public_key',
zoom: 18,
center: {"lat":10.762622,"lng":106.660172},
pitch: 60,
antialias: true // create the gl context with MSAA antialiasing, so custom layers are antialiased
}));
// World matrix parameters
var worldOrigin = [106.660172, 10.762422];
var worldAltitude = 0;
// Trackasia.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
var worldRotate = [Math.PI / 2, 0, 0];
// Calculate mercator coordinates and scale
var worldOriginMercator = trackasiagl.MercatorCoordinate.fromLngLat(
worldOrigin,
worldAltitude
);
const worldScale = worldOriginMercator.meterInMercatorCoordinateUnits();
// Calculate world matrix
var 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
var customLayer = {
id: '3d-model',
type: 'custom',
renderingMode: '3d',
onAdd: function (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(
'https://docs.track-asia.com/assets/34M_17/34M_17.gltf',
'',
this.scene
).then((modelContainer) => {
modelContainer.addAllToScene();
const rootMesh = modelContainer.createRootMesh();
// If using trackasia.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: function (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', function () {
map.addLayer(customLayer);
});
</script>
</body>
</html>