Skip to content
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

fix vectorlayer 3D entity generation by filtering duplicates #52064

Merged
merged 9 commits into from
Sep 11, 2023

Conversation

benoitdm-oslandia
Copy link
Contributor

@benoitdm-oslandia benoitdm-oslandia commented Mar 1, 2023

This PR follow #53063

The feature selection, in QgsVectorLayerChunkLoader, was made according to the intersection of the current quadtree node and the feature geometry. For all features with geometry across quadtree nodes, the geometries were duplicated inducing memory and cpu degradations. This fix uses the previous filter (bbox intersection) then filters according to the geometry centroid.

closes #50971

Geometry / entity

Old version

Capture d’écran du 2023-03-13 15-50-12

A feature is included in multiple quadtree nodes. We use 1064 primitives in 18 geometries.
If we export the scene and import it into Blender we obtain 14 full objects (11 duplicates):

Capture d’écran du 2023-03-13 16-19-37

New version

Capture d’écran du 2023-03-13 15-55-47

Features across multiple quadtree nodes are clipped in the node bbox. We use 838 primitives in 18 geometries.

If we export the scene and import it into Blender we obtain 14 partial objects (one per quadtree node). The only duplicated faces are those created by the walls when the geometry is clipped:

Capture d’écran du 2023-03-13 16-23-36

Computation time

To do this test, I use a bigger project with 57000 features (from a Geopackage) with QGIS built in release.

I add a QElapsedTimer to monitor the time (I will remove it before the merge).

Old version

Capture d’écran du 2023-03-13 15-54-04

Log extract:


new 3D view map

Warning: Logged warning: ========================== job timer restarted!
Warning: Logged warning: Job took: 81ms
Warning: Logged warning: Job took: 228ms
Warning: Logged warning: Job took: 3317ms

new 3D view map

Warning: Logged warning: ========================== job timer restarted!
Warning: Logged warning: Job took: 38ms
Warning: Logged warning: Job took: 58ms
Warning: Logged warning: Job took: 90ms
Warning: Logged warning: Job took: 2205ms

new 3D view map

Warning: Logged warning: ========================== job timer restarted!
Warning: Logged warning: Job took: 17ms
Warning: Logged warning: Job took: 65ms
Warning: Logged warning: Job took: 2895ms

new 3D view map

Warning: Logged warning: ========================== job timer restarted!
Warning: Logged warning: Job took: 9ms
Warning: Logged warning: Job took: 30ms
Warning: Logged warning: Job took: 95ms
Warning: Logged warning: Job took: 2327ms

(3317+2205+2895+2327)÷4 ~= 2686ms for 3672934 primitives ==> 0,73µs per primitives.

New version

Capture d’écran du 2023-03-13 15-57-53

Log extract:

new 3D view map

Warning: Logged warning: ========================== job timer restarted!
Warning: Logged warning: Job took: 88ms
Warning: Logged warning: Job took: 182ms
Warning: Logged warning: Job took: 3116ms

new 3D view map

Warning: Logged warning: ========================== job timer restarted!
Warning: Logged warning: Job took: 9ms
Warning: Logged warning: Job took: 42ms
Warning: Logged warning: Job took: 79ms
Warning: Logged warning: Job took: 2120ms

new 3D view map

Warning: Logged warning: ========================== job timer restarted!
Warning: Logged warning: Job took: 25ms
Warning: Logged warning: Job took: 29ms
Warning: Logged warning: Job took: 36ms
Warning: Logged warning: Job took: 2775ms

new 3D view map

Warning: Logged warning: ========================== job timer restarted!
Warning: Logged warning: Job took: 22ms
Warning: Logged warning: Job took: 43ms
Warning: Logged warning: Job took: 71ms
Warning: Logged warning: Job took: 2170ms

(3116+2120+2775+2170)÷4 ~= 2545ms ==> for 3299502 primitives ==> 0,77µs per primitive

We lost ~5% in speed and we gain ~11,3% in primitive count.

The main gain is we have no more geometry duplicates.

@github-actions github-actions bot added this to the 3.30.0 milestone Mar 1, 2023
@benoitdm-oslandia benoitdm-oslandia self-assigned this Mar 1, 2023
@benoitdm-oslandia benoitdm-oslandia added the 3D Relates to QGIS' 3D engine or rendering label Mar 1, 2023
@nyalldawson
Copy link
Collaborator

