diff options
-rw-r--r-- | gui/main-window.cpp | 6 | ||||
-rw-r--r-- | pose-widget/pose-widget.cpp | 73 | ||||
-rw-r--r-- | pose-widget/pose-widget.hpp | 21 |
3 files changed, 63 insertions, 37 deletions
diff --git a/gui/main-window.cpp b/gui/main-window.cpp index 7efec930..ee963bd7 100644 --- a/gui/main-window.cpp +++ b/gui/main-window.cpp @@ -485,7 +485,7 @@ void MainWindow::stopTracker() opts::set_teardown_flag(true); // XXX hack -sh 20160926 pose_update_timer.stop(); - ui.pose_display->rotateBy(0, 0, 0, 0, 0, 0); + ui.pose_display->rotate_sync(0,0,0, 0,0,0); if (pTrackerDialog) pTrackerDialog->unregister_tracker(); @@ -515,8 +515,8 @@ void MainWindow::display_pose(const double *mapped, const double *raw) if (!work) return; - ui.pose_display->rotateBy(mapped[Yaw], mapped[Pitch], -mapped[Roll], - mapped[TX], mapped[TY], mapped[TZ]); + ui.pose_display->rotate_async(mapped[Yaw], mapped[Pitch], -mapped[Roll], + mapped[TX], mapped[TY], mapped[TZ]); if (mapping_widget) mapping_widget->update(); diff --git a/pose-widget/pose-widget.cpp b/pose-widget/pose-widget.cpp index a0653f17..e711a617 100644 --- a/pose-widget/pose-widget.cpp +++ b/pose-widget/pose-widget.cpp @@ -23,16 +23,14 @@ pose_transform::pose_transform(QWidget* dst) : image2(w, h, QImage::Format_ARGB32), width(w), height(h) { + fresh.clear(std::memory_order_seq_cst); + front = QImage(QString(":/images/side1.png")); back = QImage(QString(":/images/side6.png")); image.fill(Qt::transparent); image2.fill(Qt::transparent); - rotateBy(0, 0, 0, 0, 0, 0, QSize(w, h)); - - project_quad_texture(); - start(); } @@ -57,15 +55,15 @@ void pose_transform::run() if (isInterruptionRequested()) break; - static struct cruft { - void lock() {} - void unlock() {} - } not_a_mutex; + lock_guard l(mtx); + const cv_status st = cvar.wait_for(l, std::chrono::milliseconds(2000)); + if (st == cv_status::timeout) + continue; - const cv_status st = cvar.wait_for(not_a_mutex, std::chrono::milliseconds(2000)); - if (st == cv_status::timeout) - continue; + rotation = rotation_; + translation = translation_; + } project_quad_texture(); } @@ -73,18 +71,22 @@ void pose_transform::run() pose_widget::pose_widget(QWidget* parent) : QWidget(parent), xform(this) { + rotate_sync(0,0,0, 0,0,0); } pose_widget::~pose_widget() { } -void pose_widget::rotateBy(double xAngle, double yAngle, double zAngle, double x, double y, double z) +void pose_widget::rotate_async(double xAngle, double yAngle, double zAngle, double x, double y, double z) { - xform.rotateBy(xAngle, yAngle, zAngle, x, y, z, size()); + if (!xform.fresh.test_and_set(std::memory_order_seq_cst)) + update(); + xform.rotate_async(xAngle, yAngle, zAngle, x, y, z); } -void pose_transform::rotateBy(double xAngle, double yAngle, double zAngle, double x, double y, double z, const QSize& size) +template<typename F> +void pose_transform::with_rotate(F&& fun, double xAngle, double yAngle, double zAngle, double x, double y, double z) { using std::sin; using std::cos; @@ -98,11 +100,31 @@ void pose_transform::rotateBy(double xAngle, double yAngle, double zAngle, doubl for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) - rotation(i, j) = num(r(i, j)); + rotation_(i, j) = num(r(i, j)); - translation = vec3(x, y, z); + translation_ = vec3(x, y, z); - cvar.notify_one(); + fun(); +} + +void pose_widget::rotate_sync(double xAngle, double yAngle, double zAngle, double x, double y, double z) +{ + xform.rotate_sync(xAngle, yAngle, zAngle, x, y, z); +} + +void pose_transform::rotate_async(double xAngle, double yAngle, double zAngle, double x, double y, double z) +{ + with_rotate([this]() { cvar.notify_one(); }, xAngle, yAngle, zAngle, x, y, z); +} + +void pose_transform::rotate_sync(double xAngle, double yAngle, double zAngle, double x, double y, double z) +{ + with_rotate([this]() { + rotation = rotation_; + translation = translation_; + project_quad_texture(); + dst->repaint(); + }, xAngle, yAngle, zAngle, x, y, z); } class Triangle { @@ -182,8 +204,6 @@ void pose_transform::project_quad_texture() const int sx = width - 1, sy = height - 1; vec2 projected[3]; - lock_guard l(mtx); - { const int sx_ = (sx - std::max(0, (sx - sy)/2)) * 5/9; const int sy_ = (sy - std::max(0, (sy - sx)/2)) * 5/9; @@ -318,21 +338,22 @@ void pose_transform::project_quad_texture() lock_guard l2(mtx2); image2.fill(Qt::transparent); std::swap(image, image2); + fresh.clear(); } - - run_in_thread_async(dst->thread(), [this]() { dst->update(); }); } vec2 pose_transform::project(const vec3 &point) { + using std::fabsf; + vec3 ret = rotation * point; - num z = std::max<num>(.75f, 1 + translation.z()/-60); + num z = std::max<num>(.5, 1 + translation.z()/-80); num w = width, h = height; - num x = w * translation.x() / 2 / -40; - if (std::abs(x) > w/2) + num x = w * translation.x() / 2 / -80; + if (fabsf(x) > w/2) x = x > 0 ? w/2 : w/-2; - num y = h * translation.y() / 2 / -40; - if (std::abs(y) > h/2) + num y = h * translation.y() / 2 / -80; + if (fabsf(y) > h/2) y = y > 0 ? h/2 : h/-2; return vec2(z * (ret.x() + x), z * (ret.y() + y)); } diff --git a/pose-widget/pose-widget.hpp b/pose-widget/pose-widget.hpp index 4f50008e..7befe72d 100644 --- a/pose-widget/pose-widget.hpp +++ b/pose-widget/pose-widget.hpp @@ -16,6 +16,7 @@ #include <mutex> #include <condition_variable> +#include <atomic> #ifdef BUILD_POSE_WIDGET # define POSE_WIDGET_EXPORT Q_DECL_EXPORT @@ -46,9 +47,11 @@ class pose_transform final : private QThread friend class pose_widget; - void rotateBy(double xAngle, double yAngle, double zAngle, - double x, double y, double z, - const QSize& size); + void rotate_async(double xAngle, double yAngle, double zAngle, double x, double y, double z); + void rotate_sync(double xAngle, double yAngle, double zAngle, double x, double y, double z); + + template<typename F> + void with_rotate(F&& fun, double xAngle, double yAngle, double zAngle, double x, double y, double z); void run() override; @@ -61,10 +64,10 @@ class pose_transform final : private QThread static vec3 normal(const vec3& p1, const vec3& p2, const vec3& p3); - rmat rotation; - vec3 translation; + rmat rotation, rotation_; + vec3 translation, translation_; - std::condition_variable_any cvar; + std::condition_variable cvar; std::mutex mtx, mtx2; QWidget* dst; @@ -74,6 +77,8 @@ class pose_transform final : private QThread int width, height; + std::atomic_flag fresh; + static constexpr int w = 320, h = 240; }; @@ -82,8 +87,8 @@ class POSE_WIDGET_EXPORT pose_widget final : public QWidget public: pose_widget(QWidget *parent = nullptr); ~pose_widget(); - void rotateBy(double xAngle, double yAngle, double zAngle, - double x, double y, double z); + void rotate_async(double xAngle, double yAngle, double zAngle, double x, double y, double z); + void rotate_sync(double xAngle, double yAngle, double zAngle, double x, double y, double z); private: pose_transform xform; |