
이번 글에서는 Street View 와 Three.js 카메라를 동기화하는 작업을 설명합니다.
지난 글에서는 GIS 데이터를 로드해서 Three.js에서 사용 가능한 좌표계로 변환하고,
Mesh를 만들었습니다.
이제 만들어놓은 Mesh들을 구글 스트리트 뷰에서 동기화 하는 작업에 대해서 설명하겠습니다.
엔진이 배를 움직이는 것이 아니다. 배는 그 자리에 가만이 있으나 엔진이 이 세상을 회전해 움직이는 것이다.
출처: OpenGL Tutorial
const streetView = map.getStreetView();
streetView.addListener('position_changed', () => { // (1)
const position = streetView.getPosition();
if (position === null) return;
const meters = this.latLngToMeters(position.lng(), position.lat()); // (2)
this.camera?.position.set(meters.x, 3, -meters.y);
this.updateCameraFov(); // (3)
this.updatePipeVisibility(); // (5)
this.updateMarkerVisibility(); // (6)
this.camera.updateMatrixWorld(); // (7)
});
streetView.addListener('pov_changed', () => { // (4)
const pov = streetView.getPov();
const deg2rad = (degrees: number) => degrees * (Math.PI / 180);
this.camera.rotation.set(deg2rad(pov.pitch), deg2rad(-pov.heading), 0, 'YXZ');
// 카메라의 월드 매트릭스를 업데이트하여 정확한 위치를 확보
this.camera.updateMatrixWorld();
this.updateCameraFov();
});
position_changed 이벤트 리스너
스트리트 뷰의 좌표를 미터 단위로 반환해서 Threes.js 카메라 위치 업데이트
Three.js 카메라 시야각(FOV) 업데이트 함수 호출
// 카메라 FOV 업데이트 함수
updateCameraFov() {
const zoom = this.panorama?.getZoom(); // Google Street View의 현재 zoom 레벨
if(zoom === undefined) return;
const fov = this.zoomLevelToFov(zoom); // Zoom 레벨에 따른 FOV 계산
this.camera.fov = fov; // THREE.js 카메라의 FOV 설정
this.camera.updateProjectionMatrix(); // 카메라의 프로젝션 매트릭스 업데이트
}
// Zoom 레벨에 따른 FOV 계산 함수 (근사값 사용)
zoomLevelToFov(zoom: number) {
// Zoom 레벨 1에서의 FOV를 90도로 가정
// Zoom 레벨이 증가함에 따라 FOV 감소
return 55 / Math.pow(2, zoom - 1);
}
zoom은 Google Street View의 줌 레벨을 의미합니다.zoom 레벨이 높아져 지도가 확대되어 보일수록 FOV가 작아져야합니다. pov_changed 이벤트 리스너
const deg2rad = (degrees: number) => degrees * (Math.PI / 180);YXZ: 회전 순서를 지정합니다.YXZ는 Y축 → X축 → Z축 순서로 회전을 적용하는 것을 의미하며, 이는 카메라 회전에서 흔히 사용하는 순서입니다.빌보드 만 추가해줍니다.updateMatrixWorld이 작업을 통해 Google Street View와 Three.js의 카메라가 동기화되며, 3D 관로와 마커가 자연스럽게 표시됩니다.