summaryrefslogtreecommitdiffhomepage
path: root/pose-widget
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2017-10-02 07:53:49 +0200
committerStanislaw Halik <sthalik@misaki.pl>2017-10-02 07:54:24 +0200
commit5c2627ec26aeae563cbaaaa7e5b68caf6f2e929f (patch)
treeabdd4418b90913fa6b0d64a9ae34639fb03100fa /pose-widget
parent146cf358925c433e1b9af022cab8e915160467f5 (diff)
pose-widget: only draw needed octopus size
Diffstat (limited to 'pose-widget')
-rw-r--r--pose-widget/pose-widget.cpp110
-rw-r--r--pose-widget/pose-widget.hpp13
2 files changed, 97 insertions, 26 deletions
diff --git a/pose-widget/pose-widget.cpp b/pose-widget/pose-widget.cpp
index e9d5b05e..3424095d 100644
--- a/pose-widget/pose-widget.cpp
+++ b/pose-widget/pose-widget.cpp
@@ -14,6 +14,8 @@
#include <algorithm>
#include <QPainter>
#include <QPaintEvent>
+#include <QPalette>
+#include <QGroupBox>
#include <QDebug>
@@ -180,21 +182,68 @@ bool Triangle::barycentric_coords(const vec2& px, vec2& uv, int& i) const
return u >= 0 && v >= 0 && u + v <= 1;
}
+std::pair<vec2i, vec2i> pose_transform::get_bounds(const vec2& size)
+{
+ const int x = size.x(), y = size.y();
+
+ const vec3 corners[] = {
+ { -x, -y, 0 },
+ { x, -y, 0 },
+ { -x, y, 0 },
+ { x, y, 0 },
+ };
+
+ vec2 min(w-1, h-1), max(0, 0);
+
+ for (unsigned k = 0; k < 4; k++)
+ {
+ const vec2 pt = project(corners[k]) + vec2(w/2, h/2);
+
+ min.x() = std::fmin(min.x(), pt.x());
+ min.y() = std::fmin(min.y(), pt.y());
+
+ max.x() = std::fmax(max.x(), pt.x());
+ max.y() = std::fmax(max.y(), pt.y());
+ }
+
+ min.x() = clamp(min.x(), 0, w-1);
+ min.y() = clamp(min.y(), 0, h-1);
+ max.x() = clamp(max.x(), 0, w-1);
+ max.y() = clamp(max.y(), 0, h-1);
+
+#if 0
+ {
+ QPainter p(&image);
+ p.drawRect(min.x(), min.y(), max.x()-min.x(), max.y()-min.y());
+ }
+#endif
+
+ return std::make_pair(vec2i(iround(min.x()), iround(min.y())),
+ vec2i(iround(max.x()), iround(max.y())));
+}
+
void pose_transform::project_quad_texture()
{
- image.fill(Qt::transparent);
+ vec3 bgcolor;
+ {
+ QColor bg = dst->palette().background().color();
+ image.fill(bg);
+ bgcolor = vec3(bg.red(), bg.green(), bg.blue());
+ }
num dir;
vec2 pt[4];
- const int sx = w, sy = h;
- vec2 projected[3];
- {
- const int sx_ = (sx - std::max(0, (sx - sy)/2)) * 5/9;
- const int sy_ = (sy - std::max(0, (sy - sx)/2)) * 5/9;
+ vec2i min, max;
+ {
static constexpr const double c = 85/100.;
+ const int sx_ = (w - std::max(0, (w - h)/2)) * 5/9;
+ const int sy_ = (h - std::max(0, (h - w)/2)) * 5/9;
+
+ std::tie(min, max) = get_bounds(vec2(sx_/2.*c, sy_/2));
+
const vec3 dst_corners[] =
{
{ -sx_/2. * c, -sy_/2., 0 },
@@ -204,15 +253,12 @@ void pose_transform::project_quad_texture()
};
for (int i = 0; i < 4; i++)
- pt[i] = project(dst_corners[i]) + vec2(sx/2, sy/2);
+ pt[i] = project(dst_corners[i]) + vec2(w/2, h/2);
{
vec3 foo[3];
for (int i = 0; i < 3; i++)
- {
foo[i] = project2(dst_corners[i]);
- projected[i] = project(dst_corners[i]) + vec2(sx/2, sy/2);
- }
vec3 p1 = foo[1] - foo[0];
vec3 p2 = foo[2] - foo[0];
@@ -231,7 +277,7 @@ void pose_transform::project_quad_texture()
const QImage& tex = dir < 0 ? back : front;
- Triangle t(projected[0], projected[1], projected[2]);
+ Triangle t(pt[0], pt[1], pt[2]);
const unsigned orig_pitch = tex.bytesPerLine();
const unsigned dest_pitch = image.bytesPerLine();
@@ -250,14 +296,16 @@ void pose_transform::project_quad_texture()
return;
}
- if (uv_vec.size() < sx * sy)
- uv_vec.resize(sx * sy);
+ const vec2u dist(max.x() - min.x(), max.y() - min.y());
+
+ if (int(uv_vec.size()) < dist.x() * dist.y())
+ uv_vec.resize(dist.x() * dist.y());
- for (unsigned y = 0; y < sy; y++)
- for (unsigned x = 0; x < sx; x++)
+ for (int y = 0; y < dist.y(); y++)
+ for (int x = 0; x < dist.x(); x++)
{
- uv_& restrict_ref uv = uv_vec[y * sx + x];
- if (!t.barycentric_coords(vec2(x, y), uv.coords, uv.i))
+ uv_& restrict_ref uv = uv_vec[y * dist.x() + x];
+ if (!t.barycentric_coords(vec2(x + min.x(), y + min.y()), uv.coords, uv.i))
uv.i = -1;
}
@@ -277,10 +325,11 @@ void pose_transform::project_quad_texture()
}
};
- for (unsigned y = 0; y < sy; y++)
- for (unsigned x = 0; x < sx; x++)
+ for (int y_ = 0; y_ < dist.y(); y_++)
+ for (int x_ = 0; x_ < dist.x(); x_++)
{
- uv_ const& restrict_ref uv__ = uv_vec[y * sx + x];
+ const int y = y_ + min.y(), x = x_ + min.x();
+ uv_ const& restrict_ref uv__ = uv_vec[y_ * dist.x() + x_];
if (uv__.i != -1)
{
@@ -330,7 +379,22 @@ void pose_transform::project_quad_texture()
const unsigned pos = y * dest_pitch + x * const_depth;
- for (int k = 0; k < const_depth; k++)
+#if defined BILINEAR_FILTER
+ float a;
+ {
+ static constexpr unsigned k = 3;
+ 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];
+
+ unsigned c((i * ax + i__ * ax_) * ay + (i___ * ax + i_ * ax_) * ay_);
+
+ a = c/255.;
+ }
+#endif
+
+ for (int k = 0; k < 3; k++)
{
#if defined BILINEAR_FILTER
const uc i = orig[orig_pos + k];
@@ -338,7 +402,9 @@ void pose_transform::project_quad_texture()
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_);
+ unsigned c((i * ax + i__ * ax_) * ay + (i___ * ax + i_ * ax_) * ay_);
+
+ dest[pos + k] = clamp(uround(bgcolor(k)*(1-a) + c*a), 0, 255);
#else
dest[pos + k] = orig[orig_pos + k];
#endif
diff --git a/pose-widget/pose-widget.hpp b/pose-widget/pose-widget.hpp
index ba94e233..cdbcdeb8 100644
--- a/pose-widget/pose-widget.hpp
+++ b/pose-widget/pose-widget.hpp
@@ -7,17 +7,19 @@
#pragma once
-#include <QtGlobal>
-#include <QWidget>
-#include <QThread>
-#include <QPixmap>
#include "api/plugin-api.hpp"
#include "compat/euler.hpp"
+#include <tuple>
#include <mutex>
#include <atomic>
#include <vector>
+#include <QtGlobal>
+#include <QWidget>
+#include <QThread>
+#include <QPixmap>
+
#ifdef BUILD_POSE_WIDGET
# define POSE_WIDGET_EXPORT Q_DECL_EXPORT
#else
@@ -29,6 +31,8 @@ namespace pose_widget_impl {
using num = float;
using vec3 = Mat<num, 3, 1>;
using vec2 = Mat<num, 2, 1>;
+using vec2i = Mat<int, 2, 1>;
+using vec2u = Mat<int, 2, 1>;
using rmat = Mat<num, 3, 3>;
@@ -62,6 +66,7 @@ struct pose_transform final : QThread
vec2 project(const vec3& point);
vec3 project2(const vec3& point);
void project_quad_texture();
+ std::pair<vec2i, vec2i> get_bounds(const vec2& size);
template<typename F>
inline void with_image_lock(F&& fun);