@@ -15,6 +15,7 @@ import {LayerTypeMask} from '../../../3d-style/util/conflation';
1515import { isValidUrl } from '../../../src/style-spec/validate/validate_model' ;
1616import { type FeatureState , type GlobalProperties } from '../../../src/style-spec/expression/index' ;
1717import Point from '@mapbox/point-geometry' ;
18+ import { ElevationFeatures , type ElevationFeature } from '../../elevation/elevation_feature' ;
1819
1920import type ModelStyleLayer from '../../style/style_layer/model_style_layer' ;
2021import type { ReplacementSource , Region } from '../../../3d-style/source/replacement_source' ;
@@ -64,6 +65,7 @@ class PerModelAttributes {
6465 instancedDataArray : InstanceVertexArray ;
6566 instancedDataBuffer : VertexBuffer ;
6667 instancesEvaluatedElevation : Array < number > ; // Gets added to DEM elevation of the instance to produce value in instancedDataArray.
68+ instancesRoadElevation : Array < number > | undefined ;
6769
6870 features : Array < ModelFeature > ;
6971 idToFeaturesIndex : Partial < Record < string | number , number > > ; // via this.features, enable lookup instancedDataArray based on feature ID.
@@ -230,6 +232,10 @@ class ModelBucket implements Bucket {
230232 const needGeometry = this . layers [ 0 ] . _featureFilter . needGeometry ;
231233 this . lookup = new Uint8Array ( this . lookupDim * this . lookupDim ) ;
232234
235+ // Only use elevation features when model-elevation-reference is set to hd-road-markup
236+ const usesHdRoadMarkupElevation = this . layers [ 0 ] . paint . get ( 'model-elevation-reference' ) === 'hd-road-markup' ;
237+ const elevationFeatures = usesHdRoadMarkupElevation ? options . elevationFeatures : undefined ;
238+
233239 for ( const { feature, id, index, sourceLayerIndex} of features ) {
234240 // use non numeric id, if in properties, too.
235241 const featureId = ( id != null ) ? id :
@@ -249,7 +255,7 @@ class ModelBucket implements Bucket {
249255 patterns : { }
250256 } ;
251257
252- const modelId = this . addFeature ( bucketFeature , bucketFeature . geometry , evaluationFeature ) ;
258+ const modelId = this . addFeature ( bucketFeature , bucketFeature . geometry , evaluationFeature , elevationFeatures , canonical ) ;
253259
254260 if ( modelId ) {
255261 // Since 3D model geometry extends over footprint or point geometry, it is important
@@ -442,6 +448,8 @@ class ModelBucket implements Bucket {
442448 feature : BucketFeature ,
443449 geometry : Array < Array < Point > > ,
444450 evaluationFeature : EvaluationFeature ,
451+ elevationFeatures ?: ElevationFeature [ ] ,
452+ canonical ?: CanonicalTileID
445453 ) : string {
446454 const layer = this . layers [ 0 ] ;
447455 const modelIdProperty = layer . layout . get ( 'model-id' ) ;
@@ -474,6 +482,13 @@ class ModelBucket implements Bucket {
474482 const instancedDataArray = perModelVertexArray . instancedDataArray ;
475483
476484 const modelFeature = new ModelFeature ( evaluationFeature , instancedDataArray . length ) ;
485+
486+ // Query elevation feature once per feature
487+ let tiledElevation : ElevationFeature | undefined ;
488+ if ( elevationFeatures ) {
489+ tiledElevation = ElevationFeatures . getElevationFeature ( feature , elevationFeatures ) ;
490+ }
491+
477492 for ( const geometries of geometry ) {
478493 for ( const point of geometries ) {
479494 if ( point . x < 0 || point . x >= EXTENT || point . y < 0 || point . y >= EXTENT ) {
@@ -493,6 +508,14 @@ class ModelBucket implements Bucket {
493508 this . instanceCount ++ ;
494509 const i = instancedDataArray . length ;
495510 instancedDataArray . resize ( i + 1 ) ;
511+
512+ if ( elevationFeatures ) {
513+ if ( ! perModelVertexArray . instancesRoadElevation ) {
514+ perModelVertexArray . instancesRoadElevation = [ ] ;
515+ }
516+ const roadElevation = tiledElevation ? tiledElevation . pointElevation ( new Point ( point . x , point . y ) ) : 0 ;
517+ perModelVertexArray . instancesRoadElevation . push ( roadElevation ) ;
518+ }
496519 perModelVertexArray . instancesEvaluatedElevation . push ( 0 ) ;
497520 instancedDataArray . float32 [ i * 16 ] = point . x ;
498521 instancedDataArray . float32 [ i * 16 + 1 ] = point . y ;
@@ -575,7 +598,8 @@ class ModelBucket implements Bucket {
575598 // Elements [4..6]: translation evaluated for the feature.
576599 va [ offset + 4 ] = translation [ 0 ] ;
577600 va [ offset + 5 ] = translation [ 1 ] ;
578- va [ offset + 6 ] = translation [ 2 ] + terrainElevationContribution ;
601+ const roadElevationContribution = perModelVertexArray . instancesRoadElevation ? perModelVertexArray . instancesRoadElevation [ instanceOffset ] : 0 ;
602+ va [ offset + 6 ] = translation [ 2 ] + roadElevationContribution + terrainElevationContribution ;
579603 // Elements [7..16] Instance modelMatrix holds combined rotation and scale 3x3,
580604 // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
581605 va [ offset + 7 ] = rotationScaleYZFlip [ 0 ] ;
0 commit comments