Animate Azure Maps

Hey guys,

I’m just getting started in 3d web developement and think babylon.js is a great starting point.

My overall goal is to animate an object on a map along a path using real world data with Azure Maps.

I already modified the original sample code to make it possible to have animations:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Babylon custom WebGL layer - Azure Maps Web SDK Samples</title>

    <meta charset="utf-8" />
    <link rel="shortcut icon" href="/favicon.ico" />

    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
    <meta name="description" content="This sample shows how to create a custom 3D layer with Babylon.js." />
    <meta name="keywords" content="3D, Microsoft maps, map, gis, API, SDK, thematic, choropleth, heatmap, heat map, animation, animate, animations, county, population, data-driven, data driven styling, temporal, temporal analysis" />
    <meta name="author" content="Microsoft Azure Maps" />
    <meta name="screenshot" content="screenshot.jpg" />

    <!-- Add references to the Azure Maps Map control JavaScript and CSS files. -->
    <link href="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.css" rel="stylesheet" />
    <script src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.js"></script>

    <!-- Babylon.js is a powerful, simple, real-time 3D and open game and rendering engine packed into a friendly framework, which Microsoft initially developed. -->
    <script src="https://cdn.babylonjs.com/babylon.js"></script>
    <script src="https://cdn.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>

    <script>
        var map, layer;

        // parameters to ensure the model is georeferenced correctly on the map
        const worldOrigin = [148.9819, -35.39847];
        const worldAltitude = 0;
        const worldRotate = [Math.PI / 2, 0, 0];
        const worldCoords = atlas.data.MercatorPoint.fromPosition([...worldOrigin, worldAltitude]);
        console.log(worldCoords)
        const worldScale = 2 * atlas.data.MercatorPoint.meterInMercatorUnits(49.923718);

        var worldMatrix = BABYLON.Matrix.Compose(
            new BABYLON.Vector3(worldScale, worldScale, worldScale),
            BABYLON.Quaternion.FromEulerAngles(worldRotate[0], worldRotate[1], worldRotate[2]),
            new BABYLON.Vector3(worldCoords[0], worldCoords[1], worldCoords[2])
        );


        var mesh1, mesh2;

        async function animateMesh(scene) {
            //Create a scaling animation at 30 FPS
            var animationBox = new BABYLON.Animation("tutoAnimation", "position", 30, BABYLON.Animation.ANIMATIONTYPE_VECTOR3, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);

            let startPosition = atlas.data.MercatorPoint.fromPosition([...[148.9819, -35.39847], 0]);
            let endPosition = atlas.data.MercatorPoint.fromPosition([...[148.977732, -35.398451], 0]);
            console.log(startPosition);
            console.log(endPosition);

            // Animation keys
            var keys = [];
            keys.push({
                frame: 0,
                value: new BABYLON.Vector3(startPosition[0], startPosition[1], startPosition[2])
            });

            keys.push({
                frame: 100,
                value: new BABYLON.Vector3(endPosition[0], endPosition[1], endPosition[2])
            });

            animationBox.setKeys(keys);

            mesh1.animations.push(animationBox);

            setTimeout(async () => {
                let anim = scene.beginAnimation(mesh1, 0, 100, true);

                await anim.waitAsync();
                console.log("Animation finished")
            })
            
        }

        // Create a renderer that implements atlas.WebGLRenderer
        var renderer = {
            renderingMode: "3d",

            // Method called when the layer is added to the map
            onAdd: (map, gl) => {
                this.map = map;

                // Initialize the Babylon.js engine.
                const engine = new BABYLON.Engine(gl, true, { useHighPrecisionMatrix: true }, true);

                this.scene = new BABYLON.Scene(engine);
                this.scene.autoClear = false;
                this.scene.detachControl();
                this.scene.beforeRender = function () {
                    engine.wipeCaches(true);
                };
                this.camera = new BABYLON.Camera("camera", new BABYLON.Vector3(), this.scene);
                const light = new BABYLON.HemisphericLight("light", BABYLON.Vector3.One(), this.scene);

                new BABYLON.AxesViewer(this.scene, 10);

                BABYLON.SceneLoader.LoadAssetContainerAsync(
                    "./34m_17/",
                    "34M_17.gltf",
                    this.scene
                ).then((modelContainer) => {
                    modelContainer.addAllToScene();
                    mesh1 = modelContainer.createRootMesh();
                    animateMesh(this.scene);
                });
            },

            // Method called on each animation frame
            render: (gl, matrix) => {

                // projection & view matrix
                const cameraMatrix = BABYLON.Matrix.FromArray(matrix);
                const mvpMatrix = worldMatrix.multiply(cameraMatrix);
                this.camera.freezeProjectionMatrix(mvpMatrix);

                this.scene.render(false);
                this.map.triggerRepaint();
            }
        };

        function GetMap() {
            map = new atlas.Map("map", {
                zoom: 18,
                pitch: 60,
                center: [148.9819, -35.39847],
                //style: "satellite_road_labels",
                antialias: true,

                // Add authentication details for connecting to Azure Maps.
                authOptions: {
                    // Use an Azure Maps key. Get an Azure Maps key at https://azuremaps.com/. NOTE: The primary key should be used as the key.
                    authType: 'subscriptionKey',
                    subscriptionKey: 'mykey'
                }
            });

            // Wait until the map resources are ready
            map.events.add("ready", function () {
                // Create a WebGL layer
                layer = new atlas.layer.WebGLLayer("babylon", { renderer });
                // Add the layer to the map
                map.layers.add(layer);

                // Add controls
                map.controls.add(
                    [
                        new atlas.control.ZoomControl(),
                        new atlas.control.PitchControl(),
                        new atlas.control.CompassControl(),
                        new atlas.control.StyleControl({
                            mapStyles: "all"
                        })
                    ],
                    {
                        position: "top-right"
                    }
                );
            });
        }
    </script>
</head>
<body onload="GetMap()">
    <div id="map" style="position:relative;width:100%;min-width:290px;height:600px;background-color:gray"></div>

    <fieldset style="width:calc(100% - 30px);min-width:290px;margin-top:10px;">
        <legend>Babylon.js custome WebGL layer</legend>
        This sample shows how to render a 3D model using <a href="https://www.babylonjs.com/">babylon.js</a>.
        Babylon.js is a powerful, simple, real-time 3D and open game and rendering engine packed into a friendly framework, which Microsoft initially developed.
    </fieldset>
</body>
</html>

This works perfectly fine for changing the scale or rotation.

However, when I try to change the position by inputting real world coordinates (eg [148.977732, -35.398451]) , as seen in my code, the movement of the model is too small to be visible.
I already figured out that the reason for this is that the values in my vector are to small. Unfortunately I have no idea what steps I have to make to be able to work with real world coordinates.

I’m really grateful for any input!

Thanks a lot
David

There is probably a scale being applied within the map rendering. Could you check with the Azure maps folks ?

1 Like