mapbox / mapbox-gl-native

Interactive, thoroughly customizable maps in native Android, iOS, macOS, Node.js, and Qt applications, powered by vector tiles and OpenGL
https://mapbox.com/mobile
Other
4.36k stars 1.33k forks source link

Add 3D camera API #16419

Closed mpulkki-mapbox closed 4 years ago

mpulkki-mapbox commented 4 years ago

This pull request is the first iteration of a "real" 3D camera API that gives the user more precise controls of the camera entity itself by exposing direct properties like position and orientation. The difference to the current viewport API is that instead of applying transformations to the map the user has (a limited) access to the underlying camera object that is orbiting around the map center point at a certain distance. Implementation follows standard conventions and is a typical way of controlling the camera in any 3D engine/software.

Both interfaces, the old and the new, are interchangeable and fully compatible with each other: changes made to the transformation via one API is immediately reflected to the other one.

Interface

Disclaimer: naming of things is not final!

struct FreeCameraOptions {
    /** Position of the camera in mercator coordinates */
    optional<std::array<double, 3>> mercatorPosition;

    /** Focus point on the map where the camera is looking at. Effectively the same value as
        map center coordinate. */
    optional<LatLng> focusPoint;

    /** Helper function for setting the mercator position using Lat&Lng and altitude */
    void setLocation(const LatLng& location, double altitudeMeters);

    /** Helper function for converting mercator position into Lat&Lng and altitude. */
    std::tuple<LatLng, double> getLocation();
};

Only two parameters are currently exposed to the user: position in mercator coordinates and focus point on the map. Focus point is equivalent of the center point in the viewport API and it's used to compute the orientation of the camera. Zoom value can't be set explicitly set as it's computed from the distance between the camera and the focus point.

This interface could be extended to give the user better control of the camera (raw orientation access as a quaternion, view frustum information, projection properties, etc.)

TODO

mpulkki-mapbox commented 4 years ago

double x, y, z, w;?

s is the scalar component of the quaternion, but it could be w as well. :)

mpulkki-mapbox commented 4 years ago

What if user passes scale 0.0, would worldSize be 0.0? cameraPosition[0] /= worldSize;

This is a very good point. I've added state validations and unit tests to the TODO-list.

mpulkki-mapbox commented 4 years ago

Maybe worth introducing new type that will represent location in 3D space? Lat,Lon,Alt?

Adding a proper type for the mercator coordinate is a good idea. Something like mercator_coordinate.js used already in gl-js.

1ec5 commented 4 years ago

Can’t wait to see a converter between SceneKit’s SCNCamera class and this new FreeCameraOptions struct. 🚀

mpulkki-mapbox commented 4 years ago

Interface update

I've updated the public interface by replacing the focusPoint field with an orientation unit quaternion. Main motivation behind this change is that representing the camera with just position and a focus point is ambiguous in certain scenarios. Having a direct access to the orientation quaternion also allows users to implement different controlling schemes as opposed to having to use only view vectors. Arbitrary quaternions are not supported though as the orientation must be valid for both APIs.

@mapbox/gl-native I'd like to get feedback especially on the FreeCameraOptions struct and on the naming of things!

chloekraw commented 4 years ago

@mpulkki-mapbox @tmpsantos is it ok if we delay merging this until after 1.6.0 is released on Thursday?

mpulkki-mapbox commented 4 years ago

@mpulkki-mapbox @tmpsantos is it ok if we delay merging this until after 1.6.0 is released on Thursday?

@chloekraw yes this is fine by me!

chloekraw commented 4 years ago

@mpulkki-mapbox 👍 thank you! I'll add the label to help us remember and remove after the release is published, even though currently there isn't an approval.