AzureMapsCodeSamples icon indicating copy to clipboard operation
AzureMapsCodeSamples copied to clipboard

Blazor 3D Integration

Open hernandoz opened this issue 1 year ago • 0 comments

Hi , I am trying to load a 3d model to azure maps in Blazor .net9 webassembly , I can load the maps ok , but I cannot get to load the 3 model, I am following this example https://github.com/Azure-Samples/AzureMapsCodeSamples/blob/main/Samples/3D-layer/three.js/three.js.html , but i am having problem converting the html code to blazer , I have created a map.js script that load the map fine but I dont how to create the render and add the layer to the map.

is there a blazor example available or can someone explain to me how to write a new script , sorry I am c# developer but never used JS before .

this the current script but i have an error on the loader: new GLTFLoader(), ReferenceError: GLTFLoader is not defined

//script map.js
var map, layer;

// 3D model to render
var modelDetails = {
    url: "/3d-layer/three.js/parrot.glb",
    origin: [-122.128929, 47.644042],
    mercatorOrigin: atlas.data.MercatorPoint.fromPosition([-122.128929, 47.644042]),
    rotateX: Math.PI / 2,
    rotateY: 0,
    rotateZ: 0,
    scale: 1e-7,
    animate: true
};

// Create a renderer that implements atlas.WebGLRenderer
var renderer = {
    renderingMode: "3d",
    loader: new GLTFLoader(),
    modelDetails: modelDetails,

    // Method called when the layer is added to the map
    onAdd: function (map, gl) {
        this.map = map;
        this.camera = new THREE.Camera();
        this.scene = new THREE.Scene();
        this.clock = new THREE.Clock();

        // Create lights to illuminate the model
        var directionalLight = new THREE.DirectionalLight(0xffffff);
        directionalLight.position.set(0, 70, 100).normalize();
        this.scene.add(directionalLight);

        var ambientLight = new THREE.AmbientLight(0x808080);
        this.scene.add(ambientLight);

        // Load the model
        this.loadModel();

        // Use the Azure Maps map canvas for three.js
        this.renderer = new THREE.WebGLRenderer({
            canvas: map.getCanvas(),
            context: gl
        });

        this.renderer.autoClear = false;
    },

    // Method called on each animation frame
    render: function (gl, matrix) {
        var md = this.modelDetails;

        if (md) {
            var rotationX = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(1, 0, 0), md.rotateX);
            var rotationY = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 1, 0), md.rotateY);
            var rotationZ = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 0, 1), md.rotateZ);

            var m = new THREE.Matrix4().fromArray(matrix);
            var l = new THREE.Matrix4()
                .makeTranslation(md.mercatorOrigin[0], md.mercatorOrigin[1], md.mercatorOrigin[2])
                .scale(new THREE.Vector3(md.scale, -md.scale, md.scale))
                .multiply(rotationX)
                .multiply(rotationY)
                .multiply(rotationZ);

            this.camera.projectionMatrix.elements = matrix;
            this.camera.projectionMatrix = m.multiply(l);
            this.renderer.resetState();
            this.renderer.render(this.scene, this.camera);
            this.renderer.resetState();
        }

        map.triggerRepaint();
    },

    loadModel: function () {
        var md = this.modelDetails;
        this.mixer = null;

        if (md) {
            // Use the three.js GLTF loader to add the 3D model to the three.js scene
            this.loader.load(
                md.url,
                function (gltf) {
                    this.gltfModelScene = gltf.scene;

                    this.scene.add(gltf.scene);

                    if (md.animate) {
                        this.mixer = new THREE.AnimationMixer(gltf.scene);
                        var action = this.mixer.clipAction(gltf.animations[0]);
                        action.play();

                        this.animate();
                    }
                }.bind(this)
            );

            this.map.setCamera({
                center: md.origin
            });
        }
    },

    animate: function () {
        if (this.mixer) {
            this.mixer.update(this.clock.getDelta());
            this.renderer.render(this.scene, this.camera);
            requestAnimationFrame(() => {
                this.animate();
            });
        }
    }
};


window.AzureMap = {
    map: null,
    layer: null,
    LoadMap: function (subKey, lat, long) {

        this.map = new atlas.Map("mapContainer", {
            authOptions: {
                authType: 'subscriptionKey',
                subscriptionKey: subKey
            },
            view: "Auto",
            center: [long, lat],
            zoom: 17.5

        });

        map.events.add("ready", function () {
            // Create a WebGL layer
            layer = new atlas.layer.WebGLLayer("3d-model", { 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"
                }
            );
        });
    }
}

thanks for your help.

hernandoz avatar Jan 23 '25 17:01 hernandoz