-
Notifications
You must be signed in to change notification settings - Fork 303
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
Refactor(core): unify SSE computation methods #674
Conversation
Also note : this PR provides almost everything needed to compute the camera far / near plane correctly in realtime (near would be minimum distance from all updated elements, far would be the max) |
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.
review on first commit: refactor(core): unify SSE computation methods
name: childname, | ||
baseurl: url, | ||
bbox: bounds, | ||
geometricError: layer.metadata.spacing / Math.pow(2, childname.length), |
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.
Evoked in the commit message, there is a reference that explains the calculation?
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 is by construction: see https://github.com/peppsac/PotreeConverter/blob/master/PotreeConverter/src/PotreeWriter.cpp#L73
src/Core/ScreenSpaceError.js
Outdated
const m2 = new THREE.Matrix4(); | ||
const m3 = new THREE.Matrix4(); | ||
|
||
function compute(vector, matrix, camera, distance, _3d) { |
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.
compute
what?
src/Core/ScreenSpaceError.js
Outdated
|
||
function compute(vector, matrix, camera, distance, _3d) { | ||
const basis = [ | ||
new THREE.Vector3(vector.x, 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.
THREE.Vector3
to declare outside the function
|
||
function findBox3Distance(camera, box3, matrix) { | ||
// TODO: can be cached | ||
m.getInverse(matrix); |
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.
matrix
it's OBB worldMatrix? you would cache in OBB.worldMatrixInv
?
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'd prefer not to cache anything first (hence the TODO node).
I believe we need to rework the notifyChange()
mechanism to allow more precise updates / cache invalidation.
src/Core/ScreenSpaceError.js
Outdated
|
||
MODE_3D: 2, | ||
|
||
computeFromBox3(camera, box3, matrix, geometricError, mode) { |
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.
there's no method to compute with sphere?
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 yet. As your other comment suggests I could move the sphere -> sse code from 3dtiles to here.
src/Core/ScreenSpaceError.js
Outdated
|
||
const size = computeSizeFromGeometricError(box3, geometricError); | ||
|
||
const sse = compute(size, matrix, camera, distance, mode == this.MODE_3D); |
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.
compute
calculates a pixel projection size?
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 change the function name.
src/Core/ScreenSpaceError.js
Outdated
} | ||
|
||
export default { | ||
MODE_2D: 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.
could you explain the modes?
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 forgot to add a comment.
The idea here is: do we want to use the 2d bounding-box (x, y) or the 3d one.
For tiles we want to use the 2d one, while for other objects (pointcloud, 3dtiles) the 3d one makes more sense.
src/Process/3dTilesProcessing.js
Outdated
worldPosition.setFromMatrixPosition(node.matrixWorld); | ||
cameraLocalPosition.copy(camera.camera3D.position).sub(worldPosition); | ||
node.distance = Math.max(0.0, node.boundingVolume.sphere.distanceToPoint(cameraLocalPosition)); | ||
const distance = Math.max(0.0, node.boundingVolume.sphere.distanceToPoint(cameraLocalPosition)); | ||
return camera.preSSE * (node.geometricError / distance); |
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 place it in ScreenSpaceError.js
src/Process/GlobeTileProcessing.js
Outdated
const sse = computeNodeSSE(context.camera, node); | ||
|
||
return SSE_SUBDIVISION_THRESHOLD < sse; | ||
node.sse = ScreenSpaceError.computeFromBox3( |
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 you replace the bounding sphere with OBBs?
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.
Because the OBB is closer to the real volume of the node
then a sphere.
@@ -164,6 +132,7 @@ export function globeSchemeTileWMTS(type) { | |||
} | |||
|
|||
export function computeTileZoomFromDistanceCamera(distance, view) { | |||
// TODO fixme |
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 have an idea?
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 didn't even try to fix this for now.
I'd rather make sure that the sse computation introduced in this PR is ok.
PR updaded. |
@gchoqueux : thanks for the feedback. The current logic is: we project both the bounding box x and y axis on the screen. Subdivision happens if SSE is > 256 (texture size) + layer.sseThreshold (5 by default). The reason here for using the min is to prevent subdivision when the camera view vector is ~tangent to the surface but I agree that it's problematic in other case, such as your 2nd screenshot. An alternative would be to keep SSE in x and y directions separately.
|
@gchoqueux I pushed an example implementation of #674 (comment) It breaks everything but the globe (because I only adapted GlobeTileProcessing). Can you give it a try and let me know what you think? |
in
|
This approach computes the sse for each axis.
Nope. The
It's used to compute the distance to camera. |
I'm talking about the box's diagonal (in x, y and z)
DEM is mapped on z axis, not only x and y
yet you go through the world space when calculating (with |
Can you compute a correct estimation of the DEM error in meters along the z axis for every tiles?
No I'm not. You misread the code: m3 is only the rotation part, not the full world matrix of the camera. |
What is your formula to estimate error on the x and y axes? You don't answer this question : the projection would be different with Vector3.Project? |
Compare size in pixels of the tile on the screen to the texture size.
Yes it would be diffrent. I detailled in my earlier comment #674 (comment) the differences between Vector3.Project and my computations. |
The texels are also on the box's diagonal (x, y, z), it can more revelant by example with box'size (100, 100, 1000)
I can't understand why there is a difference between the two, I'm going to look |
Until this commit each geometry type had its own SSE computation methods. The goal of this commit is to provide a single method based on: - bounding-box (BB) - geometricError (in meters) - distance The computation is simple: - transform camera in BB's basis - compute distance camera - BB - project geometricError on screen at distance The last step produce a screen-space-error in pixels. Geometric error values depend on the data type: - 3dtiles: the tileset defines a geometricError per node so we can use this value - pointcloud: PotreeConverter defines a spacing, which is the average distance between points in each node. We use: geometricError = spacing / 2^depth - tiles: this commit adapted the existing formula to use consistent units
Rebased. I also removed the As far as I can tell this PR improves the SSE handling in most situations. Regarding the diagonal: I still believe it isn't an issue. It's an corner case so I don't think it's worth complexifying the code to cover it. Btw, current master version SSE handling is quite bizarre anyway. E.g: in this screenshot the nearest tile in the middle of the screen is almost 600px wide. globeView.camera.camera3D.position.copy({x: 4490626.907379815, y: 506551.71291476686, z: 4500105.469154227})
globeView.camera.camera3D.rotation.copy({_x: -1.3092800928909716, _y: 0.4734022844137177, _z: -2.4859644421245957, _order: "XYZ"})
globeView.notifyChange(true); |
Project average point spacing on screen and compare to sse threshold. It's a simplification of the approach proposed in #674. This allows to drop a dependency (convexhull) and brings the SSE compuation for pointcloud closer to what is done for other geometries.
Project average point spacing on screen and compare to sse threshold. It's a simplification of the approach proposed in #674. This allows to drop a dependency (convexhull) and brings the SSE compuation for pointcloud closer to what is done for other geometries.
Project average point spacing on screen and compare to sse threshold. It's a simplification of the approach proposed in #674. This allows to drop a dependency (convexhull) and brings the SSE compuation for pointcloud closer to what is done for other geometries.
Project average point spacing on screen and compare to sse threshold. It's a simplification of the approach proposed in #674. This allows to drop a dependency (convexhull) and brings the SSE compuation for pointcloud closer to what is done for other geometries.
Project average point spacing on screen and compare to sse threshold. It's a simplification of the approach proposed in #674. This allows to drop a dependency (convexhull) and brings the SSE compuation for pointcloud closer to what is done for other geometries.
Project average point spacing on screen and compare to sse threshold. It's a simplification of the approach proposed in #674. This allows to drop a dependency (convexhull) and brings the SSE compuation for pointcloud closer to what is done for other geometries.
Project average point spacing on screen and compare to sse threshold. It's a simplification of the approach proposed in #674. This allows to drop a dependency (convexhull) and brings the SSE compuation for pointcloud closer to what is done for other geometries.
Project average point spacing on screen and compare to sse threshold. It's a simplification of the approach proposed in #674. This allows to drop a dependency (convexhull) and brings the SSE compuation for pointcloud closer to what is done for other geometries.
Project average point spacing on screen and compare to sse threshold. It's a simplification of the approach proposed in #674. This allows to drop a dependency (convexhull) and brings the SSE compuation for pointcloud closer to what is done for other geometries.
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.
some comments. could you define mathematically the sse?
// Move camera position in box3 basis | ||
// (we don't transform box3 to camera basis because box3 are AABB) | ||
const pt = camera.camera3D.position | ||
.clone(v).applyMatrix4(m); |
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 is wrong if m as some scaling (eigenvalues != 1)
b.y = b.y * camera.height * 0.5; | ||
} | ||
|
||
return basis.map(b => b.length()); |
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 looks like an approximation of some distance, which computation is optimized by considering axes independently. could you phrase mathematically the exact distance you are approximating ?
Thanks for the comments. I'll come back to this PR soon, but for now I'm focused on the more recently opened PRs. |
Until this PR each geometry type had its own SSE computation methods.
The goal of this PR is to provide a single method based on:
The computation is simple:
The last step produce a screen-space-error in pixels.
Geometric error values depend on the data type:
between points in each node. We use: geometricError = spacing / 2^depth
The second commit adds a SSE inspector debug tool:
red: computed SSE
yellow: texture resolution (only used for tile sse)
green: sse treshold