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

Model Position Incorrectly Changed from Centre for some Coordinates #2176

Open programmer443 opened 2 months ago

programmer443 commented 2 months ago

Environment

Observed behavior and steps to reproduce

I encountered an issue where the position of a model in my Mapbox implementation is being inaccurately adjusted for certain coordinates but camera position is fine. The model, which should be centered at specified coordinates, is shifting its position unexpectedly. This behavior occurs despite correct implementation of adding the model, setting camera parameters.

Code for adding model


let plane = Bundle.main.url(
    forResource: "A320",
    withExtension: "glb")!.absoluteString
var source = GeoJSONSource(id: "source-id")
source.maxzoom = 4
try? mapProxy?.map!.addStyleModel(modelId: "model-id-plane", modelUri: plane)
var planeFeature = Feature(geometry: Point(CLLocationCoordinate2D(latitude: 42.97330, longitude: -75.085930)))
planeFeature.properties = ["model-id-key": .string("model-id-plane")]
source.data = .featureCollection(FeatureCollection(features: [planeFeature]))
try? mapProxy?.map!.addSource(source)
var layer = ModelLayer(id: "model-layer-id", source: "source-id")
layer.modelId = .expression(Exp(.get) { "model-id-key" })
layer.modelType = .constant(.common3d)
layer.modelScale = .constant([1, 1, 1])
layer.modelTranslation = .constant([0, 0,  9753.60])
layer.modelRotation = .constant([0, 0, 186])
layer.maxZoom = 23
layer.minZoom = 5
layer.modelRotationTransition = StyleTransition(duration: 0.1, delay: 0.1)
layer.modelTranslationTransition = StyleTransition(duration: 0, delay: 0)
layer.modelCutoffFadeRange = .constant(0.0)
try? mapProxy?.map!.addLayer(layer)

Code for setting camera:


let freeCam = self.mapProxy?.map?.freeCameraOptions          
freeCam?.altitude = 10253.6
freeCam?.location = CLLocationCoordinate2D(latitude: 42.97330, longitude: -75.085930)
freeCam?.setPitchBearingForPitch(0, bearing: 276)
mapProxy?.map?.freeCameraOptions = freeCam!

Expected behavior

Model should appear at the centre like camera

Pictures

plane

pjleonard37 commented 2 months ago

Hi @programmer443 -

Thanks for sharing this report and the code sample. To help us replicate, could you provide a smaller example with actual values for the variables in your code for latitude, longitude, etc? This will help to isolate if the issue is in the SDK rather than with incorrect data.

It would be especially helpful if you could recreate the issue outside of your application in a simple implementation of the SDK. For example, you could modify one of our examples.

programmer443 commented 2 months ago

Hi @pjleonard37,

Thanks for your reply🙂. I updated my code with actual values for your understanding. Now, I hope so it will help you to reproduce the issue. Here is example project for your reference https://github.com/programmer443/mapbox_model_example.git

pjleonard37 commented 2 months ago

Hi @programmer443 --

Thanks for sharing this sample project; I was able to replicate the behavior in your project. I think the issue is related to how you've set up the SwiftUI <--> UIKit code. I was able to strip down the code a bit more and have made some changes to center the plane model:

Simulator Screenshot - iPhone 15 Pro - 2024-05-10 at 17 11 58

Instead of using a Swift UI and UIKit together, I just implemented the solution in Swift UI, which resolves the misalignment you were seeing. Note that this code takes advantage of new SDK features released in the v11.4.0-beta.1 pre-release. You will either need to use this pre-release or main to use these new features until the stable version of v11.4.0 is released (in a few weeks). The key changes are our new tools for Declarative Map Styling, which should dramatically simplify your SwiftUI implementation.

struct ExampleMapModel: View {
    let plane = Bundle.main.url(
        forResource: "A320",
        withExtension: "glb")
    var latitude: CGFloat = 42.97330
    var longitude: CGFloat = -75.085930

    var body: some View {
        MapReader { proxy in
            Map() {
                GeoJSONSource(id: "source-id")
                    .data(.featureCollection(planeFeatures))
                Model(id: "model-id-plane", uri: plane)
                ModelLayer(id: "model-layer-id", source: "source-id")
                    .modelId(Exp(.get) { "model-id-key" })
                    .modelType(.common3d)
                    .modelScale(x: 1, y: 1, z: 1)
                    .modelTranslation(x: 0, y: 0, z: 9753.60)
                    .modelRotation(x: 0, y: 0, z: 90)
                    .maxZoom(23)
                    .minZoom(5)
                    .modelCutoffFadeRange(0.0)
            }
            .mapStyle(.satelliteStreets)
            .onMapLoaded { _ in
                guard let map = proxy.map else { return }
                let freeCam = map.freeCameraOptions
                freeCam.altitude = 10000
                freeCam.location = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
                freeCam.setPitchBearingForPitch(0, bearing: 180.0)
                map.freeCameraOptions = freeCam
            }

        }
    }
}

