Merge branch 'master' of github.com:openlayers/ol3 into vector
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
goog.provide('ol.renderer.dom.Layer');
|
||||
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.FrameState');
|
||||
goog.require('ol.layer.Layer');
|
||||
goog.require('ol.layer.LayerState');
|
||||
goog.require('ol.renderer.Layer');
|
||||
|
||||
|
||||
@@ -13,6 +16,7 @@ goog.require('ol.renderer.Layer');
|
||||
* @param {!Element} target Target.
|
||||
*/
|
||||
ol.renderer.dom.Layer = function(mapRenderer, layer, target) {
|
||||
|
||||
goog.base(this, mapRenderer, layer);
|
||||
|
||||
/**
|
||||
@@ -21,27 +25,15 @@ ol.renderer.dom.Layer = function(mapRenderer, layer, target) {
|
||||
*/
|
||||
this.target = target;
|
||||
|
||||
/**
|
||||
* Top left corner of the target in map coords.
|
||||
*
|
||||
* @type {ol.Coordinate}
|
||||
* @protected
|
||||
*/
|
||||
this.origin = null;
|
||||
|
||||
this.handleLayerOpacityChange();
|
||||
this.handleLayerVisibleChange();
|
||||
|
||||
};
|
||||
goog.inherits(ol.renderer.dom.Layer, ol.renderer.Layer);
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @return {ol.renderer.Map} Map renderer.
|
||||
* @return {!Element} Target.
|
||||
*/
|
||||
ol.renderer.dom.Layer.prototype.getMapRenderer = function() {
|
||||
return /** @type {ol.renderer.dom.Map} */ goog.base(this, 'getMapRenderer');
|
||||
ol.renderer.dom.Layer.prototype.getTarget = function() {
|
||||
return this.target;
|
||||
};
|
||||
|
||||
|
||||
@@ -57,7 +49,7 @@ ol.renderer.dom.Layer.prototype.handleLayerLoad = function() {
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.dom.Layer.prototype.handleLayerOpacityChange = function() {
|
||||
goog.style.setOpacity(this.target, this.getLayer().getOpacity());
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
@@ -65,22 +57,12 @@ ol.renderer.dom.Layer.prototype.handleLayerOpacityChange = function() {
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.dom.Layer.prototype.handleLayerVisibleChange = function() {
|
||||
goog.style.showElement(this.target, this.getLayer().getVisible());
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Render.
|
||||
* @param {number} time Time.
|
||||
* @param {ol.FrameState} frameState Frame state.
|
||||
* @param {ol.layer.LayerState} layerState Layer state.
|
||||
*/
|
||||
ol.renderer.dom.Layer.prototype.renderFrame = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Set the location of the top left corner of the target.
|
||||
*
|
||||
* @param {ol.Coordinate} origin Origin.
|
||||
*/
|
||||
ol.renderer.dom.Layer.prototype.setOrigin = function(origin) {
|
||||
this.origin = origin;
|
||||
};
|
||||
|
||||
@@ -5,8 +5,9 @@ goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.Event');
|
||||
goog.require('goog.functions');
|
||||
goog.require('goog.style');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.FrameState');
|
||||
goog.require('ol.layer.TileLayer');
|
||||
goog.require('ol.renderer.Map');
|
||||
goog.require('ol.renderer.dom.TileLayer');
|
||||
@@ -37,92 +38,32 @@ ol.renderer.dom.Map = function(container, map) {
|
||||
goog.dom.insertChildAt(container, this.layersPane_, 0);
|
||||
|
||||
/**
|
||||
* @type {Object}
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.layerPanes_ = {};
|
||||
this.renderedVisible_ = true;
|
||||
|
||||
/**
|
||||
* @type {ol.Coordinate}
|
||||
* @private
|
||||
*/
|
||||
this.renderedCenter_ = null;
|
||||
|
||||
/**
|
||||
* @type {number | undefined}
|
||||
* @private
|
||||
*/
|
||||
this.renderedResolution_ = undefined;
|
||||
|
||||
/**
|
||||
* @type {ol.Size}
|
||||
* @private
|
||||
*/
|
||||
this.renderedSize_ = null;
|
||||
|
||||
/**
|
||||
* @type {number | undefined}
|
||||
* @private
|
||||
*/
|
||||
this.renderedRotation_ = undefined;
|
||||
|
||||
/**
|
||||
* The origin (top left) of the layers pane in map coordinates.
|
||||
*
|
||||
* @type {ol.Coordinate}
|
||||
* @private
|
||||
*/
|
||||
this.layersPaneOrigin_ = null;
|
||||
};
|
||||
goog.inherits(ol.renderer.dom.Map, ol.renderer.Map);
|
||||
|
||||
|
||||
/**
|
||||
* Apply the given transform to the layers pane.
|
||||
* @param {number} dx Translation along the x-axis.
|
||||
* @param {number} dy Translation along the y-axis.
|
||||
* @param {number} rotation Rotation angle.
|
||||
* @private
|
||||
*/
|
||||
ol.renderer.dom.Map.prototype.applyTransform_ = function(dx, dy, rotation) {
|
||||
var transform =
|
||||
'translate(' + Math.round(dx) + 'px, ' + Math.round(dy) + 'px) ' +
|
||||
'rotate(' + rotation.toFixed(6) + 'rad) ' +
|
||||
'scale3d(1, 1, 1)';
|
||||
|
||||
var style = this.layersPane_.style;
|
||||
style.WebkitTransform = transform;
|
||||
style.MozTransform = transform;
|
||||
style.OTransform = transform;
|
||||
style.msTransform = transform;
|
||||
style.transform = transform;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.dom.Map.prototype.canRotate = goog.functions.TRUE;
|
||||
ol.renderer.dom.Map.prototype.addLayer = function(layer) {
|
||||
goog.base(this, 'addLayer', layer);
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.dom.Map.prototype.createLayerRenderer = function(layer) {
|
||||
|
||||
if (layer instanceof ol.layer.TileLayer) {
|
||||
|
||||
var layerPane = goog.dom.createElement(goog.dom.TagName.DIV);
|
||||
layerPane.className = 'ol-layer';
|
||||
layerPane.style.position = 'absolute';
|
||||
goog.dom.appendChild(this.layersPane_, layerPane);
|
||||
|
||||
var layerRenderer = new ol.renderer.dom.TileLayer(this, layer, layerPane);
|
||||
|
||||
this.layerPanes_[goog.getUid(layerRenderer)] = layerPane;
|
||||
|
||||
var layerRenderer = new ol.renderer.dom.TileLayer(this, layer);
|
||||
goog.dom.appendChild(this.layersPane_, layerRenderer.getTarget());
|
||||
return layerRenderer;
|
||||
|
||||
} else {
|
||||
goog.asserts.assert(false);
|
||||
return null;
|
||||
@@ -133,8 +74,8 @@ ol.renderer.dom.Map.prototype.createLayerRenderer = function(layer) {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.dom.Map.prototype.handleCenterChanged = function() {
|
||||
goog.base(this, 'handleCenterChanged');
|
||||
ol.renderer.dom.Map.prototype.removeLayer = function(layer) {
|
||||
goog.base(this, 'removeLayer', layer);
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
@@ -142,145 +83,30 @@ ol.renderer.dom.Map.prototype.handleCenterChanged = function() {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.dom.Map.prototype.handleResolutionChanged = function() {
|
||||
goog.base(this, 'handleResolutionChanged');
|
||||
this.getMap().render();
|
||||
};
|
||||
ol.renderer.dom.Map.prototype.renderFrame = function(frameState) {
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.dom.Map.prototype.handleRotationChanged = function() {
|
||||
goog.base(this, 'handleRotationChanged');
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.dom.Map.prototype.handleSizeChanged = function() {
|
||||
goog.base(this, 'handleSizeChanged');
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Render the map. Sets up the layers pane on first render and adjusts its
|
||||
* position as needed on subsequent calls.
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.dom.Map.prototype.renderFrame = function(time) {
|
||||
var map = this.getMap();
|
||||
if (!map.isDef()) {
|
||||
if (goog.isNull(frameState)) {
|
||||
if (this.renderedVisible_) {
|
||||
goog.style.showElement(this.layersPane_, false);
|
||||
this.renderedVisible_ = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var mapCenter = map.getCenter();
|
||||
var mapSize = map.getSize();
|
||||
var mapResolution = map.getResolution();
|
||||
var mapRotation = map.getRotation();
|
||||
|
||||
goog.asserts.assert(goog.isDefAndNotNull(mapCenter));
|
||||
goog.asserts.assert(goog.isDef(mapResolution));
|
||||
goog.asserts.assert(goog.isDef(mapRotation));
|
||||
goog.asserts.assert(goog.isDefAndNotNull(mapSize));
|
||||
|
||||
if (goog.isNull(this.renderedCenter_)) {
|
||||
// first rendering
|
||||
goog.asserts.assert(!goog.isDef(this.renderedResolution_));
|
||||
goog.asserts.assert(!goog.isDef(this.renderedRotation_));
|
||||
goog.asserts.assert(goog.isNull(this.renderedSize_));
|
||||
this.resetLayersPane_();
|
||||
} else {
|
||||
goog.asserts.assert(goog.isDef(this.renderedResolution_));
|
||||
goog.asserts.assert(!goog.isNull(this.renderedSize_));
|
||||
if (mapResolution !== this.renderedResolution_ ||
|
||||
!mapSize.equals(this.renderedSize_)) {
|
||||
// resolution or size changed, adjust layers pane
|
||||
this.resetLayersPane_();
|
||||
} else if (!mapCenter.equals(this.renderedCenter_) ||
|
||||
mapRotation !== this.renderedRotation_) {
|
||||
// same resolution and size, new center or rotation
|
||||
this.transformLayersPane_();
|
||||
goog.array.forEach(frameState.layersArray, function(layer) {
|
||||
var layerState = frameState.layerStates[goog.getUid(layer)];
|
||||
if (!layerState.ready) {
|
||||
return;
|
||||
}
|
||||
var layerRenderer = this.getLayerRenderer(layer);
|
||||
layerRenderer.renderFrame(frameState, layerState);
|
||||
}, this);
|
||||
|
||||
if (!this.renderedVisible_) {
|
||||
goog.style.showElement(this.layersPane_, true);
|
||||
this.renderedVisible_ = true;
|
||||
}
|
||||
|
||||
this.renderedCenter_ = mapCenter;
|
||||
this.renderedResolution_ = mapResolution;
|
||||
this.renderedRotation_ = mapRotation;
|
||||
this.renderedSize_ = mapSize;
|
||||
|
||||
var requestRenderFrame = false;
|
||||
this.forEachReadyVisibleLayer(function(layer, layerRenderer) {
|
||||
if (layerRenderer.renderFrame(time)) {
|
||||
requestRenderFrame = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (requestRenderFrame) {
|
||||
map.requestRenderFrame();
|
||||
}
|
||||
this.calculateMatrices2D(frameState);
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Reset the layers pane to its initial position.
|
||||
* @private
|
||||
*/
|
||||
ol.renderer.dom.Map.prototype.resetLayersPane_ = function() {
|
||||
var map = this.map;
|
||||
var mapSize = map.getSize();
|
||||
var halfWidth = mapSize.width / 2;
|
||||
var halfHeight = mapSize.height / 2;
|
||||
var center = map.getCenter();
|
||||
var resolution = map.getResolution();
|
||||
var origin = new ol.Coordinate(
|
||||
center.x - resolution * halfWidth,
|
||||
center.y + resolution * halfHeight);
|
||||
this.layersPaneOrigin_ = origin;
|
||||
this.setTransformOrigin_(halfWidth, halfHeight);
|
||||
this.applyTransform_(0, 0, map.getRotation());
|
||||
goog.object.forEach(this.layerRenderers, function(layerRenderer) {
|
||||
layerRenderer.setOrigin(origin);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the transform-origin CSS property of the layers pane.
|
||||
* @param {number} x The x-axis origin.
|
||||
* @param {number} y The y-axis origin.
|
||||
* @private
|
||||
*/
|
||||
ol.renderer.dom.Map.prototype.setTransformOrigin_ = function(x, y) {
|
||||
var origin = Math.round(x) + 'px ' + Math.round(y) + 'px';
|
||||
var style = this.layersPane_.style;
|
||||
style.WebkitTransformOrigin = origin;
|
||||
style.MozTransformOrigin = origin;
|
||||
style.OTransformOrigin = origin;
|
||||
style.msTransformOrigin = origin;
|
||||
style.transformOrigin = origin;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply the appropriate transform to the layers pane.
|
||||
* @private
|
||||
*/
|
||||
ol.renderer.dom.Map.prototype.transformLayersPane_ = function() {
|
||||
var map = this.map;
|
||||
var resolution = map.getResolution();
|
||||
var center = map.getCenter();
|
||||
var size = map.getSize();
|
||||
var origin = this.layersPaneOrigin_;
|
||||
var ox = (center.x - origin.x) / resolution;
|
||||
var oy = (origin.y - center.y) / resolution;
|
||||
this.setTransformOrigin_(ox, oy);
|
||||
var dx = ox - (size.width / 2);
|
||||
var dy = oy - (size.height / 2);
|
||||
this.applyTransform_(-dx, -dy, map.getRotation());
|
||||
};
|
||||
|
||||
@@ -1,13 +1,23 @@
|
||||
// FIXME probably need to reset TileLayerZ if offsets get too large
|
||||
// FIXME when zooming out, preserve higher Z divs to avoid white flash
|
||||
|
||||
goog.provide('ol.renderer.dom.TileLayer');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.Event');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.math.Vec2');
|
||||
goog.require('goog.style');
|
||||
goog.require('goog.vec.Mat4');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.Extent');
|
||||
goog.require('ol.Size');
|
||||
goog.require('ol.TileCoord');
|
||||
goog.require('ol.TileRange');
|
||||
goog.require('ol.TileState');
|
||||
goog.require('ol.ViewHint');
|
||||
goog.require('ol.dom');
|
||||
goog.require('ol.renderer.dom.Layer');
|
||||
goog.require('ol.tilegrid.TileGrid');
|
||||
|
||||
|
||||
|
||||
@@ -16,212 +26,363 @@ goog.require('ol.renderer.dom.Layer');
|
||||
* @extends {ol.renderer.dom.Layer}
|
||||
* @param {ol.renderer.Map} mapRenderer Map renderer.
|
||||
* @param {ol.layer.TileLayer} tileLayer Tile layer.
|
||||
* @param {!Element} target Target.
|
||||
*/
|
||||
ol.renderer.dom.TileLayer = function(mapRenderer, tileLayer, target) {
|
||||
ol.renderer.dom.TileLayer = function(mapRenderer, tileLayer) {
|
||||
|
||||
var target = goog.dom.createElement(goog.dom.TagName.DIV);
|
||||
target.className = 'ol-layer';
|
||||
target.style.position = 'absolute';
|
||||
|
||||
goog.base(this, mapRenderer, tileLayer, target);
|
||||
|
||||
/**
|
||||
* @type {Object}
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.renderedTiles_ = {};
|
||||
this.renderedVisible_ = true;
|
||||
|
||||
/**
|
||||
* @type {number|undefined}
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.renderedMapResolution_ = undefined;
|
||||
this.renderedOpacity_ = 1;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<number, ol.renderer.dom.TileLayerZ_>}
|
||||
*/
|
||||
this.tileLayerZs_ = {};
|
||||
|
||||
};
|
||||
goog.inherits(ol.renderer.dom.TileLayer, ol.renderer.dom.Layer);
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.layer.TileLayer} Tile layer.
|
||||
*/
|
||||
ol.renderer.dom.TileLayer.prototype.getTileLayer = function() {
|
||||
return /** @type {ol.layer.TileLayer} */ (this.getLayer());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @return {ol.layer.TileLayer} Layer.
|
||||
*/
|
||||
ol.renderer.dom.TileLayer.prototype.getLayer = function() {
|
||||
return /** @type {ol.layer.TileLayer} */ goog.base(this, 'getLayer');
|
||||
};
|
||||
ol.renderer.dom.TileLayer.prototype.renderFrame =
|
||||
function(frameState, layerState) {
|
||||
|
||||
|
||||
/**
|
||||
* Get the pixel offset between the tile origin and the container origin.
|
||||
* @private
|
||||
* @param {number} z Z.
|
||||
* @param {number} resolution Resolution.
|
||||
* @return {ol.Coordinate} Offset.
|
||||
*/
|
||||
ol.renderer.dom.TileLayer.prototype.getTileOffset_ = function(z, resolution) {
|
||||
var tileLayer = this.getLayer();
|
||||
var tileSource = tileLayer.getTileSource();
|
||||
var tileGrid = tileSource.getTileGrid();
|
||||
var tileOrigin = tileGrid.getOrigin(z);
|
||||
var offset = new ol.Coordinate(
|
||||
Math.round((this.origin.x - tileOrigin.x) / resolution),
|
||||
Math.round((tileOrigin.y - this.origin.y) / resolution));
|
||||
return offset;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get rid of all tiles that weren't drawn in the most recent rendering.
|
||||
* @param {Object.<number, Object.<string, ol.Tile>>} tilesDrawnByZ Tiles just
|
||||
* rendered.
|
||||
* @private
|
||||
*/
|
||||
ol.renderer.dom.TileLayer.prototype.removeExtraTiles_ =
|
||||
function(tilesDrawnByZ) {
|
||||
var key, tileCoord, tilesDrawn, tile;
|
||||
for (key in this.renderedTiles_) {
|
||||
tileCoord = ol.TileCoord.createFromString(key);
|
||||
tilesDrawn = tilesDrawnByZ[tileCoord.z];
|
||||
if (!(tilesDrawn && key in tilesDrawn)) {
|
||||
tile = this.renderedTiles_[key];
|
||||
delete this.renderedTiles_[key];
|
||||
goog.dom.removeNode(tile.getImage(this));
|
||||
if (!layerState.visible) {
|
||||
if (this.renderedVisible_) {
|
||||
goog.style.showElement(this.target, false);
|
||||
this.renderedVisible_ = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.dom.TileLayer.prototype.renderFrame = function(time) {
|
||||
|
||||
var map = this.getMap();
|
||||
if (!map.isDef()) {
|
||||
return;
|
||||
}
|
||||
var mapExtent = /** @type {!ol.Extent} */ map.getRotatedExtent();
|
||||
var mapResolution = /** @type {number} */ map.getResolution();
|
||||
var resolutionChanged = (mapResolution !== this.renderedMapResolution_);
|
||||
|
||||
var tileLayer = this.getLayer();
|
||||
var view2DState = frameState.view2DState;
|
||||
|
||||
var tileLayer = this.getTileLayer();
|
||||
var tileSource = tileLayer.getTileSource();
|
||||
var tileGrid = tileSource.getTileGrid();
|
||||
var z = tileGrid.getZForResolution(view2DState.resolution);
|
||||
var tileResolution = tileGrid.getResolution(z);
|
||||
var tileRange = tileGrid.getTileRangeForExtentAndResolution(
|
||||
frameState.extent, tileResolution);
|
||||
|
||||
// z represents the "best" resolution
|
||||
var z = tileGrid.getZForResolution(mapResolution);
|
||||
|
||||
/**
|
||||
* @type {Object.<number, Object.<string, ol.Tile>>}
|
||||
*/
|
||||
/** @type {Object.<number, Object.<string, ol.Tile>>} */
|
||||
var tilesToDrawByZ = {};
|
||||
tilesToDrawByZ[z] = {};
|
||||
|
||||
var tileRange =
|
||||
tileGrid.getTileRangeForExtentAndResolution(mapExtent, mapResolution);
|
||||
var findInterimTiles = function(z, tileRange) {
|
||||
// FIXME this could be more efficient about filling partial holes
|
||||
var fullyCovered = true;
|
||||
var tile, tileCoord, tileCoordKey, x, y;
|
||||
for (x = tileRange.minX; x <= tileRange.maxX; ++x) {
|
||||
for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
|
||||
tileCoord = new ol.TileCoord(z, x, y);
|
||||
tileCoordKey = tileCoord.toString();
|
||||
if (tilesToDrawByZ[z] && tilesToDrawByZ[z][tileCoordKey]) {
|
||||
return;
|
||||
}
|
||||
tile = tileSource.getTile(tileCoord);
|
||||
if (!goog.isNull(tile) && tile.getState() == ol.TileState.LOADED) {
|
||||
if (!tilesToDrawByZ[z]) {
|
||||
tilesToDrawByZ[z] = {};
|
||||
}
|
||||
tilesToDrawByZ[z][tileCoordKey] = tile;
|
||||
} else {
|
||||
fullyCovered = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return fullyCovered;
|
||||
};
|
||||
|
||||
var allTilesLoaded = true;
|
||||
var tile, tileCenter, tileCoord, tileState, x, y;
|
||||
for (x = tileRange.minX; x <= tileRange.maxX; ++x) {
|
||||
for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
|
||||
|
||||
tileCoord = new ol.TileCoord(z, x, y);
|
||||
tile = tileSource.getTile(tileCoord);
|
||||
if (goog.isNull(tile)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
tileState = tile.getState();
|
||||
if (tileState == ol.TileState.IDLE) {
|
||||
tileCenter = tileGrid.getTileCoordCenter(tileCoord);
|
||||
frameState.tileQueue.enqueue(tile, tileCenter, tileResolution);
|
||||
} else if (tileState == ol.TileState.LOADED) {
|
||||
tilesToDrawByZ[z][tileCoord.toString()] = tile;
|
||||
continue;
|
||||
} else if (tileState == ol.TileState.ERROR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
allTilesLoaded = false;
|
||||
tileGrid.forEachTileCoordParentTileRange(tileCoord, findInterimTiles);
|
||||
|
||||
// first pass through the tile range to determine all the tiles needed
|
||||
tileRange.forEachTileCoord(z, function(tileCoord) {
|
||||
var tile = tileSource.getTile(tileCoord);
|
||||
if (goog.isNull(tile)) {
|
||||
// we're outside the source's extent, continue
|
||||
return;
|
||||
}
|
||||
|
||||
var key = tile.tileCoord.toString();
|
||||
var state = tile.getState();
|
||||
if (state == ol.TileState.IDLE) {
|
||||
tile.load();
|
||||
} else if (state == ol.TileState.LOADED) {
|
||||
tilesToDrawByZ[z][key] = tile;
|
||||
return;
|
||||
}
|
||||
|
||||
allTilesLoaded = false;
|
||||
|
||||
/**
|
||||
* Look for already loaded tiles at alternate z that can serve as
|
||||
* placeholders until tiles at the current z have loaded.
|
||||
*
|
||||
* TODO: make this more efficent for filling partial holes
|
||||
*/
|
||||
tileGrid.forEachTileCoordParentTileRange(
|
||||
tileCoord,
|
||||
function(altZ, altTileRange) {
|
||||
var fullyCovered = true;
|
||||
altTileRange.forEachTileCoord(altZ, function(altTileCoord) {
|
||||
var tileKey = altTileCoord.toString();
|
||||
if (tilesToDrawByZ[altZ] && tilesToDrawByZ[altZ][tileKey]) {
|
||||
return;
|
||||
}
|
||||
var altTile = tileSource.getTile(altTileCoord);
|
||||
if (!goog.isNull(altTile) &&
|
||||
altTile.getState() == ol.TileState.LOADED) {
|
||||
if (!(altZ in tilesToDrawByZ)) {
|
||||
tilesToDrawByZ[altZ] = {};
|
||||
}
|
||||
tilesToDrawByZ[altZ][tileKey] = altTile;
|
||||
} else {
|
||||
fullyCovered = false;
|
||||
}
|
||||
});
|
||||
return fullyCovered;
|
||||
});
|
||||
|
||||
}, this);
|
||||
}
|
||||
|
||||
/** @type {Array.<number>} */
|
||||
var zs = goog.array.map(goog.object.getKeys(tilesToDrawByZ), Number);
|
||||
goog.array.sort(zs);
|
||||
|
||||
var fragment = document.createDocumentFragment();
|
||||
var altFragment = document.createDocumentFragment();
|
||||
var newTiles = false;
|
||||
var newAltTiles = false;
|
||||
for (var i = 0, ii = zs.length; i < ii; ++i) {
|
||||
var tileZ = zs[i];
|
||||
var tilesToDraw = tilesToDrawByZ[tileZ];
|
||||
var tileOffset = this.getTileOffset_(tileZ, mapResolution);
|
||||
for (var key in tilesToDraw) {
|
||||
var tile = tilesToDraw[key];
|
||||
var tileCoord = tile.tileCoord;
|
||||
var pixelBounds = tileGrid.getPixelBoundsForTileCoordAndResolution(
|
||||
tileCoord, mapResolution);
|
||||
var img = tile.getImage(this);
|
||||
var style = img.style;
|
||||
var append = !(key in this.renderedTiles_);
|
||||
if (append || resolutionChanged) {
|
||||
style.left = (pixelBounds.minX - tileOffset.x) + 'px';
|
||||
style.top = (-pixelBounds.maxY - tileOffset.y) + 'px';
|
||||
style.width = pixelBounds.getWidth() + 'px';
|
||||
style.height = pixelBounds.getHeight() + 'px';
|
||||
}
|
||||
if (append) {
|
||||
this.renderedTiles_[key] = tile;
|
||||
style.position = 'absolute';
|
||||
if (tileZ === z) {
|
||||
goog.dom.appendChild(fragment, img);
|
||||
newTiles = true;
|
||||
} else {
|
||||
goog.dom.appendChild(altFragment, img);
|
||||
newAltTiles = true;
|
||||
/** @type {Object.<number, boolean>} */
|
||||
var newTileLayerZKeys = {};
|
||||
|
||||
var tileSize = tileGrid.getTileSize();
|
||||
var iz, tileCoordKey, tileCoordOrigin, tileLayerZ, tileLayerZKey, tilesToDraw;
|
||||
for (iz = 0; iz < zs.length; ++iz) {
|
||||
tileLayerZKey = zs[iz];
|
||||
if (tileLayerZKey in this.tileLayerZs_) {
|
||||
tileLayerZ = this.tileLayerZs_[tileLayerZKey];
|
||||
} else {
|
||||
tileCoordOrigin =
|
||||
tileGrid.getTileCoordForCoordAndZ(view2DState.center, tileLayerZKey);
|
||||
tileLayerZ = new ol.renderer.dom.TileLayerZ_(tileGrid, tileCoordOrigin);
|
||||
newTileLayerZKeys[tileLayerZKey] = true;
|
||||
this.tileLayerZs_[tileLayerZKey] = tileLayerZ;
|
||||
}
|
||||
tilesToDraw = tilesToDrawByZ[tileLayerZKey];
|
||||
for (tileCoordKey in tilesToDraw) {
|
||||
tileLayerZ.addTile(tilesToDraw[tileCoordKey]);
|
||||
}
|
||||
tileLayerZ.finalizeAddTiles();
|
||||
}
|
||||
|
||||
/** @type {Array.<number>} */
|
||||
var tileLayerZKeys =
|
||||
goog.array.map(goog.object.getKeys(this.tileLayerZs_), Number);
|
||||
goog.array.sort(tileLayerZKeys);
|
||||
|
||||
var i, j, origin, resolution;
|
||||
var transform = goog.vec.Mat4.createNumber();
|
||||
for (i = 0; i < tileLayerZKeys.length; ++i) {
|
||||
tileLayerZKey = tileLayerZKeys[i];
|
||||
tileLayerZ = this.tileLayerZs_[tileLayerZKey];
|
||||
if (!(tileLayerZKey in tilesToDrawByZ)) {
|
||||
goog.dom.removeNode(tileLayerZ.target);
|
||||
delete this.tileLayerZs_[tileLayerZKey];
|
||||
continue;
|
||||
}
|
||||
resolution = tileLayerZ.getResolution();
|
||||
origin = tileLayerZ.getOrigin();
|
||||
goog.vec.Mat4.makeIdentity(transform);
|
||||
goog.vec.Mat4.translate(
|
||||
transform, frameState.size.width / 2, frameState.size.height / 2, 0);
|
||||
goog.vec.Mat4.rotateZ(transform, view2DState.rotation);
|
||||
goog.vec.Mat4.scale(transform, resolution / view2DState.resolution,
|
||||
resolution / view2DState.resolution, 1);
|
||||
goog.vec.Mat4.translate(
|
||||
transform,
|
||||
(origin.x - view2DState.center.x) / resolution,
|
||||
(view2DState.center.y - origin.y) / resolution,
|
||||
0);
|
||||
tileLayerZ.setTransform(transform);
|
||||
if (tileLayerZKey in newTileLayerZKeys) {
|
||||
for (j = tileLayerZKey - 1; j >= 0; --j) {
|
||||
if (j in this.tileLayerZs_) {
|
||||
goog.dom.insertSiblingAfter(
|
||||
tileLayerZ.target, this.tileLayerZs_[j].target);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (newAltTiles) {
|
||||
var child = this.target.firstChild;
|
||||
if (child) {
|
||||
goog.dom.insertSiblingBefore(altFragment, child);
|
||||
if (j < 0) {
|
||||
goog.dom.insertChildAt(this.target, tileLayerZ.target, 0);
|
||||
}
|
||||
} else {
|
||||
goog.dom.appendChild(this.target, altFragment);
|
||||
if (!frameState.viewHints[ol.ViewHint.ANIMATING] &&
|
||||
!frameState.viewHints[ol.ViewHint.PANNING]) {
|
||||
tileLayerZ.removeTilesOutsideExtent(frameState.extent);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (newTiles) {
|
||||
goog.dom.appendChild(this.target, fragment);
|
||||
|
||||
if (layerState.opacity != this.renderedOpacity_) {
|
||||
goog.style.setOpacity(this.target, layerState.opacity);
|
||||
this.renderedOpacity_ = layerState.opacity;
|
||||
}
|
||||
|
||||
this.renderedMapResolution_ = mapResolution;
|
||||
if (layerState.visible && !this.renderedVisible_) {
|
||||
goog.style.showElement(this.target, true);
|
||||
this.renderedVisible_ = true;
|
||||
}
|
||||
|
||||
this.removeExtraTiles_(tilesToDrawByZ);
|
||||
if (!allTilesLoaded) {
|
||||
frameState.animate = true;
|
||||
}
|
||||
|
||||
return !allTilesLoaded;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @private
|
||||
* @param {ol.tilegrid.TileGrid} tileGrid Tile grid.
|
||||
* @param {ol.TileCoord} tileCoordOrigin Tile coord origin.
|
||||
*/
|
||||
ol.renderer.dom.TileLayerZ_ = function(tileGrid, tileCoordOrigin) {
|
||||
|
||||
/**
|
||||
* @type {!Element}
|
||||
*/
|
||||
this.target = goog.dom.createElement(goog.dom.TagName.DIV);
|
||||
this.target.style.position = 'absolute';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.tilegrid.TileGrid}
|
||||
*/
|
||||
this.tileGrid_ = tileGrid;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.TileCoord}
|
||||
*/
|
||||
this.tileCoordOrigin_ = tileCoordOrigin;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Coordinate}
|
||||
*/
|
||||
this.origin_ = tileGrid.getTileCoordExtent(tileCoordOrigin).getTopLeft();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.resolution_ = tileGrid.getResolution(tileCoordOrigin.z);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object.<string, ol.Tile>}
|
||||
*/
|
||||
this.tiles_ = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {DocumentFragment}
|
||||
*/
|
||||
this.documentFragment_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {goog.vec.Mat4.AnyType}
|
||||
*/
|
||||
this.transform_ = goog.vec.Mat4.createNumberIdentity();
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Tile} tile Tile.
|
||||
*/
|
||||
ol.renderer.dom.TileLayerZ_.prototype.addTile = function(tile) {
|
||||
var tileCoord = tile.tileCoord;
|
||||
goog.asserts.assert(tileCoord.z == this.tileCoordOrigin_.z);
|
||||
var tileCoordKey = tileCoord.toString();
|
||||
if (tileCoordKey in this.tiles_) {
|
||||
return;
|
||||
}
|
||||
var tileSize = this.tileGrid_.getTileSize();
|
||||
var image = tile.getImage(this);
|
||||
var style = image.style;
|
||||
style.position = 'absolute';
|
||||
style.left =
|
||||
((tileCoord.x - this.tileCoordOrigin_.x) * tileSize.width) + 'px';
|
||||
style.top =
|
||||
((this.tileCoordOrigin_.y - tileCoord.y) * tileSize.height) + 'px';
|
||||
if (goog.isNull(this.documentFragment_)) {
|
||||
this.documentFragment_ = document.createDocumentFragment();
|
||||
}
|
||||
goog.dom.appendChild(this.documentFragment_, image);
|
||||
this.tiles_[tileCoordKey] = tile;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* FIXME empty description for jsdoc
|
||||
*/
|
||||
ol.renderer.dom.TileLayerZ_.prototype.finalizeAddTiles = function() {
|
||||
if (!goog.isNull(this.documentFragment_)) {
|
||||
goog.dom.appendChild(this.target, this.documentFragment_);
|
||||
this.documentFragment_ = null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.Coordinate} Origin.
|
||||
*/
|
||||
ol.renderer.dom.TileLayerZ_.prototype.getOrigin = function() {
|
||||
return this.origin_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Resolution.
|
||||
*/
|
||||
ol.renderer.dom.TileLayerZ_.prototype.getResolution = function() {
|
||||
return this.resolution_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Extent} extent Extent.
|
||||
*/
|
||||
ol.renderer.dom.TileLayerZ_.prototype.removeTilesOutsideExtent =
|
||||
function(extent) {
|
||||
var tileRange =
|
||||
this.tileGrid_.getTileRangeForExtentAndZ(extent, this.tileCoordOrigin_.z);
|
||||
var tilesToRemove = [];
|
||||
var tile, tileCoordKey;
|
||||
for (tileCoordKey in this.tiles_) {
|
||||
tile = this.tiles_[tileCoordKey];
|
||||
if (!tileRange.contains(tile.tileCoord)) {
|
||||
tilesToRemove.push(tile);
|
||||
}
|
||||
}
|
||||
var i;
|
||||
for (i = 0; i < tilesToRemove.length; ++i) {
|
||||
tile = tilesToRemove[i];
|
||||
tileCoordKey = tile.tileCoord.toString();
|
||||
goog.dom.removeNode(tile.getImage(this));
|
||||
delete this.tiles_[tileCoordKey];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.vec.Mat4.AnyType} transform Transform.
|
||||
*/
|
||||
ol.renderer.dom.TileLayerZ_.prototype.setTransform = function(transform) {
|
||||
if (!goog.vec.Mat4.equals(transform, this.transform_)) {
|
||||
ol.dom.transformElement2D(this.target, transform, 6);
|
||||
goog.vec.Mat4.setFromArray(this.transform_, transform);
|
||||
}
|
||||
};
|
||||
|
||||
+68
-139
@@ -1,11 +1,15 @@
|
||||
goog.provide('ol.renderer.Map');
|
||||
|
||||
goog.require('goog.Disposable');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.functions');
|
||||
goog.require('goog.fx.anim');
|
||||
goog.require('goog.fx.anim.Animated');
|
||||
goog.require('goog.vec.Mat4');
|
||||
goog.require('ol.FrameState');
|
||||
goog.require('ol.View2D');
|
||||
goog.require('ol.View2DProperty');
|
||||
|
||||
|
||||
|
||||
@@ -43,23 +47,12 @@ ol.renderer.Map = function(container, map) {
|
||||
*/
|
||||
this.layersListenerKeys_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {goog.vec.Mat4.Number}
|
||||
*/
|
||||
this.coordinateToPixelMatrix_ = goog.vec.Mat4.createNumber();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {goog.vec.Mat4.Number}
|
||||
* @type {?number}
|
||||
*/
|
||||
this.pixelToCoordinateMatrix_ = goog.vec.Mat4.createNumber();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.matricesDirty_ = true;
|
||||
this.viewPropertyListenerKey_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
@@ -70,25 +63,17 @@ ol.renderer.Map = function(container, map) {
|
||||
map, ol.Object.getChangedEventType(ol.MapProperty.BACKGROUND_COLOR),
|
||||
this.handleBackgroundColorChanged, false, this),
|
||||
|
||||
goog.events.listen(
|
||||
map, ol.Object.getChangedEventType(ol.MapProperty.CENTER),
|
||||
this.handleCenterChanged, false, this),
|
||||
|
||||
goog.events.listen(
|
||||
map, ol.Object.getChangedEventType(ol.MapProperty.LAYERS),
|
||||
this.handleLayersChanged, false, this),
|
||||
|
||||
goog.events.listen(
|
||||
map, ol.Object.getChangedEventType(ol.MapProperty.RESOLUTION),
|
||||
this.handleResolutionChanged, false, this),
|
||||
|
||||
goog.events.listen(
|
||||
map, ol.Object.getChangedEventType(ol.MapProperty.ROTATION),
|
||||
this.handleRotationChanged, false, this),
|
||||
|
||||
goog.events.listen(
|
||||
map, ol.Object.getChangedEventType(ol.MapProperty.SIZE),
|
||||
this.handleSizeChanged, false, this)
|
||||
this.handleSizeChanged, false, this),
|
||||
|
||||
goog.events.listen(
|
||||
map, ol.Object.getChangedEventType(ol.MapProperty.VIEW),
|
||||
this.handleViewChanged, false, this)
|
||||
];
|
||||
|
||||
};
|
||||
@@ -106,9 +91,35 @@ ol.renderer.Map.prototype.addLayer = function(layer) {
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Can rotate.
|
||||
* @param {ol.FrameState} frameState FrameState.
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Map.prototype.canRotate = goog.functions.FALSE;
|
||||
ol.renderer.Map.prototype.calculateMatrices2D = function(frameState) {
|
||||
|
||||
var view2DState = frameState.view2DState;
|
||||
var coordinateToPixelMatrix = frameState.coordinateToPixelMatrix;
|
||||
|
||||
goog.vec.Mat4.makeIdentity(coordinateToPixelMatrix);
|
||||
goog.vec.Mat4.translate(coordinateToPixelMatrix,
|
||||
frameState.size.width / 2,
|
||||
frameState.size.height / 2,
|
||||
0);
|
||||
goog.vec.Mat4.scale(coordinateToPixelMatrix,
|
||||
1 / view2DState.resolution,
|
||||
-1 / view2DState.resolution,
|
||||
1);
|
||||
goog.vec.Mat4.rotateZ(coordinateToPixelMatrix,
|
||||
-view2DState.rotation);
|
||||
goog.vec.Mat4.translate(coordinateToPixelMatrix,
|
||||
-view2DState.center.x,
|
||||
-view2DState.center.y,
|
||||
0);
|
||||
|
||||
var inverted = goog.vec.Mat4.invert(
|
||||
coordinateToPixelMatrix, frameState.pixelToCoordinateMatrix);
|
||||
goog.asserts.assert(inverted);
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@@ -127,6 +138,9 @@ ol.renderer.Map.prototype.disposeInternal = function() {
|
||||
goog.dispose(layerRenderer);
|
||||
});
|
||||
goog.array.forEach(this.mapListenerKeys_, goog.events.unlistenByKey);
|
||||
if (!goog.isNull(this.viewPropertyListenerKey_)) {
|
||||
goog.events.unlistenByKey(this.viewPropertyListenerKey_);
|
||||
}
|
||||
if (!goog.isNull(this.layersListenerKeys_)) {
|
||||
goog.array.forEach(this.layersListenerKeys_, goog.events.unlistenByKey);
|
||||
}
|
||||
@@ -134,37 +148,6 @@ ol.renderer.Map.prototype.disposeInternal = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {function(this: T, ol.layer.Layer, ol.renderer.Layer, number)} f
|
||||
* Function.
|
||||
* @param {T=} opt_obj Object.
|
||||
* @template T
|
||||
*/
|
||||
ol.renderer.Map.prototype.forEachReadyVisibleLayer = function(f, opt_obj) {
|
||||
var layers = this.map.getLayers();
|
||||
if (goog.isDef(layers)) {
|
||||
layers.forEach(function(layer, index) {
|
||||
if (layer.isReady() && layer.getVisible()) {
|
||||
var layerRenderer = this.getLayerRenderer(layer);
|
||||
f.call(opt_obj, layer, layerRenderer, index);
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Pixel} pixel Pixel.
|
||||
* @return {ol.Coordinate} Coordinate.
|
||||
*/
|
||||
ol.renderer.Map.prototype.getCoordinateFromPixel = function(pixel) {
|
||||
this.updateMatrices_();
|
||||
var vec3 = [pixel.x, pixel.y, 0];
|
||||
goog.vec.Mat4.multVec3(this.pixelToCoordinateMatrix_, vec3, vec3);
|
||||
return new ol.Coordinate(vec3[0], vec3[1]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.layer.Layer} layer Layer.
|
||||
* @protected
|
||||
@@ -186,38 +169,18 @@ ol.renderer.Map.prototype.getMap = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @return {ol.Pixel} Pixel.
|
||||
*/
|
||||
ol.renderer.Map.prototype.getPixelFromCoordinate = function(coordinate) {
|
||||
this.updateMatrices_();
|
||||
var vec3 = [coordinate.x, coordinate.y, 0];
|
||||
goog.vec.Mat4.multVec3(this.coordinateToPixelMatrix_, vec3, vec3);
|
||||
return new ol.Pixel(vec3[0], vec3[1]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle background color changed.
|
||||
*/
|
||||
ol.renderer.Map.prototype.handleBackgroundColorChanged = goog.nullFunction;
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Map.prototype.handleCenterChanged = function() {
|
||||
this.matricesDirty_ = true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.CollectionEvent} collectionEvent Collection event.
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Map.prototype.handleLayersAdd = function(collectionEvent) {
|
||||
var layer = /** @type {ol.layer.Layer} */ collectionEvent.elem;
|
||||
var layer = /** @type {ol.layer.Layer} */ (collectionEvent.elem);
|
||||
this.addLayer(layer);
|
||||
};
|
||||
|
||||
@@ -226,10 +189,7 @@ ol.renderer.Map.prototype.handleLayersAdd = function(collectionEvent) {
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Map.prototype.handleLayersChanged = function() {
|
||||
var layerRenderers = goog.object.getValues(this.layerRenderers);
|
||||
goog.array.forEach(layerRenderers, function(layerRenderer) {
|
||||
this.removeLayerRenderer(layerRenderer);
|
||||
}, this);
|
||||
goog.disposeAll(goog.object.getValues(this.layerRenderers));
|
||||
this.layerRenderers = {};
|
||||
if (!goog.isNull(this.layersListenerKeys_)) {
|
||||
goog.array.forEach(this.layersListenerKeys_, goog.events.unlistenByKey);
|
||||
@@ -253,7 +213,7 @@ ol.renderer.Map.prototype.handleLayersChanged = function() {
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Map.prototype.handleLayersRemove = function(collectionEvent) {
|
||||
var layer = /** @type {ol.layer.Layer} */ collectionEvent.elem;
|
||||
var layer = /** @type {ol.layer.Layer} */ (collectionEvent.elem);
|
||||
this.removeLayer(layer);
|
||||
};
|
||||
|
||||
@@ -261,16 +221,8 @@ ol.renderer.Map.prototype.handleLayersRemove = function(collectionEvent) {
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Map.prototype.handleResolutionChanged = function() {
|
||||
this.matricesDirty_ = true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Map.prototype.handleRotationChanged = function() {
|
||||
this.matricesDirty_ = true;
|
||||
ol.renderer.Map.prototype.handleViewPropertyChanged = function() {
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
@@ -278,7 +230,25 @@ ol.renderer.Map.prototype.handleRotationChanged = function() {
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Map.prototype.handleSizeChanged = function() {
|
||||
this.matricesDirty_ = true;
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
ol.renderer.Map.prototype.handleViewChanged = function() {
|
||||
if (!goog.isNull(this.viewPropertyListenerKey_)) {
|
||||
goog.events.unlistenByKey(this.viewPropertyListenerKey_);
|
||||
this.viewPropertyListenerKey_ = null;
|
||||
}
|
||||
var view = this.getMap().getView();
|
||||
if (goog.isDefAndNotNull(view)) {
|
||||
this.viewPropertyListenerKey_ = goog.events.listen(
|
||||
view, ol.ObjectEventType.CHANGED,
|
||||
this.handleViewPropertyChanged, false, this);
|
||||
}
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
@@ -310,9 +280,9 @@ ol.renderer.Map.prototype.removeLayerRenderer = function(layer) {
|
||||
|
||||
/**
|
||||
* Render.
|
||||
* @param {number} time Time.
|
||||
* @param {?ol.FrameState} frameState Frame state.
|
||||
*/
|
||||
ol.renderer.Map.prototype.renderFrame = goog.functions.FALSE;
|
||||
ol.renderer.Map.prototype.renderFrame = goog.nullFunction;
|
||||
|
||||
|
||||
/**
|
||||
@@ -325,44 +295,3 @@ ol.renderer.Map.prototype.setLayerRenderer = function(layer, layerRenderer) {
|
||||
goog.asserts.assert(!(key in this.layerRenderers));
|
||||
this.layerRenderers[key] = layerRenderer;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.renderer.Map.prototype.updateMatrices_ = function() {
|
||||
|
||||
if (this.matricesDirty_) {
|
||||
|
||||
var map = this.map;
|
||||
var center = /** @type {!ol.Coordinate} */ map.getCenter();
|
||||
var resolution = /** @type {number} */ map.getResolution();
|
||||
var rotation = map.getRotation();
|
||||
var size = /** @type {!ol.Size} */ map.getSize();
|
||||
|
||||
goog.vec.Mat4.makeIdentity(this.coordinateToPixelMatrix_);
|
||||
goog.vec.Mat4.translate(this.coordinateToPixelMatrix_,
|
||||
size.width / 2,
|
||||
size.height / 2,
|
||||
0);
|
||||
goog.vec.Mat4.scale(this.coordinateToPixelMatrix_,
|
||||
1 / resolution,
|
||||
-1 / resolution,
|
||||
1);
|
||||
if (this.canRotate() && goog.isDef(rotation)) {
|
||||
goog.vec.Mat4.rotateZ(this.coordinateToPixelMatrix_, -rotation);
|
||||
}
|
||||
goog.vec.Mat4.translate(this.coordinateToPixelMatrix_,
|
||||
-center.x,
|
||||
-center.y,
|
||||
0);
|
||||
|
||||
var inverted = goog.vec.Mat4.invert(
|
||||
this.coordinateToPixelMatrix_, this.pixelToCoordinateMatrix_);
|
||||
goog.asserts.assert(inverted);
|
||||
|
||||
this.matricesDirty_ = false;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
// FIXME move colorMatrix_ elsewhere?
|
||||
|
||||
goog.provide('ol.renderer.webgl.Layer');
|
||||
|
||||
goog.require('goog.vec.Mat4');
|
||||
goog.require('ol.FrameState');
|
||||
goog.require('ol.layer.Layer');
|
||||
goog.require('ol.layer.LayerState');
|
||||
goog.require('ol.renderer.Layer');
|
||||
goog.require('ol.vec.Mat4');
|
||||
|
||||
|
||||
|
||||
@@ -13,7 +18,50 @@ goog.require('ol.renderer.Layer');
|
||||
* @param {ol.layer.Layer} layer Layer.
|
||||
*/
|
||||
ol.renderer.webgl.Layer = function(mapRenderer, layer) {
|
||||
|
||||
goog.base(this, mapRenderer, layer);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!goog.vec.Mat4.Float32}
|
||||
*/
|
||||
this.brightnessMatrix_ = goog.vec.Mat4.createFloat32();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!goog.vec.Mat4.Float32}
|
||||
*/
|
||||
this.contrastMatrix_ = goog.vec.Mat4.createFloat32();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!goog.vec.Mat4.Float32}
|
||||
*/
|
||||
this.hueMatrix_ = goog.vec.Mat4.createFloat32();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!goog.vec.Mat4.Float32}
|
||||
*/
|
||||
this.saturationMatrix_ = goog.vec.Mat4.createFloat32();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!goog.vec.Mat4.Float32}
|
||||
*/
|
||||
this.colorMatrix_ = goog.vec.Mat4.createFloat32();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.colorMatrixDirty_ = true;
|
||||
|
||||
this.handleLayerBrightnessChange();
|
||||
this.handleLayerContrastChange();
|
||||
this.handleLayerHueChange();
|
||||
this.handleLayerSaturationChange();
|
||||
|
||||
};
|
||||
goog.inherits(ol.renderer.webgl.Layer, ol.renderer.Layer);
|
||||
|
||||
@@ -27,17 +75,28 @@ ol.renderer.webgl.Layer.prototype.dispatchChangeEvent = function() {
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @return {ol.renderer.Map} MapRenderer.
|
||||
* @return {!goog.vec.Mat4.Float32} Color matrix.
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.getMapRenderer = function() {
|
||||
return /** @type {ol.renderer.webgl.Map} */ goog.base(
|
||||
this, 'getMapRenderer');
|
||||
ol.renderer.webgl.Layer.prototype.getColorMatrix = function() {
|
||||
if (this.colorMatrixDirty_) {
|
||||
this.updateColorMatrix_();
|
||||
}
|
||||
return this.colorMatrix_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {goog.vec.Mat4.AnyType} Matrix.
|
||||
* @inheritDoc
|
||||
* @return {ol.renderer.Map} MapRenderer.
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.getMapRenderer = function() {
|
||||
return /** @type {ol.renderer.webgl.Map} */ (goog.base(
|
||||
this, 'getMapRenderer'));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!goog.vec.Mat4.Number} Matrix.
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.getMatrix = goog.abstractMethod;
|
||||
|
||||
@@ -52,6 +111,9 @@ ol.renderer.webgl.Layer.prototype.getTexture = goog.abstractMethod;
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.handleLayerBrightnessChange = function() {
|
||||
var value = this.getLayer().getBrightness();
|
||||
ol.vec.Mat4.makeBrightness(this.brightnessMatrix_, value);
|
||||
this.colorMatrixDirty_ = true;
|
||||
this.dispatchChangeEvent();
|
||||
};
|
||||
|
||||
@@ -60,6 +122,9 @@ ol.renderer.webgl.Layer.prototype.handleLayerBrightnessChange = function() {
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.handleLayerContrastChange = function() {
|
||||
var value = this.getLayer().getContrast();
|
||||
ol.vec.Mat4.makeContrast(this.contrastMatrix_, value);
|
||||
this.colorMatrixDirty_ = true;
|
||||
this.dispatchChangeEvent();
|
||||
};
|
||||
|
||||
@@ -68,6 +133,9 @@ ol.renderer.webgl.Layer.prototype.handleLayerContrastChange = function() {
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.handleLayerHueChange = function() {
|
||||
var value = this.getLayer().getHue();
|
||||
ol.vec.Mat4.makeHue(this.hueMatrix_, value);
|
||||
this.colorMatrixDirty_ = true;
|
||||
this.dispatchChangeEvent();
|
||||
};
|
||||
|
||||
@@ -92,6 +160,9 @@ ol.renderer.webgl.Layer.prototype.handleLayerOpacityChange = function() {
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.handleLayerSaturationChange = function() {
|
||||
var saturation = this.getLayer().getSaturation();
|
||||
ol.vec.Mat4.makeSaturation(this.saturationMatrix_, saturation);
|
||||
this.colorMatrixDirty_ = true;
|
||||
this.dispatchChangeEvent();
|
||||
};
|
||||
|
||||
@@ -112,7 +183,21 @@ ol.renderer.webgl.Layer.prototype.handleWebGLContextLost = goog.nullFunction;
|
||||
|
||||
/**
|
||||
* Render.
|
||||
* @param {number} time Time.
|
||||
* @return {boolean} Request render frame.
|
||||
* @param {ol.FrameState} frameState Frame state.
|
||||
* @param {ol.layer.LayerState} layerState Layer state.
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.renderFrame = goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol.renderer.webgl.Layer.prototype.updateColorMatrix_ = function() {
|
||||
var colorMatrix = this.colorMatrix_;
|
||||
goog.vec.Mat4.makeIdentity(colorMatrix);
|
||||
goog.vec.Mat4.multMat(colorMatrix, this.contrastMatrix_, colorMatrix);
|
||||
goog.vec.Mat4.multMat(colorMatrix, this.brightnessMatrix_, colorMatrix);
|
||||
goog.vec.Mat4.multMat(colorMatrix, this.saturationMatrix_, colorMatrix);
|
||||
goog.vec.Mat4.multMat(colorMatrix, this.hueMatrix_, colorMatrix);
|
||||
this.colorMatrixDirty_ = false;
|
||||
};
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// FIXME clear textureCache
|
||||
// FIXME defer texture loads until after render when animating
|
||||
// FIXME generational tile texture garbage collector newFrame/get
|
||||
// FIXME defer cleanup until post-render
|
||||
// FIXME check against gl.getParameter(webgl.MAX_TEXTURE_SIZE)
|
||||
|
||||
goog.provide('ol.renderer.webgl.Map');
|
||||
@@ -14,10 +12,9 @@ goog.require('goog.dom.TagName');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.Event');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.functions');
|
||||
goog.require('goog.style');
|
||||
goog.require('goog.vec.Mat4');
|
||||
goog.require('goog.webgl');
|
||||
goog.require('ol.Tile');
|
||||
goog.require('ol.layer.Layer');
|
||||
goog.require('ol.layer.TileLayer');
|
||||
goog.require('ol.renderer.webgl.FragmentShader');
|
||||
@@ -119,6 +116,12 @@ ol.renderer.webgl.Map = function(container, map) {
|
||||
this.canvas_.className = 'ol-unselectable';
|
||||
goog.dom.insertChildAt(container, this.canvas_, 0);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.renderedVisible_ = true;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Size}
|
||||
@@ -143,12 +146,6 @@ ol.renderer.webgl.Map = function(container, map) {
|
||||
goog.events.listen(this.canvas_, ol.webgl.WebGLContextEventType.RESTORED,
|
||||
this.handleWebGLContextResourced, false, this);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.Color}
|
||||
*/
|
||||
this.clearColor_ = new ol.Color(1, 1, 1, 1);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {{aPosition: number,
|
||||
@@ -220,15 +217,15 @@ ol.renderer.webgl.Map.prototype.addLayer = function(layer) {
|
||||
|
||||
|
||||
/**
|
||||
* @param {Image} image Image.
|
||||
* @param {ol.Tile} tile Tile.
|
||||
* @param {number} magFilter Mag filter.
|
||||
* @param {number} minFilter Min filter.
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.bindImageTexture =
|
||||
function(image, magFilter, minFilter) {
|
||||
ol.renderer.webgl.Map.prototype.bindTileTexture =
|
||||
function(tile, magFilter, minFilter) {
|
||||
var gl = this.getGL();
|
||||
var imageKey = image.src;
|
||||
var textureCacheEntry = this.textureCache_[imageKey];
|
||||
var tileKey = tile.getKey();
|
||||
var textureCacheEntry = this.textureCache_[tileKey];
|
||||
if (goog.isDef(textureCacheEntry)) {
|
||||
gl.bindTexture(goog.webgl.TEXTURE_2D, textureCacheEntry.texture);
|
||||
if (textureCacheEntry.magFilter != magFilter) {
|
||||
@@ -245,7 +242,7 @@ ol.renderer.webgl.Map.prototype.bindImageTexture =
|
||||
var texture = gl.createTexture();
|
||||
gl.bindTexture(goog.webgl.TEXTURE_2D, texture);
|
||||
gl.texImage2D(goog.webgl.TEXTURE_2D, 0, goog.webgl.RGBA, goog.webgl.RGBA,
|
||||
goog.webgl.UNSIGNED_BYTE, image);
|
||||
goog.webgl.UNSIGNED_BYTE, tile.getImage());
|
||||
gl.texParameteri(
|
||||
goog.webgl.TEXTURE_2D, goog.webgl.TEXTURE_MAG_FILTER, magFilter);
|
||||
gl.texParameteri(
|
||||
@@ -254,7 +251,7 @@ ol.renderer.webgl.Map.prototype.bindImageTexture =
|
||||
goog.webgl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(goog.webgl.TEXTURE_2D, goog.webgl.TEXTURE_WRAP_T,
|
||||
goog.webgl.CLAMP_TO_EDGE);
|
||||
this.textureCache_[imageKey] = {
|
||||
this.textureCache_[tileKey] = {
|
||||
texture: texture,
|
||||
magFilter: magFilter,
|
||||
minFilter: minFilter
|
||||
@@ -263,75 +260,10 @@ ol.renderer.webgl.Map.prototype.bindImageTexture =
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.canRotate = goog.functions.TRUE;
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} value Hue value.
|
||||
* @return {!goog.vec.Mat4.Float32} Matrix.
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.createHueRotateMatrix = function(value) {
|
||||
var cosHue = Math.cos(value);
|
||||
var sinHue = Math.sin(value);
|
||||
var v00 = 0.213 + cosHue * 0.787 - sinHue * 0.213;
|
||||
var v01 = 0.715 - cosHue * 0.715 - sinHue * 0.715;
|
||||
var v02 = 0.072 - cosHue * 0.072 + sinHue * 0.928;
|
||||
var v03 = 0;
|
||||
var v10 = 0.213 - cosHue * 0.213 + sinHue * 0.143;
|
||||
var v11 = 0.715 + cosHue * 0.285 + sinHue * 0.140;
|
||||
var v12 = 0.072 - cosHue * 0.072 - sinHue * 0.283;
|
||||
var v13 = 0;
|
||||
var v20 = 0.213 - cosHue * 0.213 - sinHue * 0.787;
|
||||
var v21 = 0.715 - cosHue * 0.715 + sinHue * 0.715;
|
||||
var v22 = 0.072 + cosHue * 0.928 + sinHue * 0.072;
|
||||
var v23 = 0;
|
||||
var v30 = 0;
|
||||
var v31 = 0;
|
||||
var v32 = 0;
|
||||
var v33 = 1;
|
||||
var matrix = goog.vec.Mat4.createFloat32();
|
||||
goog.vec.Mat4.setFromValues(matrix,
|
||||
v00, v10, v20, v30,
|
||||
v01, v11, v21, v31,
|
||||
v02, v12, v22, v32,
|
||||
v03, v13, v23, v33);
|
||||
return matrix;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} value Brightness value.
|
||||
* @return {!goog.vec.Mat4.Float32} Matrix.
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.createBrightnessMatrix = function(value) {
|
||||
var matrix = goog.vec.Mat4.createFloat32Identity();
|
||||
goog.vec.Mat4.setColumnValues(matrix, 3, value, value, value, 1);
|
||||
return matrix;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} value Contrast value.
|
||||
* @return {!goog.vec.Mat4.Float32} Matrix.
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.createContrastMatrix = function(value) {
|
||||
var matrix = goog.vec.Mat4.createFloat32();
|
||||
goog.vec.Mat4.setDiagonalValues(matrix, value, value, value, 1);
|
||||
var translateValue = (-0.5 * value + 0.5);
|
||||
goog.vec.Mat4.setColumnValues(matrix, 3,
|
||||
translateValue, translateValue, translateValue, 1);
|
||||
return matrix;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.createLayerRenderer = function(layer) {
|
||||
var gl = this.getGL();
|
||||
if (layer instanceof ol.layer.TileLayer) {
|
||||
return new ol.renderer.webgl.TileLayer(this, layer);
|
||||
} else {
|
||||
@@ -341,38 +273,6 @@ ol.renderer.webgl.Map.prototype.createLayerRenderer = function(layer) {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} value Saturation value.
|
||||
* @return {!goog.vec.Mat4.Float32} Matrix.
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.createSaturateMatrix = function(value) {
|
||||
var v00 = 0.213 + 0.787 * value;
|
||||
var v01 = 0.715 - 0.715 * value;
|
||||
var v02 = 0.072 - 0.072 * value;
|
||||
var v03 = 0;
|
||||
var v10 = 0.213 - 0.213 * value;
|
||||
var v11 = 0.715 + 0.285 * value;
|
||||
var v12 = 0.072 - 0.072 * value;
|
||||
var v13 = 0;
|
||||
var v20 = 0.213 - 0.213 * value;
|
||||
var v21 = 0.715 - 0.715 * value;
|
||||
var v22 = 0.072 + 0.928 * value;
|
||||
var v23 = 0;
|
||||
var v30 = 0;
|
||||
var v31 = 0;
|
||||
var v32 = 0;
|
||||
var v33 = 1;
|
||||
var matrix = goog.vec.Mat4.createFloat32();
|
||||
goog.vec.Mat4.setFromValues(matrix,
|
||||
v00, v10, v20, v30,
|
||||
v01, v11, v21, v31,
|
||||
v02, v12, v22, v32,
|
||||
v03, v13, v23, v33);
|
||||
return matrix;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@@ -464,21 +364,6 @@ ol.renderer.webgl.Map.prototype.getShader = function(shaderObject) {
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.handleBackgroundColorChanged = function() {
|
||||
var backgroundColor = this.getMap().getBackgroundColor();
|
||||
this.clearColor_ = new ol.Color(
|
||||
backgroundColor.r / 255,
|
||||
backgroundColor.g / 255,
|
||||
backgroundColor.b / 255,
|
||||
backgroundColor.a / 255);
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.handleCenterChanged = function() {
|
||||
goog.base(this, 'handleCenterChanged');
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
@@ -492,33 +377,6 @@ ol.renderer.webgl.Map.prototype.handleLayerRendererChange = function(event) {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.handleResolutionChanged = function() {
|
||||
goog.base(this, 'handleResolutionChanged');
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.handleRotationChanged = function() {
|
||||
goog.base(this, 'handleRotationChanged');
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.handleSizeChanged = function() {
|
||||
goog.base(this, 'handleSizeChanged');
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.events.Event} event Event.
|
||||
* @protected
|
||||
@@ -565,11 +423,11 @@ ol.renderer.webgl.Map.prototype.initializeGL_ = function() {
|
||||
|
||||
|
||||
/**
|
||||
* @param {Image} image Image.
|
||||
* @return {boolean} Is image texture loaded.
|
||||
* @param {ol.Tile} tile Tile.
|
||||
* @return {boolean} Is tile texture loaded.
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.isImageTextureLoaded = function(image) {
|
||||
return image.src in this.textureCache_;
|
||||
ol.renderer.webgl.Map.prototype.isTileTextureLoaded = function(tile) {
|
||||
return tile.getKey() in this.textureCache_;
|
||||
};
|
||||
|
||||
|
||||
@@ -601,40 +459,38 @@ ol.renderer.webgl.Map.prototype.removeLayerRenderer = function(layer) {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.renderFrame = function(time) {
|
||||
ol.renderer.webgl.Map.prototype.renderFrame = function(frameState) {
|
||||
|
||||
if (!this.getMap().isDef()) {
|
||||
return;
|
||||
var gl = this.getGL();
|
||||
|
||||
if (goog.isNull(frameState)) {
|
||||
if (this.renderedVisible_) {
|
||||
goog.style.showElement(this.canvas_, false);
|
||||
this.renderedVisible_ = false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
var requestRenderFrame = false;
|
||||
|
||||
this.forEachReadyVisibleLayer(function(layer, layerRenderer) {
|
||||
if (layerRenderer.renderFrame(time)) {
|
||||
requestRenderFrame = true;
|
||||
goog.array.forEach(frameState.layersArray, function(layer) {
|
||||
var layerState = frameState.layerStates[goog.getUid(layer)];
|
||||
if (!layerState.visible || !layerState.ready) {
|
||||
return;
|
||||
}
|
||||
});
|
||||
var layerRenderer = this.getLayerRenderer(layer);
|
||||
layerRenderer.renderFrame(frameState, layerState);
|
||||
}, this);
|
||||
|
||||
var size = /** @type {ol.Size} */ this.getMap().getSize();
|
||||
var size = frameState.size;
|
||||
if (!this.canvasSize_.equals(size)) {
|
||||
this.canvas_.width = size.width;
|
||||
this.canvas_.height = size.height;
|
||||
this.canvasSize_ = size;
|
||||
}
|
||||
|
||||
var animate = false;
|
||||
this.forEachReadyVisibleLayer(function(layer, layerRenderer) {
|
||||
if (layerRenderer.renderFrame(time)) {
|
||||
animate = true;
|
||||
}
|
||||
});
|
||||
|
||||
var gl = this.getGL();
|
||||
|
||||
gl.bindFramebuffer(goog.webgl.FRAMEBUFFER, null);
|
||||
|
||||
gl.clearColor(this.clearColor_.r, this.clearColor_.g, this.clearColor_.b,
|
||||
this.clearColor_.a);
|
||||
var clearColor = frameState.backgroundColor;
|
||||
gl.clearColor(clearColor.r, clearColor.g, clearColor.b, clearColor.a);
|
||||
gl.clear(goog.webgl.COLOR_BUFFER_BIT);
|
||||
gl.enable(goog.webgl.BLEND);
|
||||
gl.viewport(0, 0, size.width, size.height);
|
||||
@@ -674,28 +530,28 @@ ol.renderer.webgl.Map.prototype.renderFrame = function(time) {
|
||||
this.locations_.aTexCoord, 2, goog.webgl.FLOAT, false, 16, 8);
|
||||
gl.uniform1i(this.locations_.uTexture, 0);
|
||||
|
||||
this.forEachReadyVisibleLayer(function(layer, layerRenderer) {
|
||||
goog.array.forEach(frameState.layersArray, function(layer) {
|
||||
var layerState = frameState.layerStates[goog.getUid(layer)];
|
||||
if (!layerState.visible || !layerState.ready) {
|
||||
return;
|
||||
}
|
||||
var layerRenderer = this.getLayerRenderer(layer);
|
||||
gl.uniformMatrix4fv(
|
||||
this.locations_.uMatrix, false, layerRenderer.getMatrix());
|
||||
var hueRotateMatrix = this.createHueRotateMatrix(layer.getHue());
|
||||
var saturateMatrix = this.createSaturateMatrix(layer.getSaturation());
|
||||
var brightnessMatrix = this.createBrightnessMatrix(layer.getBrightness());
|
||||
var contrastMatrix = this.createContrastMatrix(layer.getContrast());
|
||||
var colorMatrix = goog.vec.Mat4.createFloat32Identity();
|
||||
goog.vec.Mat4.multMat(colorMatrix, contrastMatrix, colorMatrix);
|
||||
goog.vec.Mat4.multMat(colorMatrix, brightnessMatrix, colorMatrix);
|
||||
goog.vec.Mat4.multMat(colorMatrix, saturateMatrix, colorMatrix);
|
||||
goog.vec.Mat4.multMat(colorMatrix, hueRotateMatrix, colorMatrix);
|
||||
gl.uniformMatrix4fv(this.locations_.uColorMatrix, false, colorMatrix);
|
||||
gl.uniformMatrix4fv(
|
||||
this.locations_.uColorMatrix, false, layerRenderer.getColorMatrix());
|
||||
gl.uniform1f(this.locations_.uOpacity, layer.getOpacity());
|
||||
gl.bindTexture(goog.webgl.TEXTURE_2D, layerRenderer.getTexture());
|
||||
gl.drawArrays(goog.webgl.TRIANGLE_STRIP, 0, 4);
|
||||
}, this);
|
||||
|
||||
if (requestRenderFrame) {
|
||||
this.getMap().requestRenderFrame();
|
||||
if (!this.renderedVisible_) {
|
||||
goog.style.showElement(this.canvas_, true);
|
||||
this.renderedVisible_ = true;
|
||||
}
|
||||
|
||||
this.calculateMatrices2D(frameState);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -3,12 +3,6 @@ goog.provide('ol.renderer.webgl');
|
||||
goog.require('ol.webgl');
|
||||
|
||||
|
||||
/**
|
||||
* @define {boolean} Free resources immediately.
|
||||
*/
|
||||
ol.renderer.webgl.FREE_RESOURCES_IMMEDIATELY = false;
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Is supported.
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// FIXME large resolutions lead to too large framebuffers :-(
|
||||
// FIXME animated shaders! check in redraw
|
||||
// FIXME throttle texture uploads
|
||||
// FIXME prioritize texture uploads
|
||||
|
||||
goog.provide('ol.renderer.webgl.TileLayer');
|
||||
goog.provide('ol.renderer.webgl.tilelayerrenderer');
|
||||
@@ -10,13 +8,14 @@ goog.provide('ol.renderer.webgl.tilelayerrenderer.shader.Vertex');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.debug.Logger');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.object');
|
||||
goog.require('goog.structs.PriorityQueue');
|
||||
goog.require('goog.vec.Mat4');
|
||||
goog.require('goog.vec.Vec4');
|
||||
goog.require('goog.webgl');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.FrameState');
|
||||
goog.require('ol.Size');
|
||||
goog.require('ol.TileState');
|
||||
goog.require('ol.layer.TileLayer');
|
||||
@@ -88,14 +87,6 @@ ol.renderer.webgl.TileLayer = function(mapRenderer, tileLayer) {
|
||||
|
||||
goog.base(this, mapRenderer, tileLayer);
|
||||
|
||||
if (goog.DEBUG) {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.logger = goog.debug.Logger.getLogger(
|
||||
'ol.renderer.webgl.tilelayerrenderer.' + goog.getUid(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.renderer.webgl.FragmentShader}
|
||||
@@ -145,7 +136,7 @@ ol.renderer.webgl.TileLayer = function(mapRenderer, tileLayer) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {goog.vec.Mat4.AnyType}
|
||||
* @type {!goog.vec.Mat4.Number}
|
||||
*/
|
||||
this.matrix_ = goog.vec.Mat4.createNumber();
|
||||
|
||||
@@ -166,11 +157,12 @@ goog.inherits(ol.renderer.webgl.TileLayer, ol.renderer.webgl.Layer);
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.FrameState} frameState Frame state.
|
||||
* @param {number} framebufferDimension Framebuffer dimension.
|
||||
* @private
|
||||
*/
|
||||
ol.renderer.webgl.TileLayer.prototype.bindFramebuffer_ =
|
||||
function(framebufferDimension) {
|
||||
function(frameState, framebufferDimension) {
|
||||
|
||||
var mapRenderer = this.getMapRenderer();
|
||||
var gl = mapRenderer.getGL();
|
||||
@@ -178,33 +170,14 @@ ol.renderer.webgl.TileLayer.prototype.bindFramebuffer_ =
|
||||
if (!goog.isDef(this.framebufferDimension_) ||
|
||||
this.framebufferDimension_ != framebufferDimension) {
|
||||
|
||||
if (goog.DEBUG) {
|
||||
this.logger.info('re-sizing framebuffer');
|
||||
}
|
||||
|
||||
if (ol.renderer.webgl.FREE_RESOURCES_IMMEDIATELY) {
|
||||
if (goog.DEBUG) {
|
||||
this.logger.info('freeing WebGL resources');
|
||||
}
|
||||
if (!gl.isContextLost()) {
|
||||
gl.deleteFramebuffer(this.framebuffer_);
|
||||
gl.deleteTexture(this.texture_);
|
||||
}
|
||||
} else {
|
||||
var map = this.getMap();
|
||||
goog.events.listenOnce(
|
||||
map,
|
||||
ol.MapEventType.POSTRENDER,
|
||||
goog.partial(function(gl, framebuffer, texture) {
|
||||
if (goog.DEBUG) {
|
||||
this.logger.info('freeing WebGL resources on postrender');
|
||||
}
|
||||
if (!gl.isContextLost()) {
|
||||
gl.deleteFramebuffer(framebuffer);
|
||||
gl.deleteTexture(texture);
|
||||
}
|
||||
}, gl, this.framebuffer_, this.texture_));
|
||||
}
|
||||
var map = this.getMap();
|
||||
frameState.postRenderFunctions.push(
|
||||
goog.partial(function(gl, framebuffer, texture) {
|
||||
if (!gl.isContextLost()) {
|
||||
gl.deleteFramebuffer(framebuffer);
|
||||
gl.deleteTexture(texture);
|
||||
}
|
||||
}, gl, this.framebuffer_, this.texture_));
|
||||
|
||||
var texture = gl.createTexture();
|
||||
gl.bindTexture(goog.webgl.TEXTURE_2D, texture);
|
||||
@@ -247,15 +220,6 @@ ol.renderer.webgl.TileLayer.prototype.disposeInternal = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.layer.TileLayer} Layer.
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.TileLayer.prototype.getLayer = function() {
|
||||
return /** @type {ol.layer.TileLayer} */ goog.base(this, 'getLayer');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@@ -272,6 +236,14 @@ ol.renderer.webgl.TileLayer.prototype.getTexture = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {ol.layer.TileLayer} Tile layer.
|
||||
*/
|
||||
ol.renderer.webgl.TileLayer.prototype.getTileLayer = function() {
|
||||
return /** @type {ol.layer.TileLayer} */ (this.getLayer());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@@ -287,28 +259,22 @@ ol.renderer.webgl.TileLayer.prototype.handleWebGLContextLost = function() {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.TileLayer.prototype.renderFrame = function(time) {
|
||||
|
||||
var requestRenderFrame = false;
|
||||
ol.renderer.webgl.TileLayer.prototype.renderFrame =
|
||||
function(frameState, layerState) {
|
||||
|
||||
var mapRenderer = this.getMapRenderer();
|
||||
var map = this.getMap();
|
||||
var gl = mapRenderer.getGL();
|
||||
|
||||
goog.asserts.assert(map.isDef());
|
||||
var mapCenter = map.getCenter();
|
||||
var mapExtent = map.getExtent();
|
||||
var mapResolution = /** @type {number} */ map.getResolution();
|
||||
var mapRotatedExtent = map.getRotatedExtent();
|
||||
var mapRotation = map.getRotation();
|
||||
var view2DState = frameState.view2DState;
|
||||
var center = view2DState.center;
|
||||
|
||||
var tileLayer = this.getLayer();
|
||||
var tileLayer = this.getTileLayer();
|
||||
var tileSource = tileLayer.getTileSource();
|
||||
var tileGrid = tileSource.getTileGrid();
|
||||
var z = tileGrid.getZForResolution(mapResolution);
|
||||
var z = tileGrid.getZForResolution(view2DState.resolution);
|
||||
var tileResolution = tileGrid.getResolution(z);
|
||||
var tileRange = tileGrid.getTileRangeForExtentAndResolution(
|
||||
mapRotatedExtent, tileResolution);
|
||||
frameState.extent, tileResolution);
|
||||
|
||||
var framebufferExtent;
|
||||
|
||||
@@ -337,7 +303,7 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame = function(time) {
|
||||
minX + framebufferExtentSize.width,
|
||||
minY + framebufferExtentSize.height);
|
||||
|
||||
this.bindFramebuffer_(framebufferDimension);
|
||||
this.bindFramebuffer_(frameState, framebufferDimension);
|
||||
gl.viewport(0, 0, framebufferDimension, framebufferDimension);
|
||||
|
||||
gl.clearColor(0, 0, 0, 0);
|
||||
@@ -382,65 +348,73 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame = function(time) {
|
||||
* @type {Object.<number, Object.<string, ol.Tile>>}
|
||||
*/
|
||||
var tilesToDrawByZ = {};
|
||||
tilesToDrawByZ[z] = {};
|
||||
|
||||
/**
|
||||
* @type {Array.<Image>}
|
||||
*/
|
||||
var imagesToLoad = [];
|
||||
var findInterimTiles = function(z, tileRange) {
|
||||
// FIXME this could be more efficient about filling partial holes
|
||||
var fullyCovered = true;
|
||||
var tile, tileCoord, tileCoordKey, x, y;
|
||||
for (x = tileRange.minX; x <= tileRange.maxX; ++x) {
|
||||
for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
|
||||
tileCoord = new ol.TileCoord(z, x, y);
|
||||
tileCoordKey = tileCoord.toString();
|
||||
if (tilesToDrawByZ[z] && tilesToDrawByZ[z][tileCoordKey]) {
|
||||
return;
|
||||
}
|
||||
tile = tileSource.getTile(tileCoord);
|
||||
if (!goog.isNull(tile) &&
|
||||
tile.getState() == ol.TileState.LOADED &&
|
||||
mapRenderer.isTileTextureLoaded(tile)) {
|
||||
if (!tilesToDrawByZ[z]) {
|
||||
tilesToDrawByZ[z] = {};
|
||||
}
|
||||
tilesToDrawByZ[z][tileCoordKey] = tile;
|
||||
} else {
|
||||
fullyCovered = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return fullyCovered;
|
||||
};
|
||||
|
||||
var tilesToLoad = new goog.structs.PriorityQueue();
|
||||
|
||||
var allTilesLoaded = true;
|
||||
var deltaX, deltaY, priority, tile, tileCenter, tileCoord, tileState, x, y;
|
||||
for (x = tileRange.minX; x <= tileRange.maxX; ++x) {
|
||||
for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
|
||||
|
||||
tilesToDrawByZ[z] = {};
|
||||
tileRange.forEachTileCoord(z, function(tileCoord) {
|
||||
|
||||
var tile = tileSource.getTile(tileCoord);
|
||||
|
||||
if (goog.isNull(tile)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var tileState = tile.getState();
|
||||
if (tileState == ol.TileState.IDLE) {
|
||||
tile.load();
|
||||
} else if (tileState == ol.TileState.LOADED) {
|
||||
var image = tile.getImage();
|
||||
if (mapRenderer.isImageTextureLoaded(image)) {
|
||||
tilesToDrawByZ[z][tileCoord.toString()] = tile;
|
||||
return;
|
||||
} else {
|
||||
imagesToLoad.push(image);
|
||||
tileCoord = new ol.TileCoord(z, x, y);
|
||||
tile = tileSource.getTile(tileCoord);
|
||||
if (goog.isNull(tile)) {
|
||||
continue;
|
||||
}
|
||||
} else if (tileState == ol.TileState.ERROR) {
|
||||
return;
|
||||
|
||||
tileState = tile.getState();
|
||||
if (tileState == ol.TileState.IDLE) {
|
||||
tileCenter = tileGrid.getTileCoordCenter(tileCoord);
|
||||
frameState.tileQueue.enqueue(tile, tileCenter, tileResolution);
|
||||
} else if (tileState == ol.TileState.LOADED) {
|
||||
if (mapRenderer.isTileTextureLoaded(tile)) {
|
||||
tilesToDrawByZ[z][tileCoord.toString()] = tile;
|
||||
continue;
|
||||
} else {
|
||||
tileCenter = tileGrid.getTileCoordCenter(tileCoord);
|
||||
deltaX = tileCenter.x - center.x;
|
||||
deltaY = tileCenter.y - center.y;
|
||||
priority = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
||||
tilesToLoad.enqueue(priority, tile);
|
||||
}
|
||||
} else if (tileState == ol.TileState.ERROR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
allTilesLoaded = false;
|
||||
tileGrid.forEachTileCoordParentTileRange(tileCoord, findInterimTiles);
|
||||
|
||||
}
|
||||
|
||||
allTilesLoaded = false;
|
||||
|
||||
// FIXME this could be more efficient about filling partial holes
|
||||
tileGrid.forEachTileCoordParentTileRange(
|
||||
tileCoord,
|
||||
function(z, tileRange) {
|
||||
var fullyCovered = true;
|
||||
tileRange.forEachTileCoord(z, function(tileCoord) {
|
||||
var tileCoordKey = tileCoord.toString();
|
||||
if (tilesToDrawByZ[z] && tilesToDrawByZ[z][tileCoordKey]) {
|
||||
return;
|
||||
}
|
||||
var tile = tileSource.getTile(tileCoord);
|
||||
if (!goog.isNull(tile) &&
|
||||
tile.getState() == ol.TileState.LOADED) {
|
||||
if (!tilesToDrawByZ[z]) {
|
||||
tilesToDrawByZ[z] = {};
|
||||
}
|
||||
tilesToDrawByZ[z][tileCoordKey] = tile;
|
||||
} else {
|
||||
fullyCovered = false;
|
||||
}
|
||||
});
|
||||
return fullyCovered;
|
||||
});
|
||||
|
||||
}, this);
|
||||
}
|
||||
|
||||
/** @type {Array.<number>} */
|
||||
var zs = goog.array.map(goog.object.getKeys(tilesToDrawByZ), Number);
|
||||
@@ -457,29 +431,22 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame = function(time) {
|
||||
framebufferExtentSize.height - 1;
|
||||
goog.vec.Vec4.setFromValues(uTileOffset, sx, sy, tx, ty);
|
||||
gl.uniform4fv(this.locations_.uTileOffset, uTileOffset);
|
||||
mapRenderer.bindImageTexture(
|
||||
tile.getImage(), goog.webgl.LINEAR, goog.webgl.LINEAR);
|
||||
mapRenderer.bindTileTexture(tile, goog.webgl.LINEAR, goog.webgl.LINEAR);
|
||||
gl.drawArrays(goog.webgl.TRIANGLE_STRIP, 0, 4);
|
||||
}, this);
|
||||
}, this);
|
||||
|
||||
if (!goog.array.isEmpty(imagesToLoad)) {
|
||||
goog.events.listenOnce(
|
||||
map,
|
||||
ol.MapEventType.POSTRENDER,
|
||||
goog.partial(function(mapRenderer, imagesToLoad) {
|
||||
if (goog.DEBUG) {
|
||||
this.logger.info(
|
||||
'uploading ' + imagesToLoad.length + ' textures');
|
||||
if (!tilesToLoad.isEmpty()) {
|
||||
frameState.postRenderFunctions.push(
|
||||
goog.partial(function(mapRenderer, tilesToLoad) {
|
||||
var i, tile;
|
||||
// FIXME determine a suitable number of textures to upload per frame
|
||||
for (i = 0; !tilesToLoad.isEmpty() && i < 4; ++i) {
|
||||
tile = /** @type {ol.Tile} */ (tilesToLoad.remove());
|
||||
mapRenderer.bindTileTexture(
|
||||
tile, goog.webgl.LINEAR, goog.webgl.LINEAR);
|
||||
}
|
||||
goog.array.forEach(imagesToLoad, function(image) {
|
||||
mapRenderer.bindImageTexture(
|
||||
image, goog.webgl.LINEAR, goog.webgl.LINEAR);
|
||||
});
|
||||
if (goog.DEBUG) {
|
||||
this.logger.info('uploaded textures');
|
||||
}
|
||||
}, mapRenderer, imagesToLoad));
|
||||
}, mapRenderer, tilesToLoad));
|
||||
}
|
||||
|
||||
if (allTilesLoaded) {
|
||||
@@ -488,25 +455,23 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame = function(time) {
|
||||
} else {
|
||||
this.renderedTileRange_ = null;
|
||||
this.renderedFramebufferExtent_ = null;
|
||||
requestRenderFrame = true;
|
||||
frameState.animate = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
goog.vec.Mat4.makeIdentity(this.matrix_);
|
||||
goog.vec.Mat4.translate(this.matrix_,
|
||||
(mapCenter.x - framebufferExtent.minX) /
|
||||
(view2DState.center.x - framebufferExtent.minX) /
|
||||
(framebufferExtent.maxX - framebufferExtent.minX),
|
||||
(mapCenter.y - framebufferExtent.minY) /
|
||||
(view2DState.center.y - framebufferExtent.minY) /
|
||||
(framebufferExtent.maxY - framebufferExtent.minY),
|
||||
0);
|
||||
if (goog.isDef(mapRotation)) {
|
||||
goog.vec.Mat4.rotateZ(this.matrix_, mapRotation);
|
||||
}
|
||||
goog.vec.Mat4.rotateZ(this.matrix_, view2DState.rotation);
|
||||
goog.vec.Mat4.scale(this.matrix_,
|
||||
(mapExtent.maxX - mapExtent.minX) /
|
||||
frameState.size.width * view2DState.resolution /
|
||||
(framebufferExtent.maxX - framebufferExtent.minX),
|
||||
(mapExtent.maxY - mapExtent.minY) /
|
||||
frameState.size.height * view2DState.resolution /
|
||||
(framebufferExtent.maxY - framebufferExtent.minY),
|
||||
1);
|
||||
goog.vec.Mat4.translate(this.matrix_,
|
||||
@@ -514,6 +479,4 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame = function(time) {
|
||||
-0.5,
|
||||
0);
|
||||
|
||||
return requestRenderFrame;
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user