feature is included in only one quadtree node

Wouldn't this mean that features will become invisible as soon as the node containing their centroid out of view? (Even if other nodes containing part of the geometry are still visible)

@benoitdm-oslandia
Copy link
Contributor Author

Wouldn't this mean that features will become invisible as soon as the node containing their centroid out of view? (Even if other nodes containing part of the geometry are still visible)

Yes, exactly!

@benoitdm-oslandia benoitdm-oslandia marked this pull request as draft March 2, 2023 07:16
@nyalldawson
Copy link
Collaborator

@benoitdm-oslandia isn't that a regression? Objects will disappear unexpectedly from the edge of views as a 3d map is navigated....

@nyalldawson nyalldawson modified the milestones: 3.30.0, 3.32 (feature) Mar 6, 2023
@uclaros
Copy link
Contributor

uclaros commented Mar 6, 2023

@benoitdm-oslandia also, keep in mind to perform any benchmarking on the optimized release build, as the debug build can have significantly different results!

@benoitdm-oslandia
Copy link
Contributor Author

You were right! It was more obvious for concave geometries.

I rework my PR by clipping the 2D polygon with the bbox of the current chunk node. Only the used part is kept in the chunk node entity. There is no more duplicate but the clipping increase by a little (17µs per geom) the rendering time.

I will push some perf stats on monday.

@benoitdm-oslandia benoitdm-oslandia force-pushed the fix/50971-export branch 3 times, most recently from 69632bf to a0e3ffc Compare March 14, 2023 16:28
@benoitdm-oslandia benoitdm-oslandia marked this pull request as ready for review March 15, 2023 08:15
@github-actions
Copy link

The QGIS project highly values your contribution and would love to see this work merged! Unfortunately this PR has not had any activity in the last 14 days and is being automatically marked as "stale". If you think this pull request should be merged, please check

  • that all unit tests are passing

  • that all comments by reviewers have been addressed

  • that there is enough information for reviewers, in particular

    • link to any issues which this pull request fixes

    • add a description of workflows which this pull request fixes

    • add screenshots if applicable

  • that you have written unit tests where possible
    In case you should have any uncertainty, please leave a comment and we will be happy to help you proceed with this pull request.
    If there is no further activity on this pull request, it will be closed in a week.

@github-actions github-actions bot added the stale Uh oh! Seems this work is abandoned, and the PR is about to close. label Mar 30, 2023
@benoitdm-oslandia benoitdm-oslandia removed the stale Uh oh! Seems this work is abandoned, and the PR is about to close. label Mar 30, 2023
@benoitdm-oslandia
Copy link
Contributor Author

@uclaros @nyalldawson can you please have a look?

@uclaros
Copy link
Contributor

uclaros commented Mar 30, 2023

