-
Notifications
You must be signed in to change notification settings - Fork 299
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refacto limit dependency on layeredmaterial #792
Conversation
ed80474
to
9bb0578
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This definitely goes in the right direction !
I made a few comments.
src/Core/TileMesh.js
Outdated
@@ -224,8 +219,10 @@ TileMesh.prototype.getCoordsForLayer = function getCoordsForLayer(layer) { | |||
} else { | |||
return OGCWebServiceHelper.computeTMSCoordinates(this, layer.extent, layer.origin); | |||
} | |||
} else { | |||
} else if (layer.extent.crs() == this.extent.crs()) { | |||
return [this.extent]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this test go into Extent.as
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could but actually the as()
function should be improved to support a 'no-clone' argument (currently we always clone the extent, even if the requested crs is the same).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add some comment to explain your choice
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
src/utils/DEMUtils.js
Outdated
@@ -169,7 +169,7 @@ function tileAt(pt, tile) { | |||
return t; | |||
} | |||
} | |||
if (tile.getLayerTextures(l_ELEVATION)[0].coords.zoom > -1) { | |||
if (tile.material.textures[l_ELEVATION][0].coords.zoom > -1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it equivalent to isElevationLayerLoaded
? (which would be clearer)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes.
I'll use this but I'll remove it from TileMesh and move it where it belongs = LayeredMaterial.
src/Core/TileMesh.js
Outdated
@@ -11,10 +11,12 @@ import RendererConstant from '../Renderer/RendererConstant'; | |||
import OGCWebServiceHelper, { SIZE_TEXTURE_TILE } from '../Provider/OGCWebServiceHelper'; | |||
import { is4326 } from './Geographic/Coordinates'; | |||
|
|||
function TileMesh(geometry, params) { | |||
function TileMesh(layer, geometry, params) { | |||
// Constructor | |||
THREE.Mesh.call(this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the call to super could pass directly the geometry and material : super(geometry, material)
(with a material constructed at the call site) and the constructor could be more explicit with : TileMesh(geometry, material, extent, level)
, as in 6dd1ba5
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
src/Core/TileMesh.js
Outdated
// Constructor | ||
THREE.Mesh.call(this); | ||
|
||
this.layer = layer; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the semantics of this layer ? which one is it ? I would rather keep it outside of TileMesh as with other meshes in itowns.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's the GeometryLayer, and as stated above it was already stored in TileMesh (and I think it's useful).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
where tile.layer
is used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For instance here.
And I'll repeat myself: this isn't a new thing. I simply moved the layer
assignement inside the constructor.
@@ -37,6 +39,7 @@ function TileMesh(geometry, params) { | |||
this.frustumCulled = false; | |||
|
|||
this.updateGeometricError(); | |||
this.wmtsCoords = {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it makes more sense to move this to Extent
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah... I moved it here, again because it was assigned somewhere else (https://github.com/iTowns/itowns/pull/792/files#diff-5e0253bd7132719c7fe2322c297efe16L48).
I propose to keep it that way for this PR, and use your PR #785 as an opportunity to fix this since it's more focused on the extent side. WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not rename it to a more appropriate name in the same time ?
@@ -66,7 +66,7 @@ function initNodeElevationTextureFromParent(node, parent, layer) { | |||
elevation.max = max; | |||
} | |||
|
|||
node.setTextureElevation(elevation); | |||
node.setTextureElevation(layer, elevation); | |||
node.material.elevationLayersId = | |||
parent.material.elevationLayersId; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you removed it...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you still support material.elevationLayersId ? I tought you proposed to remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah ok. I pushed a commit removing this line.
src/Renderer/LayeredMaterial.js
Outdated
opacity: layer.opacity, | ||
fx: layer.fx, | ||
idLayer: layer.id, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do you create this intermediate object instead of using layer
directly ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved this intermediate object from elsewhere, but you're right it's useless. I'll remove it.
}; | ||
|
||
LayeredMaterial.prototype.setLayerVisibility = function setLayerVisibility(index, visible) { | ||
LayeredMaterial.prototype.setLayerVisibility = function setLayerVisibility(layer, visible) { | ||
const index = Number.isInteger(layer) ? layer : this.indexOfColorLayer(layer.id); | ||
this.uniforms.visibility.value[index] = visible; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we deprecate the index-based api (with a console.warn) ? is it still used elsewhere ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's only used internally in LayeredMaterial.
There are a bunch of other index based method in LayeredMaterial and I think they should all be removed. I'll do a separate PR for this stuff.
src/Core/TileMesh.js
Outdated
return mat.getColorLayerLevelById(layerId) > -1; | ||
const textures = mat.getLayerTextures(layer); | ||
if (textures.length) { | ||
return textures[0].coords.zoom > -1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should not it be textures.every(texture => texture.coords.zoom == this.level)
or textures.every(texture => somefun(layer, this.extent, texture.coords)
for a suitable function ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually it doesn't matter, since we always set textures in one shot (this is what getColorLayerLevelById was doing anyway)
@@ -371,7 +371,7 @@ function _readZ(layer, method, coord, nodes, cache) { | |||
} | |||
|
|||
const tile = tileWithValidElevationTexture; | |||
const src = tileWithValidElevationTexture.getLayerTextures(l_ELEVATION)[0]; | |||
const src = tileWithValidElevationTexture.material.textures[l_ELEVATION][0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tileWithValidElevationTexture.getLayerTextures(layer)[0]
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah no, because layer
here is the geometry layer. And the calling site is not aware of which elevation layer we can use.
So for now I'll leave it like that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and with the famous tile.layer
?
you could write:
tileWithValidElevationTexture.getLayerTextures(tile.layer)[0]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and with the famous tile.layer?
Are you sure the famous
bit is needed?
you could write: tileWithValidElevationTexture.getLayerTextures(tile.layer)[0]
And it would be incorrect. tile.layer
is the GeometryLayer, not the Layer used for the elevation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok,
So we don't know in elevation layer the data is searched for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should add tests to DEMUtils, if it doesn't exist
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not the scope of this PR. I'm only changing this file to remove one useless abstraction (and it's a 2 line diff)
Pushed a commit which should fix the above issues. Thanks for the review @mbredif :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should also add the tests on the layeredMaterial
src/Core/TileMesh.js
Outdated
// Constructor | ||
THREE.Mesh.call(this); | ||
|
||
this.layer = layer; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
where tile.layer
is used?
src/Core/TileMesh.js
Outdated
return this.material.loadedTexturesCount[l_ELEVATION] > 0; | ||
const textures = mat.getLayerTextures(layer); | ||
if (textures.length) { | ||
return textures[0].coords.zoom > -1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use EMPTY_TEXTURE_ZOOM
instead of -1
src/Core/TileMesh.js
Outdated
@@ -224,8 +219,10 @@ TileMesh.prototype.getCoordsForLayer = function getCoordsForLayer(layer) { | |||
} else { | |||
return OGCWebServiceHelper.computeTMSCoordinates(this, layer.extent, layer.origin); | |||
} | |||
} else { | |||
} else if (layer.extent.crs() == this.extent.crs()) { | |||
return [this.extent]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add some comment to explain your choice
src/Process/GlobeTileProcessing.js
Outdated
currentElevationLevel >= 0 && | ||
(node.level - currentElevationLevel) >= maxDeltaElevationLevel) { | ||
return false; | ||
const currentTexture = node.material.textures[0][0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use l_color
instead of 0
src/Process/GlobeTileProcessing.js
Outdated
const offsetScale = node.material.offsetScale[0][0]; | ||
const ratio = offsetScale.z; | ||
// ratio is node size / texture size | ||
if (ratio < 1 / Math.pow(2, maxDeltaElevationLevel)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's a ratio, between the tile's extent and texture's extent?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes.
src/Process/PlanarTileProcessing.js
Outdated
currentElevationLevel >= 0 && | ||
(node.level - currentElevationLevel) >= maxDeltaElevationLevel) { | ||
return false; | ||
const currentTexture = node.material.textures[0][0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this part of this process is identical to the globe processing, it should be encapsulated in one place. Duplicate code is harder and longer to maintain
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicate code is harder and longer to maintain
This is not an absolute truth, and here I disagree. This is a 5 line copy-paste so I don't think it hurts to keep them separate.
If you really want to improve code sharing between part of itowns I opened a PR sometimes ago: #674
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the duplicate code is technical debt
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicate code is harder and longer to maintain
Abusive factorization too, by introducing another layer of abstraction.
the duplicate code is technical debt
The program without technical debt is the one with 0 codes. I agree duplicate code has a cost, but introducing another function has one too. I call it more or less even here. But as it is not the scope of this PR and as this snippet is quite short, maybe you can let this one go?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function can be factorized:
- as an OGC conversion tool. there is WMTS_WGS84Parent. Why not have the opposite function?
- it's an identified conversion tool, so no code duplication
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually this code is a hack to workaround a bug in the SSE logic (= computing the geometric error using a sphere - except that a sphere is a poor approximation for a square tile).
So I'd rather get rid of it, instead of transforming it in a API that would be used in other places of iTowns.
src/Process/SubdivisionControl.js
Outdated
@@ -28,7 +28,7 @@ export default { | |||
if (node.layerUpdateState[c.id] && node.layerUpdateState[c.id].inError()) { | |||
continue; | |||
} | |||
if (c.tileInsideLimit(node, c) && !node.isColorLayerLoaded(c.id)) { | |||
if (c.tileInsideLimit(node, c) && !node.isColorLayerLoaded(c)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if isElevationLayerLoaded
is material function, why isColorLayerLoaded
is tileMesh
function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mainly because this PR is a part of a bigger PR. I tried to extract a meaningful part of it, but there are left over like this one that doesn't make sense.
I'm moving isColorLayerLoaded to LayeredMaterial.
src/Provider/TileProvider.js
Outdated
@@ -80,8 +80,7 @@ function executeCommand(command) { | |||
}; | |||
|
|||
geometry._count++; | |||
const tile = new TileMesh(geometry, params); | |||
tile.layer = layer; | |||
const tile = new TileMesh(layer, geometry, params); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same question, you remember where tile.layer
is used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Answered above.
} else { | ||
this.setLayerVisibility(index, false); | ||
break; | ||
LayeredMaterial.prototype.setLayerTextures = function setLayerTextures(layer, textures) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you saw @mbredif's proposal for the LayeredMaterial
@@ -371,7 +371,7 @@ function _readZ(layer, method, coord, nodes, cache) { | |||
} | |||
|
|||
const tile = tileWithValidElevationTexture; | |||
const src = tileWithValidElevationTexture.getLayerTextures(l_ELEVATION)[0]; | |||
const src = tileWithValidElevationTexture.material.textures[l_ELEVATION][0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and with the famous tile.layer
?
you could write:
tileWithValidElevationTexture.getLayerTextures(tile.layer)[0]
Updated. |
@gchoqueux could you update your review please? |
Ok, so IMHO this PR improves greatly itowns and will allow to reuse the texture update process for other types of data. @gchoqueux: I don't think your Request Changes on this PR is justified. |
yes, but you also need the missing tests of impacted objects |
Most of them already have some tests or are pretty well exercised during with the Stop blocking PRs for random reasons: being a reviewer is a responsability, you can't just click Request Changes without valid concerns about the code being merged. |
5176049
to
906720d
Compare
Rebased. |
906720d
to
2fb058e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see a lot of good things here, thanks for this !
@@ -92,11 +92,8 @@ | |||
globeView.scene.traverse(function _(obj) { | |||
if (obj.material && obj.material.setLayerVisibility && obj.material.visible) { | |||
material = obj.material; | |||
orthoIndex = material.indexOfColorLayer(orthoLayer.id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can remove their declaration above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -37,6 +39,7 @@ function TileMesh(geometry, params) { | |||
this.frustumCulled = false; | |||
|
|||
this.updateGeometricError(); | |||
this.wmtsCoords = {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not rename it to a more appropriate name in the same time ?
src/Renderer/LayeredMaterial.js
Outdated
} | ||
} else if (textures.texture !== null) { | ||
this._setTexture(textures.texture, | ||
layer.type == 'color' ? l_COLOR : l_ELEVATION, (slotOffset || 0), textures.pitch); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Condition unnecessary, result is always l_COLOR
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -32,11 +28,10 @@ function TileMesh(geometry, params) { | |||
this.boundingSphere = new THREE.Sphere(); | |||
this.OBB().box3D.getBoundingSphere(this.boundingSphere); | |||
|
|||
this.material = new LayeredMaterial(params.materialOptions); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
geometry._count++; | ||
const tile = new TileMesh(geometry, params); | ||
tile.layer = layer; | ||
const material = new LayeredMaterial(layer.materialOptions); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add somewhere a documentation to what is materialOptions
? Even if it is a quick comment, so we do no forget when we'll generate a better documentation on layers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. Note that these options are a workaround to limitations in the current code.
Hopefully these limitations will be removed soon and so will the options :)
LayeredMaterial.prototype.getLayerTextures = function getLayerTextures(layerType, layerId) { | ||
if (layerType === l_ELEVATION) { | ||
LayeredMaterial.prototype.getLayerTextures = function getLayerTextures(layer) { | ||
if (layer.type === 'elevation') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Side note: shouldn't it be more practical to change the constants in LayeredMaterialConstants
to elevation
, color
and all ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMHO, LayeredMaterialConstants
should be removed soon because that should be an implementation details.
But we'll also need to have valid layer types as constants somewhere (elevation
, color
, etc).
I can't answer inline for this one so I'll reply here: the PR #785 tackles this part, so I limited myself to moving code around. |
@zarov PR updated. |
Ok this is looking good to me. One last thing: do you have a suggestion for removing the |
Not really, and I feel it's useful (another use case: in the picking code where we need to filter if an mesh belongs to the requested layer). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok good to go then, squash your last commit please.
Currently the 'level' concept from WMTS has leaked everywhere in iTowns codebase. This commits replace its usage in one part of iTowns, by something equivalent but that doesn't force texture Providers to mock WMTS level mechanism.
This commits is a step forward stopping to rely on LayeredMaterial internal representation of textures (using an index and such) in other parts of iTowns. This will allow to reuse all this code for objects that don't use a LayerMaterial instance as their material.
a460af0
to
182ba92
Compare
2 commits, related to the same context: stop leaking internal attributes (WMTS level, LayeredMateiral texture indexing schema) in all iTowns.
First commit content:
2nd one is:
refacto(core): avoid manipulating LayeredMaterial internal state