Merge branch 'master' of github.com:mapbox/llmr-native

This commit is contained in:
Justin R. Miller
2014-05-14 11:43:09 -07:00
32 changed files with 243 additions and 172 deletions

View File

@@ -26,3 +26,6 @@ script:
- make llmr
- make linux
- make run-tests
notifications:
- hipchat: WB52YkcbCGMbNcStsGeaoRO7cyBSK4wX2ZHo2Y4b@GL

View File

@@ -77,11 +77,11 @@ module.exports = {
"value": "park",
"type": "fill"
},
"landuse_cemetary": {
"landuse_cemetery": {
"source": "mapbox streets",
"layer": "landuse",
"field": "class",
"value": "cemetary",
"value": "cemetery",
"type": "fill"
},
"landuse_hospital": {
@@ -567,7 +567,7 @@ module.exports = {
"land": "#f8f4f0",
"water": "#a0c8f0",
"park": "#d8e8c8",
"cemetary": "#e0e4dd",
"cemetery": "#e0e4dd",
"hospital": "#fde",
"school": "#f0e8f8",
"wood": "#6a4",
@@ -610,8 +610,8 @@ module.exports = {
"name": "landuse_park",
"bucket": "landuse_park"
}, {
"name": "landuse_cemetary",
"bucket": "landuse_cemetary"
"name": "landuse_cemetery",
"bucket": "landuse_cemetery"
}, {
"name": "landuse_hospital",
"bucket": "landuse_hospital"
@@ -943,8 +943,8 @@ module.exports = {
"landuse_park": {
"color": "park",
},
"landuse_cemetary": {
"color": "cemetary",
"landuse_cemetery": {
"color": "cemetery",
},
"landuse_hospital": {
"color": "hospital",
@@ -1005,9 +1005,10 @@ module.exports = {
"building_shadow": {
"color": "building_shadow",
"translate": [
2,
2
1,
1
],
"translate-anchor": "viewport",
"opacity": [
"stops", {
"z": 0,

View File

@@ -88,10 +88,10 @@ void GLFWView::scroll(GLFWwindow *window, double /*xoffset*/, double yoffset) {
GLFWView *view = (GLFWView *)glfwGetWindowUserPointer(window);
double delta = yoffset * 40;
bool is_wheel = delta != 0 && fmod(delta, 4.000244140625) == 0;
bool is_wheel = delta != 0 && std::fmod(delta, 4.000244140625) == 0;
double absdelta = delta < 0 ? -delta : delta;
double scale = 2.0 / (1.0 + exp(-absdelta / 100.0));
double scale = 2.0 / (1.0 + std::exp(-absdelta / 100.0));
// Make the scroll wheel a bit slower.
if (!is_wheel) {

View File

@@ -33,7 +33,7 @@ public:
: w((x < 0 ? x - (1 << z) + 1 : x) / (1 << z)), z(z), x(x), y(y) {}
inline uint64_t to_uint64() const {
return ((pow(2, z) * y + x) * 32) + z;
return ((std::pow(2, z) * y + x) * 32) + z;
}
inline operator std::string() const {

View File

@@ -81,8 +81,8 @@ private:
// Limit the amount of zooming possible on the map.
// TODO: make these modifiable from outside.
const double min_scale = pow(2, 0);
const double max_scale = pow(2, 20);
const double min_scale = std::pow(2, 0);
const double max_scale = std::pow(2, 20);
// cache values for spherical mercator math
double zc, Bc, Cc;

View File

@@ -7,6 +7,7 @@
#include <llmr/util/mat4.hpp>
#include <llmr/util/noncopyable.hpp>
#include <llmr/renderer/frame_history.hpp>
#include <llmr/style/properties.hpp>
#include <llmr/shader/plain_shader.hpp>
#include <llmr/shader/outline_shader.hpp>
@@ -88,7 +89,7 @@ public:
bool needsAnimation() const;
private:
void setupShaders();
void translateLayer(std::array<float, 2> translation, bool reverse = false);
const mat4 &translatedMatrix(const std::array<float, 2> &translation, const Tile::ID &id, TranslateAnchor anchor = TranslateAnchor::Map);
void prepareTile(const Tile& tile);
void useProgram(uint32_t program);
@@ -97,6 +98,7 @@ private:
public:
mat4 matrix;
mat4 vtxMatrix;
mat4 projMatrix;
mat4 nativeMatrix;
mat4 extrudeMatrix;

View File

@@ -8,6 +8,7 @@
namespace llmr {
// Stores a premultiplied color, with all four channels ranging from 0..1
typedef std::array<float, 4> Color;
enum class Winding {
@@ -31,6 +32,11 @@ enum class Property {
Linear = 4
};
enum class TranslateAnchor : uint8_t {
Map = 1,
Viewport = 2
};
namespace functions {
float null(float z, const std::vector<float>&);
@@ -57,6 +63,7 @@ struct FunctionProperty {
struct PointClass {
FunctionProperty enabled = true;
std::array<FunctionProperty, 2> translate = {{ 0, 0 }};
TranslateAnchor translateAnchor = TranslateAnchor::Map;
FunctionProperty size;
Color color = {{ 0, 0, 0, 1 }};
FunctionProperty opacity = 1;
@@ -68,6 +75,7 @@ struct PointClass {
struct PointProperties {
bool enabled = true;
std::array<float, 2> translate = {{ 0, 0 }};
TranslateAnchor translateAnchor = TranslateAnchor::Map;
float size = 0;
Color color = {{ 0, 0, 0, 1 }};
float opacity = 1.0;
@@ -79,6 +87,7 @@ struct PointProperties {
struct LineClass {
FunctionProperty enabled = true;
std::array<FunctionProperty, 2> translate = {{ 0, 0 }};
TranslateAnchor translateAnchor = TranslateAnchor::Map;
FunctionProperty width;
FunctionProperty offset;
Color color = {{ 0, 0, 0, 1 }};
@@ -89,6 +98,7 @@ struct LineClass {
struct LineProperties {
bool enabled = true;
std::array<float, 2> translate = {{ 0, 0 }};
TranslateAnchor translateAnchor = TranslateAnchor::Map;
float width = 0;
float offset = 0;
Color color = {{ 0, 0, 0, 1 }};
@@ -99,6 +109,7 @@ struct LineProperties {
struct FillClass {
FunctionProperty enabled = true;
std::array<FunctionProperty, 2> translate = {{ 0, 0 }};
TranslateAnchor translateAnchor = TranslateAnchor::Map;
Winding winding = Winding::NonZero;
FunctionProperty antialias = true;
Color fill_color = {{ 0, 0, 0, 1 }};
@@ -110,6 +121,7 @@ struct FillClass {
struct FillProperties {
bool enabled = true;
std::array<float, 2> translate = {{ 0, 0 }};
TranslateAnchor translateAnchor = TranslateAnchor::Map;
Winding winding = Winding::NonZero;
bool antialias = true;
Color fill_color = {{ 0, 0, 0, 1 }};
@@ -121,6 +133,7 @@ struct FillProperties {
struct TextClass {
FunctionProperty enabled = true;
std::array<FunctionProperty, 2> translate = {{ 0, 0 }};
TranslateAnchor translateAnchor = TranslateAnchor::Map;
Color color = {{ 0, 0, 0, 1 }};
Color halo = {{ 1, 1, 1, 0.75 }};
FunctionProperty haloRadius = 0.25f;
@@ -133,6 +146,7 @@ struct TextClass {
struct TextProperties {
bool enabled = true;
std::array<float, 2> translate = {{ 0, 0 }};
TranslateAnchor translateAnchor = TranslateAnchor::Map;
Color color = {{ 0, 0, 0, 1 }};
Color halo = {{ 1, 1, 1, 0.75 }};
float haloRadius = 0.25f;

View File

@@ -44,7 +44,7 @@ inline T min(T a, T b, T c, T d) {
// a x b = |a||b|sin(θ) for θ.
template <typename T = double, typename S>
inline T angle_between(S ax, S ay, S bx, S by) {
return atan2((ax * by - ay * bx), ax * bx + ay * by);
return std::atan2((ax * by - ay * bx), ax * bx + ay * by);
}
template <typename T = double, typename S>
@@ -54,7 +54,7 @@ inline T angle_between(const vec2<S>& a, const vec2<S>& b) {
template <typename T = double, typename S>
inline T angle_to(const vec2<S>& a, const vec2<S>& b) {
return atan2(a.y - b.y, a.x - b.x);
return std::atan2(a.y - b.y, a.x - b.x);
}
template <typename T, typename S1, typename S2>
@@ -75,7 +75,7 @@ template <typename T, typename S1, typename S2>
inline vec2<T> normal(const S1& a, const S2& b) {
T dx = b.x - a.x;
T dy = b.y - a.y;
T c = sqrt(dx * dx + dy * dy);
T c = std::sqrt(dx * dx + dy * dy);
return { dx / c, dy / c };
}
@@ -83,14 +83,14 @@ template <typename T, typename S1, typename S2>
inline T dist(const S1& a, const S2& b) {
T dx = b.x - a.x;
T dy = b.y - a.y;
T c = sqrt(dx * dx + dy * dy);
T c = std::sqrt(dx * dx + dy * dy);
return c;
}
// Take the magnitude of vector a.
template <typename T = double, typename S>
inline T mag(const S& a) {
return sqrt(a.x * a.x + a.y * a.y);
return std::sqrt(a.x * a.x + a.y * a.y);
}
}

View File

@@ -15,7 +15,11 @@ namespace uv {
class mutex {
public:
inline mutex() { assert(uv_mutex_init(&mtx) == 0); }
inline mutex() {
if (uv_mutex_init(&mtx) != 0) {
throw std::runtime_error("failed to initialize mutex");
}
}
inline ~mutex() { uv_mutex_destroy(&mtx); }
inline void lock() { uv_mutex_lock(&mtx); }
inline void unlock() { uv_mutex_unlock(&mtx); }
@@ -35,7 +39,11 @@ private:
class rwlock {
public:
inline rwlock() { assert(uv_rwlock_init(&mtx) == 0); }
inline rwlock() {
if (uv_rwlock_init(&mtx) != 0) {
throw std::runtime_error("failed to initialize read-write lock");
}
}
inline ~rwlock() { uv_rwlock_destroy(&mtx); }
inline void rdlock() { uv_rwlock_rdlock(&mtx); }
inline void wrlock() { uv_rwlock_wrlock(&mtx); }

View File

@@ -114,7 +114,7 @@ const std::map<std::string, Color> kCSSColorTable = {
template <typename T>
uint8_t clamp_css_byte(T i) { // Clamp to integer 0 .. 255.
i = round(i); // Seems to be what Chrome does (vs truncation).
i = std::round(i); // Seems to be what Chrome does (vs truncation).
return i < 0 ? 0 : i > 255 ? 255 : i;
}

View File

@@ -31,8 +31,8 @@ void DebugFontBuffer::addText(const char *text, double left, double baseline, do
if (glyph.data[j] == -1 && glyph.data[j + 1] == -1) {
prev = false;
} else {
int16_t x = round(left + glyph.data[j] * scale);
int16_t y = round(baseline - glyph.data[j + 1] * scale);
int16_t x = std::round(left + glyph.data[j] * scale);
int16_t y = std::round(baseline - glyph.data[j + 1] * scale);
if (prev) {
coords = static_cast<uint16_t *>(addElement());
coords[0] = prev_x;

View File

@@ -14,8 +14,8 @@ size_t LineVertexBuffer::add(vertex_type x, vertex_type y, float ex, float ey, i
coords[1] = (y * 2) | ty;
int8_t *extrude = static_cast<int8_t *>(data);
extrude[4] = round(extrudeScale * ex);
extrude[5] = round(extrudeScale * ey);
extrude[4] = std::round(extrudeScale * ex);
extrude[5] = std::round(extrudeScale * ey);
coords[3] = linesofar;

View File

@@ -15,21 +15,21 @@ size_t TextVertexBuffer::add(int16_t x, int16_t y, float ox, float oy, uint16_t
int16_t *shorts = static_cast<int16_t *>(data);
shorts[0] = x;
shorts[1] = y;
shorts[2] = round(ox * 64); // use 1/64 pixels for placement
shorts[3] = round(oy * 64);
shorts[2] = std::round(ox * 64); // use 1/64 pixels for placement
shorts[3] = std::round(oy * 64);
uint8_t *ubytes = static_cast<uint8_t *>(data);
// a_data1
ubytes[8] = tx / 4;
ubytes[9] = ty / 4;
ubytes[10] = labelminzoom * 10;
ubytes[11] = (int16_t)round(angle * angleFactor) % 256;
ubytes[11] = (int16_t)std::round(angle * angleFactor) % 256;
// a_data2
ubytes[12] = minzoom * 10; // 1/10 zoom levels: z16 == 160.
ubytes[13] = fmin(maxzoom, 25) * 10; // 1/10 zoom levels: z16 == 160.
ubytes[14] = util::max((int16_t)round(range[0] * angleFactor), (int16_t)0) % 256;
ubytes[15] = util::min((int16_t)round(range[1] * angleFactor), (int16_t)255) % 256;
ubytes[13] = std::fmin(maxzoom, 25) * 10; // 1/10 zoom levels: z16 == 160.
ubytes[14] = util::max((int16_t)std::round(range[0] * angleFactor), (int16_t)0) % 256;
ubytes[15] = util::min((int16_t)std::round(range[1] * angleFactor), (int16_t)255) % 256;
return idx;
}

View File

@@ -312,8 +312,8 @@ edge _edge(const llmr::vec2<double> a, const llmr::vec2<double> b) {
// scan-line conversion
void _scanSpans(edge e0, edge e1, int32_t ymin, int32_t ymax, ScanLine scanLine) {
double y0 = fmax(ymin, floor(e1.y0)),
y1 = fmin(ymax, ceil(e1.y1));
double y0 = std::fmax(ymin, std::floor(e1.y0)),
y1 = std::fmin(ymax, std::ceil(e1.y1));
// sort edges by x-coordinate
if ((e0.x0 == e1.x0 && e0.y0 == e1.y0) ?
@@ -328,9 +328,9 @@ void _scanSpans(edge e0, edge e1, int32_t ymin, int32_t ymax, ScanLine scanLine)
d0 = e0.dx > 0, // use y + 1 to compute x0
d1 = e1.dx < 0; // use y + 1 to compute x1
for (int32_t y = y0; y < y1; y++) {
double x0 = m0 * fmax(0, fmin(e0.dy, y + d0 - e0.y0)) + e0.x0,
x1 = m1 * fmax(0, fmin(e1.dy, y + d1 - e1.y0)) + e1.x0;
scanLine(floor(x1), ceil(x0), y, ymax);
double x0 = m0 * std::fmax(0, std::fmin(e0.dy, y + d0 - e0.y0)) + e0.x0,
x1 = m1 * std::fmax(0, std::fmin(e1.dy, y + d1 - e1.y0)) + e1.x0;
scanLine(std::floor(x1), std::ceil(x0), y, ymax);
}
}
@@ -357,7 +357,7 @@ double Source::getZoom() const {
}
std::forward_list<llmr::Tile::ID> Source::covering_tiles(int32_t zoom, const box& points) {
int32_t dim = pow(2, zoom);
int32_t dim = std::pow(2, zoom);
std::forward_list<llmr::Tile::ID> tiles;
bool is_raster = (type == Type::raster);
double search_zoom = getZoom();
@@ -389,8 +389,8 @@ std::forward_list<llmr::Tile::ID> Source::covering_tiles(int32_t zoom, const box
const vec2<double>& center = points.center;
tiles.sort([&center](const Tile::ID& a, const Tile::ID& b) {
// Sorts by distance from the box center
return fabs(a.x - center.x) + fabs(a.y - center.y) <
fabs(b.x - center.x) + fabs(b.y - center.y);
return std::fabs(a.x - center.x) + std::fabs(a.y - center.y) <
std::fabs(b.x - center.x) + std::fabs(b.y - center.y);
});
tiles.unique();

View File

@@ -12,7 +12,7 @@ Tile::Tile(const ID& id)
Tile::ID Tile::ID::parent(int8_t parent_z) const {
assert(parent_z < z);
int32_t dim = pow(2, z - parent_z);
int32_t dim = std::pow(2, z - parent_z);
return Tile::ID{
parent_z,
(x >= 0 ? x : x - dim + 1) / dim,
@@ -22,7 +22,7 @@ Tile::ID Tile::ID::parent(int8_t parent_z) const {
std::forward_list<Tile::ID> Tile::ID::children(int32_t child_z) const {
assert(child_z > z);
int32_t factor = pow(2, child_z - z);
int32_t factor = std::pow(2, child_z - z);
std::forward_list<ID> children;
for (int32_t ty = y * factor, y_max = (y + 1) * factor; ty < y_max; ++ty) {
@@ -34,7 +34,7 @@ std::forward_list<Tile::ID> Tile::ID::children(int32_t child_z) const {
}
Tile::ID Tile::ID::normalized() const {
int32_t dim = pow(2, z);
int32_t dim = std::pow(2, z);
int32_t nx = x, ny = y;
while (nx < 0) nx += dim;
while (nx >= dim) nx -= dim;
@@ -45,7 +45,7 @@ bool Tile::ID::isChildOf(const Tile::ID &parent) const {
if (parent.z >= z || parent.w != w) {
return false;
}
int32_t scale = pow(2, z - parent.z);
int32_t scale = std::pow(2, z - parent.z);
return parent.x == ((x < 0 ? x - scale + 1 : x) / scale) &&
parent.y == y / scale;
}

View File

@@ -49,8 +49,8 @@ void Transform::moveBy(const double dx, const double dy, const time duration) {
void Transform::_moveBy(const double dx, const double dy, const time duration) {
// This is only called internally, so we don't need a lock here.
final.x = current.x + cos(current.angle) * dx + sin(current.angle) * dy;
final.y = current.y + cos(current.angle) * dy + sin(-current.angle) * dx;
final.x = current.x + std::cos(current.angle) * dx + std::sin(current.angle) * dy;
final.y = current.y + std::cos(current.angle) * dy + std::sin(-current.angle) * dx;
if (duration == 0) {
current.x = final.x;
@@ -68,9 +68,9 @@ void Transform::_moveBy(const double dx, const double dy, const time duration) {
void Transform::setLonLat(const double lon, const double lat, const time duration) {
uv::writelock lock(mtx);
const double f = fmin(fmax(sin(D2R * lat), -0.9999), 0.9999);
double xn = -round(lon * Bc);
double yn = round(0.5 * Cc * log((1 + f) / (1 - f)));
const double f = std::fmin(std::fmax(std::sin(D2R * lat), -0.9999), 0.9999);
double xn = -std::round(lon * Bc);
double yn = std::round(0.5 * Cc * std::log((1 + f) / (1 - f)));
_setScaleXY(current.scale, xn, yn, duration);
}
@@ -79,16 +79,16 @@ void Transform::setLonLatZoom(const double lon, const double lat, const double z
const time duration) {
uv::writelock lock(mtx);
double new_scale = pow(2.0, zoom);
double new_scale = std::pow(2.0, zoom);
const double s = new_scale * util::tileSize;
zc = s / 2;
Bc = s / 360;
Cc = s / (2 * M_PI);
const double f = fmin(fmax(sin(D2R * lat), -0.9999), 0.9999);
double xn = -round(lon * Bc);
double yn = round(0.5 * Cc * log((1 + f) / (1 - f)));
const double f = std::fmin(std::fmax(std::sin(D2R * lat), -0.9999), 0.9999);
double xn = -std::round(lon * Bc);
double yn = std::round(0.5 * Cc * log((1 + f) / (1 - f)));
_setScaleXY(new_scale, xn, yn, duration);
}
@@ -97,7 +97,7 @@ void Transform::getLonLat(double &lon, double &lat) const {
uv::readlock lock(mtx);
lon = -final.x / Bc;
lat = R2D * (2 * atan(exp(final.y / Cc)) - 0.5 * M_PI);
lat = R2D * (2 * std::atan(std::exp(final.y / Cc)) - 0.5 * M_PI);
}
void Transform::getLonLatZoom(double &lon, double &lat, double &zoom) const {
@@ -159,7 +159,7 @@ void Transform::setScale(const double scale, const double cx, const double cy,
void Transform::setZoom(const double zoom, const time duration) {
uv::writelock lock(mtx);
_setScale(pow(2.0, zoom), -1, -1, duration);
_setScale(std::pow(2.0, zoom), -1, -1, duration);
}
double Transform::getZoom() const {
@@ -224,8 +224,8 @@ void Transform::_setScale(double new_scale, double cx, double cy, const time dur
const double dy = (cy - current.height / 2) * (1.0 - factor);
// Account for angle
const double angle_sin = sin(-current.angle);
const double angle_cos = cos(-current.angle);
const double angle_sin = std::sin(-current.angle);
const double angle_cos = std::cos(-current.angle);
const double ax = angle_cos * dx - angle_sin * dy;
const double ay = angle_sin * dx + angle_cos * dy;
@@ -276,15 +276,15 @@ void Transform::rotateBy(const double start_x, const double start_y, const doubl
const double begin_center_y = start_y - center_y;
const double beginning_center_dist =
sqrt(begin_center_x * begin_center_x + begin_center_y * begin_center_y);
std::sqrt(begin_center_x * begin_center_x + begin_center_y * begin_center_y);
// If the first click was too close to the center, move the center of rotation by 200 pixels
// in the direction of the click.
if (beginning_center_dist < 200) {
const double offset_x = -200, offset_y = 0;
const double rotate_angle = atan2(begin_center_y, begin_center_x);
const double rotate_angle_sin = sin(rotate_angle);
const double rotate_angle_cos = cos(rotate_angle);
const double rotate_angle = std::atan2(begin_center_y, begin_center_x);
const double rotate_angle_sin = std::sin(rotate_angle);
const double rotate_angle_cos = std::cos(rotate_angle);
center_x = start_x + rotate_angle_cos * offset_x - rotate_angle_sin * offset_y;
center_y = start_y + rotate_angle_sin * offset_x + rotate_angle_cos * offset_y;
}

View File

@@ -6,7 +6,7 @@ using namespace llmr;
#pragma mark - Matrix
void TransformState::matrixFor(mat4& matrix, const Tile::ID& id) const {
const double tile_scale = pow(2, id.z);
const double tile_scale = std::pow(2, id.z);
const double tile_size = scale * util::tileSize / tile_scale;
matrix::identity(matrix);
@@ -23,10 +23,10 @@ void TransformState::matrixFor(mat4& matrix, const Tile::ID& id) const {
}
box TransformState::cornersToBox(uint32_t z) const {
const double ref_scale = pow(2, z);
const double ref_scale = std::pow(2, z);
const double angle_sin = sin(-angle);
const double angle_cos = cos(-angle);
const double angle_sin = std::sin(-angle);
const double angle_cos = std::cos(-angle);
const double w_2 = width / 2;
const double h_2 = height / 2;
@@ -88,15 +88,15 @@ float TransformState::getPixelRatio() const {
#pragma mark - Zoom
float TransformState::getNormalizedZoom() const {
return log(scale * util::tileSize / 256.0f) / M_LN2;
return std::log(scale * util::tileSize / 256.0f) / M_LN2;
}
int32_t TransformState::getIntegerZoom() const {
return floor(getZoom());
return std::floor(getZoom());
}
double TransformState::getZoom() const {
return log(scale) / M_LN2;
return std::log(scale) / M_LN2;
}
double TransformState::getScale() const {

View File

@@ -155,7 +155,7 @@ void FillBucket::tessellate() {
for (size_t i = 0; i < vertex_count; ++i) {
if (vertex_indices[i] == TESS_UNDEF) {
vertexBuffer.add(round(vertices[i * 2]), round(vertices[i * 2 + 1]));
vertexBuffer.add(std::round(vertices[i * 2]), std::round(vertices[i * 2 + 1]));
vertex_indices[i] = (TESSindex)total_vertex_count;
total_vertex_count++;
}

View File

@@ -159,12 +159,12 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) {
double joinAngularity = nextNormal.x * joinNormal.y - nextNormal.y * joinNormal.x;
joinNormal.x /= joinAngularity;
joinNormal.y /= joinAngularity;
double roundness = fmax(abs(joinNormal.x), abs(joinNormal.y));
double roundness = std::fmax(std::abs(joinNormal.x), std::abs(joinNormal.y));
// Switch to miter joins if the angle is very low.
if (currentJoin != JoinType::Miter) {
if (fabs(joinAngularity) < 0.5 && roundness < miterLimit) {
if (std::fabs(joinAngularity) < 0.5 && roundness < miterLimit) {
currentJoin = JoinType::Miter;
}
}
@@ -209,7 +209,7 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) {
else if (currentJoin == JoinType::Miter) {
// MITER JOIN
if (fabs(joinAngularity) < 0.01) {
if (std::fabs(joinAngularity) < 0.01) {
// The two normals are almost parallel.
joinNormal.x = -nextNormal.y;
joinNormal.y = nextNormal.x;

View File

@@ -7,6 +7,7 @@
#include <llmr/util/timer.hpp>
#include <llmr/util/time.hpp>
#include <llmr/util/clip_ids.hpp>
#include <llmr/util/constants.hpp>
#include <cassert>
#include <algorithm>
@@ -170,17 +171,28 @@ void Painter::renderTileLayer(const Tile& tile, const LayerDescription &layer_de
}
}
void Painter::translateLayer(std::array<float, 2> translation, bool reverse) {
if (translation[0] || translation[1]) {
if (reverse) {
translation[0] *= -1;
translation[1] *= -1;
const mat4 &Painter::translatedMatrix(const std::array<float, 2> &translation, const Tile::ID &id, TranslateAnchor anchor) {
if (translation[0] == 0 && translation[1] == 0) {
return matrix;
} else {
// TODO: Get rid of the 8 (scaling from 4096 to tile size)
const double factor = ((double)(1 << id.z)) / map.getState().getScale() * (4096.0 / util::tileSize);
if (anchor == TranslateAnchor::Viewport) {
const double sin_a = std::sin(-map.getState().getAngle());
const double cos_a = std::cos(-map.getState().getAngle());
matrix::translate(vtxMatrix, matrix,
factor * (translation[0] * cos_a - translation[1] * sin_a),
factor * (translation[0] * sin_a + translation[1] * cos_a),
0);
} else {
matrix::translate(vtxMatrix, matrix,
factor * translation[0],
factor * translation[1],
0);
}
matrix::translate(matrix,
matrix,
translation[0] / map.getState().getPixelRatio(),
translation[1] / map.getState().getPixelRatio(),
0);
return vtxMatrix;
}
}

View File

@@ -35,13 +35,13 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons
stroke_color = fill_color;
}
translateLayer(properties.translate);
const mat4 &vtxMatrix = translatedMatrix(properties.translate, id, properties.translateAnchor);
// Because we're drawing top-to-bottom, and we update the stencil mask
// below, we have to draw the outline first (!)
if (outline && pass == Translucent) {
useProgram(outlineShader->program);
outlineShader->setMatrix(matrix);
outlineShader->setMatrix(vtxMatrix);
lineWidth(2.0f); // This is always fixed and does not depend on the pixelRatio!
outlineShader->setColor(stroke_color);
@@ -77,8 +77,8 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons
// Draw texture fill
ImagePosition imagePos = sprite->getPosition(properties.image, true);
float factor = 8.0 / pow(2, map.getState().getIntegerZoom() - id.z);
float mix = fmod(map.getState().getZoom(), 1.0);
float factor = 8.0 / std::pow(2, map.getState().getIntegerZoom() - id.z);
float mix = std::fmod(map.getState().getZoom(), 1.0);
std::array<float, 2> imageSize = {{
imagePos.size.x * factor,
@@ -87,13 +87,13 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons
};
std::array<float, 2> offset = {{
(float)fmod(id.x * 4096, imageSize[0]),
(float)fmod(id.y * 4096, imageSize[1])
(float)std::fmod(id.x * 4096, imageSize[0]),
(float)std::fmod(id.y * 4096, imageSize[1])
}
};
useProgram(patternShader->program);
patternShader->setMatrix(matrix);
patternShader->setMatrix(vtxMatrix);
patternShader->setOffset(offset);
patternShader->setPatternSize(imageSize);
patternShader->setPatternTopLeft({{ imagePos.tl.x, imagePos.tl.y }});
@@ -111,7 +111,7 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons
// fragments
// Draw filling rectangle.
useProgram(plainShader->program);
plainShader->setMatrix(matrix);
plainShader->setMatrix(vtxMatrix);
plainShader->setColor(fill_color);
// Draw the actual triangles into the color & stencil buffer.
@@ -124,7 +124,7 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons
// below, we have to draw the outline first (!)
if (fringeline && pass == Translucent) {
useProgram(outlineShader->program);
outlineShader->setMatrix(matrix);
outlineShader->setMatrix(vtxMatrix);
lineWidth(2.0f); // This is always fixed and does not depend on the pixelRatio!
outlineShader->setColor(fill_color);
@@ -138,6 +138,4 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons
glDepthRange(strata + strata_epsilon, 1.0f);
bucket.drawVertices(*outlineShader);
}
translateLayer(properties.translate, true);
}

View File

@@ -4,7 +4,7 @@
using namespace llmr;
void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, const Tile::ID& /*id*/) {
void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, const Tile::ID& id) {
// Abort early.
if (pass == Opaque) return;
if (!bucket.hasData()) return;
@@ -21,8 +21,8 @@ void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, cons
// These are the radii of the line. We are limiting it to 16, which will result
// in a point size of 64 on retina.
float inset = fmin((fmax(-1, offset - width / 2 - 0.5) + 1), 16.0f);
float outset = fmin(offset + width / 2 + 0.5, 16.0f);
float inset = std::fmin((std::fmax(-1, offset - width / 2 - 0.5) + 1), 16.0f);
float outset = std::fmin(offset + width / 2 + 0.5, 16.0f);
Color color = properties.color;
color[0] *= properties.opacity;
@@ -33,14 +33,14 @@ void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, cons
float dash_length = properties.dash_array[0];
float dash_gap = properties.dash_array[1];
translateLayer(properties.translate);
const mat4 &vtxMatrix = translatedMatrix(properties.translate, id, properties.translateAnchor);
glDepthRange(strata, 1.0f);
// We're only drawing end caps + round line joins if the line is > 2px. Otherwise, they aren't visible anyway.
if (bucket.hasPoints() && outset > 1.0f) {
useProgram(linejoinShader->program);
linejoinShader->setMatrix(matrix);
linejoinShader->setMatrix(vtxMatrix);
linejoinShader->setColor(color);
linejoinShader->setWorld({{
map.getState().getFramebufferWidth() * 0.5f,
@@ -53,7 +53,7 @@ void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, cons
}
});
float pointSize = ceil(map.getState().getPixelRatio() * outset * 2.0);
float pointSize = std::ceil(map.getState().getPixelRatio() * outset * 2.0);
#if defined(GL_ES_VERSION_2_0)
linejoinShader->setSize(pointSize);
#else
@@ -79,7 +79,7 @@ void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, cons
} else {
useProgram(lineShader->program);
lineShader->setMatrix(matrix);
lineShader->setMatrix(vtxMatrix);
lineShader->setExtrudeMatrix(extrudeMatrix);
lineShader->setDashArray({{ dash_length, dash_gap }});
lineShader->setLineWidth({{ outset, inset }});
@@ -87,6 +87,4 @@ void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, cons
lineShader->setColor(color);
bucket.drawLines(*lineShader);
}
translateLayer(properties.translate, true);
}

View File

@@ -5,7 +5,7 @@
using namespace llmr;
void Painter::renderPoint(PointBucket& bucket, const std::string& layer_name, const Tile::ID& /*id&*/) {
void Painter::renderPoint(PointBucket& bucket, const std::string& layer_name, const Tile::ID& id) {
// Abort early.
if (!bucket.hasData()) return;
if (pass == Opaque) return;
@@ -17,8 +17,6 @@ void Painter::renderPoint(PointBucket& bucket, const std::string& layer_name, co
const PointProperties& properties = point_properties_it->second;
if (!properties.enabled) return;
translateLayer(properties.translate);
Color color = properties.color;
color[0] *= properties.opacity;
color[1] *= properties.opacity;
@@ -37,9 +35,11 @@ void Painter::renderPoint(PointBucket& bucket, const std::string& layer_name, co
imagePos = sprite->getPosition(sized_image, false);
}
const mat4 &vtxMatrix = translatedMatrix(properties.translate, id, properties.translateAnchor);
if (!imagePos.size) {
useProgram(dotShader->program);
dotShader->setMatrix(matrix);
dotShader->setMatrix(vtxMatrix);
dotShader->setColor(color);
const float pointSize = (properties.radius ? properties.radius * 2 : 8) * map.getState().getPixelRatio();
@@ -55,7 +55,7 @@ void Painter::renderPoint(PointBucket& bucket, const std::string& layer_name, co
bucket.drawPoints(*dotShader);
} else {
useProgram(pointShader->program);
pointShader->setMatrix(matrix);
pointShader->setMatrix(vtxMatrix);
pointShader->setColor(color);
pointShader->setImage(0);
@@ -75,6 +75,4 @@ void Painter::renderPoint(PointBucket& bucket, const std::string& layer_name, co
glDepthRange(strata, 1.0f);
bucket.drawPoints(*pointShader);
}
translateLayer(properties.translate, true);
}

View File

@@ -4,7 +4,7 @@
using namespace llmr;
void Painter::renderText(TextBucket& bucket, const std::string& layer_name, const Tile::ID& /*id*/) {
void Painter::renderText(TextBucket& bucket, const std::string& layer_name, const Tile::ID& id) {
// Abort early.
if (pass == Opaque) return;
if (!bucket.hasData()) return;
@@ -16,8 +16,6 @@ void Painter::renderText(TextBucket& bucket, const std::string& layer_name, cons
const TextProperties& properties = text_properties_it->second;
if (!properties.enabled) return;
translateLayer(properties.translate);
mat4 exMatrix;
matrix::copy(exMatrix, projMatrix);
if (bucket.geom_desc.path == TextPathType::Curve) {
@@ -30,11 +28,13 @@ void Painter::renderText(TextBucket& bucket, const std::string& layer_name, cons
}
// If layerStyle.size > bucket.info.fontSize then labels may collide
float fontSize = fmin(properties.size, bucket.geom_desc.font_size);
float fontSize = std::fmin(properties.size, bucket.geom_desc.font_size);
matrix::scale(exMatrix, exMatrix, fontSize / 24.0f, fontSize / 24.0f, 1.0f);
const mat4 &vtxMatrix = translatedMatrix(properties.translate, id, properties.translateAnchor);
useProgram(textShader->program);
textShader->setMatrix(matrix);
textShader->setMatrix(vtxMatrix);
textShader->setExtrudeMatrix(exMatrix);
map.getGlyphAtlas().bind();
@@ -44,7 +44,7 @@ void Painter::renderText(TextBucket& bucket, const std::string& layer_name, cons
textShader->setGamma(2.5f / fontSize / map.getState().getPixelRatio());
// Convert the -pi..pi to an int8 range.
float angle = round((map.getState().getAngle() + rotate) / M_PI * 128);
float angle = std::round((map.getState().getAngle() + rotate) / M_PI * 128);
// adjust min/max zooms for variable font sies
float zoomAdjust = log(fontSize / bucket.geom_desc.font_size) / log(2);
@@ -75,8 +75,8 @@ void Painter::renderText(TextBucket& bucket, const std::string& layer_name, cons
float startingZ = history.front().z;
const FrameSnapshot lastFrame = history.back();
float endingZ = lastFrame.z;
float lowZ = fmin(startingZ, endingZ);
float highZ = fmax(startingZ, endingZ);
float lowZ = std::fmin(startingZ, endingZ);
float highZ = std::fmax(startingZ, endingZ);
// Calculate the speed of zooming, and how far it would zoom in terms of zoom levels in one duration
float zoomDiff = endingZ - history[1].z,
@@ -91,8 +91,8 @@ void Painter::renderText(TextBucket& bucket, const std::string& layer_name, cons
float bump = (currentTime - lastFrame.timestamp) / duration * fadedist;
textShader->setFadeDist(fadedist * 10);
textShader->setMinFadeZoom(floor(lowZ * 10));
textShader->setMaxFadeZoom(floor(highZ * 10));
textShader->setMinFadeZoom(std::floor(lowZ * 10));
textShader->setMaxFadeZoom(std::floor(highZ * 10));
textShader->setFadeZoom((map.getState().getZoom() + bump) * 10);
// We're drawing in the translucent pass which is bottom-to-top, so we need
@@ -109,6 +109,4 @@ void Painter::renderText(TextBucket& bucket, const std::string& layer_name, cons
textShader->setBuffer((256.0f - 64.0f) / 256.0f);
glDepthRange(strata + strata_epsilon, 1.0f);
bucket.drawGlyphs(*textShader);
translateLayer(properties.translate, true);
}

View File

@@ -52,7 +52,7 @@ float functions::stops(float z, const std::vector<float>& stops) {
// Linear interpolation if base is 0
if (smaller_val == 0) return factor * larger_val;
// Exponential interpolation between the values
return smaller_val * pow(larger_val / smaller_val, factor);
return smaller_val * std::pow(larger_val / smaller_val, factor);
} else if (larger || smaller) {
// Do not draw a line.
return -std::numeric_limits<float>::infinity();
@@ -77,7 +77,7 @@ float functions::linear(float z, const std::vector<float>& values) {
const float min = values[3];
const float max = values[4];
return fmin(fmax(min, val + (z - z_base) * slope), max);
return std::fmin(std::fmax(min, val + (z - z_base) * slope), max);
}
float functions::exponential(float z, const std::vector<float>& values) {
@@ -91,5 +91,5 @@ float functions::exponential(float z, const std::vector<float>& values) {
const float min = values[3];
const float max = values[4];
return fmin(fmax(min, val + pow(1.75, (z - z_base)) * slope), max);
return std::fmin(std::fmax(min, val + std::pow(1.75, (z - z_base)) * slope), max);
}

View File

@@ -40,6 +40,7 @@ void Style::cascade(float z) {
fill.enabled = layer.enabled.evaluate<bool>(z);
fill.translate = {{ layer.translate[0].evaluate<float>(z),
layer.translate[1].evaluate<float>(z) }};
fill.translateAnchor = layer.translateAnchor;
fill.winding = layer.winding;
fill.antialias = layer.antialias.evaluate<bool>(z);
fill.fill_color = layer.fill_color;
@@ -59,6 +60,7 @@ void Style::cascade(float z) {
stroke.enabled = layer.enabled.evaluate<bool>(z);
stroke.translate = {{ layer.translate[0].evaluate<float>(z),
layer.translate[1].evaluate<float>(z) }};
stroke.translateAnchor = layer.translateAnchor;
stroke.width = layer.width.evaluate<float>(z);
stroke.offset = layer.offset.evaluate<float>(z);
stroke.color = layer.color;
@@ -78,6 +80,7 @@ void Style::cascade(float z) {
point.enabled = layer.enabled.evaluate<bool>(z);
point.translate = {{ layer.translate[0].evaluate<float>(z),
layer.translate[1].evaluate<float>(z) }};
point.translateAnchor = layer.translateAnchor;
point.color = layer.color;
point.size = layer.size.evaluate<float>(z);
point.opacity = layer.opacity.evaluate<float>(z);
@@ -97,6 +100,7 @@ void Style::cascade(float z) {
text.enabled = layer.enabled.evaluate<bool>(z);
text.translate = {{ layer.translate[0].evaluate<float>(z),
layer.translate[1].evaluate<float>(z) }};
text.translateAnchor = layer.translateAnchor;
text.color = layer.color;
text.size = layer.size.evaluate<float>(z);
text.halo = layer.halo;

View File

@@ -194,6 +194,19 @@ void StyleParser::parseConstants(JSVal value) {
}
}
TranslateAnchor parseTranslateAnchor(JSVal anchor) {
if (anchor.IsString()) {
std::string a { anchor.GetString(), anchor.GetStringLength() };
if (a == "viewport") {
return TranslateAnchor::Viewport;
} else {
return TranslateAnchor::Map;
}
} else {
throw Style::exception("translate anchor must be a string");
}
}
void StyleParser::parseClasses(JSVal value, std::map<std::string, ClassDescription>& classes, std::map<std::string, BucketDescription>& buckets, std::vector<LayerDescription>& layers) {
if (value.IsArray()) {
for (rapidjson::SizeType i = 0; i < value.Size(); ++i) {
@@ -333,18 +346,25 @@ Color StyleParser::parseColor(JSVal value) {
throw Style::exception("color values must be numbers");
}
return {{static_cast<float>(r.GetDouble()),
static_cast<float>(g.GetDouble()),
static_cast<float>(b.GetDouble()),
static_cast<float>(a.GetDouble())}};
// Premultiply the color.
const double alpha = a.GetDouble();
return {{static_cast<float>(alpha * r.GetDouble()),
static_cast<float>(alpha * g.GetDouble()),
static_cast<float>(alpha * b.GetDouble()),
static_cast<float>(alpha)}};
} else if (!rvalue.IsString()) {
throw Style::exception("color value must be a string");
}
CSSColorParser::Color css_color = CSSColorParser::parse({ rvalue.GetString(), rvalue.GetStringLength() });
return {{(float)css_color.r / 255, (float)css_color.g / 255,
(float)css_color.b / 255, css_color.a}};
// Premultiply the color.
const float factor = css_color.a / 255;
return {{(float)css_color.r * factor,
(float)css_color.g * factor,
(float)css_color.b * factor,
css_color.a}};
}
FunctionProperty::fn StyleParser::parseFunctionType(JSVal type) {
@@ -427,6 +447,10 @@ FillClass StyleParser::parseFillClass(JSVal value) {
klass.translate = std::array<FunctionProperty, 2> {{ values[0], values[1] }};
}
if (value.HasMember("translate-anchor")) {
klass.translateAnchor = parseTranslateAnchor(value["translate-anchor"]);
}
if (value.HasMember("color")) {
klass.fill_color = parseColor(value["color"]);
}
@@ -464,6 +488,10 @@ LineClass StyleParser::parseLineClass(JSVal value) {
klass.translate = std::array<FunctionProperty, 2> {{ values[0], values[1] }};
}
if (value.HasMember("translate-anchor")) {
klass.translateAnchor = parseTranslateAnchor(value["translate-anchor"]);
}
if (value.HasMember("color")) {
klass.color = parseColor(value["color"]);
}
@@ -496,6 +524,10 @@ PointClass StyleParser::parsePointClass(JSVal value) {
klass.translate = std::array<FunctionProperty, 2> {{ values[0], values[1] }};
}
if (value.HasMember("translate-anchor")) {
klass.translateAnchor = parseTranslateAnchor(value["translate-anchor"]);
}
if (value.HasMember("color")) {
klass.color = parseColor(value["color"]);
}
@@ -523,7 +555,6 @@ PointClass StyleParser::parsePointClass(JSVal value) {
return klass;
}
TextClass StyleParser::parseTextClass(JSVal value) {
TextClass klass;
@@ -536,6 +567,10 @@ TextClass StyleParser::parseTextClass(JSVal value) {
klass.translate = std::array<FunctionProperty, 2> {{ values[0], values[1] }};
}
if (value.HasMember("translate-anchor")) {
klass.translateAnchor = parseTranslateAnchor(value["translate-anchor"]);
}
if (value.HasMember("color")) {
klass.color = parseColor(value["color"]);
}

View File

@@ -104,7 +104,7 @@ PlacementProperty Collision::place(const PlacedGlyphs &placed_glyphs,
const CollisionRect &box = glyph.box;
float x12 = box.tl.x * box.tl.x, y12 = box.tl.y * box.tl.y,
x22 = box.br.x * box.br.x, y22 = box.br.y * box.br.y,
diag = sqrt(
diag = std::sqrt(
util::max(x12 + y12, x12 + y22, x22 + y12, x22 + y22));
glyph.bbox = CollisionRect{{-diag, -diag}, {diag, diag}};
@@ -147,7 +147,7 @@ float Collision::getPlacementScale(const GlyphBoxes &glyphs,
return -1;
}
float minScale = fmax(minPlacementScale, glyph.minScale);
float minScale = std::fmax(minPlacementScale, glyph.minScale);
float maxScale = glyph.maxScale;
if (minScale >= maxScale) {
@@ -184,7 +184,7 @@ float Collision::getPlacementScale(const GlyphBoxes &glyphs,
}
// todo: unhardcode the 8 = tileExtent/tileSize
float padding = fmax(pad, placement.padding) * 8.0f;
float padding = std::fmax(pad, placement.padding) * 8.0f;
// Original algorithm:
float s1 = (ob.tl.x - nb.br.x - padding) /
@@ -207,7 +207,7 @@ float Collision::getPlacementScale(const GlyphBoxes &glyphs,
s3 = s4 = 1;
}
float collisionFreeScale = fmin(fmax(s1, s2), fmax(s3, s4));
float collisionFreeScale = std::fmin(std::fmax(s1, s2), std::fmax(s3, s4));
// Only update label's min scale if the glyph was
// restricted by a collision
@@ -278,12 +278,12 @@ PlacementRange Collision::getPlacementRange(const GlyphBoxes &glyphs,
if (!(intersectX && intersectY))
continue;
float scale = fmax(placementScale, b.placementScale);
float scale = std::fmax(placementScale, b.placementScale);
// TODO? glyph.box or glyph.bbox?
CollisionRange range = rotationRange(glyph, b, scale);
placementRange[0] = fmin(placementRange[0], range[0]);
placementRange[1] = fmax(placementRange[1], range[1]);
placementRange[0] = std::fmin(placementRange[0], range[0]);
placementRange[1] = std::fmax(placementRange[1], range[1]);
}
}
@@ -300,7 +300,7 @@ void Collision::insert(const GlyphBoxes &glyphs, const CollisionAnchor &anchor,
const CollisionRect &bbox = glyph.bbox;
const CollisionRect &box = glyph.box;
float minScale = fmax(placementScale, glyph.minScale);
float minScale = std::fmax(placementScale, glyph.minScale);
Box bounds{Point{anchor.x + bbox.tl.x / minScale,
anchor.y + bbox.tl.y / minScale},

View File

@@ -28,7 +28,7 @@ Placement::Placement(int8_t zoom)
// glyphs be placed, slowing down collision checking. Only place labels if
// they will show up within the intended zoom range of the tile.
// TODO make this not hardcoded to 3
maxPlacementScale(exp(log(2) * util::min((25.5 - zoom), 3.0))) {}
maxPlacementScale(std::exp(log(2) * util::min((25.5 - zoom), 3.0))) {}
bool byScale(const Anchor &a, const Anchor &b) { return a.scale < b.scale; }
@@ -95,20 +95,20 @@ void getSegmentGlyphs(std::back_insert_iterator<GlyphInstances> glyphs,
float prevscale = std::numeric_limits<float>::infinity();
float prevAngle = 0.0f;
offset = fabs(offset);
offset = std::fabs(offset);
const float placementScale = anchor.scale;
while (true) {
const float dist = util::dist<float>(newAnchor, end);
const float scale = offset / dist;
float angle = -atan2(end.x - newAnchor.x, end.y - newAnchor.y) +
float angle = -std::atan2(end.x - newAnchor.x, end.y - newAnchor.y) +
direction * M_PI / 2.0f;
if (upsideDown)
angle += M_PI;
// Don't place around sharp corners
float angleDiff = fmod((angle - prevAngle), (2.0f * M_PI));
float angleDiff = std::fmod((angle - prevAngle), (2.0f * M_PI));
if (prevAngle && angleDiff > maxAngleDelta) {
anchor.scale = prevscale;
break;
@@ -120,7 +120,7 @@ void getSegmentGlyphs(std::back_insert_iterator<GlyphInstances> glyphs,
/* minScale */ scale,
/* maxScale */ prevscale,
/* angle */ static_cast<float>(
fmod((angle + 2.0 * M_PI), (2.0 * M_PI)))};
std::fmod((angle + 2.0 * M_PI), (2.0 * M_PI)))};
if (scale <= placementScale)
break;
@@ -228,8 +228,8 @@ PlacedGlyphs getGlyphs(Anchor &anchor, float advance, const Shaping &shaping,
if (angle) {
// Compute the transformation matrix.
float angle_sin = sin(angle);
float angle_cos = cos(angle);
float angle_sin = std::sin(angle);
float angle_cos = std::cos(angle);
std::array<float, 4> matrix = {
{angle_cos, -angle_sin, angle_sin, angle_cos}};
@@ -251,7 +251,7 @@ PlacedGlyphs getGlyphs(Anchor &anchor, float advance, const Shaping &shaping,
glyphs.emplace_back(PlacedGlyph{
tl, tr, bl, br, glyph.rect, width, height,
static_cast<float>(
fmod((anchor.angle + rotate + instance.offset + 2 * M_PI),
std::fmod((anchor.angle + rotate + instance.offset + 2 * M_PI),
(2 * M_PI))),
GlyphBox{box, instance.minScale, instance.maxScale,
instance.anchor, horizontal}});

View File

@@ -54,19 +54,19 @@ rotatingRotatingCollisions(const CollisionRect &a, const CollisionRect &b,
// Calculate angles at which collisions may occur
const std::array<float, 8> c = {{
// top/bottom
/*[0]*/ static_cast<float>(asin((float)(a.br.y - b.tl.y) / d)),
/*[1]*/ static_cast<float>(asin((float)(a.br.y - b.tl.y) / d) + M_PI),
/*[0]*/ static_cast<float>(std::asin((float)(a.br.y - b.tl.y) / d)),
/*[1]*/ static_cast<float>(std::asin((float)(a.br.y - b.tl.y) / d) + M_PI),
/*[2]*/ static_cast<float>(2 * M_PI -
asin((float)(-a.tl.y + b.br.y) / d)),
/*[3]*/ static_cast<float>(M_PI - asin((float)(-a.tl.y + b.br.y) / d)),
std::asin((float)(-a.tl.y + b.br.y) / d)),
/*[3]*/ static_cast<float>(M_PI - std::asin((float)(-a.tl.y + b.br.y) / d)),
// left/right
/*[4]*/ static_cast<float>(2 * M_PI -
acos((float)(a.br.x - b.tl.x) / d)),
/*[5]*/ static_cast<float>(acos((float)(a.br.x - b.tl.x) / d)),
/*[6]*/ static_cast<float>(M_PI - acos((float)(-a.tl.x + b.br.x) / d)),
std::acos((float)(a.br.x - b.tl.x) / d)),
/*[5]*/ static_cast<float>(std::acos((float)(a.br.x - b.tl.x) / d)),
/*[6]*/ static_cast<float>(M_PI - std::acos((float)(-a.tl.x + b.br.x) / d)),
/*[7]*/ static_cast<float>(M_PI +
acos((float)(-a.tl.x + b.br.x) / d))}};
std::acos((float)(-a.tl.x + b.br.x) / d))}};
const float rl = a.br.x - b.tl.x;
const float lr = -a.tl.x + b.br.x;
@@ -98,7 +98,7 @@ rotatingRotatingCollisions(const CollisionRect &a, const CollisionRect &b,
// between anchors.
// Convert the angles to angles from north.
f.push_back(
fmod((c[i] + angleBetweenAnchors + 2 * M_PI), (2 * M_PI)));
std::fmod((c[i] + angleBetweenAnchors + 2 * M_PI), (2 * M_PI)));
}
}
@@ -117,7 +117,7 @@ rotatingRotatingCollisions(const CollisionRect &a, const CollisionRect &b,
double getAngle(const CollisionPoint &p1, const CollisionPoint &p2,
CollisionAngle d, const CollisionPoint &corner) {
return fmod(util::angle_between(util::interp(p1.x, p2.x, d),
return std::fmod(util::angle_between(util::interp(p1.x, p2.x, d),
util::interp(p1.y, p2.y, d), corner.x,
corner.y) +
2 * M_PI,
@@ -141,8 +141,8 @@ void circleEdgeCollisions(std::back_insert_iterator<CollisionAngles> angles,
// a collision exists only if line intersects circle at two points
if (discriminant > 0) {
CollisionAngle x1 = (-b - sqrt(discriminant)) / (2 * a);
CollisionAngle x2 = (-b + sqrt(discriminant)) / (2 * a);
CollisionAngle x1 = (-b - std::sqrt(discriminant)) / (2 * a);
CollisionAngle x2 = (-b + std::sqrt(discriminant)) / (2 * a);
// only add points if within line segment
// hack to handle floating point representations of 0 and 1

View File

@@ -87,16 +87,16 @@ void matrix::copy(mat4& out, const mat4& a) {
}
void matrix::translate(mat4& out, const mat4& a, float x, float y, float z) {
float a00, a01, a02, a03,
a10, a11, a12, a13,
a20, a21, a22, a23;
if (a == out) {
out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
} else {
float a00, a01, a02, a03,
a10, a11, a12, a13,
a20, a21, a22, a23;
a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];
@@ -113,8 +113,8 @@ void matrix::translate(mat4& out, const mat4& a, float x, float y, float z) {
}
void matrix::rotate_z(mat4& out, const mat4& a, float rad) {
float s = sin(rad),
c = cos(rad),
float s = std::sin(rad),
c = std::cos(rad),
a00 = a[0],
a01 = a[1],
a02 = a[2],

View File

@@ -49,8 +49,8 @@ TEST(RotationRange, rotatingFixedCollisions) {
CollisionRect{CollisionPoint{1.4142, -10}, CollisionPoint{10, 10}});
EXPECT_EQ(1, collisions.size());
EXPECT_EQ(135, round(deg(collisions.front()[0])));
EXPECT_EQ(135, round(deg(collisions.front()[1])));
EXPECT_EQ(135, std::round(deg(collisions.front()[0])));
EXPECT_EQ(135, std::round(deg(collisions.front()[1])));
}
TEST(RotationRange, cornerBoxCollisions) {
@@ -122,10 +122,10 @@ TEST(RotationRange, rotatingRotatingCollisions) {
CollisionAnchor{1, 1});
EXPECT_EQ(2, c.size());
EXPECT_EQ(135, round(deg(c[0][0])));
EXPECT_EQ(135, round(deg(c[0][1])));
EXPECT_EQ(315, round(deg(c[1][0])));
EXPECT_EQ(315, round(deg(c[1][1])));
EXPECT_EQ(135, std::round(deg(c[0][0])));
EXPECT_EQ(135, std::round(deg(c[0][1])));
EXPECT_EQ(315, std::round(deg(c[1][0])));
EXPECT_EQ(315, std::round(deg(c[1][1])));
}
{