[core] allow changing the orientation
You can now change the orientation of north to be to the right, bottom, left in addition to the default of top
This commit is contained in:
@@ -133,6 +133,10 @@ public:
|
||||
void setPitch(double pitch, const Duration& = Duration::zero());
|
||||
double getPitch() const;
|
||||
|
||||
// North Orientation
|
||||
void setNorthOrientation(NorthOrientation);
|
||||
NorthOrientation getNorthOrientation() const;
|
||||
|
||||
// Size
|
||||
uint16_t getWidth() const;
|
||||
uint16_t getHeight() const;
|
||||
|
||||
@@ -50,6 +50,8 @@ private:
|
||||
static std::shared_ptr<const mbgl::SpriteImage>
|
||||
makeSpriteImage(int width, int height, float pixelRatio);
|
||||
|
||||
void nextOrientation();
|
||||
|
||||
void addRandomPointAnnotations(int count);
|
||||
void addRandomShapeAnnotations(int count);
|
||||
void addRandomCustomPointAnnotations(int count);
|
||||
|
||||
@@ -100,6 +100,14 @@ struct MetersBounds {
|
||||
}
|
||||
};
|
||||
|
||||
// Determines the orientation of the map.
|
||||
enum class NorthOrientation : uint8_t {
|
||||
Upwards, // Default
|
||||
Rightwards,
|
||||
Downwards,
|
||||
Leftwards,
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -38,6 +38,7 @@ void perspective(mat4& out, double fovy, double aspect, double near, double far)
|
||||
void copy(mat4& out, const mat4& a);
|
||||
void translate(mat4& out, const mat4& a, double x, double y, double z);
|
||||
void rotate_x(mat4& out, const mat4& a, double rad);
|
||||
void rotate_y(mat4& out, const mat4& a, double rad);
|
||||
void rotate_z(mat4& out, const mat4& a, double rad);
|
||||
void scale(mat4& out, const mat4& a, double x, double y, double z);
|
||||
void multiply(mat4& out, const mat4& a, const mat4& b);
|
||||
|
||||
@@ -92,6 +92,7 @@ GLFWView::GLFWView(bool fullscreen_, bool benchmark_)
|
||||
printf("- Press `X` to reset the transform\n");
|
||||
printf("- Press `N` to reset north\n");
|
||||
printf("- Press `R` to toggle any available `night` style class\n");
|
||||
printf("- Press `Z` to cycle through north orientations\n");
|
||||
printf("\n");
|
||||
printf("- Press `1` through `6` to add increasing numbers of point annotations for testing\n");
|
||||
printf("- Press `7` through `0` to add increasing numbers of shape annotations for testing\n");
|
||||
@@ -153,6 +154,9 @@ void GLFWView::onKey(GLFWwindow *window, int key, int /*scancode*/, int action,
|
||||
if (!mods)
|
||||
view->map->resetNorth();
|
||||
break;
|
||||
case GLFW_KEY_Z:
|
||||
view->nextOrientation();
|
||||
break;
|
||||
case GLFW_KEY_Q:
|
||||
view->clearAnnotations();
|
||||
break;
|
||||
@@ -218,6 +222,16 @@ GLFWView::makeSpriteImage(int width, int height, float pixelRatio) {
|
||||
return std::make_shared<mbgl::SpriteImage>(width, height, pixelRatio, std::move(pixels));
|
||||
}
|
||||
|
||||
void GLFWView::nextOrientation() {
|
||||
using NO = mbgl::NorthOrientation;
|
||||
switch (map->getNorthOrientation()) {
|
||||
case NO::Upwards: map->setNorthOrientation(NO::Rightwards); break;
|
||||
case NO::Rightwards: map->setNorthOrientation(NO::Downwards); break;
|
||||
case NO::Downwards: map->setNorthOrientation(NO::Leftwards); break;
|
||||
default: map->setNorthOrientation(NO::Upwards); break;
|
||||
}
|
||||
}
|
||||
|
||||
void GLFWView::addRandomCustomPointAnnotations(int count) {
|
||||
std::vector<mbgl::PointAnnotation> points;
|
||||
|
||||
|
||||
@@ -343,6 +343,18 @@ double Map::getPitch() const {
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - North Orientation
|
||||
|
||||
void Map::setNorthOrientation(NorthOrientation orientation) {
|
||||
transform->setNorthOrientation(orientation);
|
||||
update(Update::Repaint);
|
||||
}
|
||||
|
||||
NorthOrientation Map::getNorthOrientation() const {
|
||||
return transform->getNorthOrientation();
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Projection
|
||||
|
||||
MetersBounds Map::getWorldBoundsMeters() const {
|
||||
|
||||
@@ -498,6 +498,17 @@ double Transform::getPitch() const {
|
||||
return state.pitch;
|
||||
}
|
||||
|
||||
#pragma mark - North Orientation
|
||||
|
||||
void Transform::setNorthOrientation(NorthOrientation orientation) {
|
||||
state.orientation = orientation;
|
||||
state.constrain(state.scale, state.x, state.y);
|
||||
}
|
||||
|
||||
NorthOrientation Transform::getNorthOrientation() const {
|
||||
return state.getNorthOrientation();
|
||||
}
|
||||
|
||||
#pragma mark - Transition
|
||||
|
||||
void Transform::startTransition(std::function<double(double)> easing,
|
||||
|
||||
@@ -52,6 +52,10 @@ public:
|
||||
void setPitch(double pitch, const Duration& = Duration::zero());
|
||||
double getPitch() const;
|
||||
|
||||
// North Orientation
|
||||
void setNorthOrientation(NorthOrientation);
|
||||
NorthOrientation getNorthOrientation() const;
|
||||
|
||||
// Transitions
|
||||
bool inTransition() const;
|
||||
Update updateTransitions(const TimePoint& now);
|
||||
|
||||
@@ -37,10 +37,17 @@ void TransformState::getProjMatrix(mat4& projMatrix) const {
|
||||
|
||||
// After the rotateX, z values are in pixel units. Convert them to
|
||||
// altitude unites. 1 altitude unit = the screen height.
|
||||
matrix::scale(projMatrix, projMatrix, 1, -1, 1.0f / getHeight());
|
||||
matrix::scale(projMatrix, projMatrix, 1, -1, 1.0f / (rotatedNorth() ? getWidth() : getHeight()));
|
||||
|
||||
matrix::rotate_x(projMatrix, projMatrix, getPitch());
|
||||
matrix::rotate_z(projMatrix, projMatrix, getAngle());
|
||||
using NO = NorthOrientation;
|
||||
switch (getNorthOrientation()) {
|
||||
case NO::Rightwards: matrix::rotate_y(projMatrix, projMatrix, getPitch()); break;
|
||||
case NO::Downwards: matrix::rotate_x(projMatrix, projMatrix, -getPitch()); break;
|
||||
case NO::Leftwards: matrix::rotate_y(projMatrix, projMatrix, -getPitch()); break;
|
||||
default: matrix::rotate_x(projMatrix, projMatrix, getPitch()); break;
|
||||
}
|
||||
|
||||
matrix::rotate_z(projMatrix, projMatrix, getAngle() + getNorthOrientationAngle());
|
||||
|
||||
matrix::translate(projMatrix, projMatrix, pixel_x() - getWidth() / 2.0f,
|
||||
pixel_y() - getHeight() / 2.0f, 0);
|
||||
@@ -72,6 +79,24 @@ uint16_t TransformState::getHeight() const {
|
||||
return height;
|
||||
}
|
||||
|
||||
#pragma mark - North Orientation
|
||||
|
||||
NorthOrientation TransformState::getNorthOrientation() const {
|
||||
return orientation;
|
||||
}
|
||||
|
||||
double TransformState::getNorthOrientationAngle() const {
|
||||
double angleOrientation = 0;
|
||||
if (orientation == NorthOrientation::Rightwards) {
|
||||
angleOrientation += M_PI / 2.0f;
|
||||
} else if (orientation == NorthOrientation::Downwards) {
|
||||
angleOrientation += M_PI;
|
||||
} else if (orientation == NorthOrientation::Leftwards) {
|
||||
angleOrientation -= M_PI / 2.0f;
|
||||
}
|
||||
return angleOrientation;
|
||||
}
|
||||
|
||||
#pragma mark - Position
|
||||
|
||||
LatLng TransformState::getLatLng() const {
|
||||
@@ -318,21 +343,26 @@ mat4 TransformState::getPixelMatrix() const {
|
||||
|
||||
#pragma mark - (private helper functions)
|
||||
|
||||
bool TransformState::rotatedNorth() const {
|
||||
using NO = NorthOrientation;
|
||||
return (orientation == NO::Leftwards || orientation == NO::Rightwards);
|
||||
}
|
||||
|
||||
void TransformState::constrain(double& scale_, double& x_, double& y_) const {
|
||||
// Constrain minimum scale to avoid zooming out far enough to show off-world areas.
|
||||
if (constrainMode == ConstrainMode::WidthAndHeight) {
|
||||
scale_ = std::max(scale_, static_cast<double>(width / util::tileSize));
|
||||
scale_ = std::max(scale_, static_cast<double>((rotatedNorth() ? height : width) / util::tileSize));
|
||||
}
|
||||
|
||||
scale_ = std::max(scale_, static_cast<double>(height / util::tileSize));
|
||||
scale_ = std::max(scale_, static_cast<double>((rotatedNorth() ? width : height) / util::tileSize));
|
||||
|
||||
// Constrain min/max pan to avoid showing off-world areas.
|
||||
if (constrainMode == ConstrainMode::WidthAndHeight) {
|
||||
double max_x = (scale_ * util::tileSize - width) / 2;
|
||||
double max_x = (scale_ * util::tileSize - (rotatedNorth() ? height : width)) / 2;
|
||||
x_ = std::max(-max_x, std::min(x_, max_x));
|
||||
}
|
||||
|
||||
double max_y = (scale_ * util::tileSize - height) / 2;
|
||||
double max_y = (scale_ * util::tileSize - (rotatedNorth() ? width : height)) / 2;
|
||||
y_ = std::max(-max_y, std::min(y_, max_y));
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,10 @@ public:
|
||||
uint16_t getWidth() const;
|
||||
uint16_t getHeight() const;
|
||||
|
||||
// North Orientation
|
||||
NorthOrientation getNorthOrientation() const;
|
||||
double getNorthOrientationAngle() const;
|
||||
|
||||
std::array<float, 2> locationCoordinate(float lon, float lat) const;
|
||||
void getLonLat(double &lon, double &lat) const;
|
||||
|
||||
@@ -74,12 +78,15 @@ public:
|
||||
TileCoordinate pointToCoordinate(const PrecisionPoint&) const;
|
||||
|
||||
private:
|
||||
bool rotatedNorth() const;
|
||||
void constrain(double& scale, double& x, double& y) const;
|
||||
|
||||
// Limit the amount of zooming possible on the map.
|
||||
double min_scale = std::pow(2, 0);
|
||||
double max_scale = std::pow(2, 18);
|
||||
|
||||
NorthOrientation orientation = NorthOrientation::Upwards;
|
||||
|
||||
// logical dimensions
|
||||
uint16_t width = 0, height = 0;
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ void Painter::renderSDF(SymbolBucket &bucket,
|
||||
exMatrix = extrudeMatrix;
|
||||
s = state.getAltitude();
|
||||
gammaScale = 1.0f;
|
||||
matrix::rotate_z(exMatrix, exMatrix, state.getNorthOrientationAngle());
|
||||
}
|
||||
matrix::scale(exMatrix, exMatrix, s, s, 1);
|
||||
|
||||
@@ -218,6 +219,7 @@ void Painter::renderSymbol(SymbolBucket& bucket, const SymbolLayer& layer, const
|
||||
s = 4096.0f / util::tileSize / id.overscaling / std::pow(2, state.getZoom() - id.z);
|
||||
} else {
|
||||
exMatrix = extrudeMatrix;
|
||||
matrix::rotate_z(exMatrix, exMatrix, state.getNorthOrientationAngle());
|
||||
s = state.getAltitude();
|
||||
}
|
||||
matrix::scale(exMatrix, exMatrix, s, s, 1);
|
||||
|
||||
@@ -214,6 +214,40 @@ void matrix::rotate_x(mat4& out, const mat4& a, double rad) {
|
||||
out[11] = a23 * c - a13 * s;
|
||||
}
|
||||
|
||||
void matrix::rotate_y(mat4& out, const mat4& a, double rad) {
|
||||
double s = std::sin(rad),
|
||||
c = std::cos(rad),
|
||||
a00 = a[0],
|
||||
a01 = a[1],
|
||||
a02 = a[2],
|
||||
a03 = a[3],
|
||||
a20 = a[8],
|
||||
a21 = a[9],
|
||||
a22 = a[10],
|
||||
a23 = a[11];
|
||||
|
||||
if (&a != &out) { // If the source and destination differ, copy the unchanged rows
|
||||
out[4] = a[4];
|
||||
out[5] = a[5];
|
||||
out[6] = a[6];
|
||||
out[7] = a[7];
|
||||
out[12] = a[12];
|
||||
out[13] = a[13];
|
||||
out[14] = a[14];
|
||||
out[15] = a[15];
|
||||
}
|
||||
|
||||
// Perform axis-specific matrix multiplication
|
||||
out[0] = a00 * c - a20 * s;
|
||||
out[1] = a01 * c - a21 * s;
|
||||
out[2] = a02 * c - a22 * s;
|
||||
out[3] = a03 * c - a23 * s;
|
||||
out[8] = a00 * s + a20 * c;
|
||||
out[9] = a01 * s + a21 * c;
|
||||
out[10] = a02 * s + a22 * c;
|
||||
out[11] = a03 * s + a23 * c;
|
||||
}
|
||||
|
||||
void matrix::rotate_z(mat4& out, const mat4& a, double rad) {
|
||||
double s = std::sin(rad),
|
||||
c = std::cos(rad),
|
||||
|
||||
Reference in New Issue
Block a user