A Pen by Aleksandar Stojiljković on CodePen.
Created
November 8, 2021 05:26
-
-
Save gk525152097/982dbd370bbbe4692004e9e999f47bf8 to your computer and use it in GitHub Desktop.
Mapbox THREE.js raycaster test
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div id="map"></div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This codepen attempts to use THREE.js's raycaster with a Mapbox custom layer. If I've done things correctly, | |
// hovering over the cube should turn it red. It seems though that the intersection is never detected. | |
// See: https://github.com/mapbox/mapbox-gl-js/issues/10595 | |
mapboxgl.accessToken = 'pk.eyJ1IjoibmFnaXgiLCJhIjoiY2treGZoNzY5MHE1OTJ4bzQ5NmYyY2twNiJ9.ZX7a6VWavDoOMbDoRR7IOg'; | |
var map = new mapboxgl.Map({ | |
container: 'map', | |
zoom: 14, | |
center: [139.7670, 35.6814], | |
pitch: 30, | |
style: 'mapbox://styles/mapbox/streets-v10' | |
}); | |
const mouse = new THREE.Vector4(-1000, -1000, 1, 1); | |
// parameters to ensure the model is georeferenced correctly on the map | |
var modelOrigin = [139.7670, 35.6814]; | |
var modelAltitude = 150; | |
var modelAsMercatorCoordinate = mapboxgl.MercatorCoordinate.fromLngLat( | |
modelOrigin, | |
modelAltitude | |
); | |
// transformation parameters to position, rotate and scale the 3D model onto the map | |
var modelTransform = { | |
translateX: modelAsMercatorCoordinate.x, | |
translateY: modelAsMercatorCoordinate.y, | |
translateZ: modelAsMercatorCoordinate.z, | |
/* Since our 3D model is in real world meters, a scale transform needs to be | |
* applied since the CustomLayerInterface expects units in MercatorCoordinates. | |
*/ | |
scale: modelAsMercatorCoordinate.meterInMercatorCoordinateUnits() | |
}; | |
// configuration of the custom layer for a 3D model per the CustomLayerInterface | |
var customLayer = { | |
id: '3d-model', | |
type: 'custom', | |
renderingMode: '3d', | |
onAdd: function(map, gl) { | |
this.camera = new THREE.PerspectiveCamera(); | |
this.scene = new THREE.Scene(); | |
var cube = new THREE.Mesh( | |
new THREE.BoxGeometry( 300, 300, 300 ), | |
new THREE.MeshNormalMaterial() | |
); | |
this.scene.add(cube) | |
let cube1 = cube.clone(); | |
cube1.material = new THREE.MeshNormalMaterial(); | |
cube1.translateX(1000); | |
this.scene.add(cube1) | |
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; | |
this.raycaster = new THREE.Raycaster(); | |
}, | |
render: function(gl, matrix) { | |
var m = new THREE.Matrix4().fromArray(matrix); | |
var l = new THREE.Matrix4() | |
.makeTranslation( | |
modelTransform.translateX, | |
modelTransform.translateY, | |
modelTransform.translateZ | |
) | |
.scale( | |
new THREE.Vector3( | |
modelTransform.scale, | |
-modelTransform.scale, | |
modelTransform.scale | |
) | |
); | |
this.camera.projectionMatrix = m.clone().multiply(l); | |
this.camera.matrixWorldInverse = new THREE.Matrix4(); | |
this.renderer.resetState(); | |
const freeCamera = this.map.getFreeCameraOptions(); | |
let cameraPosition = new THREE.Vector4(freeCamera.position.x, freeCamera.position.y, freeCamera.position.z, 1); | |
cameraPosition.applyMatrix4(l.invert()); | |
let direction = mouse.clone().applyMatrix4(this.camera.projectionMatrix.clone().invert()); | |
direction.divideScalar(direction.w); | |
this.raycaster.set(cameraPosition, direction.sub(cameraPosition).normalize()); | |
const intersects = this.raycaster.intersectObjects( this.scene.children ); | |
console.log('Intersection count:', intersects.length) | |
for ( let i = 0; i < intersects.length; i ++ ) { | |
intersects[ i ].object.material.wireframe = true; | |
} | |
this.renderer.render(this.scene, this.camera); | |
for ( let i = 0; i < intersects.length; i ++ ) { | |
intersects[ i ].object.material.wireframe = false; | |
} | |
} | |
}; | |
map.on('load', function() { | |
map.addLayer(customLayer); | |
map.on('mousemove', function (event) { | |
mouse.x = ( event.point.x / window.innerWidth ) * 2 - 1; | |
mouse.y = - ( event.point.y / window.innerHeight ) * 2 + 1; | |
map.triggerRepaint(); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="https://cdnjs.cloudflare.com/ajax/libs/mapbox-gl/2.2.0/mapbox-gl.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r126/three.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/suncalc/1.8.0/suncalc.min.js"></script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
body { margin: 0; padding: 0; } | |
#map { position: absolute; top: 0; bottom: 0; width: 100%; } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<link href="https://cdnjs.cloudflare.com/ajax/libs/mapbox-gl/2.1.1/mapbox-gl.css" rel="stylesheet" /> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment