-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
369 additions
and
202 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/* eslint-disable import/no-extraneous-dependencies */ | ||
import * as THREE from 'three'; | ||
import maplibregl from 'maplibre-gl'; | ||
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; | ||
import { COORDS_EKATERINBURG } from 'constants/coords'; | ||
|
||
// parameters to ensure the model is georeferenced correctly on the map | ||
const modelOrigin = COORDS_EKATERINBURG; | ||
const modelAltitude = 0; | ||
const modelRotate = [Math.PI / 2, 0, 0]; | ||
|
||
const modelAsMercatorCoordinate = maplibregl.MercatorCoordinate.fromLngLat( | ||
modelOrigin, | ||
modelAltitude, | ||
); | ||
|
||
// transformation parameters to position, rotate and scale the 3D model onto the map | ||
const modelTransform = { | ||
translateX: modelAsMercatorCoordinate.x, | ||
translateY: modelAsMercatorCoordinate.y, | ||
translateZ: modelAsMercatorCoordinate.z, | ||
rotateX: modelRotate[0], | ||
rotateY: modelRotate[1], | ||
rotateZ: modelRotate[2], | ||
/* 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 | ||
export const getModelLayer = (id: string, path: string) => ({ | ||
id, | ||
type: 'custom', | ||
renderingMode: '3d', | ||
onAdd(map, gl) { | ||
this.camera = new THREE.Camera(); | ||
this.scene = new THREE.Scene(); | ||
|
||
// create two three.js lights to illuminate the model | ||
const directionalLight = new THREE.DirectionalLight(0xffffff); | ||
directionalLight.position.set(0, -70, 100).normalize(); | ||
this.scene.add(directionalLight); | ||
|
||
const 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 | ||
const loader = new GLTFLoader(); | ||
loader.load(path, (gltf) => { | ||
this.scene.add(gltf.scene); | ||
}); | ||
this.map = map; | ||
|
||
// use the MapLibre GL JS map canvas for three.js | ||
this.renderer = new THREE.WebGLRenderer({ | ||
canvas: map.getCanvas(), | ||
context: gl, | ||
antialias: true, | ||
}); | ||
|
||
this.renderer.autoClear = false; | ||
}, | ||
render(gl, matrix) { | ||
const rotationX = new THREE.Matrix4().makeRotationAxis( | ||
new THREE.Vector3(1, 0, 0), | ||
modelTransform.rotateX, | ||
); | ||
const rotationY = new THREE.Matrix4().makeRotationAxis( | ||
new THREE.Vector3(0, 1, 0), | ||
modelTransform.rotateY, | ||
); | ||
const rotationZ = new THREE.Matrix4().makeRotationAxis( | ||
new THREE.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 THREE.Vector3( | ||
modelTransform.scale, | ||
-modelTransform.scale, | ||
modelTransform.scale, | ||
), | ||
) | ||
.multiply(rotationX) | ||
.multiply(rotationY) | ||
.multiply(rotationZ); | ||
|
||
this.camera.projectionMatrix = m.multiply(l); | ||
this.renderer.resetState(); | ||
this.renderer.render(this.scene, this.camera); | ||
this.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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import React from 'react'; | ||
import { useMap } from 'react-map-gl'; | ||
import { getModelLayer } from 'components/Layers/Model'; | ||
|
||
export function ModelSource() { | ||
const ekbMap = useMap(); | ||
|
||
return ( | ||
<input | ||
style={{ position: 'absolute', top: 0, left: 0, zIndex: 1000 }} | ||
type="file" | ||
onChange={(e) => { | ||
const map = ekbMap?.current?.getMap?.(); | ||
map.addLayer( | ||
// @ts-ignore | ||
getModelLayer( | ||
`3d-model-${Math.round(Math.random() * 1000)}`, | ||
URL.createObjectURL(e.target.files[0]), | ||
), | ||
); | ||
}} | ||
/> | ||
); | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,10 +18,10 @@ | |
"@types/lodash": "^4.14.197", | ||
"@types/node": "20.5.4", | ||
"@types/react": "^18.2.21", | ||
"@types/three": "^0.155.1", | ||
"classnames": "^2.3.2", | ||
"ekb": "^1.1.4", | ||
"framer-motion": "^10.16.1", | ||
"hls.js": "^1.4.10", | ||
"lodash": "^4.17.21", | ||
"mapbox-gl": "npm:[email protected]", | ||
"maplibre-gl": "^3.3.0", | ||
|
@@ -36,6 +36,7 @@ | |
"react-modal-sheet": "^2.0.0", | ||
"react-redux": "^8.1.2", | ||
"redux": "^4.2.1", | ||
"three": "^0.156.0", | ||
"typescript": "^5.1.6" | ||
}, | ||
"devDependencies": { | ||
|
Oops, something went wrong.
57acbc1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Deploy preview for map ready!
✅ Preview
https://map-eg8lz7ncj-ekbdev.vercel.app
https://ekbdev-map-gltf.vercel.app
Built with commit 57acbc1.
This pull request is being automatically deployed with vercel-action