@@ -20,6 +20,7 @@ define([
20
20
'./QuantizedMeshTerrainData' ,
21
21
'./Request' ,
22
22
'./RequestType' ,
23
+ './RuntimeError' ,
23
24
'./TerrainProvider' ,
24
25
'./TileAvailability' ,
25
26
'./TileProviderError'
@@ -45,11 +46,21 @@ define([
45
46
QuantizedMeshTerrainData ,
46
47
Request ,
47
48
RequestType ,
49
+ RuntimeError ,
48
50
TerrainProvider ,
49
51
TileAvailability ,
50
52
TileProviderError ) {
51
53
'use strict' ;
52
54
55
+ function LayerInformation ( layer ) {
56
+ this . isHeightmap = layer . isHeightmap ;
57
+ this . tileUrlTemplates = layer . tileUrlTemplates ;
58
+ this . availability = layer . availability ;
59
+ this . hasVertexNormals = layer . hasVertexNormals ;
60
+ this . hasWaterMask = layer . hasWaterMask ;
61
+ this . littleEndianExtensionSize = layer . littleEndianExtensionSize ;
62
+ }
63
+
53
64
/**
54
65
* A {@link TerrainProvider} that accesses terrain data in a Cesium terrain format.
55
66
* The format is described on the
@@ -114,22 +125,16 @@ define([
114
125
115
126
this . _heightmapStructure = undefined ;
116
127
this . _hasWaterMask = false ;
117
-
118
- /**
119
- * Boolean flag that indicates if the Terrain Server can provide vertex normals.
120
- * @type {Boolean }
121
- * @default false
122
- * @private
123
- */
124
128
this . _hasVertexNormals = false ;
129
+
125
130
/**
126
131
* Boolean flag that indicates if the client should request vertex normals from the server.
127
132
* @type {Boolean }
128
133
* @default false
129
134
* @private
130
135
*/
131
136
this . _requestVertexNormals = defaultValue ( options . requestVertexNormals , false ) ;
132
- this . _littleEndianExtensionSize = true ;
137
+
133
138
/**
134
139
* Boolean flag that indicates if the client should request tile watermasks from the server.
135
140
* @type {Boolean }
@@ -139,17 +144,19 @@ define([
139
144
this . _requestWaterMask = defaultValue ( options . requestWaterMask , false ) ;
140
145
141
146
this . _errorEvent = new Event ( ) ;
142
- this . _availability = undefined ;
143
147
144
148
var credit = options . credit ;
145
149
if ( typeof credit === 'string' ) {
146
150
credit = new Credit ( credit ) ;
147
151
}
148
152
this . _credit = credit ;
149
153
154
+ this . _availability = undefined ;
155
+
150
156
this . _ready = false ;
151
157
this . _readyPromise = when . defer ( ) ;
152
158
159
+ var lastUrl = this . _url ;
153
160
var metadataUrl = joinUrls ( this . _url , 'layer.json' ) ;
154
161
if ( defined ( this . _proxy ) ) {
155
162
metadataUrl = this . _proxy . getURL ( metadataUrl ) ;
@@ -158,7 +165,11 @@ define([
158
165
var that = this ;
159
166
var metadataError ;
160
167
161
- function metadataSuccess ( data ) {
168
+ var layers = this . _layers = [ ] ;
169
+ var attribution = '' ;
170
+ var overallAvailability = [ ] ;
171
+
172
+ function parseMetadataSuccess ( data ) {
162
173
var message ;
163
174
164
175
if ( ! data . format ) {
@@ -173,8 +184,14 @@ define([
173
184
return ;
174
185
}
175
186
187
+ var hasVertexNormals = false ;
188
+ var hasWaterMask = false ;
189
+ var littleEndianExtensionSize = true ;
190
+ var isHeightmap = false ;
176
191
if ( data . format === 'heightmap-1.0' ) {
177
- that . _heightmapStructure = {
192
+ isHeightmap = true ;
193
+ if ( ! defined ( that . _heightmapStructure ) ) {
194
+ that . _heightmapStructure = {
178
195
heightScale : 1.0 / 5.0 ,
179
196
heightOffset : - 1000.0 ,
180
197
elementsPerHeight : 1 ,
@@ -184,63 +201,131 @@ define([
184
201
lowestEncodedHeight : 0 ,
185
202
highestEncodedHeight : 256 * 256 - 1
186
203
} ;
187
- that . _hasWaterMask = true ;
204
+ }
205
+ hasWaterMask = true ;
188
206
that . _requestWaterMask = true ;
189
207
} else if ( data . format . indexOf ( 'quantized-mesh-1.' ) !== 0 ) {
190
208
message = 'The tile format "' + data . format + '" is invalid or not supported.' ;
191
209
metadataError = TileProviderError . handleError ( metadataError , that , that . _errorEvent , message , undefined , undefined , undefined , requestMetadata ) ;
192
210
return ;
193
211
}
194
212
195
- that . _tileUrlTemplates = data . tiles ;
196
- for ( var i = 0 ; i < that . _tileUrlTemplates . length ; ++ i ) {
197
- var template = new Uri ( that . _tileUrlTemplates [ i ] ) ;
198
- var baseUri = new Uri ( that . _url ) ;
213
+ var tileUrlTemplates = data . tiles ;
214
+ for ( var i = 0 ; i < tileUrlTemplates . length ; ++ i ) {
215
+ var template = new Uri ( tileUrlTemplates [ i ] ) ;
216
+ var baseUri = new Uri ( lastUrl ) ;
199
217
if ( template . authority && ! baseUri . authority ) {
200
218
baseUri . authority = template . authority ;
201
219
baseUri . scheme = template . scheme ;
202
220
}
203
- that . _tileUrlTemplates [ i ] = joinUrls ( baseUri , template ) . toString ( ) . replace ( '{version}' , data . version ) ;
221
+ tileUrlTemplates [ i ] = joinUrls ( baseUri , template ) . toString ( ) . replace ( '{version}' , data . version ) ;
204
222
}
205
223
206
224
var availableTiles = data . available ;
207
-
225
+ var availability ;
208
226
if ( defined ( availableTiles ) ) {
209
- that . _availability = new TileAvailability ( that . _tilingScheme , availableTiles . length ) ;
227
+ availability = new TileAvailability ( that . _tilingScheme , availableTiles . length ) ;
210
228
211
229
for ( var level = 0 ; level < availableTiles . length ; ++ level ) {
212
230
var rangesAtLevel = availableTiles [ level ] ;
213
231
var yTiles = that . _tilingScheme . getNumberOfYTilesAtLevel ( level ) ;
232
+ if ( ! defined ( overallAvailability [ level ] ) ) {
233
+ overallAvailability [ level ] = [ ] ;
234
+ }
214
235
215
236
for ( var rangeIndex = 0 ; rangeIndex < rangesAtLevel . length ; ++ rangeIndex ) {
216
237
var range = rangesAtLevel [ rangeIndex ] ;
217
- that . _availability . addAvailableTileRange ( level , range . startX , yTiles - range . endY - 1 , range . endX , yTiles - range . startY - 1 ) ;
238
+ var yStart = yTiles - range . endY - 1 ;
239
+ var yEnd = yTiles - range . startY - 1 ;
240
+ overallAvailability [ level ] . push ( [ range . startX , yStart , range . endX , yEnd ] ) ;
241
+ availability . addAvailableTileRange ( level , range . startX , yStart , range . endX , yEnd ) ;
218
242
}
219
243
}
220
244
}
221
245
222
- if ( ! defined ( that . _credit ) && defined ( data . attribution ) && data . attribution !== null ) {
223
- that . _credit = new Credit ( data . attribution ) ;
224
- }
225
-
226
246
// The vertex normals defined in the 'octvertexnormals' extension is identical to the original
227
247
// contents of the original 'vertexnormals' extension. 'vertexnormals' extension is now
228
248
// deprecated, as the extensionLength for this extension was incorrectly using big endian.
229
249
// We maintain backwards compatibility with the legacy 'vertexnormal' implementation
230
250
// by setting the _littleEndianExtensionSize to false. Always prefer 'octvertexnormals'
231
251
// over 'vertexnormals' if both extensions are supported by the server.
232
252
if ( defined ( data . extensions ) && data . extensions . indexOf ( 'octvertexnormals' ) !== - 1 ) {
233
- that . _hasVertexNormals = true ;
253
+ hasVertexNormals = true ;
234
254
} else if ( defined ( data . extensions ) && data . extensions . indexOf ( 'vertexnormals' ) !== - 1 ) {
235
- that . _hasVertexNormals = true ;
236
- that . _littleEndianExtensionSize = false ;
255
+ hasVertexNormals = true ;
256
+ littleEndianExtensionSize = false ;
237
257
}
238
258
if ( defined ( data . extensions ) && data . extensions . indexOf ( 'watermask' ) !== - 1 ) {
239
- that . _hasWaterMask = true ;
259
+ hasWaterMask = true ;
260
+ }
261
+
262
+ that . _hasWaterMask = that . _hasWaterMask || hasWaterMask ;
263
+ that . _hasVertexNormals = that . _hasVertexNormals || hasVertexNormals ;
264
+ if ( defined ( data . attribution ) ) {
265
+ if ( attribution . length > 0 ) {
266
+ attribution += ' ' ;
267
+ }
268
+ attribution += data . attribution ;
269
+ }
270
+
271
+ layers . push ( new LayerInformation ( {
272
+ isHeightmap : isHeightmap ,
273
+ tileUrlTemplates : tileUrlTemplates ,
274
+ availability : availability ,
275
+ hasVertexNormals : hasVertexNormals ,
276
+ hasWaterMask : hasWaterMask ,
277
+ littleEndianExtensionSize : littleEndianExtensionSize
278
+ } ) ) ;
279
+
280
+ var parentUrl = data . parentUrl ;
281
+ if ( defined ( parentUrl ) ) {
282
+ if ( ! defined ( availability ) ) {
283
+ console . log ( 'A layer.json can\'t have a parentUrl if it does\'t have an available array.' ) ;
284
+ return when . resolve ( ) ;
285
+ }
286
+ lastUrl = joinUrls ( lastUrl , parentUrl ) ;
287
+ metadataUrl = joinUrls ( lastUrl , 'layer.json' ) ;
288
+ if ( defined ( that . _proxy ) ) {
289
+ metadataUrl = that . _proxy . getURL ( metadataUrl ) ;
290
+ }
291
+ var parentMetadata = loadJson ( metadataUrl ) ;
292
+ return when ( parentMetadata , parseMetadataSuccess , parseMetadataFailure ) ;
240
293
}
241
294
242
- that . _ready = true ;
243
- that . _readyPromise . resolve ( true ) ;
295
+ return when . resolve ( ) ;
296
+ }
297
+
298
+ function parseMetadataFailure ( data ) {
299
+ var message = 'An error occurred while accessing ' + metadataUrl + '.' ;
300
+ metadataError = TileProviderError . handleError ( metadataError , that , that . _errorEvent , message , undefined , undefined , undefined , requestMetadata ) ;
301
+ }
302
+
303
+ function metadataSuccess ( data ) {
304
+ parseMetadataSuccess ( data )
305
+ . then ( function ( ) {
306
+ if ( defined ( metadataError ) ) {
307
+ return ;
308
+ }
309
+
310
+ var length = overallAvailability . length ;
311
+ if ( length > 0 ) {
312
+ var availability = that . _availability = new TileAvailability ( that . _tilingScheme , length ) ;
313
+ for ( var level = 0 ; level < length ; ++ level ) {
314
+ var levelRanges = overallAvailability [ level ] ;
315
+ for ( var i = 0 ; i < levelRanges . length ; ++ i ) {
316
+ var range = levelRanges [ i ] ;
317
+ availability . addAvailableTileRange ( level , range [ 0 ] , range [ 1 ] , range [ 2 ] , range [ 3 ] ) ;
318
+ }
319
+ }
320
+ }
321
+
322
+ if ( ! defined ( that . _credit ) && attribution . length > 0 ) {
323
+ that . _credit = new Credit ( attribution ) ;
324
+ }
325
+
326
+ that . _ready = true ;
327
+ that . _readyPromise . resolve ( true ) ;
328
+ } ) ;
244
329
}
245
330
246
331
function metadataFailure ( data ) {
@@ -257,8 +342,7 @@ define([
257
342
} ) ;
258
343
return ;
259
344
}
260
- var message = 'An error occurred while accessing ' + metadataUrl + '.' ;
261
- metadataError = TileProviderError . handleError ( metadataError , that , that . _errorEvent , message , undefined , undefined , undefined , requestMetadata ) ;
345
+ parseMetadataFailure ( data ) ;
262
346
}
263
347
264
348
function requestMetadata ( ) {
@@ -320,7 +404,7 @@ define([
320
404
} ) ;
321
405
}
322
406
323
- function createQuantizedMeshTerrainData ( provider , buffer , level , x , y , tmsY ) {
407
+ function createQuantizedMeshTerrainData ( provider , buffer , level , x , y , tmsY , littleEndianExtensionSize ) {
324
408
var pos = 0 ;
325
409
var cartesian3Elements = 3 ;
326
410
var boundingSphereElements = cartesian3Elements + 1 ;
@@ -431,7 +515,7 @@ define([
431
515
while ( pos < view . byteLength ) {
432
516
var extensionId = view . getUint8 ( pos , true ) ;
433
517
pos += Uint8Array . BYTES_PER_ELEMENT ;
434
- var extensionLength = view . getUint32 ( pos , provider . _littleEndianExtensionSize ) ;
518
+ var extensionLength = view . getUint32 ( pos , littleEndianExtensionSize ) ;
435
519
pos += Uint32Array . BYTES_PER_ELEMENT ;
436
520
437
521
if ( extensionId === QuantizedMeshExtensionIds . OCT_VERTEX_NORMALS && provider . _requestVertexNormals ) {
@@ -505,7 +589,27 @@ define([
505
589
}
506
590
//>>includeEnd('debug');
507
591
508
- var urlTemplates = this . _tileUrlTemplates ;
592
+ var layers = this . _layers ;
593
+ var layerToUse ;
594
+ var layerCount = layers . length ;
595
+
596
+ if ( layerCount === 1 ) { // Optimized path for single layers
597
+ layerToUse = layers [ 0 ] ;
598
+ } else {
599
+ for ( var i = 0 ; i < layerCount ; ++ i ) {
600
+ var layer = layers [ i ] ;
601
+ if ( ! defined ( layer . availability ) || layer . availability . isTileAvailable ( level , x , y ) ) {
602
+ layerToUse = layer ;
603
+ break ;
604
+ }
605
+ }
606
+ }
607
+
608
+ if ( ! defined ( layerToUse ) ) {
609
+ return when . reject ( new RuntimeError ( 'Terrain tile doesn\'t exist' ) ) ;
610
+ }
611
+
612
+ var urlTemplates = layerToUse . tileUrlTemplates ;
509
613
if ( urlTemplates . length === 0 ) {
510
614
return undefined ;
511
615
}
@@ -522,10 +626,10 @@ define([
522
626
}
523
627
524
628
var extensionList = [ ] ;
525
- if ( this . _requestVertexNormals && this . _hasVertexNormals ) {
526
- extensionList . push ( this . _littleEndianExtensionSize ? 'octvertexnormals' : 'vertexnormals' ) ;
629
+ if ( this . _requestVertexNormals && layerToUse . hasVertexNormals ) {
630
+ extensionList . push ( layerToUse . littleEndianExtensionSize ? 'octvertexnormals' : 'vertexnormals' ) ;
527
631
}
528
- if ( this . _requestWaterMask && this . _hasWaterMask ) {
632
+ if ( this . _requestWaterMask && layerToUse . hasWaterMask ) {
529
633
extensionList . push ( 'watermask' ) ;
530
634
}
531
635
@@ -540,7 +644,7 @@ define([
540
644
if ( defined ( that . _heightmapStructure ) ) {
541
645
return createHeightmapTerrainData ( that , buffer , level , x , y , tmsY ) ;
542
646
}
543
- return createQuantizedMeshTerrainData ( that , buffer , level , x , y , tmsY ) ;
647
+ return createQuantizedMeshTerrainData ( that , buffer , level , x , y , tmsY , layerToUse . littleEndianExtensionSize ) ;
544
648
} ) ;
545
649
} ;
546
650
@@ -723,10 +827,11 @@ define([
723
827
* @returns {Boolean } Undefined if not supported, otherwise true or false.
724
828
*/
725
829
CesiumTerrainProvider . prototype . getTileDataAvailable = function ( x , y , level ) {
726
- if ( ! defined ( this . availability ) ) {
830
+ if ( ! defined ( this . _availability ) ) {
727
831
return undefined ;
728
832
}
729
- return this . availability . isTileAvailable ( level , x , y ) ;
833
+
834
+ return this . _availability . isTileAvailable ( level , x , y ) ;
730
835
} ;
731
836
732
837
return CesiumTerrainProvider ;
0 commit comments