@@ -3,11 +3,13 @@ import {
33 TilesFadePlugin ,
44 TileCompressionPlugin ,
55 GLTFExtensionsPlugin ,
6- GoogleCloudAuthPlugin
6+ GoogleCloudAuthPlugin ,
7+ TileFlatteningPlugin
78} from '3d-tiles-renderer/plugins' ;
89
9- console . log ( '3d-tiles-renderer' , TilesRenderer ) ;
1010const MathUtils = AFRAME . THREE . MathUtils ;
11+ const Vector3 = AFRAME . THREE . Vector3 ;
12+ const Box3 = AFRAME . THREE . Box3 ;
1113
1214if ( typeof AFRAME === 'undefined' ) {
1315 throw new Error (
@@ -23,7 +25,9 @@ AFRAME.registerComponent('google-maps-aerial', {
2325 minDistance : { type : 'number' , default : 500 } ,
2426 maxDistance : { type : 'number' , default : 20000 } ,
2527 ellipsoidalHeight : { type : 'number' , default : 0 } ,
26- copyrightEl : { type : 'selector' }
28+ copyrightEl : { type : 'selector' } ,
29+ enableFlattening : { type : 'boolean' , default : false } ,
30+ flatteningShape : { type : 'string' , default : '' }
2731 } ,
2832
2933 init : function ( ) {
@@ -44,6 +48,9 @@ AFRAME.registerComponent('google-maps-aerial', {
4448 } )
4549 ) ;
4650
51+ // Always create flattening plugin to support runtime toggling
52+ this . flatteningPlugin = new TileFlatteningPlugin ( ) ;
53+ this . tiles . registerPlugin ( this . flatteningPlugin ) ;
4754 // Set location
4855 this . tiles . setLatLonToYUp (
4956 this . data . latitude * MathUtils . DEG2RAD ,
@@ -55,6 +62,15 @@ AFRAME.registerComponent('google-maps-aerial', {
5562 this . data . copyrightEl . innerHTML =
5663 this . tiles . getAttributions ( ) [ 0 ] ?. value || '' ;
5764 }
65+
66+ // Add flattening shape after tiles are loaded
67+ if (
68+ this . data . enableFlattening &&
69+ this . data . flatteningShape &&
70+ ! this . flatteningShape
71+ ) {
72+ this . addFlatteningShape ( this . data . flatteningShape ) ;
73+ }
5874 } ) ;
5975
6076 // Create a child entity for the height offset
@@ -77,6 +93,46 @@ AFRAME.registerComponent('google-maps-aerial', {
7793 }
7894 } ,
7995
96+ addFlatteningShape : function ( shapeSelector ) {
97+ if ( ! this . flatteningPlugin || ! shapeSelector ) return ;
98+
99+ const testMeshEl = document . querySelector ( shapeSelector ) ;
100+ if ( ! testMeshEl ) return ;
101+
102+ const testMesh = testMeshEl . object3D . children [ 0 ] ;
103+ if ( ! testMesh ) return ;
104+
105+ // Ensure world transforms are up to date
106+ this . tiles . group . updateMatrixWorld ( ) ;
107+ testMesh . updateMatrixWorld ( true ) ;
108+
109+ // Transform the shape into the local frame of the tile set
110+ const relativeShape = testMesh . clone ( ) ;
111+ relativeShape . matrixWorld
112+ . premultiply ( this . tiles . group . matrixWorldInverse )
113+ . decompose (
114+ relativeShape . position ,
115+ relativeShape . quaternion ,
116+ relativeShape . scale
117+ ) ;
118+
119+ // Calculate the direction to flatten on using ellipsoid
120+ const direction = new Vector3 ( ) ;
121+ const box = new Box3 ( ) ;
122+ box . setFromObject ( relativeShape ) ;
123+ box . getCenter ( direction ) ;
124+ this . tiles . ellipsoid
125+ . getPositionToNormal ( direction , direction )
126+ . multiplyScalar ( - 1 ) ;
127+
128+ // Add the transformed plane as a flattening shape
129+ this . flatteningPlugin . addShape ( relativeShape , direction , Infinity ) ;
130+
131+ // Store references for cleanup and updates
132+ this . flatteningShape = relativeShape ;
133+ this . originalFlatteningMesh = testMesh ;
134+ } ,
135+
80136 tick : function ( ) {
81137 if ( this . tiles && this . el . sceneEl . camera ) {
82138 // Ensure camera is set on each tick
@@ -85,12 +141,45 @@ AFRAME.registerComponent('google-maps-aerial', {
85141 this . el . sceneEl . camera ,
86142 this . renderer
87143 ) ;
144+
145+ // Update flattening shape if it exists
146+ if (
147+ this . flatteningPlugin &&
148+ this . flatteningShape &&
149+ this . originalFlatteningMesh
150+ ) {
151+ // Update world transforms
152+ this . tiles . group . updateMatrixWorld ( ) ;
153+ this . originalFlatteningMesh . updateMatrixWorld ( true ) ;
154+
155+ // Re-transform the shape into the local frame of the tile set
156+ this . flatteningShape . matrixWorld . copy (
157+ this . originalFlatteningMesh . matrixWorld
158+ ) ;
159+ this . flatteningShape . matrixWorld
160+ . premultiply ( this . tiles . group . matrixWorldInverse )
161+ . decompose (
162+ this . flatteningShape . position ,
163+ this . flatteningShape . quaternion ,
164+ this . flatteningShape . scale
165+ ) ;
166+
167+ this . flatteningPlugin . updateShape ( this . flatteningShape ) ;
168+ }
169+
88170 this . tiles . update ( ) ;
89171 }
90172 } ,
91173
92174 remove : function ( ) {
93175 if ( this . tiles ) {
176+ // Clean up flattening shape
177+ if ( this . flatteningPlugin && this . flatteningShape ) {
178+ this . flatteningPlugin . deleteShape ( this . flatteningShape ) ;
179+ this . flatteningShape = null ;
180+ this . originalFlatteningMesh = null ;
181+ }
182+
94183 if ( this . offsetEl ) {
95184 this . offsetEl . removeFromParent ( ) ;
96185 this . offsetEl = null ;
@@ -114,5 +203,24 @@ AFRAME.registerComponent('google-maps-aerial', {
114203 ) ;
115204 this . offsetEl . object3D . position . y = - this . data . ellipsoidalHeight ;
116205 }
206+
207+ // Handle flattening changes
208+ const flatteningChanged =
209+ oldData . enableFlattening !== this . data . enableFlattening ;
210+ const shapeChanged = oldData . flatteningShape !== this . data . flatteningShape ;
211+
212+ if ( flatteningChanged || shapeChanged ) {
213+ // Remove old shape if it exists
214+ if ( this . flatteningShape ) {
215+ this . flatteningPlugin . deleteShape ( this . flatteningShape ) ;
216+ this . flatteningShape = null ;
217+ this . originalFlatteningMesh = null ;
218+ }
219+
220+ // Add new shape if flattening is enabled and we have a shape
221+ if ( this . data . enableFlattening && this . data . flatteningShape ) {
222+ this . addFlatteningShape ( this . data . flatteningShape ) ;
223+ }
224+ }
117225 }
118226} ) ;
0 commit comments