mapbox-gl-js
mapbox-gl-js copied to clipboard
Unable to implement THREEjs Transform Control
mapbox-gl-js version is 2.6.1:
Question
I'd like to implement transformcontrol threejs in mapbox. First I add cube to the scene and attach it to the control. In current mapbox I have some other layer, Icon, 3d building etc. The problem is I can't hover transformcontrol threejs properly and can't move the cube. Seems this happened because layer of mapbox.
Links to related documentation
export class ModelLayerAOA implements mapboxgl.CustomLayerInterface {
constructor(options: SpriteOption) {
this.modelOrigin = options.origin;
this.modelAltitude = options.altitude;
this.onLoad = options.onLoad;
this.id = options.id;
this.type = 'custom';
this.renderingMode = '3d';
this.color = options.color;
const rotate = [Math.PI / 2, THREE.MathUtils.degToRad(options.rotateY), 0];
const mercator = mapboxgl.MercatorCoordinate.fromLngLat(
this.modelOrigin,
this.modelAltitude,
);
const scale = mercator.meterInMercatorCoordinateUnits();
this.modelTransform = {
translateX: mercator.x,
translateY: mercator.y,
translateZ: mercator.z ?? 0,
rotateX: rotate[0],
rotateY: rotate[1],
rotateZ: rotate[2],
scale,
};
}
async onAdd(map: mapboxgl.Map, gl: WebGLRenderingContext) {
this.map = map;
this.camera = new THREE.PerspectiveCamera(75);
this.camera.position.z = 1;
this.scene = new THREE.Scene();
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
this.scene.add(ambientLight);
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({
color: 0x00ff00,
transparent: true,
opacity: 0.3,
});
this.renderer = new THREE.WebGLRenderer({
canvas: map.getCanvas(),
context: gl,
antialias: true,
});
if (this.renderer?.domElement && this.camera) {
this.transformControl = new TransformControls(
this.camera,
this.renderer?.domElement,
);
this.transformControl.size = 5;
this.transformControl.addEventListener('change', this.updateRender);
}
const cube = new THREE.Mesh(geometry, material);
let pos = new THREE.Vector3();
cube.getWorldPosition(pos);
this.model = cube;
this.renderer.autoClear = false;
this.addTransformControl();
}
addTransformControl = () => {
if (this.transformControl && this.model) {
this.transformControl?.attach(this.model);
this.scene?.add(this.transformControl);
this.scene?.add(this.model);
}
};
onRemove(map: mapboxgl.Map) {
map.removeLayer(this.id);
if (this.model) {
this.scene?.remove(this.model);
}
this.camera?.clear();
this.scene?.clear();
}
render(gl: WebGLRenderingContext, matrix: number[]) {
const modelTransform = this.modelTransform;
const rotationX = new THREE.Matrix4().makeRotationAxis(
new Vector3(1, 0, 0),
modelTransform.rotateX,
);
const rotationY = new THREE.Matrix4().makeRotationAxis(
new Vector3(0, 1, 0),
modelTransform.rotateY,
);
const rotationZ = new THREE.Matrix4().makeRotationAxis(
new Vector3(0, 0, 1),
modelTransform.rotateZ,
);
const m = new THREE.Matrix4().fromArray(matrix);
const l = new THREE.Matrix4()
.makeTranslation(
modelTransform.translateX,
modelTransform.translateY,
modelTransform.translateZ,
)
.scale(
new Vector3(
modelTransform.scale,
-modelTransform.scale,
modelTransform.scale,
),
)
.multiply(rotationX)
.multiply(rotationY)
.multiply(rotationZ);
if (this.camera && this.scene && this.map) {
this.camera.projectionMatrix.elements = matrix;
this.camera.projectionMatrix = m.multiply(l);
this.renderer?.resetState();
this.updateRender();
this.map.triggerRepaint();
}
}
updateRender = () => {
if (this.scene && this.camera) {
this.renderer?.render(this.scene, this.camera);
}
};
}
Can you please provide a live reproducible test case?
I am closing this issue due to inactivity. Please feel free to re-open with a minimal reproducible code example with jsbin or codepen. Thanks
@suryakumara Did you have solution? I have same problem :((
I have no Idea to solve this..sp I open 2 viewer threejs and mapbox. if you want to transform any 3d. @Amela-Son
@suryakumara In my case, I display model location at specific location on map. So if load 2 viewer, it is not correct about coordinate. Do you have any suggest for my case :((
@Amela-Son You can make a function to convert Geolocation + altitude to 3D world coordinate.
@suryakumara Do you have any example about this. I try but it not work