본문으로 건너뛰기

3D Web Pilot Project

· 약 13분
윤성호

안녕하세요. IT사업그룹 윤성호 차장입니다.😏

옛날 옛적 2020년 초, 2개월간 실험정신을 바탕으로 무대뽀로 만들어봤던

3D Web Pilot Project (feat. OpenSource)의 개발 과정과 사용된 기술에 대해 공유해보고자 합니다.


Chapter Ⅰ - 개요

1️⃣ 시장조사 및 목표 설정

이 프로젝트의 목표는 단순했습니다.

🔥🔥🔥3D GIS 데이터를 웹으로 가시화하자!!🔥🔥🔥

일단 기존 솔루션들을 시장조사하며, Open Source를 중심으로 진행해보았습니다.

대표적으로 Cesium의 서비스를 살펴보면, 아래 그림과 같이 일부분을 비공개로 유료화 하여 서비스합니다. Cesium-ion

  • 3D Web 가시화 -> Cesium JS (Open Source)
  • 3D Data 렌더링 -> Cesium Ion (Closed Source), 클라우드 형태로 사용량 만큼 비용 청구
info

대부분의 3D 솔루션은 Cesium과 같이 데이터 렌더링 부분을 상용화 하여 서비스 하고 있습니다.

기존 솔루션들의 다른 특징은 3D 데이터를 파일 기반으로 서비스 하는 것입니다. image-20220518142055085 파일 기반이면 가시화 속도는 빠르지만, CRUD & 데이터 관리 등의 작업에 어려움이 많은 단점이 존재합니다.

이런 단점과 기존 솔루션과의 차별성을 가지기 위해 구체적인 기획을 설정해 보았습니다. (이게 구체적..?) 구체적 기획안

목표1 - 3D 데이터를 DB에 적재

목표2 - DB를 웹으로 3D 가시화


2️⃣ 구조 설계

시장조사와 여러 Open Source를 검토한 결과를 토대로 구조를 설계하였습니다.

  • DB: 3D City DB (PostgreSQL)
  • Middle Ware: OpenSource가 없어서 직접 만들기!!😨 (GeoServer Extension 형태로..)
  • Client: Cesium JS

image-20220516175627850

🏁 선정기준

Open Source 활동이 활발하며, 계속 성장해 갈것 같은가?

타 솔루션과 차별성이 있는가?

내 실력으로 커스텀이 가능할 것인가? 😢


3️⃣결과

최종 결과물 입니다. (고정 서버가 없어서 동영상으로...)

  • Montreal (Canada)
 개인 노트북(메모리 8G)에서 모든 서버를 실행하고 녹화하니 버벅거리네요....(T_T)

Chapter Ⅱ - 3D DB

1️⃣ 3D Data

2D는 Vector(Point, Line, Polygon), Raster 등으로 구성되어 있습니다.

3D 데이터는 어떤 형식으로 되어있을까요❓❓

일단 대표적인 포맷을 간단히 살펴보겠습니다.

  • KML (Keyhole Markup Language) .kml .kmz
    Google에서 사용하는 포맷. Google Earth에서 확인하기 좋음.

  • COLLADA (COLLAborative Design Activity) .dae
    3D 애플리케이션 간의 호환을 위해 만든 포맷.
    캐드나 게임엔진에서도 사용함.

  • glTF/GLB (GL Transmission Forma) .gltf .glb
    glTF는 JSON형식으로 COLLADA와 WebGL을 통합하기 위해 제작됨.
    특징은 3D 가시화에 필요한 좌표, 매쉬, 애니메이션 정보 등을 통합한 포맷.
    WebGL을 고려해 만들었기에 런타임을 최소화 하기 위한 처리도 들어감.
    GLB는 glTF를 이진파일 포맷으로 전환한것.

  • CityGML .gml
    도시의 구성체(건물, 도로, 강, 다리, 초목 등)를 표현하기 위한 포맷.
    Xml로 구성되어있고, LOD, 텍스쳐 정보도 포함할 수 있음.

  • IFC (Industry Foundation Classes) .ifc
    BIM분야의 대표 격인 buildingSMART사에서 만든 포맷

