Skip to content

Commit

Permalink
refactor(MaterialLayer): MaterialLayer to RasterNode.
Browse files Browse the repository at this point in the history
  • Loading branch information
gchoqueux committed Feb 16, 2021
1 parent 53a9f6f commit 46b19f1
Show file tree
Hide file tree
Showing 7 changed files with 189 additions and 118 deletions.
1 change: 1 addition & 0 deletions docs/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"PotreeLayer",
"C3DTilesLayer",
"LabelLayer",
"RasterNode",

"GlobeLayer",
"PlanarLayer"
Expand Down
40 changes: 36 additions & 4 deletions src/Layer/ColorLayer.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import RasterLayer from 'Layer/RasterLayer';
import { updateLayeredMaterialNodeImagery } from 'Process/LayeredMaterialNodeProcessing';
import { RasterColorTile } from 'Renderer/RasterTile';
import Style from 'Core/Style';

/**
Expand All @@ -20,6 +21,16 @@ import Style from 'Core/Style';
* @property {boolean} isColorLayer - Used to checkout whether this layer is a
* ColorLayer. Default is true. You should not change this, as it is used
* internally for optimisation.
* @property {Style} style - default style apply layer features.
* @property {boolean} visible - property to display or to hide layer.
* @property {number} opacity - property to adjust transparency, opacity is between 0. and 1.
* @property {boolean} transparent - specify if the layer could be transparent.
* @property {boolean} noTextureParentOutsideLimit - don't parent texture if it's outside limit.
* @property {number} fx - special effects apply on raster color.
* if `fx` equals:
* * `0`: no special effect.
* * `> 0. to < 2.0`: light color to invisible effect.
* * `>= 2`: white color to invisible effect.
*/
class ColorLayer extends RasterLayer {
/**
Expand All @@ -43,12 +54,15 @@ class ColorLayer extends RasterLayer {
* @example
* // Create a ColorLayer
* const color = new ColorLayer('roads', {
* source: {
* source: new SourceWMTS({
* protocol: 'wmts',
* url: 'http://server.geo/wmts/SERVICE=WMTS&TILEMATRIX=%TILEMATRIX&TILEROW=%ROW&TILECOL=%COL',
* url: 'http://server.geo/wmts/....',
* format: 'image/png',
* }
* transparent: true
* name: 'nameService',
* tileMatrixSet: 'PM',
* }),
* transparent: true,
* opacity: 0.5,
* });
*
* // Add the layer
Expand All @@ -63,13 +77,31 @@ class ColorLayer extends RasterLayer {
this.defineLayerProperty('sequence', 0);
this.transparent = config.transparent || (this.opacity < 1.0);
this.noTextureParentOutsideLimit = config.source ? config.source.isFileSource : false;
this.fx = config.fx || 0;

// Feature options
this.buildExtent = true;
this.withNormal = false;
this.withAltitude = false;
}

/**
* Setup RasterColorTile added to TileMesh. This RasterColorTile handles
* the ColorLayer textures mapped on this TileMesh.
*
* @param {TileMesh} node The node to apply new RasterColorTile;
* @return {RasterColorTile} The raster color node added.
*/
setupRasterNode(node) {
const rasterColorNode = new RasterColorTile(node.material, this);

node.material.addLayer(rasterColorNode);
// set up ColorLayer ordering.
node.material.setSequence(this.parent.colorLayersOrder);

return rasterColorNode;
}

update(context, layer, node, parent) {
return updateLayeredMaterialNodeImagery(context, this, node, parent);
}
Expand Down
45 changes: 39 additions & 6 deletions src/Layer/ElevationLayer.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import RasterLayer from 'Layer/RasterLayer';
import { updateLayeredMaterialNodeElevation } from 'Process/LayeredMaterialNodeProcessing';
import { RasterElevationTile } from 'Renderer/RasterTile';

/**
* @property {boolean} isElevationLayer - Used to checkout whether this layer is
Expand All @@ -9,6 +10,16 @@ import { updateLayeredMaterialNodeElevation } from 'Process/LayeredMaterialNodeP
* @property {number} scale - Used to apply a scale on the elevation value. It
* can be used for exageration of the elevation, like in [this
* example](https://www.itowns-project.org/itowns/examples/#plugins_pyramidal_tiff).
* @property {boolean} useColorTextureElevation - the elevation is computed with one color texture channel,
* `this.colorTextureElevationMaxZ` and `this.colorTextureElevationMinZ`.
*
* The formula is:
*
* ```js
* elevation = color.r * (this.colorTextureElevationMaxZ - this.colorTextureElevationMinZ) + this.colorTextureElevationMinZ
* ```
* @property {number} colorTextureElevationMinZ - elevation minimum in `useColorTextureElevation` mode.
* @property {number} colorTextureElevationMaxZ - elevation maximum in `useColorTextureElevation` mode.
*/
class ElevationLayer extends RasterLayer {
/**
Expand All @@ -26,16 +37,16 @@ class ElevationLayer extends RasterLayer {
* contains three elements `name, protocol, extent`, these elements will be
* available using `layer.name` or something else depending on the property
* name.
* @param {Source} [config.source] - Description and options of the source.
*
* @example
* // Create an ElevationLayer
* const elevation = new ElevationLayer('IGN_MNT', {
* source: {
* url: 'http://server.geo/wmts/SERVICE=WMTS&TILEMATRIX=%TILEMATRIX&TILEROW=%ROW&TILECOL=%COL',
* protocol: 'wmts',
* format: 'image/x-bil;bits=32',
* },
* source: new WMTSSource({
* "url": "https://wxs.ign.fr/3ht7xcw6f7nciopo16etuqp2/geoportail/wmts",
* "crs": "EPSG:4326",
* "format": "image/x-bil;bits=32",
* "name": "ELEVATION.ELEVATIONGRIDCOVERAGE",
* }),
* });
*
* // Add the layer
Expand All @@ -61,6 +72,28 @@ class ElevationLayer extends RasterLayer {
});
}

/**
* Setup RasterElevationTile added to TileMesh. This RasterElevationTile handles
* the elevation texture to displace TileMesh vertices.
*
* @param {TileMesh} node The node to apply new RasterElevationTile;
* @return {RasterElevationTile} The raster elevation node added.
*/
setupRasterNode(node) {
const rasterElevationNode = new RasterElevationTile(node.material, this);

node.material.addLayer(rasterElevationNode);
node.material.setSequenceElevation(this.id);
// bounding box initialisation
const updateBBox = () => node.setBBoxZ(rasterElevationNode.min, rasterElevationNode.max, this.scale);
updateBBox();

// listen elevation updating
rasterElevationNode.addEventListener('updatedElevation', updateBBox);

return rasterElevationNode;
}

update(context, layer, node, parent) {
return updateLayeredMaterialNodeElevation(context, this, node, parent);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Layer/LayerUpdateStrategy.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { EMPTY_TEXTURE_ZOOM } from 'Renderer/MaterialLayer';
import { EMPTY_TEXTURE_ZOOM } from 'Renderer/RasterTile';
/**
* This modules implements various layer update strategies.
*
Expand Down
50 changes: 11 additions & 39 deletions src/Process/LayeredMaterialNodeProcessing.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { chooseNextLevelToFetch } from 'Layer/LayerUpdateStrategy';
import LayerUpdateState from 'Layer/LayerUpdateState';
import { computeMinMaxElevation } from 'Parser/XbilParser';
import handlingError from 'Process/handlerNodeError';

export const SIZE_TEXTURE_TILE = 256;
Expand Down Expand Up @@ -76,9 +75,10 @@ export function updateLayeredMaterialNodeImagery(context, layer, node, parent) {
}

if (!nodeLayer) {
// Create new MaterialLayer
nodeLayer = material.addLayer(layer);
// Init the new MaterialLayer by parent
// Create new raster node
nodeLayer = layer.setupRasterNode(node);

// Init the node by parent
const parentLayer = parent.material && parent.material.getLayer(layer.id);
nodeLayer.initFromParent(parentLayer, extentsDestination);
}
Expand Down Expand Up @@ -178,7 +178,7 @@ export function updateLayeredMaterialNodeElevation(context, layer, node, parent)
// Init elevation layer, and inherit from parent if possible
let nodeLayer = material.getElevationLayer();
if (!nodeLayer) {
nodeLayer = material.addLayer(layer);
nodeLayer = layer.setupRasterNode(node);
}

if (node.layerUpdateState[layer.id] === undefined) {
Expand All @@ -187,18 +187,9 @@ export function updateLayeredMaterialNodeElevation(context, layer, node, parent)
const parentLayer = parent.material && parent.material.getLayer(layer.id);
nodeLayer.initFromParent(parentLayer, extentsDestination);

if (nodeLayer.level >= 0) {
// Compute min max elevation if the node is initialized
const { min, max } = computeMinMaxElevation(
nodeLayer.textures[0],
nodeLayer.offsetScales[0],
nodeLayer.layer.noDataValue);
node.setBBoxZ(min, max, layer.scale);

if (nodeLayer.level >= layer.source.zoom.min) {
context.view.notifyChange(node, false);
return;
}
if (nodeLayer.level >= layer.source.zoom.min) {
context.view.notifyChange(node, false);
return;
}
}

Expand Down Expand Up @@ -232,36 +223,17 @@ export function updateLayeredMaterialNodeElevation(context, layer, node, parent)
const command = buildCommand(context.view, layer, extentsSource, extentsDestination, node);

return context.scheduler.execute(command).then(
(textures) => {
(result) => {
// Do not apply the new texture if its level is < than the current
// one. This is only needed for elevation layers, because we may
// have several concurrent layers but we can only use one texture.
if (targetLevel <= nodeLayer.level) {
node.layerUpdateState[layer.id].noMoreUpdatePossible();
return;
}
const elevation = {
texture: textures[0],
pitch: extentsDestination[0].offsetToParent(textures[0].extent, nodeLayer.offsetScales[0]),
};

const pitchs = extentsDestination.map((ext, i) => ext.offsetToParent(result[i].extent, nodeLayer.offsetScales[i]));
nodeLayer.setTextures(result, pitchs);
node.layerUpdateState[layer.id].success();

if (elevation.texture) {
if (layer.useColorTextureElevation) {
elevation.min = layer.colorTextureElevationMinZ;
elevation.max = layer.colorTextureElevationMaxZ;
} else {
const { min, max } = computeMinMaxElevation(elevation.texture, elevation.pitch, layer.noDataValue);
elevation.min = !min ? 0 : min;
elevation.max = !max ? 0 : max;
}
}

node.setBBoxZ(elevation.min, elevation.max, layer.scale);
nodeLayer.setTexture(0, elevation.texture, elevation.pitch);
const nodeParent = parent.material && parent.material.getElevationLayer();
nodeLayer.replaceNoDataValueFromParent(nodeParent, layer.noDataValue);
},
err => handlingError(err, node, layer, targetLevel, context.view));
}
Expand Down
15 changes: 4 additions & 11 deletions src/Renderer/LayeredMaterial.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import TileFS from 'Renderer/Shader/TileFS.glsl';
import ShaderUtils from 'Renderer/Shader/ShaderUtils';
import Capabilities from 'Core/System/Capabilities';
import RenderMode from 'Renderer/RenderMode';
import MaterialLayer from 'Renderer/MaterialLayer';
import CommonMaterial from 'Renderer/CommonMaterial';

const identityOffsetScale = new THREE.Vector4(0.0, 0.0, 1.0, 1.0);
Expand Down Expand Up @@ -54,6 +53,7 @@ function updateLayersUniforms(uniforms, olayers, max) {
// flatten the 2d array [i,j] -> layers[_layerIds[i]].textures[j]
let count = 0;
for (const layer of olayers) {
// textureOffset property is added to RasterTile
layer.textureOffset = count;
for (let i = 0, il = layer.textures.length; i < il; ++i, ++count) {
if (count < max) {
Expand Down Expand Up @@ -232,18 +232,11 @@ class LayeredMaterial extends THREE.RawShaderMaterial {
}
}

addLayer(layer) {
if (layer.id in this.layers) {
addLayer(rasterNode) {
if (rasterNode.layer.id in this.layers) {
console.warn('The "{layer.id}" layer was already present in the material, overwritting.');
}
const lml = new MaterialLayer(this, layer);
this.layers.push(lml);
if (layer.isColorLayer) {
this.setSequence(layer.parent.colorLayersOrder);
} else {
this.setSequenceElevation(layer.id);
}
return lml;
this.layers.push(rasterNode);
}

getLayer(id) {
Expand Down
Loading

0 comments on commit 46b19f1

Please sign in to comment.