我正在this example之后的Mapbox GL JS页面中使用Three.js渲染一些自定义图层。我想添加光线投射以确定用户单击了哪个对象。
问题在于,我只能从Mapbox获得一个投影矩阵,用于渲染场景:
class CustomLayer {
type = 'custom';
renderingMode = '3d';
onAdd(map,gl) {
this.map = map;
this.camera = new THREE.Camera();
this.renderer = new THREE.WebGLRenderer({
canvas: map.getcanvas(),context: gl,antialias: true,});
this.scene = new THREE.Scene();
// ...
}
render(gl,matrix) {
this.camera.projectionmatrix = new THREE.Matrix4()
.fromArray(matrix)
.multiply(this.cameraTransform);
this.renderer.state.reset();
this.renderer.render(this.scene,this.camera);
}
}
这很好渲染,并且可以在平移/旋转/缩放地图时跟踪视图的变化。
不幸的是,当我尝试添加光线投射时,出现错误:
raycast(point) {
var mouse = new THREE.Vector2();
mouse.x = ( point.x / this.map.transform.width ) * 2 - 1;
mouse.y = 1 - ( point.y / this.map.transform.height ) * 2;
const raycaster = new THREE.Raycaster();
raycaster.setfromCamera(mouse,this.camera);
console.log(raycaster.intersectObjects(this.scene.children,true));
}
这给了我一个例外:
THREE.Raycaster: Unsupported camera type.
我可以从通用THREE.Camera
更改为THREE.PerspectiveCamera
,而不会影响场景的渲染:
this.camera = new THREE.PerspectiveCamera(28,window.innerWidth / window.innerHeight,0.1,1e6);
这可以修复异常,但也不会导致记录任何对象。稍微挖掘一下可以发现相机的projectionmatrixInverse
就是所有NaN
了,我们可以通过计算来解决:
raycast(point) {
var mouse = new THREE.Vector2();
mouse.x = ( point.x / this.map.transform.width ) * 2 - 1;
mouse.y = 1 - ( point.y / this.map.transform.height ) * 2;
this.camera.projectionmatrixInverse.getInverse(this.camera.projectionmatrix); // <--
const raycaster = new THREE.Raycaster();
raycaster.setfromCamera(mouse,true));
}
现在,无论单击何处,我都会得到两个相交点,分别是立方体的两个面。他们的距离是0:
[
{ distance: 0,faceIndex: 10,point: Vector3 { x: 0,y: 0,z: 0 },uv: Vector2 {x: 0.5,y: 0.5},... },{ distance: 0,faceIndex: 11,]
很明显,这里有些东西行不通。从code for setCamera
看,它涉及projectionmatrix
和matrixWorld
。有没有一种方法我可以设置matrixWorld
或仅使用投影矩阵直接构造光线投射器的光线?看来我只需要投影矩阵即可渲染场景,所以我希望它也将是我投射光线的全部。
完整示例in this codepen。