diff options
Diffstat (limited to 'pose-widget')
| -rw-r--r-- | pose-widget/pose-widget.cpp | 92 | ||||
| -rw-r--r-- | pose-widget/pose-widget.hpp | 17 | 
2 files changed, 71 insertions, 38 deletions
| diff --git a/pose-widget/pose-widget.cpp b/pose-widget/pose-widget.cpp index 8646df30..aaa6bd36 100644 --- a/pose-widget/pose-widget.cpp +++ b/pose-widget/pose-widget.cpp @@ -136,14 +136,6 @@ void pose_transform::rotate_sync(double xAngle, double yAngle, double zAngle, do      }, xAngle, yAngle, zAngle, x, y, z);  } -class Triangle { -    num dot00, dot01, dot11, invDenom; -    vec2 v0, v1, origin; -public: -    Triangle(const vec2& p1, const vec2& p2, const vec2& p3); -    bool barycentric_coords(const vec2& px, vec2& uv, int& i) const; -}; -  Triangle::Triangle(const vec2& p1, const vec2& p2, const vec2& p3)  {      origin = p1; @@ -183,6 +175,9 @@ bool Triangle::barycentric_coords(const vec2& px, vec2& uv, int& i) const      return u >= 0 && v >= 0 && u + v <= 1;  } +#if defined __GNUG__ +__attribute__((optimize("unroll-loops"))) +#endif  void pose_transform::project_quad_texture()  {      image.fill(Qt::transparent); @@ -233,55 +228,66 @@ void pose_transform::project_quad_texture()      }      const QImage& tex = dir < 0 ? back : front; -    const int ow = tex.width(), oh = tex.height(); - -    vec2 origs[2][3] = -    { -        { -            vec2(0, 0), -            vec2(ow-1, 0), -            vec2(0, oh-1) -        }, -        { -            vec2(ow-1, oh-1), -            vec2(0, oh-1) - vec2(ow-1, oh-1), -            vec2(ow-1, 0) - vec2(ow-1, oh-1), -        } -    };      Triangle t(projected[0], projected[1], projected[2]);      const unsigned orig_pitch = tex.bytesPerLine();      const unsigned dest_pitch = image.bytesPerLine(); -    const unsigned char* orig = tex.bits(); -    unsigned char* dest = image.bits() + offset*dest_pitch; +    const unsigned char* restrict orig = tex.bits(); +    unsigned char* restrict dest = image.bits() + offset*dest_pitch;      const int orig_depth = tex.depth() / 8;      const int dest_depth = image.depth() / 8; -    /* image breakage? */ -    if (orig_depth != 4) +    if (unlikely(orig_depth != 4 || dest_depth != 4))      {          qDebug() << "pose-widget: octopus must be saved as .png with 32 bits pixel"; +        qDebug() << "pose-widget: target texture must be ARGB32";          return;      } -    if (dest_depth != 4) +    static constexpr unsigned xmax = w, ymax = h; + +    if (uv_vec.size() < xmax * ymax) +        uv_vec.resize(xmax * ymax); + +    for (unsigned y = 0; y < ymax; y++) +        for (unsigned x = 0; x < xmax; x++) +        { +            uv_& restrict_ref uv = uv_vec[y * xmax + x]; +            if (!t.barycentric_coords(vec2(x, y), uv.coords, uv.i)) +                uv.i = -1; +        } + +    const int ow = tex.width(), oh = tex.height(); + +    vec2 const origs[2][3] =      { -        qDebug() << "pose-widget: target texture must be ARGB32"; -        return; -    } +        { +            { 0, 0 }, +            { ow, 0 }, +            { 0, oh }, +        }, +        { +            { ow, oh }, +            vec2(0, oh) - vec2(ow, oh), +            vec2(ow, 0) - vec2(ow, oh), +        } +    }; -    for (int y = 0; y < sy; y++) -        for (int x = 0; x < sx; x++) +    for (unsigned y = 0; y < ymax; y++) +        for (unsigned x = 0; x < xmax; x++)          { -            vec2 pos(x, y); -            vec2 uv; -            int i; +            uv_ const& restrict_ref uv__ = uv_vec[y * xmax + x]; -            if (t.barycentric_coords(pos, uv, i)) +            if (uv__.i != -1)              { +                using uc = unsigned char; + +                vec2 const& uv = uv__.coords; +                int const i = uv__.i; +                  const float fx = origs[i][0].x()                                   + uv.x() * origs[i][2].x()                                   + uv.y() * origs[i][1].x(); @@ -289,17 +295,21 @@ void pose_transform::project_quad_texture()                                   + uv.x() * origs[i][2].y()                                   + uv.y() * origs[i][1].y(); -                using uc = unsigned char; +#define BILINEAR_FILTER +#if defined BILINEAR_FILTER                  const unsigned px_ = fx + 1;                  const unsigned py_ = fy + 1; +#endif                  const unsigned px = fx;                  const unsigned py = fy;                  const unsigned orig_pos = py * orig_pitch + px * orig_depth; +#if defined BILINEAR_FILTER                  const unsigned orig_pos_ = py_ * orig_pitch + px_ * orig_depth;                  const unsigned orig_pos__ = py * orig_pitch + px_ * orig_depth;                  const unsigned orig_pos___ = py_ * orig_pitch + px * orig_depth; +#endif                  // 1, 0 -- ax_, ay                  // 0, 1 -- ax, ay_ @@ -307,21 +317,27 @@ void pose_transform::project_quad_texture()                  // 0, 0 -- ax, ay                  //const uc alpha = (a1 * ax + a3 * ax_) * ay + (a4 * ax + a2 * ax_) * ay_; +#if defined BILINEAR_FILTER                  const float ax_ = fx - unsigned(fx);                  const float ay_ = fy - unsigned(fy);                  const float ax = 1 - ax_;                  const float ay = 1 - ay_; +#endif                  const unsigned pos = y * dest_pitch + (x+offset) * dest_depth;                  for (int k = 0; k < 4; k++)                  { +#if defined BILINEAR_FILTER                      const uc i = orig[orig_pos + k];                      const uc i_ = orig[orig_pos_ + k];                      const uc i__ = orig[orig_pos__ + k];                      const uc i___ = orig[orig_pos___ + k];                      dest[pos + k] = uc((i * ax + i__ * ax_) * ay + (i___ * ax + i_ * ax_) * ay_); +#else +                    dest[pos + k] = orig[orig_pos + k]; +#endif                  }              }          } diff --git a/pose-widget/pose-widget.hpp b/pose-widget/pose-widget.hpp index fc606e13..7bc66cd2 100644 --- a/pose-widget/pose-widget.hpp +++ b/pose-widget/pose-widget.hpp @@ -16,6 +16,7 @@  #include <mutex>  #include <atomic> +#include <vector>  #ifdef BUILD_POSE_WIDGET  #   define POSE_WIDGET_EXPORT Q_DECL_EXPORT @@ -37,6 +38,14 @@ using lock_guard = std::unique_lock<std::mutex>;  class pose_widget; +class Triangle { +    num dot00, dot01, dot11, invDenom; +    vec2 v0, v1, origin; +public: +    Triangle(const vec2& p1, const vec2& p2, const vec2& p3); +    bool barycentric_coords(const vec2& px, vec2& uv, int& i) const; +}; +  struct pose_transform final : private QThread  {      pose_transform(QWidget* dst); @@ -67,6 +76,14 @@ struct pose_transform final : private QThread      QImage front, back;      QImage image, image2; +    struct uv_ +    { +        vec2 coords; +        int i; +    }; + +    std::vector<uv_> uv_vec; +      std::atomic<bool> fresh;      static constexpr int w = 320, h = 240; | 
