지난 시간에는 cesium을 처음 사용하여, 내가 원하는 좌표에 3D 모델로 화면을 띄우는 것을 구현했었다. 그 이후도 나는 꾸준히 cesium을 가지고 공부했다.
오늘은 공부했던 내용 중에서 한반도에 운석을 떨구는 내용을 정리하려고 한다.
운석을 떨구기 전 고려해야하는 상황을 정해보았다. 오늘은 이 플로우에 맞춰서 글을 작성할 예정이다.
- 운석이 떨어질 지구 모델과 관찰 카메라 위치 및 각도
- 운석이 떨어지는 과정
- 3D 운석 이미지를 표현해줄 gltf 확장자 파일 적용
그렇다면 코드를 통해 한번 살펴보자
// 0.header-ceisum 연결 <head> <meta charset="utf-8"> <!-- Include the CesiumJS JavaScript and CSS files --> <script src="https://cesium.com/downloads/cesiumjs/releases/1.111/Build/Cesium/Cesium.js"></script> <link href="https://cesium.com/downloads/cesiumjs/releases/1.111/Build/Cesium/Widgets/widgets.css" rel="stylesheet"> </head> // 1.body-cesiumContainer 준비 <body> <div id="cesiumContainer"></div> </body> // 2.scirpt를 통한 조작 <script type="module"> // 3.토큰 입력 Cesium.Ion.defaultAccessToken = '발급 받은 토큰 '; // 4.viewer에 다음과 같이 지구 모델을 생성 const viewer = new Cesium.Viewer('cesiumContainer', { terrain: Cesium.Terrain.fromWorldTerrain(), }); // 5.지구 모델을 바라볼 카메라 설정(운석이 떨어지는 모습을 보기 위해 다음과 같이 설정) var position = Cesium.Cartesian3.fromDegrees(170.0, 40.0, 25000000); // 경도, 위도, 고도 var heading = Cesium.Math.toRadians(0); // 방위각 var pitch = Cesium.Math.toRadians(-90); // 경사각 var roll = Cesium.Math.toRadians(0); // 롤각 // 6. 설정한 카메라 각도에 맞춰 지구 모델 생성 viewer.scene.camera.setView({ destination: position, orientation: { heading: heading, pitch: pitch, roll: roll } }); </script>
위의 코드에 따라 지구 모형이 생성되었다.
이제 도형(운석 이미지 적용 전)을 동적으로 움직여서 지구에 떨어지는 모습을 표현할 것이다.
// 운석의 초기 위치 설정 (지구 중심 좌표계) var initialPosition = Cesium.Cartesian3.fromDegrees(127, 37.0, 10000000); // 초기 위치 (한반도 경도, 위도, 고도 10000000 상공) var fixedFrameTransform = Cesium.Transforms.eastNorthUpToFixedFrame(initialPosition); // 좌표계 변환 // 운석 도달 위치 설정 var destinationLatitude = 37.0; // 도달 지점의 위도 var destinationLongitude = 127.0; // 도달 지점의 경도 var destinationAltitude = 10000; // 도달 지점의 고도 var destinationPosition = Cesium.Cartesian3.fromDegrees(destinationLongitude, destinationLatitude, destinationAltitude); // 도형 생성 var shape = new Cesium.Entity({ name: 'Custom Shape', position: new Cesium.CallbackProperty(function(time, result) { var seconds = Cesium.JulianDate.secondsDifference(time, Cesium.JulianDate.now()); var newPosition = Cesium.Matrix4.multiplyByPoint(fixedFrameTransform, new Cesium.Cartesian3(0, 0, 1000000 * seconds), new Cesium.Cartesian3()); var cartographic = Cesium.Cartographic.fromCartesian(newPosition); var altitude = cartographic.height; // 도달 여부 확인 if (altitude <= 10000) { // 지구에 도달한 경우, 이전 위치 반환하여 위치 업데이트 중지 return destinationPosition; }else { // 도달하지 않은 경우, 새로운 위치 반환 return newPosition; } }, false), ellipsoid: { radii: new Cesium.Cartesian3(100000, 100000, 100000), // 도형의 크기 (x축 반지름: 1000000, y축 반지름: 1000000, z축 반지름: 1000000) material: Cesium.Color.RED.withAlpha(0.5) // 도형의 색상 (빨간색, 투명도: 0.5) } }); // 도형을 뷰어에 추가 viewer.entities.add(shape);
위의 코드처럼 운석의 초기 위치, 도달한 위치 등 설정을 마치고 Cesium.CallbackProperty 를 통해 동적으로 움직일 수 있게 구현하였다.
마지막 중요한 운석을 표현해줄 차례이다. 바로 이전에 설명한 내용에서는 빨간 동그라미를 운석으로 대체하였으나, 실제 운석을 통해 리얼리티를 살리고 싶었다. 그러나 3D로 구현된 이 환경에서 2D 이미지를 대체할 것인가? 아니다.
나는 이 문제를 해결하기 위해 많은 구글링을 시도하였고, 그 결과 3D 이미지 대체로는 gltf 파일 확장자로 표현이 가능하다는 것을 알았다. 그리고 오픈 소스를 통해 실제 운석 이미지를 적용하였다.
// 도형 생성 var shape = new Cesium.Entity({ name: 'Custom Shape', position: new Cesium.CallbackProperty(function(time, result) { var seconds = Cesium.JulianDate.secondsDifference(time, Cesium.JulianDate.now()); var newPosition = Cesium.Matrix4.multiplyByPoint(fixedFrameTransform, new Cesium.Cartesian3(0, 0, 1000000 * seconds), new Cesium.Cartesian3()); var cartographic = Cesium.Cartographic.fromCartesian(newPosition); var altitude = cartographic.height; // 도달 여부 확인 if (altitude <= 10000) { // 지구에 도달한 경우, 이전 위치 반환하여 위치 업데이트 중지 return destinationPosition; }else { // 도달하지 않은 경우, 새로운 위치 반환 return newPosition; } }, false), model: { uri: '/images/rock-boulder-dry-3d-model/rock_boulder_dry_4k.gltf', // glTF 파일의 경로 scale: 500000.0 } }); // 도형을 뷰어에 추가 viewer.entities.add(shape);
기존에 도형으로 대체 했던 부분(ellipsoid)을 운석 모델(model)로 변경해주었다.
ellipsoid: { radii: new Cesium.Cartesian3(100000, 100000, 100000), // 도형의 크기 (x축 반지름: 1000000, y축 반지름: 1000000, z축 반지름: 1000000) material: Cesium.Color.RED.withAlpha(0.5) // 도형의 색상 (빨간색, 투명도: 0.5) }
model: { uri: '/images/rock-boulder-dry-3d-model/rock_boulder_dry_4k.gltf', // glTF 파일의 경로 scale: 500000.0 }
cesium 개인적으로 재밌어서 꾸준히 보고 있는 거 같다. 앞으로도 꾸준한 포스팅 이어가면서 자세한 사용법 및 기술들에 대해 서술하도록 하겠다🌍