Implement frame state and animation architecture
This commit is contained in:
@@ -1,7 +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');
|
||||
|
||||
|
||||
@@ -60,6 +62,7 @@ ol.renderer.dom.Layer.prototype.handleLayerVisibleChange = function() {
|
||||
|
||||
|
||||
/**
|
||||
* @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;
|
||||
|
||||
@@ -9,6 +9,7 @@ goog.require('goog.events');
|
||||
goog.require('goog.events.Event');
|
||||
goog.require('goog.functions');
|
||||
goog.require('ol.Coordinate');
|
||||
goog.require('ol.FrameState');
|
||||
goog.require('ol.layer.TileLayer');
|
||||
goog.require('ol.renderer.Map');
|
||||
goog.require('ol.renderer.dom.TileLayer');
|
||||
@@ -93,26 +94,20 @@ ol.renderer.dom.Map.prototype.handleViewChanged = function() {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.dom.Map.prototype.renderFrame = function(time) {
|
||||
ol.renderer.dom.Map.prototype.renderFrame = function(frameState) {
|
||||
|
||||
var map = this.getMap();
|
||||
if (!map.isDef()) {
|
||||
if (goog.isNull(frameState)) {
|
||||
// FIXME remove everything
|
||||
return;
|
||||
}
|
||||
|
||||
var requestRenderFrame = false;
|
||||
var layers = map.getLayers();
|
||||
if (goog.isDef(layers)) {
|
||||
layers.forEach(function(layer) {
|
||||
var layerRenderer = this.getLayerRenderer(layer);
|
||||
if (layerRenderer.renderFrame(time)) {
|
||||
requestRenderFrame = true;
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
|
||||
if (requestRenderFrame) {
|
||||
map.requestRenderFrame();
|
||||
}
|
||||
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);
|
||||
|
||||
};
|
||||
|
||||
@@ -67,47 +67,36 @@ ol.renderer.dom.TileLayer.prototype.getTileLayer = function() {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.dom.TileLayer.prototype.renderFrame = function(time) {
|
||||
ol.renderer.dom.TileLayer.prototype.renderFrame =
|
||||
function(frameState, layerState) {
|
||||
|
||||
var map = this.getMap();
|
||||
goog.asserts.assert(map.isDef());
|
||||
|
||||
var view = map.getView().getView2D();
|
||||
var mapCenter = /** @type {!ol.Coordinate} */ (view.getCenter());
|
||||
var mapResolution = /** @type {number} */ (view.getResolution());
|
||||
var mapSize = /** @type {!ol.Size} */ (map.getSize());
|
||||
var mapRotatedExtent = /** @type {!ol.Extent} */
|
||||
(view.getRotatedExtent(mapSize));
|
||||
var mapRotation = view.getRotation();
|
||||
var mapScale = 1 / mapResolution;
|
||||
var view2DState = frameState.view2DState;
|
||||
|
||||
var tileLayer = this.getTileLayer();
|
||||
|
||||
var visible = tileLayer.getVisible();
|
||||
if (!visible) {
|
||||
if (!layerState.visible) {
|
||||
if (this.renderedVisible_) {
|
||||
goog.style.showElement(this.target, false);
|
||||
this.renderedVisible_ = false;
|
||||
}
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
var opacity = tileLayer.getOpacity();
|
||||
if (opacity != this.renderedOpacity_) {
|
||||
goog.style.setOpacity(this.target, opacity);
|
||||
this.renderedOpacity_ = opacity;
|
||||
if (layerState.opacity != this.renderedOpacity_) {
|
||||
goog.style.setOpacity(this.target, layerState.opacity);
|
||||
this.renderedOpacity_ = layerState.opacity;
|
||||
}
|
||||
|
||||
var tileSource = tileLayer.getTileSource();
|
||||
var tileGrid = tileSource.getTileGrid();
|
||||
|
||||
var z = tileGrid.getZForResolution(mapResolution);
|
||||
var z = tileGrid.getZForResolution(view2DState.resolution);
|
||||
|
||||
/** @type {Object.<number, Object.<string, ol.Tile>>} */
|
||||
var tilesToDrawByZ = {};
|
||||
|
||||
var tileRange = tileGrid.getTileRangeForExtentAndResolution(
|
||||
mapRotatedExtent, mapResolution);
|
||||
frameState.extent, view2DState.resolution);
|
||||
|
||||
var allTilesLoaded = true;
|
||||
|
||||
@@ -173,7 +162,7 @@ ol.renderer.dom.TileLayer.prototype.renderFrame = function(time) {
|
||||
tileLayerZ = this.tileLayerZs_[tileLayerZKey];
|
||||
} else {
|
||||
tileCoordOrigin =
|
||||
tileGrid.getTileCoordForCoordAndZ(mapCenter, tileLayerZKey);
|
||||
tileGrid.getTileCoordForCoordAndZ(view2DState.center, tileLayerZKey);
|
||||
tileLayerZ = new ol.renderer.dom.TileLayerZ_(tileGrid, tileCoordOrigin);
|
||||
newTileLayerZKeys[tileLayerZKey] = true;
|
||||
this.tileLayerZs_[tileLayerZKey] = tileLayerZ;
|
||||
@@ -204,14 +193,15 @@ ol.renderer.dom.TileLayer.prototype.renderFrame = function(time) {
|
||||
origin = tileLayerZ.getOrigin();
|
||||
goog.vec.Mat4.makeIdentity(transform);
|
||||
goog.vec.Mat4.translate(
|
||||
transform, mapSize.width / 2, mapSize.height / 2, 0);
|
||||
if (goog.isDef(mapRotation)) {
|
||||
goog.vec.Mat4.rotateZ(transform, mapRotation);
|
||||
}
|
||||
goog.vec.Mat4.scale(
|
||||
transform, resolution / mapResolution, resolution / mapResolution, 1);
|
||||
goog.vec.Mat4.translate(transform, (origin.x - mapCenter.x) / resolution,
|
||||
(mapCenter.y - origin.y) / resolution, 0);
|
||||
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) {
|
||||
@@ -225,16 +215,18 @@ ol.renderer.dom.TileLayer.prototype.renderFrame = function(time) {
|
||||
goog.dom.insertChildAt(this.target, tileLayerZ.target, 0);
|
||||
}
|
||||
} else {
|
||||
tileLayerZ.removeTilesOutsideExtent(mapRotatedExtent);
|
||||
tileLayerZ.removeTilesOutsideExtent(frameState.extent);
|
||||
}
|
||||
}
|
||||
|
||||
if (visible && !this.renderedVisible_) {
|
||||
if (layerState.visible && !this.renderedVisible_) {
|
||||
goog.style.showElement(this.target, true);
|
||||
this.renderedVisible_ = true;
|
||||
}
|
||||
|
||||
return !allTilesLoaded;
|
||||
if (!allTilesLoaded) {
|
||||
frameState.animate = true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ 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');
|
||||
|
||||
@@ -294,9 +295,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;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
// 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');
|
||||
|
||||
@@ -179,8 +183,8 @@ 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;
|
||||
|
||||
|
||||
@@ -143,12 +143,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,
|
||||
@@ -303,26 +297,6 @@ ol.renderer.webgl.Map.prototype.disposeInternal = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {function(this: T, ol.layer.Layer, ol.renderer.webgl.Layer, number)} f
|
||||
* Function.
|
||||
* @param {T=} opt_obj Object.
|
||||
* @template T
|
||||
*/
|
||||
ol.renderer.webgl.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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {WebGLRenderingContext} GL.
|
||||
*/
|
||||
@@ -394,12 +368,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();
|
||||
};
|
||||
|
||||
@@ -522,34 +490,37 @@ 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) {
|
||||
|
||||
var map = this.getMap();
|
||||
if (!map.isDef()) {
|
||||
return;
|
||||
var gl = this.getGL();
|
||||
|
||||
if (goog.isNull(frameState)) {
|
||||
gl.bindFramebuffer(goog.webgl.FRAMEBUFFER, null);
|
||||
gl.clearColor(0, 0, 0, 0);
|
||||
gl.clear(goog.webgl.COLOR_BUFFER_BIT);
|
||||
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 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);
|
||||
@@ -589,7 +560,12 @@ 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());
|
||||
gl.uniformMatrix4fv(
|
||||
@@ -599,10 +575,6 @@ ol.renderer.webgl.Map.prototype.renderFrame = function(time) {
|
||||
gl.drawArrays(goog.webgl.TRIANGLE_STRIP, 0, 4);
|
||||
}, this);
|
||||
|
||||
if (requestRenderFrame) {
|
||||
this.getMap().requestRenderFrame();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -287,30 +287,21 @@ 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();
|
||||
var view = map.getView().getView2D();
|
||||
|
||||
goog.asserts.assert(map.isDef());
|
||||
var mapSize = map.getSize();
|
||||
var mapCenter = view.getCenter();
|
||||
var mapExtent = view.getExtent(mapSize);
|
||||
var mapResolution = /** @type {number} */ (view.getResolution());
|
||||
var mapRotatedExtent = view.getRotatedExtent(mapSize);
|
||||
var mapRotation = view.getRotation();
|
||||
var view2DState = frameState.view2DState;
|
||||
|
||||
var tileLayer = this.getLayer();
|
||||
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;
|
||||
|
||||
@@ -465,7 +456,7 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame = function(time) {
|
||||
|
||||
if (!goog.array.isEmpty(tilesToLoad)) {
|
||||
goog.events.listenOnce(
|
||||
map,
|
||||
this.getMap(),
|
||||
ol.MapEventType.POSTRENDER,
|
||||
goog.partial(function(mapRenderer, tilesToLoad) {
|
||||
if (goog.DEBUG) {
|
||||
@@ -488,25 +479,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 +503,4 @@ ol.renderer.webgl.TileLayer.prototype.renderFrame = function(time) {
|
||||
-0.5,
|
||||
0);
|
||||
|
||||
return requestRenderFrame;
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user