I'm not sure I like the idea of clipping on the chunk extents. The seams will be visible when rendering edges is enabled.
If the only problem with the currently duplicated primitives is exporting, then would it be possible to implement some fid based filtering when exporting (I've no clue about the exporting code) to avoid exporting the same fid twice?

On another note, I love the tidying up and setting of objectNames! That will help debugging and exploring the scene in Gammaray!
I'd suggest you wrap those unrelated fixes in a separate PR

@benoitdm-oslandia
Copy link
Contributor Author

I'm not sure I like the idea of clipping on the chunk extents. The seams will be visible when rendering edges is enabled.

Yes indeed.

If the only problem with the currently duplicated primitives is exporting, then would it be possible to implement some fid based filtering when exporting (I've no clue about the exporting code) to avoid exporting the same fid twice?

From the exporting function pov the only known objects are the QEntity objects obtained by the createEntity function of a chunkLoader. These Qt entities do not have any fid field.

  1. solution would be to create a base object Qgs3DFeatureEntity (inheriting QEntity) and change every chunkLoader logic to handle the new object and assign fid.

  2. solution would be to use the composition design already available to the QEntity and add a new component (with fid) to each QEntity. But we will need to change every chunkLoader logic to handle the component.

  3. solution would be to add a dynamic property to the QEntity with the fid and again to change every chunkLoader logic to handle the property.

IMHO the 2. and 3. solution are prone to error due to the need to think (or to forget) to add the property or the component. 1. solution in another hand, by changing the chunkLoader signature can force to add the fid.

But this is a big change just to filter objects during export.

@wonder-sk
Copy link
Member

One more issue with the current clipping approach is that it is likely not going to work with polygons that are not horizontal (this is common with city models, for example with roofs) - as far as I know, GEOS only does the operations in 2D.

By the way, in the PR, expected_polygon3d_extrusion_opacity.png seems to have a visible horizontal shift compared to the original image - is that correct?

The de-duplication of features in export should be doable with the current implementation - for the purposes of the identify tool, we keep a data structure to understand what triangles map to what feature ID (for tessellated polygon geometries), so this data structure could be used for de-duplication too.

A proper solution would be nice to have for the 3D view too - for solid objects it's all fine, but semi-transparent objects on tile boundaries may be drawn more solid due to the duplication. Apart from the original approach with one feature being only in one tile, and the current approach with clipping, I can imagine a third approach - entities for tiles would only contain features fully inside, and the features spanning more than one tile would be rendered on special "shared" entities which would be enabled whenever adjacent entity gets enabled. That approach would solve all the issues: edge highlighting, semi-transparent objects and export.

@github-actions github-actions bot added the stale Uh oh! Seems this work is abandoned, and the PR is about to close. label Apr 15, 2023
@benoitdm-oslandia benoitdm-oslandia force-pushed the fix/50971-export branch 2 times, most recently from 3e3ac5d to 0ca88ca Compare September 5, 2023 12:22
@benoitdm-oslandia
Copy link
Contributor Author

please @nyalldawson, @lbartoletti or @troopa81, can I have a review?

@benoitdm-oslandia
Copy link
Contributor Author

@nyalldawson @uclaros can you review please?

src/3d/qgs3dexportobject.cpp Outdated Show resolved Hide resolved
src/3d/symbols/qgspolygon3dsymbol.cpp Outdated Show resolved Hide resolved
src/3d/qgsvectorlayerchunkloader_p.cpp Outdated Show resolved Hide resolved
src/3d/qgstessellatedpolygongeometry.h Outdated Show resolved Hide resolved
src/3d/qgs3dsceneexporter.cpp Outdated Show resolved Hide resolved
src/3d/qgs3dsceneexporter.cpp Outdated Show resolved Hide resolved
@nyalldawson
Copy link
Collaborator

Just some very minor changes from my end, otherwise all looks good!

@benoitdm-oslandia
Copy link
Contributor Author

@nyalldawson I have squashed the history too. Let me know!

Copy link
Contributor

@uclaros uclaros left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few consts here and there

tests/src/3d/testqgs3drendering.cpp Outdated Show resolved Hide resolved
tests/src/3d/testqgs3drendering.cpp Outdated Show resolved Hide resolved
src/3d/symbols/qgspolygon3dsymbol.cpp Outdated Show resolved Hide resolved
src/3d/qgs3dsceneexporter.cpp Outdated Show resolved Hide resolved
src/3d/qgs3dsceneexporter.cpp Outdated Show resolved Hide resolved
src/3d/qgs3dsceneexporter.cpp Outdated Show resolved Hide resolved
@benoitdm-oslandia benoitdm-oslandia removed the request for review from vcloarec September 11, 2023 13:16
@nyalldawson nyalldawson merged commit 1cf6dfc into qgis:master Sep 11, 2023
28 checks passed
@benoitdm-oslandia benoitdm-oslandia deleted the fix/50971-export branch September 12, 2023 05:54
@benoitdm-oslandia
Copy link
Contributor Author

thanks @nyalldawson @uclaros!

@nyalldawson
Copy link
Collaborator

@benoitdm-oslandia looks like the new test is a bit fragile -- see eg https://github.com/qgis/QGIS/actions/runs/6179574806/job/16777801856?pr=54578 for a random failure it's been triggering

@benoitdm-oslandia
Copy link
Contributor Author

Train trip today! I will try to fix that asap

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3D Relates to QGIS' 3D engine or rendering
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Exporting 3D scene to .obj stores the same feature 16x
6 participants