var planeFeatures: FeatureCollection {
    var planeFeature = Feature(geometry: Point(CLLocationCoordinate2D(latitude: 42.97330, longitude: -75.085930)))
    planeFeature.properties = ["model-id-key": .string("model-id-plane")]
    return FeatureCollection(features: [planeFeature])
}

These features are currently experimental, so breaking changes may occur across versions. As we refine these features we are very interested in hearing your feedback!

One other note: I'd recommend rotating the access token in your shared project. Instructions can be found here: https://docs.mapbox.com/accounts/guides/tokens/#rotating-access-tokens.

programmer443 commented 1 month ago

Hi @pjleonard37 , Thanks for your feedback😊. The model position issue is resolved but now I'm facing issue that Model disappears during movement. I attached video for your reference. I am moving the model through translation from position a to b. As you can see from video, camera is still moving to position b but plane disappear.

For model translation I am using this code:

func updateModelPositionByTraslation(lat: Double, lng: Double, alt: Double, head: Double) {
            try? mapProxy?.map?.updateLayer(withId: "model-layer-id", type: ModelLayer.self) { layer in
                // Update layer properties
                layer.modelTranslation = .constant([lng, lat, (50.0).feetToMeter()])
                let headingAngle = head - 90
                layer.modelRotation = .constant([0, 0, headingAngle])
            }
        }

And for camera position I'm using same above code.

Video:

https://github.com/mapbox/mapbox-maps-ios/assets/82497041/81c2ab4a-3f5d-4e79-8035-563f2364ae4a

programmer443 commented 1 month ago

@pjleonard37 just checking in on the status of this issue—any updates or ETA for a resolution? cc: @mapbox-maps-ios

pjleonard37 commented 1 month ago

Hi @programmer443 --

I have not been able to reproduce the issue you are seeing locally, and am still investigating.

As a friendly reminder, Model layers are an experimental feature.

programmer443 commented 1 month ago

Hi @pjleonard37 @astojilj, Thank you for your assistance with my previous issue. The solution using SwiftUI has helped simplify the implementation significantly. However, it hasn't solved the actual issue I was experiencing. The problem where the model wasn't centered correctly was due to the maxZoom setting in the GeoJSONSource. Without setting maxZoom, the model disappears randomly.

Related link: https://github.com/mapbox/mapbox-maps-ios/issues/2152

pjleonard37 commented 1 month ago

Hi @programmer443 -

I'm glad to hear that your implementation has been simplified using SwiftUI.

The problem where the model wasn't centered correctly was due to the maxZoom setting in the GeoJSONSource. Without setting maxZoom, the model disappears randomly.

Just to confirm, when you set the maxZoom the issue was resolved for you?

programmer443 commented 1 month ago

Hi @pjleonard37

Yes, if I set maxzoom to 6+ the model is positioned in the center but it disappears randomly. If I set maxZoom below 6 the model doesn't disappear anymore but its location shifts away from the center.

astojilj commented 1 month ago

@programmer443

Is maxzoom 6 used in this video? Could you please also set source's "buffer" to 512?

https://github.com/mapbox/mapbox-maps-ios/issues/2176#issuecomment-2129394486

qandeelcc commented 1 month ago

@astojilj there was no max zoom in the above video, and we didn't specifically change the source's buffer. Later when we realized that the model was disappearing due to missing maxZoom, we tried different values 4, 6, and 8. With maxZoom 4 and 6 the model was not in the center, more so with value 4. With maxZoom 8 the model was positioned in the center but it would still disappear in certain cases and in rare cases, it shifts away from the center as well.

Setting the buffer might prevent the disappearance issue, I will try that. But I am still not sure what's the foolproof way to keep the model always in the center, any ideas?

Thanks!

qandeelcc commented 2 weeks ago

@astojilj @pjleonard37 We've tried all suggested solutions but unfortunately the model either shifts away from the center or disappears after some time. Do you have any other ideas, or should we wait for the ModelLayer to get stable?

FYI, we are animating the model layer over a long distance using modelTranslation while keeping its coordinates the same. Do you think it could be the cause of model disappearance after some time? Also, we tried animating the model position using updateGeoJSONSource but the animation was choppy. #2200