info

2D는 파일 포맷이 어느정도 표준화되어 있는데 비해, 3D는 포맷이 계속 업그레이드 되어지고 있습니다.

추가적으로 LOD(Level Of Detail)라는 개념에 대해서도 알아보겠습니다.

그래픽 렌더링의 부하를 줄이기 위해 구체화 레벨을 나눈것으로, 분야에 따라 정의하는 수준이 조금씩 다르지만 보통 아래 그림과 같은 수준으로 나누어져 있습니다.

LOD 레벨이 오를수록 구체화 되지만, 그만큼 데이터 용량이나 시스템 부하가 급증하기에 적절한 레벨을 정의할 필요가 있습니다.

image-20220517151303126

tip

이 프로젝트는 도시를 표현하기에, NewYork은 LOD2, Montreal은 LOD2 + 텍스쳐를 입힌 것으로 구현하였습니다.

구현지역과 대상을 집중시킨다면 LOD4로 구체적인 가시화도 가능하겠지요?😎


2️⃣3D City DB

3DCityDB는 Spatial RDBMS에 3D 데이터를 사용하기 위한 오픈소스 입니다.
현재 Oracle, Postgres를 지원하고 있습니다.

간단히 보면 도시를 구성하는 건물, 사물, 환경 등의 공간정보를 분류 별로 DB에서 관리하며
DB관리에 필요한 도구 등을 지원합니다. (스키마 기준: CityGML 표준)

image-20220517171648647

쉽게 말해 도시를 건물, 다리, 지형, 물길 등으로 나누어 해당 테이블에 Geometry 저장!!😄

🏠건물을 예로 자세히 보면 [지붕, 벽, 바닥, 창문 등등] 구성 요소를 나누어서 관리하고 있습니다.

image-20220517172027049

3D City DB 프로젝트는 DB에 데이터를 Import / Export 하기 위한 도구도 제공합니다.

image-20220517174130375

info

Importer-Exporter는 OpenSource라서 GitHub에 오픈되어 있습니다. (커스텀이 가능!!)

CityGML 포맷의 3D 데이터를 Import하면 DB로 3D 데이터를 관리할수 있는 기반이 완성됩니다.

image-20220518145845162

info

이번 프로젝트에서 구성해본 NewYorkMontreal은 각 해당 시에서 제공하는 오픈 데이터를 다운받아 Import 하였습니다.

데스크탑에서 데이터를 확인하실때는 FME프로그램을 사용하시면 편리합니다.



Chapter Ⅲ - 3DTiles

1️⃣ 3D 구현 방식

2D에서 Geometry를 가시화 하기 위해서는 WMS, WFS, VectorTile 같은 방식으로 Geometry 정보를 받아왔습니다.

3D에서 어떻게 해야될까요❓❓

3가지 방식을 구현하여 테스트를 진행해 보았습니다.

  • 1번 : DB 정보를 그대로 Cesium으로 전달하고 Client에서 Czml으로 변환하여 가시화 image-20220518151537181

  • 2번 : DB의 Geometry를 GeoServer에서 CZML로 변환하고 Cesium에 전달하여 가시화 image-20220520140256188

  • 3번 : DB의 Geometry를 GeoServer에서 3DTiles로 변환하여 Cesium에 전달하여 가시화 image-20220518151440382

테스트 결과를 확인해보면

데이터 포맷구현 방식결과
LOD21번Normal
LOD22번Good!!👍
LOD23번Normal
LOD2 + Texture1번사용불가
LOD2 + Texture2번사용불가
LOD2 + Texture3번Good!!👍
info

테스트 결과 3DTiles 방식이 제일 합리적이라는 결론을 도출할 수 있었습니다.

그렇다면 3DTiles에 대해 자세히 살펴보겠습니다.


2️⃣ 3DTiles - 기반지식

3DTiles는 3D 데이터를 효과적으로 스트리밍 하기 위해 만든 개방형 포맷 입니다.

3D의 스트리밍과 렌더링에 목적성을 두고, WebGL에 최적화된 glTF를 기반으로 개발되었습니다.

