heremaps/harp.gl

Optimisation possible for rendering. Only evaluate expressions for items which are in viewport.

Closed this issue ยท 1 comments

Hi! ๐Ÿ‘‹

Firstly, thanks for your work on this project! ๐Ÿ™‚

Today I used patch-package to patch @here/harp-mapview@0.27.1 for the project I'm working on.

Here is the diff that solved my problem:

diff --git a/node_modules/@here/harp-mapview/lib/MapView.js b/node_modules/@here/harp-mapview/lib/MapView.js
index dd4d22a..7507d21 100644
--- a/node_modules/@here/harp-mapview/lib/MapView.js
+++ b/node_modules/@here/harp-mapview/lib/MapView.js
@@ -2308,11 +2308,18 @@ class MapView extends EventDispatcher_1.EventDispatcher {
         if (gatherStatistics) {
             cullTime = harp_utils_1.PerformanceTimer.now();
         }
+        const frustum = new THREE.Frustum();
+        const projScreenMatrix = new THREE.Matrix4();
+        this.m_camera.updateMatrixWorld();
+        this.m_camera.updateProjectionMatrix();
+        projScreenMatrix.multiplyMatrices(this.m_camera.projectionMatrix, this.m_camera.matrixWorldInverse);
+        frustum.setFromProjectionMatrix(projScreenMatrix);
+
         const renderList = this.m_visibleTiles.dataSourceTileList;
         // no need to check everything if we're not going to create text renderer.
         renderList.forEach(({ zoomLevel, renderedTiles }) => {
             renderedTiles.forEach(tile => {
-                this.m_tileObjectRenderer.render(tile, zoomLevel, this.zoomLevel, this.m_camera.position, this.m_sceneRoot);
+                this.m_tileObjectRenderer.render(tile, zoomLevel, this.zoomLevel, this.m_camera.position, this.m_sceneRoot, frustum);
                 //We know that rendered tiles are visible (in the view frustum), so we update the
                 //frame number, note we don't do this for the visibleTiles because some may still be
                 //loading (and therefore aren't visible in the sense of being seen on the screen).
diff --git a/node_modules/@here/harp-mapview/lib/TileObjectsRenderer.js b/node_modules/@here/harp-mapview/lib/TileObjectsRenderer.js
index afd9f31..9cb2981 100644
--- a/node_modules/@here/harp-mapview/lib/TileObjectsRenderer.js
+++ b/node_modules/@here/harp-mapview/lib/TileObjectsRenderer.js
@@ -19,21 +19,44 @@ class TileObjectRenderer {
         // Valid values start at 1, because the screen is cleared to zero
         this.m_stencilValue = DEFAULT_STENCIL_VALUE;
     }
-    render(tile, storageLevel, zoomLevel, cameraPosition, rootNode) {
+    render(tile, storageLevel, zoomLevel, cameraPosition, rootNode, frustum) {
         const worldOffsetX = tile.computeWorldOffsetX();
         if (tile.willRender(storageLevel)) {
             for (const object of tile.objects) {
-                const mapObjectAdapter = MapObjectAdapter_1.MapObjectAdapter.get(object);
-                if (!this.processTileObject(tile, storageLevel, zoomLevel, object, mapObjectAdapter)) {
-                    continue;
-                }
-                this.updateStencilRef(object);
+
+                // Set object in world space
                 object.position.copy(tile.center);
                 if (object.displacement !== undefined) {
                     object.position.add(object.displacement);
                 }
                 object.position.x += worldOffsetX;
+
+                // Optimization to not process objects which are outside the camera.
+                let visible = false;
+                if (object.geometry) {
+                    if (!object.geometry.boundingSphere) {
+                        object.geometry.computeBoundingSphere();
+                    }
+                    const s = object.geometry.boundingSphere;
+                    // Temporarily transform the sphere to world space
+                    s.center.add(tile.center);
+                    visible = frustum.intersectsSphere(s);
+                    // Transform it back, perhaps it is used elsewhere?
+                    s.center.sub(tile.center);
+                }
+
+                if (!visible) {
+                    continue;
+                }
+
+                // Move object relative to camera
                 object.position.sub(cameraPosition);
+
+                const mapObjectAdapter = MapObjectAdapter_1.MapObjectAdapter.get(object);
+                if (!this.processTileObject(tile, storageLevel, zoomLevel, object, mapObjectAdapter)) {
+                    continue;
+                }
+                this.updateStencilRef(object);
                 if (tile.localTangentSpace) {
                     object.setRotationFromMatrix(tile.boundingBox.getRotationMatrix());
                 }

This issue body was partially generated by patch-package.

stale commented

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.