I'm trying to get my 3D object to move in my Mapbox created scene. I'm using a custom layer to create my object on the map with Three.js, as shown in the following code:
var map = action.map;
var orign = {
lon: -8.34,
lat: 41.21
}
var camera, scene;
var fromLL = function (lon, lat) {
var extent = 20037508.34;
var x = lon * extent / 180;
var y = Math.log(Math.tan((90 + lat) * Math.PI / 360)) / (Math.PI / 180);
y = y * extent / 180;
return [(x + extent) / (2 * extent), 1 - ((y + extent) / (2 * extent))];
}
var translate = fromLL(orign.lon, orign.lat);
const transform = {
translateX: translate[0],
translateY: translate[1],
translateZ: 0,
rotateX: Math.PI / 2,
rotateY: 0,
rotateZ: 0,
scale: 5.41843220338983e-6
}
// configuration of the custom layer for a 3D model per the CustomLayerInterface
var customLayer = {
id: '3d-model' + uuid(),
type: 'custom',
renderingMode: '3d',
onAdd: function (map, gl) {
this.camera = new THREE.Camera();
this.scene = new THREE.Scene();
// create two three.js lights to illuminate the model
var directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set(0, -70, 100).normalize();
this.scene.add(directionalLight);
var directionalLight2 = new THREE.DirectionalLight(0xffffff);
directionalLight2.position.set(0, 70, 100).normalize();
this.scene.add(directionalLight2);
// use the three.js GLTF loader to add the 3D model to the three.js scene
var loader = new GLTFLoader();
const bus = 'https://threejsfundamentals.org/threejs/resources/models/animals/Horse.gltf';
loader.load(
bus,
(gltf) => {
this.scene.add(gltf.scene);
},
(xhr) => {
console.log(`${(xhr.loaded / xhr.total * 100)}% loaded`);
},
(error) => {
// called when loading has errors
console.error('An error happened', error);
}
);
this.map = map;
// use the Mapbox GL JS map canvas for three.js
this.renderer = new THREE.WebGLRenderer({
canvas: map.getCanvas(),
context: gl,
antialias: true
});
this.renderer.autoClear = false;
},
render: function (gl, matrix) {
const rotationX = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(1, 0, 0), transform.rotateX);
const rotationY = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 1, 0), transform.rotateY);
const rotationZ = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 0, 1), transform.rotateZ);
const m = new THREE.Matrix4().fromArray(matrix);
const l = new THREE.Matrix4().makeTranslation(transform.translateX, transform.translateY, transform.translateZ)
.scale(new THREE.Vector3(transform.scale, -transform.scale, transform.scale))
.multiply(rotationX)
.multiply(rotationY)
.multiply(rotationZ);
this.camera.projectionMatrix.elements = matrix;
this.camera.projectionMatrix = m.multiply(l);
this.renderer.state.reset();
this.renderer.render(this.scene, this.camera);
this.map.triggerRepaint();
}
}
The next step I'm taking after putting my object in the scene is to use the methods provided for Mapbox to control the camera. My doubt is how to make the "setInterval" function change the positioning values of my previously rendered object and not only the camera on the map, through the "WASD" keys. Below is the code used that I am trying to adapt for the movement of my object:
map.on('load', function () {
map.addLayer(customLayer);
var keys = {};
window.onkeyup = function (e) { keys[e.keyCode] = false; }
window.onkeydown = function (e) { keys[e.keyCode] = true; }
var heading = 180;
setInterval(function () {
var speed = 0;
if (keys[68]) {
heading += 2;
}
if (keys[65]) {
heading -= 2;
}
if (keys[87]) {
speed = 0.0002;
}
if (keys[83]) {
speed = -0.0002;
}
var rad = heading * 0.0174532925;
orign.lat += Math.cos(rad) * speed;
orign.lon += Math.sin(rad) * speed;
map.setBearing(heading);
map.setCenter([orign.lon, orign.lat]);
}, 1000 / 60);
});
So far what I have is this: 3D Object in map