summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--pose-widget/pose-widget.cpp92
-rw-r--r--pose-widget/pose-widget.hpp17
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;