코드조각 저장소

pg2b3dm을 이용한 3D Tile 만들기 본문

Programing/GIS &

pg2b3dm을 이용한 3D Tile 만들기

basic 2021. 9. 13. 09:14

Web에서 3차원 데이터를 다루는 라이브러리들은 많이 있습니다. WebGL, ThreeJS, CesiumJS... 하지만 일을 진행하다보면 빅데이터 모델에 대한 근본적인 대처방안이 있어야 무난한 디스플레이가되고 시스템도 가벼워질 수 있을것입니다.

이번에 진행해 본 스터디는 CesiumJS에 사용하는 3D tile 을 생성해 보는 것입니다. 물론 Cesium ION을 이용한다면 훨씬 정신건강에 도움이 됩니다. :)

기본적으로 사용하는 데이터는 PLY 포멧 기준으로 10Mb 이상(100Mb 이상)을 대상으로 해보았습니다. 작업 후에 만들어진 타일데이터 역시 20Mb(원본 250Mb) 가까이 되지만, ThreeJS PLYLoader를 사용했을때 보다 좋은 성능을 보였습니다. 이는 대용량 데이터를 염두한 GlTF파일 포멧과 3D Tilie 데이터 셋(b3dm, i3dm)의 구조와 구현 라이브러리의 성능 때문이지 않을까 생각이 듭니다.

 결론적으로는 CesiumJS를 사용하는 환경에서 원본 3D(PLY) 모델을 b3dm(GlTF) tile로 변환하여[ new Cesium.Cesium3DTileset]으로 Cesium Viewer에서 사용하는 것입니다.

https://github.com/Geodan/pg2b3dm

 

GitHub - Geodan/pg2b3dm: Tool for converting from PostGIS to b3dm tiles

Tool for converting from PostGIS to b3dm tiles. Contribute to Geodan/pg2b3dm development by creating an account on GitHub.

github.com

마지막에 pg2b3dm을 사용하게 되었지만 [obj23dtile] 라이브러리도 검토해 볼만 합니다.

https://github.com/PrincessGod/objTo3d-tiles

 

GitHub - PrincessGod/objTo3d-tiles: Convert obj model file to 3d tiles

Convert obj model file to 3d tiles. Contribute to PrincessGod/objTo3d-tiles development by creating an account on GitHub.

github.com

 

사실 PLY를 3dTile로 만든다고 했지만 pg2b3dm에서 사용하는 데이터 소스는 Postgres상의 geometry Table이고 geometry TYPE은 polyhedralsurface를 사용합니다. 

프로젝트 getting_started 보시면 아시겠지만 PG에 데이터(Building footprint:SHP)를 로드하고 건물 속에 따라 3D 모델을 생성하는 전처리 프로세스가 필요하고 이를 통해 생성된 테이블 구조의 3D 데이터를 Tiling 합니다.

https://github.com/Geodan/pg2b3dm/blob/master/getting_started.md

 

GitHub - Geodan/pg2b3dm: Tool for converting from PostGIS to b3dm tiles

Tool for converting from PostGIS to b3dm tiles. Contribute to Geodan/pg2b3dm development by creating an account on GitHub.

github.com

 

Shape (Buding footprint) to PostGIS Polyhedralsurface

https://github.com/bertt/tesselate_building

 

GitHub - bertt/tesselate_building

Contribute to bertt/tesselate_building development by creating an account on GitHub.

github.com

 

이런 Postgres geometry Table 3D 데이터를 기반으로 b3dm 한개의 파일과 tileset.json 파일이 생성됩니다. 이후에는 CesiumJS Cesium3DTileset을 이용하여 사용할 수 있게 됩니다.

 몇가지 필수 사항을 요약하자면

1. EPSG 4987 Transform
2. id String cloume
3. Style (Shader) Colume
4. Polyhedralsurface type geometry cloume

--DDL
CREATE TABLE public.delaware_buildings (
	ogc_fid int8 NULL,
	wkb_geometry geometry NULL,
	height float8 NULL,
	id text NULL,
	geom_triangle geometry NULL,
	style json NULL,
	shaders json NULL
);
/* height, id, geom_triangle_geometry는 "tesselate_building"과 관련 됨 */

4987 프로젝션에 대해서는 Cesium을 이용할 경우 별다른 변환 작업없이 pg2b3dm 출력결과를 확인 할 수 있습니다. 원본데이터가 같은 경우에는 필요 없는 부분이도 합니다.

 설명대로 진행할 때 shape을 로드하는 과정에서 docker를 이용하지 않고 QGIS에서 바로 import하면서 번거로운 부분이 있긴 했지만 결과물에서는 문제가 없어 보였습니다.

pg2b3dm tile on Cesium

 

pg2b3dm은 .Net 5.0을 사용합니다. Docker 이미지가 존재하여 별다른 환경 셋팅 없이 사용할 수 있습니다. 하지만 데이터 구조가 정해져 있어 활용하기에 다소 까다로운 부분이 있어서 사용하고 있는 gepmetry colume이 Polygon이여서 해당하는 부분만 수정하여 진해해 보았습니다. 데이터 로드하는 부분과 Styling하는 부분을 좀 수정하였습니다.

pg2b3dm

구조를 살펴 보니 의존 라이브러리들이 보였습니다. SharpGLTF, Triaglerator

처음 b3dm 포멧을 이용하려고 시도 할 때 obj2b3dm을 사용해 봤는데 정위치에 모델을 표출하는 방법을 몰라서 tileset.json 구조와 추가적인 GlTF 포멧의 이해가 필요 했던 부분이 다소 해소된듯 합니다. GlTF가 3D 환경에서의 jpeg라고 했던 이야기가 떠오르더군요 :)

pg2b3dm\wkb2gltf.core\Triangulator.cs

public static List<Triangle> GetTriangles(Geometry geom, int batchId, ShaderColors shadercolors = null, string faceColor="")
        {
            var degenerated_triangles = 0;
            var allTriangles = new List<Triangle>();

            if ( "Polygon".Equals( geom.GeometryType+"") ) {

                var triangle = GetTriangle((Polygon)geom, batchId);
                if (triangle!=null && shadercolors != null) {                    
                    // shadercolors.Validate(1);
                    triangle.Shader = shadercolors.ToShaderColor(faceColor);
                }

                if (triangle != null) {
                    allTriangles.Add(triangle);
                }
                else {
                    degenerated_triangles++;
                }
            }
            else {
                var polyhedralsurface = (PolyhedralSurface)geom;

                for(var i=0;i<polyhedralsurface.Geometries.Count;i++) {
                    var geometry = polyhedralsurface.Geometries[i];
                    var triangle = GetTriangle(geometry, batchId);

                    if (triangle!=null && shadercolors != null) {
                        shadercolors.Validate(polyhedralsurface.Geometries.Count);
                        triangle.Shader = shadercolors.ToShader(i);
                    }

                    if (triangle != null) {
                        allTriangles.Add(triangle);
                    }
                    else {
                        degenerated_triangles++;
                    }
                }
            }

            return allTriangles;
        }

약간 수정된 코드입니다. Polygon geometry에 지정 컬러를 입혀서 Tiling 하는 소스로 씁니다.

추가적으로 좀더 보고 싶은 내용은 천천히 진행해 보려 합니다. 감사합니다.

https://github.com/KhronosGroup/glTF/tree/master/specification/2.0
https://pypi.org/project/pygltflib/
https://github.com/Oslandia/py3dtiles

 

 

 

 

Comments