GeoServer를 통해 3DTiles로 서비스 하는 방식을 개발하기 위해서는 삼각분할과 법선(Normal)에 대한 상식이 필요합니다.

  • 삼각분할
    2D는 표면을 폴리곤으로 표현하는데에 비해, 3D는 삼각형으로 관리합니다. image-20220518162037762

    3DCityDB에서는 폴리곤으로 데이터를 관리하기에, 삼각형으로 변환할 필요가 있습니다.
    저는 일단 가장 보편적으로 사용되는 들로네 삼각분할(Delaunay triangulation)을 사용했보았습니다.

    3D Conforming Delaunay Triangulation | SpringerLink

caution

결과적으로 단순한 폴리곤 모양들은 문제없이 삼각분할 되었지만, 자유의여신상 같은 복잡한 물체는 삼각분할이 정확히 이루어지지 않았습니다.

차후 다방면으로 개선할 필요가 있습니다.

  • 법선(Normal) 3D에서 Normal[보통]이라는 뜻이 아니라 [법선]을 의미합니다.
    Normal은 3D에서 아주 중요한 개념이고, 많은 것들을 정의하고 처리합니다.

    image-20220518165408334

    법선은 일단 표면의 앞뒤, 벡터를 뜻합니다.
    이 정보를 기준으로 3D엔진에서 Geometry를 렌더링 하는데요.
    광원이나 표면의 굴곡과도 관련이 있어서 아래 그림과 같이 노말에 따라 물체의 형태가 달라질 수도 있습니다.

    image-20220518165537187

Normal 처리 방법의 발전으로 각진 인체가 실제 사람처럼 부드러워 졌습니다.

image-20220518170037310

tip

Normal의 처리방법은 3D에서 매우 중요하기에, 수준도 깊고 따로 공부할 필요가 있습니다.

3DTiles에서는 Vertax마다 Normal값을 설정해주면 됩니다.
이번 프로젝트에서는 건물만 표현하기에 Hard Shading방식으로 단순하게 처리하였습니다.

img


3️⃣ 3DTiles - 구현

3DTiles의 기본 구성은 TileSet, Formats, Structure 정도로 나눠서 볼 수 있습니다.

  • TileSet

    2D에서는 단순히 화면의 X,Y 위치에 따라 Bounding 범위를 지정했습니다.
    하지만 3D에서는 Z축이 존재하고 렌더링에 대한 리소스 관리를 위하여 전체 영역의 Bounding, 각 객체별 Bounding을 계산하고 TileSet을 지정해 줘야됩니다.

    • 전체 Bounding
      image-20220518172126372
    • 객체별 Bounding image-20220518172231914 속도 향상을 위해서는 객체 내 에서도 TileSet을 분리해줘야됩니다.
      예를 들어 건물을 멀리서 봤을때는 건물 외형만 보이고, 가까이가면 창문이나 문도 보이게끔 구성해 주어야 합니다.
      image-20220518172426794
  • Formats

    각 객체들의 bounding과 TileSet을 정리했다면, 다음으로 객체정보를 작성할 Format을 지정해야됩니다. 3DTiles에서는 3개의 Format이 있습니다.

    • b3dm (Batched 3D Models)
      각각의 다른 물체들을 표현할때 사용하는 포맷입니다. 이번 프로젝트에서 사용한 포맷입니다. image-20220518173203814

    • i3dm (Instanced 3D Models)
      동일한 물체를 여러군데 사용할때 사용하는 포맷입니다. (나무, 전봇대 같은 시설물 들)

      image-20220518173319372

    • pnts (Point Clouds)
      포인트 클라우드로 표현할때 사용하는 포맷입니다.

      image-20220518173433574

  • Structure

    위에서 포맷에 대한 정의를 끝냈다면, 이제 공간정보를 구조에 맞게 작성해야됩니다. 3DTiles는 glTF와 GLB 포맷을 토대로 작성을 합니다.

    glTF의 구조에 대해 간단히 보면 Image 2a: The glTF JSON structure
    이런 구조로 Geometry를 정리하여 JSON으로 작성해주시면 됩니다. (참 쉽죠..?😱)

    image-20220518175130015

    자세한 사항은 glTF 규격을 참조해주세요. 블로그에 적기엔 너무 방대합니다. 😢

    GLB는 glTF와 유사합니다. glTF에서 작성한 내용을 바이너리로 변환하고, 헤더정보, Texture 정보들을 따로 정리해주면 끝납니다.

    image-20220518175242102

