port perspective projection matrix from -js

This commit is contained in:
Ansis Brammanis
2015-08-14 12:41:18 +03:00
parent d513910712
commit 8d22e2bf01
4 changed files with 40 additions and 16 deletions

View File

@@ -10,19 +10,11 @@ using namespace mbgl;
void TransformState::matrixFor(mat4& matrix, const TileID& id, const int8_t z) const {
const double tile_scale = std::pow(2, z);
const double tile_size = scale * util::tileSize / tile_scale;
double s = util::tileSize * scale / tile_scale;
matrix::identity(matrix);
matrix::translate(matrix, matrix, 0.5f * (float)width, 0.5f * (float)height, 0);
matrix::rotate_z(matrix, matrix, angle);
matrix::translate(matrix, matrix, -0.5f * (float)width, -0.5f * (float)height, 0);
matrix::translate(matrix, matrix, pixel_x() + id.x * tile_size, pixel_y() + id.y * tile_size, 0);
// TODO: Get rid of the 8 (scaling from 4096 to tile size);
float factor = scale / tile_scale / (4096.0f / util::tileSize);
matrix::scale(matrix, matrix, factor, factor, 1);
matrix::translate(matrix, matrix, id.x * s, id.y * s, 0);
matrix::scale(matrix, matrix, s / 4096.0f, s / 4096.0f, 1);
}
box TransformState::cornersToBox(uint32_t z) const {
@@ -154,6 +146,13 @@ float TransformState::getAngle() const {
return angle;
}
float TransformState::getAltitude() const {
return altitude;
}
float TransformState::getPitch() const {
return pitch;
}
#pragma mark - Projection

View File

@@ -49,6 +49,9 @@ public:
// Rotation
float getAngle() const;
float getAltitude() const;
float getPitch() const;
// Projection
const vec2<double> pixelForLatLng(const LatLng latLng) const;
const LatLng latLngForPixel(const vec2<double> pixel) const;
@@ -56,6 +59,9 @@ public:
// Changing
bool isChanging() const;
double pixel_x() const;
double pixel_y() const;
private:
void constrain(double& scale, double& y) const;
@@ -63,9 +69,6 @@ private:
double min_scale = std::pow(2, 0);
double max_scale = std::pow(2, 18);
double pixel_x() const;
double pixel_y() const;
// logical dimensions
uint16_t width = 0, height = 0;
@@ -80,6 +83,8 @@ private:
double x = 0, y = 0;
double angle = 0;
double scale = 1;
double altitude = 1.5;
double pitch = 0;
// cache values for spherical mercator math
double Bc = (scale * util::tileSize) / 360;

View File

@@ -117,6 +117,7 @@ struct DepthTest {
static const Type Default;
inline static void Set(const Type& value) {
MBGL_CHECK_ERROR(value ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST));
MBGL_CHECK_ERROR(glDisable(GL_DEPTH_TEST));
}
};

View File

@@ -132,8 +132,27 @@ void Painter::lineWidth(float line_width) {
}
void Painter::changeMatrix() {
// Initialize projection matrix
matrix::ortho(projMatrix, 0, state.getWidth(), state.getHeight(), 0, -1, 1);
double halfFov = std::atan(0.5 / state.getAltitude());
double topHalfSurfaceDistance = std::sin(halfFov) * state.getAltitude() /
std::sin(M_PI / 2.0f - state.getPitch() - halfFov);
// Calculate z value of the farthest fragment that should be rendered.
double farZ = std::cos(M_PI / 2.0f - state.getPitch()) * topHalfSurfaceDistance + state.getAltitude();
matrix::perspective(projMatrix, 2.0f * std::atan((state.getHeight() / 2.0f) / state.getAltitude()),
double(state.getWidth()) / state.getHeight(), 0.1, farZ);
matrix::translate(projMatrix, projMatrix, 0, 0, -state.getAltitude());
// 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 / state.getHeight());
matrix::rotate_x(projMatrix, projMatrix, state.getPitch());
matrix::rotate_z(projMatrix, projMatrix, state.getAngle());
matrix::translate(projMatrix, projMatrix, state.pixel_x() - state.getWidth() / 2.0f,
state.pixel_y() - state.getWidth() / 2.0f, 0);
// The extrusion matrix.
matrix::identity(extrudeMatrix);