Vworld 3D Data를 Three.js로 출력하기
Vworld WebGL기반 3차원 지도
Vworld WebGL기반 3차원 지도 에 접속하시면 아래와 같은 화면을 볼 수 있습니다.
여기서 WebGL 이란
웹 기반의 그래픽 라이브러리
자바스크립트 프로그래밍 언어를 통해서 사용
호환성이 있는 웹 브라우저에서 인터랙티브한 3D 그래픽을 사용할 수 있도록 제공
(출처: 위키피디아)
데이터 API는 브이월드에서 제공하는 다양한 국가공간정보를 외부(기관,기업,개인등)에서 활용할 수 있도록 XML또는 JSON형식으로 데이터를 제공하는 API서비스
입니다.
어떻게 사용해야 하나요?
어떤 데이터가 어떻게 제공 되나요?
키 발급
개발자센터 > 인증키 > 인증키 발급
에서 키를 발급 받을 수 있습니다. (로그인
되어 있어야 이용 가능합니다. )
1 2 3 4 3XE3C10E-82B7-3E7F-AC31 -37175F32CDE4
개인 키를 발급 받아서 사용하시기 바랍니다.
출력 결과
각 요소별 정의
데이터 요청
발급받은 키를 사용하여 요청합니다.
// 요청 URL
http://xdworld.vworld.kr:8080/XDServer/3DData?Version=2.0.0.0&Request=GetCapabilities&Key=3XE3C10E-82B7-3E7F-AC31-37175F32CDE4
요청 결과
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 <GetCapabilities > <SCRIPT id ="allow-copy_script" > (function agent ( ) { let isUnlockingCached = false const isUnlocking = ( ) => isUnlockingCached document .addEventListener ('allow_copy' , event => { const { unlock } = event.detail isUnlockingCached = unlock }) const copyEvents = [ 'copy' , 'cut' , 'contextmenu' , 'selectstart' , 'mousedown' , 'mouseup' , 'mousemove' , 'keydown' , 'keypress' , 'keyup' , ] const rejectOtherHandlers = e => { if (isUnlocking ()) { e.stopPropagation () if (e.stopImmediatePropagation ) e.stopImmediatePropagation () } } copyEvents.forEach (evt => { document .documentElement .addEventListener (evt, rejectOtherHandlers, { capture : true , }) }) })() </SCRIPT > <Version > 2.0.0.0</Version > <Layers Count ="77" > <Layer Name ="tile" Type ="terrainImg" MinLevel ="0" MaxLevel ="15" /> <Layer Name ="dem" Type ="terrainDEM" MinLevel ="0" MaxLevel ="15" /> <Layer Name ="2015" Type ="time" MinLevel ="0" MaxLevel ="15" /> <Layer Name ="2016" Type ="time" MinLevel ="0" MaxLevel ="15" /> <Layer Name ="2017" Type ="time" MinLevel ="0" MaxLevel ="15" /> <Layer Name ="2018" Type ="time" MinLevel ="0" MaxLevel ="16" /> <Layer Name ="tile_mo" Type ="terrainImg_MO" MinLevel ="0" MaxLevel ="18" /> <Layer Name ="tile_mo_2015" Type ="terrainImg_2015" MinLevel ="0" MaxLevel ="18" /> <Layer Name ="tile_mo_HD" Type ="terrainImg_MO_HD" MinLevel ="0" MaxLevel ="18" /> <Layer Name ="tile_mo2d" Type ="terrainImg_MO2D" MinLevel ="0" MaxLevel ="15" /> <Layer Name ="tile_mo2d_HD" Type ="terrainImg_MO2DHD" MinLevel ="0" MaxLevel ="15" /> <Layer Name ="dem_mo" Type ="terrainDEM_MO" MinLevel ="0" MaxLevel ="15" /> <Layer Name ="indoor_build" Type ="Indoor" MinLevel ="0" MaxLevel ="15" /> <Layer Name ="indoor_build_HD" Type ="Indoor" MinLevel ="0" MaxLevel ="15" /> <Layer Name ="facility_build_boan" Type ="boan1" MinLevel ="0" MaxLevel ="15" /> <Layer Name ="facility_bridge_boan" Type ="boan1" MinLevel ="0" MaxLevel ="15" /> <Layer Name ="facility_build_lod1" Type ="boan1" MinLevel ="0" MaxLevel ="15" /> <Layer Name ="hybrid_2017" Type ="boan2" MinLevel ="5" MaxLevel ="15" /> <Layer Name ="facility_build" Type ="Real3D" MinLevel ="0" MaxLevel ="15" /> <Layer Name ="facility_build_world" Type ="Real3D" MinLevel ="0" MaxLevel ="15" /> <Layer Name ="facility_build_world_mo" Type ="Real3D" MinLevel ="0" MaxLevel ="15" /> <Layer Name ="facility_bridge" Type ="Real3D" MinLevel ="0" MaxLevel ="14" /> <Layer Name ="facility_dokdo" Type ="Real3D" MinLevel ="0" MaxLevel ="13" /> <Layer Name ="facility_build_at" Type ="Real3D" MinLevel ="0" MaxLevel ="15" /> <Layer Name ="facility_build_mo" Type ="Real3D" MinLevel ="0" MaxLevel ="15" /> <Layer Name ="facility_dokdo_mo" Type ="Real3D" MinLevel ="0" MaxLevel ="13" /> <Layer Name ="facility_bridge_mo" Type ="Real3D" MinLevel ="0" MaxLevel ="14" /> <Layer Name ="facility_bridge_ag" Type ="Real3D" MinLevel ="0" MaxLevel ="14" /> <Layer Name ="facility_build_ag" Type ="Real3D" MinLevel ="0" MaxLevel ="15" /> <Layer Name ="facility_bridge_ag_mo" Type ="Real3D" MinLevel ="0" MaxLevel ="14" /> <Layer Name ="facility_build_ag_mo" Type ="Real3D" MinLevel ="0" MaxLevel ="15" /> <Layer Name ="facility_indoor" Type ="Real3D" MinLevel ="0" MaxLevel ="15" /> <Layer Name ="facility_olympic2018" Type ="Real3D" MinLevel ="0" MaxLevel ="15" /> <Layer Name ="tile_bridge_mo" Type ="terrainImg_wgt" MinLevel ="10" MaxLevel ="14" /> <Layer Name ="tile_build_mo" Type ="terrainImg_wgt" MinLevel ="10" MaxLevel ="15" /> <Layer Name ="poi_base" Type ="Point3D" MinLevel ="0" MaxLevel ="16" /> <Layer Name ="poi_base_u8" Type ="Point3D" MinLevel ="0" MaxLevel ="16" /> <Layer Name ="poi_base_north" Type ="Point3D" MinLevel ="0" MaxLevel ="14" /> <Layer Name ="poi_base_world" Type ="Point3D" MinLevel ="0" MaxLevel ="14" /> <Layer Name ="poi_bound" Type ="Point3D" MinLevel ="0" MaxLevel ="11" /> <Layer Name ="poi_bound_north" Type ="Point3D" MinLevel ="0" MaxLevel ="8" /> <Layer Name ="poi_bound_world" Type ="Point3D" MinLevel ="0" MaxLevel ="7" /> <Layer Name ="poi_road" Type ="Point3D" MinLevel ="0" MaxLevel ="14" /> <Layer Name ="poi_road_north" Type ="Point3D" MinLevel ="0" MaxLevel ="14" /> <Layer Name ="poi_em_base" Type ="Point3D" MinLevel ="0" MaxLevel ="16" /> <Layer Name ="poi_em_bound" Type ="Point3D" MinLevel ="0" MaxLevel ="12" /> <Layer Name ="poi_em_dept" Type ="Point3D" MinLevel ="0" MaxLevel ="7" /> <Layer Name ="poi_em_dokdo" Type ="Point3D" MinLevel ="0" MaxLevel ="15" /> <Layer Name ="poi_em_embassy" Type ="Point3D" MinLevel ="0" MaxLevel ="6" /> <Layer Name ="poi_em_issue" Type ="Point3D" MinLevel ="0" MaxLevel ="4" /> <Layer Name ="poi_em_korea" Type ="Point3D" MinLevel ="0" MaxLevel ="4" /> <Layer Name ="poi_em_park" Type ="Point3D" MinLevel ="0" MaxLevel ="4" /> <Layer Name ="poi_em_whc" Type ="Point3D" MinLevel ="0" MaxLevel ="4" /> <Layer Name ="poi_base_north_u8" Type ="Point3D" MinLevel ="0" MaxLevel ="14" /> <Layer Name ="poi_base_world_u8" Type ="Point3D" MinLevel ="0" MaxLevel ="14" /> <Layer Name ="poi_bound_u8" Type ="Point3D" MinLevel ="0" MaxLevel ="11" /> <Layer Name ="poi_bound_north_u8" Type ="Point3D" MinLevel ="0" MaxLevel ="8" /> <Layer Name ="poi_bound_world_u8" Type ="Point3D" MinLevel ="0" MaxLevel ="7" /> <Layer Name ="poi_road_u8" Type ="Point3D" MinLevel ="0" MaxLevel ="14" /> <Layer Name ="poi_road_north_u8" Type ="Point3D" MinLevel ="0" MaxLevel ="14" /> <Layer Name ="poi_indoor" Type ="Point3D" MinLevel ="0" MaxLevel ="14" /> <Layer Name ="hybrid_road" Type ="HybridImg" MinLevel ="5" MaxLevel ="16" /> <Layer Name ="hybrid_bound" Type ="HybridImg" MinLevel ="0" MaxLevel ="14" /> <Layer Name ="hybrid_add_sansatai" Type ="HybridImg" MinLevel ="5" MaxLevel ="14" /> <Layer Name ="hybrid_road_mo" Type ="HybridImg" MinLevel ="5" MaxLevel ="16" /> <Layer Name ="hybrid_silgam" Type ="HybridImg" MinLevel ="5" MaxLevel ="15" /> <Layer Name ="hybrid_2016" Type ="HybridImg" MinLevel ="5" MaxLevel ="15" /> <Layer Name ="bill_Tree" Type ="Billboard3D" MinLevel ="0" MaxLevel ="16" /> <Layer Name ="timeseries" Type ="TimeseriesImg" MinLevel ="0" MaxLevel ="16" /> <Layer Name ="T197801" Type ="TimeseriesImg" MinLevel ="0" MaxLevel ="16" /> <Layer Name ="T198901" Type ="TimeseriesImg" MinLevel ="0" MaxLevel ="16" /> <Layer Name ="T195001" Type ="TimeseriesImg" MinLevel ="0" MaxLevel ="16" /> <Layer Name ="T195101" Type ="TimeseriesImg" MinLevel ="0" MaxLevel ="16" /> <Layer Name ="T195212" Type ="TimeseriesImg" MinLevel ="0" MaxLevel ="16" /> <Layer Name ="T199601" Type ="TimeseriesImg" MinLevel ="0" MaxLevel ="16" /> <Layer Name ="T200601" Type ="TimeseriesImg" MinLevel ="0" MaxLevel ="16" /> <Layer Name ="T200712" Type ="TimeseriesImg" MinLevel ="0" MaxLevel ="14" /> </Layers > </GetCapabilities >
이 중에서 facility_build
를 사용하겠습니다.
1 <Layer Name ="facility_build" Type ="Real3D" MinLevel ="0" MaxLevel ="15" />
요청 변수
출력결과
각 요소별 정의
데이터 요청
발급받은 키를 사용하여 요청합니다.
추가 되는 내용들
Layer
facility_build
Level
15
BBOX
126.976987,37.570187,126.979433,37.574251
CheckFlag
True
http://xdworld.vworld.kr:8080/XDServer/3DData?Version=2.0.0.0&Request=GetLayerExists&Key=3XE3C10E-82B7-3E7F-AC31-37175F32CDE4&Layer=facility_build&Level=15&BBOX=126.976987,37.570187,126.979433,37.574251&CheckFlag=True
요청 결과
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <SearchResult > <Version > 2.0.0.0</Version > <Layer Name ="facility_build" > <Nodes Level ="15" NodeCount ="18" > <Node IDX ="279417" IDY ="116117" Flag ="false" /> <Node IDX ="279418" IDY ="116117" Flag ="false" /> <Node IDX ="279419" IDY ="116117" Flag ="false" /> <Node IDX ="279420" IDY ="116117" Flag ="false" /> <Node IDX ="279417" IDY ="116118" Flag ="false" /> <Node IDX ="279418" IDY ="116118" Flag ="false" /> <Node IDX ="279419" IDY ="116118" Flag ="false" /> <Node IDX ="279420" IDY ="116118" Flag ="false" /> <Node IDX ="279417" IDY ="116119" Flag ="false" /> <Node IDX ="279418" IDY ="116119" Flag ="false" /> <Node IDX ="279419" IDY ="116119" Flag ="false" /> <Node IDX ="279420" IDY ="116119" Flag ="false" /> <Node IDX ="279417" IDY ="116120" Flag ="false" /> <Node IDX ="279418" IDY ="116120" Flag ="false" /> <Node IDX ="279419" IDY ="116120" Flag ="false" /> <Node IDX ="279420" IDY ="116120" Flag ="false" /> <Node IDX ="279417" IDY ="116121" Flag ="false" /> <Node IDX ="279418" IDY ="116121" Flag ="false" /> <Node IDX ="279419" IDY ="116121" Flag ="false" /> <Node IDX ="279420" IDY ="116121" Flag ="false" /> </Nodes > </Layer > </SearchResult >
이 중에서 가장 마지막에 있는 것을 이용해보도록 하겠습니다.
1 <Node IDX ="279420" IDY ="116121" Flag ="false" />
요청 URL
요청 변수
데이터 요청
추가 되는 내용들
Layer
facility_build
Level
15
IDX
279420
IDY
116121
http://xdworld.vworld.kr:8080/XDServer/3DData?Version=2.0.0.0&Request=GetLayer&Key=3XE3C10E-82B7-3E7F-AC31-37175F32CDE4&Layer=facility_build&Level=15&IDX=279420&IDY=116121
위의 요청을 보내면 3DData 바이너리 파일이 리턴됩니다.
요청 결과
VWorld 3D Map Binary Data File Format 을 확인하여 리턴된 바이너리 파일을 분석합니다.
Name
Size(byte)
Type
설명
Level
4
u32
레벨 (0 베이스)
IDX
4
u32
경도 ID
IDY
4
u32
위도 ID
Object Count
4
u32
객체의 총수
Model Object 정보
Name
Size(byte)
Type
설명
Version
4
u32
객체의 등록 버전 (XDO 파일의 버전정보)
Type
1
u8
객체의 타입 (객체의 타입정보 - 8로 고정: 예약됨)
KeyLen
1
u8
객체의 키값 크기
Key
KeyLen
char*
객체의 키값 (객체의 고유 ID 값)
CenterPos
16
vector2dd
객체의 중심좌표 (경위도 radian) (Model이 위치 할 공간좌표 경위도값)
altitude
4
f32
객체의 고도값 (Model이 위치 할 공간의 해발고도 높이)
box
48
aabbox3dd
객체의 바운더리 (구면 Vector) (Model 의 3차원 최대, 최소 공간 영역 좌표 정보)
ImgLevel
1
u8
이미지 레벨 (사용되는 LOD 레벨의 수)
dataFileLen
1
u8
객체의 파일이름 길이
dataFile
dataFileLen
char*
객체의 파일이름 (확장자 포함) (Tile 내에 실제 Model의 XDO 파일명)
imgFileNameLen
1
u8
이미지 파일이름 길이
imgFileName
imgFileNameLen
char*
이미지 파일이름 (XDO 파일이 사용하는 Texture 이미지 명)
Parsing
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 var idx = 279420 var idy = 116121 var layerUrl = `http://xdworld.vworld.kr:8080/XDServer/3DData?Version=2.0.0.0&Request=GetLayer&Key=3XE3C10E-82B7-3E7F-AC31-37175F32CDE4&Layer=facility_build&Level=15&IDX=${idx} &IDY=${idy} ` ;var promise = $.ajax ({ url : layerUrl, dataType : "binary" , }); promise.done (function (data ) { var p = new Parser (data); _data.level = p.getUint4 (); _data.idx = p.getUint4 (); _data.idy = p.getUint4 (); _data.objectCount = p.getUint4 (); _data.version = p.getVersion (); _data.type = p.getUint1 (); var lenStr = p.getLenStr (); _data.keyLen = lenStr.len ; _data.key = lenStr.str ; _data.centerPosX = p.getFloat8 (); _data.centerPosY = p.getFloat8 (); _data.altitude = p.getFloat4 (); _data.box = p.getBox3dd (); _data.imgLevel = p.getUint1 (); var lenStr = p.getLenStr (); _data.dataFileLen = lenStr.len ; _data.dataFileName = lenStr.str ; var lenStr = p.getLenStr (); _data.imgFileLen = lenStr.len ; _data.imgFileName = lenStr.str ; resolve (); });
이렇게 하면 아래와 같은 정보를 얻을 수 있습니다.
여기서 얻은 파일명을 사용하여 3D data 를 조회합니다.
dataFileName : a13_52.xdo
imgFileName: a13_52.jpg
Parser Class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 $(document ).ready (function ( ) { $.ajaxSetup ({ beforeSend : function (jqXHR, settings ) { if (settings.dataType === 'binary' ) { settings.xhr ().responseType = 'blob' ; } } }); $.ajaxTransport ("+binary" , function (options, originalOptions, jqXHR ) { if (window .FormData && ((options.dataType && (options.dataType == 'binary' )) || (options.data && ((window .ArrayBuffer && options.data instanceof ArrayBuffer ) || (window .Blob && options.data instanceof Blob ))))) { return { send : function (headers, callback ) { var xhr = new XMLHttpRequest (), url = options.url , type = options.type , async = options.async || true , dataType = options.responseType || "arraybuffer" , data = options.data || null ; xhr.addEventListener ('load' , function ( ) { var data = {}; data[options.dataType ] = xhr.response ; callback (xhr.status , xhr.statusText , data, xhr.getAllResponseHeaders ()); }); xhr.open (type, url, async ); for (var i in headers) { xhr.setRequestHeader (i, headers[i]); } xhr.responseType = dataType; xhr.send (data); }, abort : function ( ) { } }; } }); }); class Parser { constructor (data ) { this .dv = new DataView (data); this .endian = true ; this .offset = 0 ; } getUint4 ( ) { const val = this .dv .getUint32 (this .offset , this .endian ); this .offset += 4 ; return val; } getUint1 ( ) { const val = this .dv .getUint8 (this .offset , this .endian ); this .offset += 1 ; return val; } getUint2 ( ) { const val = this .dv .getUint16 (this .offset , this .endian ); this .offset += 2 ; return val; } getLenStr ( ) { const len = this .getUint1 (); var str = "" ; var val = "" ; for (var i = 0 ; i < len; i++) { val = this .getUint1 (); str += String .fromCharCode (val); } return { len : len, str : str, }; } getFloat8 ( ) { const val = this .dv .getFloat64 (this .offset , this .endian ); this .offset += 8 ; return val; } getFloat4 ( ) { const val = this .dv .getFloat32 (this .offset , this .endian ); this .offset += 4 ; return val; } getVersion ( ) { const val = `${this .getUint1()} .${this .getUint1()} .${this .getUint1()} .${this .getUint1()} ` ; return val; } getBox ( ) { var minX = this .getFloat8 (); var maxX = this .getFloat8 (); var minY = this .getFloat8 (); var maxY = this .getFloat8 (); var minZ = this .getFloat8 (); var maxZ = this .getFloat8 (); return { minX : minX, maxX : maxX, minY : minY, maxY : maxY, minZ : minZ, maxZ : maxZ } } getVector2df ( ) { var x = this .getFloat4 (); var y = this .getFloat4 (); return { x : x, y : y } } getVector3df ( ) { var x = this .getFloat4 (); var y = this .getFloat4 (); var z = this .getFloat4 (); return { x : x, y : y, z : z } } getVector3dd ( ) { var x = this .getFloat8 (); var y = this .getFloat8 (); var z = this .getFloat8 (); return { x : x, y : y, z : z } } getCountVert ( ) { const count = this .getUint4 (); var vert = []; for (var i = 0 ; i < count; i++) { const pos = this .getVector3df (); const normal = this .getVector3df (); const uv = this .getVector2df (); vert.push ({ pos : pos, normal : normal, uv : uv }) } return { count : count, vert : vert }; } getCountIndex ( ) { const count = this .getUint4 (); var index = []; for (var i = 0 ; i < count; i++) { const val = this .getUint2 (); index.push (val) } return { count : count, index : index }; } getBox3dd ( ) { const min = this .getVector3dd (); const max = this .getVector3dd (); return { min : min, max : max } } }
데이터 파일 조회
위에서 얻은 데이터 파일명을 사용하여 조회합니다.
요청 URL
http://xdworld.vworld.kr:8080/XDServer/3DData?Version=2.0.0.0&Request=GetLayer&Key=3XE3C10E-82B7-3E7F-AC31-37175F32CDE4&Layer=facility_build&Level=15&IDX=279420&IDY=116121&DataFile=a13_112.xdo
VWorld 3D Map Binary Data File Format 을 확인하여 리턴된 바이너리 파일을 분석합니다.
Real3D Model Data (*.xdo) Format 구성
Object Attribute
Name
Size(byte)
Type
설명
Type
1
u8
객체의 타입 (객체의 형식 Real3D Model 은 8 고정으로 사용)
Object ID
4
u32
객체의 고유번호 (객체의 고유 ID 식별번호, 레이어 기준으로 객체 등록 번호)
KeyLen
1
u8
객체의 키값 길이
Key
KeyLen
char*
객체의 키값 (객체의 고유 식별 문자열)
Object Box
48
aabbox3dd
객체의 범위 (구면 Vector) (객체의 최대 최소 영역 범위, World Wind 구면 Vector 좌표계)
Altitude
4
f32
객체의 높이 (객체의 바닥면 기준 해발고도 높이)
3D Mesh Data
Name
Size (byte)
Type
설명
Vertex Count
4
u32
버텍스 총수
Vertex
Vertex Count
S3DVertex*
버텍스 값 (형상을 구성하는 정규화된 공간 좌표점)
Indexed Count
4
u32
인덱스 총수
Indexed
Indexed Count
u16*
인덱스 값 (Vertex 정점을 삼각형 그릴 시에 그리는 순서 리스트)
Color
4
u32
객체색상 (Mesh의 재질의 색상(A8R8G8B8))
ImageLevel
1
byte
이미지 LOD 총 레벨 (LOD 텍스처의 레벨 단계)
ImageNameLen
1
byte
텍스쳐 이미지명 길이
imageName
ImageNameLen
char*
텍스처 이미지명(확장자 제외, jpg) (LOD 텍스처 파일명)
index를 확인합니다.
vertex 를 확인합니다.
S3DVertex
Name
Size(byte)
Type
설명
Pos
12
vector3df
버텍스 좌표
Normal
12
vector3df
버텍스 노말
UV
8
vector2df
텍스처 UV
aabbox3d
Name
Size(byte)
Type
설명
Min
24
vector3dd
최소 좌표점
Max
24
vector3dd
최대 좌표점
vector2df
Name
Size(byte)
Type
설명
x
4
float
x축 값
y
4
float
y축 값
vector2dd
Name
Size(byte)
Type
설명
x
8
double
x축 값
y
8
double
y축 값
vector3df
Name
Size(byte)
Type
설명
x
4
float
x축 값
y
4
float
y축 값
z
4
float
z축 값
vector3dd
Name
Size(byte)
Type
설명
x
8
double
x축 값
y
8
double
y축 값
z
8
double
z축 값
이미지 파일 조회
위에서 얻은 이미지 파일명을 사용하여 조회합니다.
http://xdworld.vworld.kr:8080/XDServer/3DData?Version=2.0.0.0&Request=GetLayer&Key=3XE3C10E-82B7-3E7F-AC31-37175F32CDE4&Layer=facility_build&Level=15&IDX=279420&IDY=116121&DataFile=a13_52.jpg
다운로드 받은 파일의 확장자를 jpg
로 변경하여 이미지를 확인할 수 있습니다.
여기까지 해서 오브젝트 생성을 위한 데이터를 모두 얻었습니다.
오브젝트 생성 (Three.js 사용)
기본 구조는 이렇습니다.
Geometry 생성
버텍스 추가
버텍스 인덱스 추가
UV 추가
이미지 파일 추가
메테리얼 생성
메시 생성
샘플 코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 var vert = data.vert ;var index = data.index ;var geometry = new THREE .Geometry ();for (var i = 0 ; i < vert.length ; i += 3 ) { var v1 = vert[i]; var v2 = vert[i + 1 ]; var v3 = vert[i + 2 ]; geometry.vertices .push (new THREE .Vector3 (v1.pos .x , v1.pos .y , v1.pos .z )); geometry.vertices .push (new THREE .Vector3 (v2.pos .x , v2.pos .y , v2.pos .z )); geometry.vertices .push (new THREE .Vector3 (v3.pos .x , v3.pos .y , v3.pos .z )); geometry.faces .push (new THREE .Face3 (index[i], index[i + 1 ], index[i + 2 ])); geometry.faceVertexUvs [0 ].push ([ new THREE .Vector2 (v1.uv .x , 1 - v1.uv .y ), new THREE .Vector2 (v3.uv .x , 1 - v3.uv .y ), new THREE .Vector2 (v2.uv .x , 1 - v2.uv .y ) ]); } geometry.uvsNeedUpdate = true ; const textureLoader = new THREE .TextureLoader ();textureLoader.crossOrigin = "Anonymous" ; const myTexture = textureLoader.load (jpgUrl);var material = new THREE .MeshBasicMaterial ({ side : THREE .DoubleSide , map : myTexture }); var build = new THREE .Mesh (geometry, material);
코드상에 잘못된 부분이 있으면 말씀해 주세요.
여기까지가 메시를 생성하는 부분이고, 이후에는 Three.js Scene
에 추가합니다.
Scene 생성
카메라 생성
렌더러 생성
컨테이너에 추가
메쉬 추가
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <html > <div id ="ThreeContainer" > </div > <script > function initThree ( ) { var fov = 45 ; var width = window .innerWidth ; var height = window .innerHeight ; var aspect = width / height; var near = 1 ; var far = 10 * 1000 * 1000 ; _three.scene = new THREE .Scene (); _three.camera = new THREE .PerspectiveCamera (fov, aspect, near, far); _three.renderer = new THREE .WebGLRenderer ({alpha : true }); _ThreeContainer.appendChild (_three.renderer .domElement ); } function init3DObject ( ){ var buildGroup = new THREE .Group (); buildGroup.add (build); _three.scene .add (buildGroup); } initThree (); init3DObject (); </script > </html >
이렇게 하면 Vworld 로 부터 받은 3D data 를 Three.js 로 그릴 수 있습니다.