이렇게 하여 DB에 적재된 3D 데이터를 3DTiles로 변환하는 방법에 대해 알아보았습니다.

tip

3DTiles의 자세한 사항은 3DTiles 규격을 확인해 보시기 바랍니다.



Chapter Ⅳ - 3D Visualization

1️⃣ 3D GeoServer

저번 장에서 3DTiles에 대해 알아보았었습니다.

3DTiles를 서비스 하기 위한 Middle Ware로는 GeoServer의 Extension을 만들기로 하였습니다. GeoServer를 선정한 핵심포인트는 GWC (GeoWebCache)를 활용하기 위함이었습니다.
image-20220520105801007

GWC를 통해 3DTiles로 변환한 파일을 캐싱함으로써, 1번만 렌더링하면 바로 3DTiles 파일를 받을 수 있습니다.

또한, GWC에서 제공하는 Seed 기능으로 미리 캐시파일을 만들어 놓을수도 있습니다.

구체적으로 GeoServer에 forcewave3D라는 Extension 프로젝트를 구성하였고, 레이어 발행시 새로 정의한 application/json;type=forcewave-3dtiles라는 포맷을 타일캐시로 추가해 주었습니다.

image-20220520113033657


2️⃣ CesiumJS

GeoServer와 Cesium을 연동하기 위해서 따로 클래스를 추가해보았습니다.

image-20220520131439960

일단 캐쉬를 쓸려면 WMTS 타일 형태로 Cesium상에 레이어를 설정해야됩니다.

WMTS에 타일을 요청할때는 좌표계에 따라 X, Y, Z 로 타일을 정의합니다.

좌표계에 따른 타일 정의는 ESPG:4326 좌표계 같은 경우 Cesium의 viewer.scene.globe._surface._tilesToRender객체를 통해 X, Y, Z값을 추출할 수 있습니다.

CesiumJS에 구현하는 상세 순서는 아래와 같습니다.

  • 카메라 이벤트로 타일 구현 시점 설정
  • 타일 값과 여러 설정값을 도출하여 GWC에 3DTiles 파일 요청
  • 받아온 3DTiles 파일 내용을 Cesium.Cesium3DTileset 객체를 사용하여 가시화
    성능 향상을 위한다면 가시화 객체를 직접 만들어 제어해야겠죠?(T_T)

앞의 작업들을 통하여 최종적으로 Web에 3D 데이터를 가시화하게 되어집니다.

1. 3D Data를 DB에 적재
2. GeoServer를 활용하여 DB 데이터를 3DTiles로 렌더링
3. CesiumJS와 GeoServer를 연계하여 GWC에 적재된 3DTiles를 가시화

image-20220520111020784

tip

debugShowBoundingVolume 옵션을 사용하면 3DTiles의 외각 Bounding과 객체 간의 TileSet을 확인할 수 있습니다.


3️⃣ 후기

처음엔 2D에 비해 Z축 하나만 추가된걸로만 생각을 했었습니다.

하지만 직접 개발해보니 2D에 비해 몇배는 어렵네요...😢

딱 이게 표준이다 라는게 없어서 더 어려운것 같습니다.

그리고 이 프로젝트는 제가 3D에 관련된 업무를 해본 경험이 없어, 현업과는 많이 동떨어져 있을 것입니다. (스터디 레벨 프로젝트..)

3D 사업과 연관짓기보다는 개발에 관한 면을 포커스로 봐주시기 바랍니다. 😄

이번 블로그 내용과 관련하여 궁금하신게 있으시면 언제든 편하게 연락주세요~ 😘


프로젝트 소스는 회사 Redmine의 "10.사내개발 및 연구 프로젝트 » Cesium" 프로젝트 저장소를 보시면 확인하실 수 있습니다.