Skip to content

Commit ac78082

Browse files
committed
Merge pull request #3696 from AnalyticalGraphicsInc/imagery-reprojection
Fix texture loading and re-projection bug
2 parents 7338c29 + 4349564 commit ac78082

7 files changed

+111
-9
lines changed

CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Change Log
1111
* Fixed loading for KML `NetworkLink` to not append a `?` if there isn't a query string.
1212
* Fixed `Color.fromCssColorString` from reusing the input `result` alpha value in some cases.
1313
* Fix issue with billboard collections that have at least one billboard with an aligned axis and at least one billboard without an aligned axis. [#3318](https://github.com/AnalyticalGraphicsInc/cesium/issues/3318)
14+
* Fix a race condition that would cause the terrain to continue loading and unloading or cause a crash when changing terrain providers. [#3690](https://github.com/AnalyticalGraphicsInc/cesium/issues/3690)
1415

1516
### 1.19 - 2016-03-01
1617

Source/Scene/Globe.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ define([
426426

427427
that._oceanNormalMap = that._oceanNormalMap && that._oceanNormalMap.destroy();
428428
that._oceanNormalMap = new Texture({
429-
context : context,
429+
context : frameState.context,
430430
source : image
431431
});
432432
});

Source/Scene/GlobeSurfaceTileProvider.js

+13-2
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,12 @@ define([
289289
* @param {FrameState} frameState The frame state.
290290
*/
291291
GlobeSurfaceTileProvider.prototype.initialize = function(frameState) {
292-
this._imageryLayers._update();
292+
var imageryLayers = this._imageryLayers;
293+
294+
// update collection: imagery indices, base layers, raise layer show/hide event
295+
imageryLayers._update();
296+
// update each layer for texture reprojection.
297+
imageryLayers.queueReprojectionCommands(frameState);
293298

294299
if (this._layerOrderChanged) {
295300
this._layerOrderChanged = false;
@@ -307,7 +312,6 @@ define([
307312
creditDisplay.addCredit(this._terrainProvider.credit);
308313
}
309314

310-
var imageryLayers = this._imageryLayers;
311315
for (var i = 0, len = imageryLayers.length; i < len; ++i) {
312316
var imageryProvider = imageryLayers.get(i).imageryProvider;
313317
if (imageryProvider.ready && defined(imageryProvider.credit)) {
@@ -407,6 +411,13 @@ define([
407411
}
408412
};
409413

414+
/**
415+
* Cancels any imagery re-projections in the queue.
416+
*/
417+
GlobeSurfaceTileProvider.prototype.cancelReprojections = function() {
418+
this._imageryLayers.cancelReprojections();
419+
};
420+
410421
/**
411422
* Gets the maximum geometric error allowed in a tile at a given level, in meters. This function should not be
412423
* called before {@link GlobeSurfaceTileProvider#ready} returns true.

Source/Scene/ImageryLayer.js

+29-2
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,8 @@ define([
235235
this._isBaseLayer = false;
236236

237237
this._requestImageError = undefined;
238+
239+
this._reprojectComputeCommands = [];
238240
}
239241

240242
defineProperties(ImageryLayer.prototype, {
@@ -739,7 +741,7 @@ define([
739741
}
740742

741743
/**
742-
* Reproject a texture to a {@link GeographicProjection}, if necessary, and generate
744+
* Enqueues a command re-projecting a texture to a {@link GeographicProjection} on the next update, if necessary, and generate
743745
* mipmaps for the geographic texture.
744746
*
745747
* @private
@@ -773,12 +775,37 @@ define([
773775
finalizeReprojectTexture(that, context, imagery, outputTexture);
774776
}
775777
});
776-
frameState.commandList.push(computeCommand);
778+
this._reprojectComputeCommands.push(computeCommand);
777779
} else {
778780
finalizeReprojectTexture(this, context, imagery, texture);
779781
}
780782
};
781783

784+
/**
785+
* Updates frame state to execute any queued texture re-projections.
786+
*
787+
* @private
788+
*
789+
* @param {FrameState} frameState The frameState.
790+
*/
791+
ImageryLayer.prototype.queueReprojectionCommands = function(frameState) {
792+
var computeCommands = this._reprojectComputeCommands;
793+
var length = computeCommands.length;
794+
for (var i = 0; i < length; ++i) {
795+
frameState.commandList.push(computeCommands[i]);
796+
}
797+
computeCommands.length = 0;
798+
};
799+
800+
/**
801+
* Cancels re-projection commands queued for the next frame.
802+
*
803+
* @private
804+
*/
805+
ImageryLayer.prototype.cancelReprojections = function() {
806+
this._reprojectComputeCommands.length = 0;
807+
};
808+
782809
ImageryLayer.prototype.getImageryFromCache = function(x, y, level, imageryRectangle) {
783810
var cacheKey = getImageryCacheKey(x, y, level);
784811
var imagery = this._imageryCache[cacheKey];

Source/Scene/ImageryLayerCollection.js

+26
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,32 @@ define([
459459
});
460460
};
461461

462+
/**
463+
* Updates frame state to execute any queued texture re-projections.
464+
*
465+
* @private
466+
*
467+
* @param {FrameState} frameState The frameState.
468+
*/
469+
ImageryLayerCollection.prototype.queueReprojectionCommands = function(frameState) {
470+
var layers = this._layers;
471+
for (var i = 0, len = layers.length; i < len; ++i) {
472+
layers[i].queueReprojectionCommands(frameState);
473+
}
474+
};
475+
476+
/**
477+
* Cancels re-projection commands queued for the next frame.
478+
*
479+
* @private
480+
*/
481+
ImageryLayerCollection.prototype.cancelReprojections = function() {
482+
var layers = this._layers;
483+
for (var i = 0, len = layers.length; i < len; ++i) {
484+
layers[i].cancelReprojections();
485+
}
486+
};
487+
462488
/**
463489
* Returns true if this object was destroyed; otherwise, false.
464490
* <br /><br />

Source/Scene/QuadtreePrimitive.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,8 @@ define([
193193
}
194194

195195
this._levelZeroTiles = undefined;
196+
197+
this._tileProvider.cancelReprojections();
196198
};
197199

198200
/**
@@ -268,6 +270,7 @@ define([
268270
return;
269271
}
270272

273+
// Gets commands for any texture re-projections and updates the credit display
271274
this._tileProvider.initialize(frameState);
272275

273276
var debug = this._debug;
@@ -281,8 +284,6 @@ define([
281284
debug.tilesRendered = 0;
282285
debug.tilesWaitingForChildren = 0;
283286

284-
processTileLoadQueue(this, frameState);
285-
286287
this._tileLoadQueue.length = 0;
287288
this._tileReplacementQueue.markStartOfRenderFrame();
288289
};
@@ -316,6 +317,8 @@ define([
316317
return;
317318
}
318319

320+
// Load/create resources for terrain and imagery. Prepare texture re-projections for the next frame.
321+
processTileLoadQueue(this, frameState);
319322
updateHeights(this, frameState);
320323

321324
var debug = this._debug;

Specs/Scene/ImageryLayerSpec.js

+36-2
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ defineSuite([
6666
loadJsonp.loadAndExecuteScript = loadJsonp.defaultLoadAndExecuteScript;
6767
loadImage.createImage = loadImage.defaultCreateImage;
6868
loadWithXhr.load = loadWithXhr.defaultLoad;
69+
70+
frameState.commandList.length = 0;
6971
});
7072

7173
function CustomDiscardPolicy() {
@@ -117,7 +119,7 @@ defineSuite([
117119
});
118120
});
119121

120-
it('reprojects web mercator images', function() {
122+
function createWebMercatorProvider() {
121123
loadJsonp.loadAndExecuteScript = function(url, functionName) {
122124
window[functionName]({
123125
"authenticationResultCode" : "ValidCredentials",
@@ -152,11 +154,14 @@ defineSuite([
152154
loadWithXhr.defaultLoad('Data/Images/Red16x16.png', responseType, method, data, headers, deferred);
153155
};
154156

155-
var provider = new BingMapsImageryProvider({
157+
return new BingMapsImageryProvider({
156158
url : 'http://host.invalid',
157159
tileDiscardPolicy : new NeverTileDiscardPolicy()
158160
});
161+
}
159162

163+
it('reprojects web mercator images', function() {
164+
var provider = createWebMercatorProvider();
160165
var layer = new ImageryLayer(provider);
161166

162167
return pollToPromise(function() {
@@ -176,6 +181,7 @@ defineSuite([
176181
}).then(function() {
177182
var textureBeforeReprojection = imagery.texture;
178183
layer._reprojectTexture(frameState, imagery);
184+
layer.queueReprojectionCommands(frameState);
179185
frameState.commandList[0].execute(computeEngine);
180186

181187
return pollToPromise(function() {
@@ -189,6 +195,34 @@ defineSuite([
189195
});
190196
});
191197

198+
it('cancels reprojection', function() {
199+
var provider = createWebMercatorProvider();
200+
var layer = new ImageryLayer(provider);
201+
202+
return pollToPromise(function() {
203+
return provider.ready;
204+
}).then(function() {
205+
var imagery = new Imagery(layer, 0, 0, 0);
206+
imagery.addReference();
207+
layer._requestImagery(imagery);
208+
209+
return pollToPromise(function() {
210+
return imagery.state === ImageryState.RECEIVED;
211+
}).then(function() {
212+
layer._createTexture(context, imagery);
213+
214+
return pollToPromise(function() {
215+
return imagery.state === ImageryState.TEXTURE_LOADED;
216+
}).then(function() {
217+
layer._reprojectTexture(frameState, imagery);
218+
layer.cancelReprojections();
219+
layer.queueReprojectionCommands(frameState);
220+
expect(frameState.commandList.length).toEqual(0);
221+
});
222+
});
223+
});
224+
});
225+
192226
it('basic properties work as expected', function() {
193227
var provider = new SingleTileImageryProvider({
194228
url : 'Data/Images/Red16x16.png'

0 commit comments

Comments
 (0)