mapbox / mapbox-maps-ios

Interactive, thoroughly customizable maps for iOS powered by vector tiles and Metal
https://www.mapbox.com/mapbox-mobile-sdk
Other
452 stars 149 forks source link

ModelLayer disappears abruptly on panning when pitch is applied #2152

Open qandeelabbassi opened 3 months ago

qandeelabbassi commented 3 months ago

Environment

Observed behavior and steps to reproduce

ModelLayer disappears abruptly on panning when pitch is applied. Sometimes, initially, it doesn't even appear until I move the camera around

Code for adding model

 let plane = Bundle.main.url(
      forResource: MapViewModel.MapViewLabels.modelName,
      withExtension: MapViewModel.MapViewLabels.modelExt)!.absoluteString
  var source = GeoJSONSource(id: MapViewLabels.sourseID)
  try? mapProxy?.map!.addStyleModel(modelId: MapViewLabels.modelID, modelUri: plane)
  var planeFeature = Feature(geometry: Point(CLLocationCoordinate2D(latitude: position?.latitude ?? self.latitude, longitude: position?.longitude ?? self.longitude)))
  planeFeature.properties = [MapViewLabels.modelKey: .string(MapViewLabels.modelID)]
  source.data = .featureCollection(FeatureCollection(features: [planeFeature]))
  try? mapProxy?.map!.addSource(source)
  var layer = ModelLayer(id: MapViewLabels.layerId, source: MapViewLabels.sourseID)
  layer.modelId = .expression(Exp(.get) { MapViewLabels.modelKey })
  layer.modelType = .constant(.common3d)
  layer.modelScale = .constant(MapViewModel.MapViewLabels.modelScale)
  let altitude = position?.altitude?.feetToMeter() ?? Double(self.altitude)
  layer.modelTranslation = .constant([0, 0, altitude])
  let headingAngle = Double(position?.heading ?? heading) - 180
  layer.modelRotation = .constant([0, 0, headingAngle])
  layer.maxZoom = 22
  layer.minZoom = 0  
  try? mapProxy?.map!.addLayer(layer)

Code for setting camera:

let freeCam = self.mapProxy?.map?.freeCameraOptions
freeCam?.location = CLLocationCoordinate2D(latitude: lat, longitude: lng)
freeCam?.altitude = camAltitude
freeCam?.lookAtPoint(forLocation: CLLocationCoordinate2D(latitude: modelLat, longitude: modelLng), altitude: modelAltitude)
mapProxy?.map?.freeCameraOptions = freeCam!

Video

https://github.com/mapbox/mapbox-maps-ios/assets/14296772/93b8176b-8cfc-4997-9f64-518aeea589fc

Expected behavior

The model shouldn't disappear

astojilj commented 3 months ago

@qandeelabbassi Thanks. This issue is related to tile cover: internally, geojson is split into tiles, and when the underlying tile gets out of the viewport, each of the 3D model objects anchored to the positions on that tile is not rendered.

We will work on resolving this. Meanwhile, as a workaround, would it help to lower layer.maxZoom = 22, to e.g. layer.maxZoom = 5? Larger tiles (occupying larger geometry) would be less likely to get out of the viewport. The workaround would be problematic for a high zoom situations due to precision loss.

qandeelabbassi commented 3 months ago

@astojilj, thanks for the quick response.

  1. I forgot to mention that the 2 models in the above video are two different instances, they are not connected in any way, should the tile cover still be an issue?
  2. When the underlying tile gets out of the viewport, each of the 3D model objects anchored to the positions on that tile is not rendered.

But the models never get out of the viewport in the above video. My understanding of the viewport might be incorrect, so I would like to know what viewport you are referring to here.

  1. Meanwhile, as a workaround, would it help to lower layer.maxZoom = 22, to e.g. layer.maxZoom = 5?

According to my understanding, decreasing the maxZoom would cause the model to disappear quickly or when we get closer to the model. Wouldn't this worsen the issue?

astojilj commented 3 months ago

@qandeelabbassi My mistake here:

Meanwhile, as a workaround, would it help to lower layer.maxZoom = 22, to e.g. layer.maxZoom = 5?

According to my understanding, decreasing the maxZoom would cause the model to disappear quickly or when we get closer to the model. Wouldn't this worsen the issue?

I meant GeoJSONSource source's maxzoom.

But the models never get out of the viewport in the above video. My understanding of the viewport might be incorrect, so I would like to know what viewport you are referring to here.

Models don't, but the tile on the ground gets out of viewport. This we need to resolve but I hope that the workaround (lower maxzoom for source) would help on this meanwhile.

qandeelcc commented 3 months ago

@astojilj, setting maxzoon on geojson source doesn't solve the issue. If i use 3D puck would it solve the problem?

astojilj commented 3 months ago

3D puck should solve the issue, and could be used as a workaround until we fix this, since the underlying data is not tiled.

qandeelabbassi commented 2 months ago

@astojilj using maxzoom=4 (or even 0) fixed the issue for now. Thanks a lot for the help!

astojilj commented 2 months ago

@qandeelabbassi thanks, good to know that the workaround helped. We are working on a proper solution for this

qandeelcc commented 1 month ago

@astojilj Although maxZoom solves the described issue, it causes the model to shift away from the center of the map. Any idea how I can fix this? I am willing to contribute if you can point me in the right direction

astojilj commented 1 month ago

@qandeelcc if setting geojson source's "maxzoom" to 6, and "buffer" to 512, the effect on precision should be visible only after zoom 20.

With maxzoom set to 0, precision issue would be the worst, visible also on lower zooms. What value are you using for maxzoom: 4 or 0?