summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2014-01-17 13:33:39 +0100
committerKonstantin Käfer <mail@kkaefer.com>2014-01-17 13:33:39 +0100
commit509b223fbf63ea326b60e82dec2f0c0cdb160a66 (patch)
treeb10a8529540fe11c4822d994a8dd893876b45150
parentfc8a0d00ac17dfaa16c363a88c4c4c14298ec1dc (diff)
downloadqtlocation-mapboxgl-509b223fbf63ea326b60e82dec2f0c0cdb160a66.tar.gz
animate northing
-rw-r--r--.gitignore5
-rw-r--r--include/llmr/map/transform.hpp13
-rw-r--r--include/llmr/platform/platform.hpp1
-rw-r--r--include/llmr/util/animation.hpp30
-rw-r--r--include/llmr/util/unitbezier.hpp121
-rw-r--r--macosx/main.mm4
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/map/map.cpp6
-rw-r--r--src/map/transform.cpp24
-rw-r--r--src/util/animation.cpp26
10 files changed, 222 insertions, 10 deletions
diff --git a/.gitignore b/.gitignore
index 6bc0b9d208..d097e98f25 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,6 @@
*.o
/emscripten/main.js
-/emscripten/main.js.map \ No newline at end of file
+/emscripten/main.js.map
+/build
+/xcode
+*.sublime-* \ No newline at end of file
diff --git a/include/llmr/map/transform.hpp b/include/llmr/map/transform.hpp
index cf1ae6fff3..cee9d32a6a 100644
--- a/include/llmr/map/transform.hpp
+++ b/include/llmr/map/transform.hpp
@@ -1,9 +1,12 @@
#ifndef LLMR_MAP_TRANSFORM
#define LLMR_MAP_TRANSFORM
-#include <cstdint>
#include <llmr/util/vec2.hpp>
+#include <llmr/util/animation.hpp>
+
+#include <cstdint>
+#include <forward_list>
namespace llmr {
@@ -15,6 +18,10 @@ class transform {
public:
transform();
+ // Animations
+ bool needsAnimation() const;
+ void updateAnimations();
+
// Relative changes
void moveBy(double dx, double dy);
void scaleBy(double ds, double cx, double cy);
@@ -22,7 +29,7 @@ public:
// Absolute changes
void setScale(double scale);
- void setAngle(double angle);
+ void setAngle(double angle, double duration = 0);
void setZoom(double zoom);
void setLonLat(double lon, double lat);
@@ -58,6 +65,8 @@ private:
// cache values for spherical mercator math
double zc, Bc, Cc;
+
+ std::forward_list<util::animation> animations;
};
}
diff --git a/include/llmr/platform/platform.hpp b/include/llmr/platform/platform.hpp
index e198f5331c..30dca6216b 100644
--- a/include/llmr/platform/platform.hpp
+++ b/include/llmr/platform/platform.hpp
@@ -11,6 +11,7 @@ namespace platform {
void restart(void *obj);
void request(void *obj, std::shared_ptr<tile> tile);
+double time();
}
diff --git a/include/llmr/util/animation.hpp b/include/llmr/util/animation.hpp
new file mode 100644
index 0000000000..bb52614407
--- /dev/null
+++ b/include/llmr/util/animation.hpp
@@ -0,0 +1,30 @@
+#ifndef LLMR_UTIL_ANIMATION
+#define LLMR_UTIL_ANIMATION
+
+namespace llmr {
+namespace util {
+
+class animation {
+public:
+ enum state {
+ running,
+ complete
+ };
+
+ animation(double from, double to, double &value, double duration);
+ animation(const animation &) = delete;
+ animation(const animation &&) = delete;
+ animation &operator=(const animation &) = delete;
+
+ state update() const;
+
+private:
+ const double start, duration;
+ const double from, to;
+ double &value;
+};
+
+}
+}
+
+#endif
diff --git a/include/llmr/util/unitbezier.hpp b/include/llmr/util/unitbezier.hpp
new file mode 100644
index 0000000000..e64f7abd4a
--- /dev/null
+++ b/include/llmr/util/unitbezier.hpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LLMR_UTIL_UNITBEZIER
+#define LLMR_UTIL_UNITBEZIER
+
+#include <cmath>
+
+namespace llmr {
+namespace util {
+
+struct UnitBezier {
+ UnitBezier(double p1x, double p1y, double p2x, double p2y) {
+ // Calculate the polynomial coefficients, implicit first and last control points are (0,0) and (1,1).
+ cx = 3.0 * p1x;
+ bx = 3.0 * (p2x - p1x) - cx;
+ ax = 1.0 - cx - bx;
+
+ cy = 3.0 * p1y;
+ by = 3.0 * (p2y - p1y) - cy;
+ ay = 1.0 - cy - by;
+ }
+
+ double sampleCurveX(double t) {
+ // `ax t^3 + bx t^2 + cx t' expanded using Horner's rule.
+ return ((ax * t + bx) * t + cx) * t;
+ }
+
+ double sampleCurveY(double t) {
+ return ((ay * t + by) * t + cy) * t;
+ }
+
+ double sampleCurveDerivativeX(double t) {
+ return (3.0 * ax * t + 2.0 * bx) * t + cx;
+ }
+
+ // Given an x value, find a parametric value it came from.
+ double solveCurveX(double x, double epsilon) {
+ double t0;
+ double t1;
+ double t2;
+ double x2;
+ double d2;
+ int i;
+
+ // First try a few iterations of Newton's method -- normally very fast.
+ for (t2 = x, i = 0; i < 8; i++) {
+ x2 = sampleCurveX(t2) - x;
+ if (fabs (x2) < epsilon)
+ return t2;
+ d2 = sampleCurveDerivativeX(t2);
+ if (fabs(d2) < 1e-6)
+ break;
+ t2 = t2 - x2 / d2;
+ }
+
+ // Fall back to the bisection method for reliability.
+ t0 = 0.0;
+ t1 = 1.0;
+ t2 = x;
+
+ if (t2 < t0)
+ return t0;
+ if (t2 > t1)
+ return t1;
+
+ while (t0 < t1) {
+ x2 = sampleCurveX(t2);
+ if (fabs(x2 - x) < epsilon)
+ return t2;
+ if (x > x2)
+ t0 = t2;
+ else
+ t1 = t2;
+ t2 = (t1 - t0) * .5 + t0;
+ }
+
+ // Failure.
+ return t2;
+ }
+
+ double solve(double x, double epsilon) {
+ return sampleCurveY(solveCurveX(x, epsilon));
+ }
+
+private:
+ double ax;
+ double bx;
+ double cx;
+
+ double ay;
+ double by;
+ double cy;
+};
+
+}
+}
+
+#endif
diff --git a/macosx/main.mm b/macosx/main.mm
index 80a7df00d4..3f8d8a54f5 100644
--- a/macosx/main.mm
+++ b/macosx/main.mm
@@ -255,6 +255,10 @@ void request(void *, tile::ptr tile) {
}];
}
+double time() {
+ return glfwGetTime();
+}
+
}
}
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 4db400e113..8d596e65f4 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -9,6 +9,7 @@ SET(llmr_SOURCES
renderer/shader-line.cpp
renderer/shader.cpp
shader/shaders.c
+ util/animation.cpp
util/mat4.c
)
@@ -25,6 +26,7 @@ SET(llmr_HEADERS
../include/llmr/renderer/shader-fill.hpp
../include/llmr/renderer/shader-line.hpp
../include/llmr/renderer/shader.hpp
+ ../include/llmr/util/animation.hpp
../include/llmr/util/math.hpp
../include/llmr/util/vec2.hpp
)
diff --git a/src/map/map.cpp b/src/map/map.cpp
index f550d90967..0fff04d75a 100644
--- a/src/map/map.cpp
+++ b/src/map/map.cpp
@@ -65,7 +65,7 @@ void map::rotateBy(double cx, double cy, double sx, double sy, double ex, double
}
void map::resetNorth() {
- transform->setAngle(0);
+ transform->setAngle(0, 0.5); // 500 ms
update();
settings->angle = transform->getAngle();
@@ -261,6 +261,8 @@ void map::updateTiles() {
}
bool map::render() {
+ transform->updateAnimations();
+
painter->clear();
for (tile::ptr& tile : tiles) {
@@ -270,7 +272,7 @@ bool map::render() {
}
}
- return false;
+ return transform->needsAnimation();
}
void map::tileLoaded(tile::ptr tile) {
diff --git a/src/map/transform.cpp b/src/map/transform.cpp
index 6dbfad1711..e314bcd3a8 100644
--- a/src/map/transform.cpp
+++ b/src/map/transform.cpp
@@ -1,5 +1,4 @@
#include <llmr/map/transform.hpp>
-
#include <llmr/util/mat4.h>
#include <llmr/util/math.hpp>
#include <cmath>
@@ -29,6 +28,16 @@ transform::transform()
setAngle(angle);
}
+bool transform::needsAnimation() const {
+ return !animations.empty();
+}
+
+void transform::updateAnimations() {
+ animations.remove_if([](const util::animation& animation) {
+ return animation.update() == util::animation::complete;
+ });
+}
+
void transform::moveBy(double dx, double dy) {
x += cos(angle) * dx + sin(angle) * dy;
y += cos(angle) * dy + sin(-angle) * dx;
@@ -82,10 +91,15 @@ void transform::rotateBy(double anchor_x, double anchor_y, double start_x, doubl
setAngle(ang);
}
-void transform::setAngle(double new_angle) {
- angle = new_angle;
- while (angle > M_PI) angle -= M2PI;
- while (angle <= -M_PI) angle += M2PI;
+void transform::setAngle(double new_angle, double duration) {
+ while (new_angle > M_PI) new_angle -= M2PI;
+ while (new_angle <= -M_PI) new_angle += M2PI;
+
+ if (duration == 0) {
+ angle = new_angle;
+ } else {
+ animations.emplace_front(angle, new_angle, angle, duration);
+ }
}
void transform::setScale(double new_scale) {
diff --git a/src/util/animation.cpp b/src/util/animation.cpp
new file mode 100644
index 0000000000..a2c3e778e8
--- /dev/null
+++ b/src/util/animation.cpp
@@ -0,0 +1,26 @@
+#include <llmr/util/animation.hpp>
+#include <llmr/util/unitbezier.hpp>
+#include <llmr/platform/platform.hpp>
+
+using namespace llmr::util;
+
+UnitBezier ease(0.25, 0.1, 0.25, 1);
+
+animation::animation(double from, double to, double &value, double duration)
+ : start(platform::time()),
+ duration(duration),
+ from(from),
+ to(to),
+ value(value) {
+}
+
+animation::state animation::update() const {
+ double t = (platform::time() - start) / duration;
+ if (t >= 1) {
+ value = to;
+ return complete;
+ } else {
+ value = from + (to - from) * ease.solve(t, 0.001);
+ return running;
+ }
+}