diff options
Diffstat (limited to 'pose-widget/glwidget.cpp')
-rw-r--r-- | pose-widget/glwidget.cpp | 232 |
1 files changed, 130 insertions, 102 deletions
diff --git a/pose-widget/glwidget.cpp b/pose-widget/glwidget.cpp index b2ec68a7..5de26eef 100644 --- a/pose-widget/glwidget.cpp +++ b/pose-widget/glwidget.cpp @@ -51,44 +51,13 @@ void GLWidget::rotateBy(float xAngle, float yAngle, float zAngle, float x, float update(); } - class Triangle { using num = GLWidget::num; using vec2 = GLWidget::vec2; using vec3 = GLWidget::vec3; public: - Triangle(const vec2& p1, - const vec2& p2, - const vec2& p3) - { - origin = p1; - v0 = vec2(p3.x() - p1.x(), p3.y() - p1.y()); - v1 = vec2(p2.x() - p1.x(), p2.y() - p1.y()); - dot00 = v0.dot(v0); - dot01 = v0.dot(v1); - dot11 = v1.dot(v1); - const num denom = dot00 * dot11 - dot01 * dot01; - if (std::fabs(denom) < 1e3f) - { - // for perpendicular plane, ensure u and v don't come out right - // this is done here to avoid branching below, in a hot loop - invDenom = 0; - dot00 = dot01 = dot11 = 0; - v0 = v1 = vec2(0, 0); - } - else - invDenom = 1 / denom; - } - bool barycentric_coords(const vec2& px, vec2& uv) const - { - const vec2 v2 = px - origin; - const num dot12 = v1.dot(v2); - const num dot02 = v0.dot(v2); - const num u = (dot11 * dot02 - dot01 * dot12) * invDenom; - const num v = (dot00 * dot12 - dot01 * dot02) * invDenom; - uv = vec2(u, v); - return (u >= 0) && (v >= 0) && (u + v <= 1); - } + Triangle(const vec2& p1, const vec2& p2, const vec2& p3); + bool barycentric_coords(const vec2& px, vec2& uv, int& i) const; private: num dot00, dot01, dot11, invDenom; @@ -109,7 +78,56 @@ inline GLWidget::vec3 GLWidget::normal(const vec3& p1, const vec3& p2, const vec return tmp * i; } -void GLWidget::project_quad_texture() { +Triangle::Triangle(const Triangle::vec2& p1, const Triangle::vec2& p2, const Triangle::vec2& p3) +{ + using std::fabs; + + origin = p1; + + v0 = vec2(p3 - p1); + v1 = vec2(p2 - p1); + + dot00 = v0.dot(v0); + dot01 = v0.dot(v1); + dot11 = v1.dot(v1); + + const num denom = dot00 * dot11 - dot01 * dot01; + + if (fabs(denom) < num(1e3)) + { + // for perpendicular plane, ensure u and v don't come out right + // this is done here to avoid branching below, in a hot loop + invDenom = 0; + dot00 = dot01 = dot11 = 0; + v0 = v1 = vec2(0, 0); + } + else + invDenom = 1 / denom; +} + +bool Triangle::barycentric_coords(const Triangle::vec2& px, Triangle::vec2& uv, int& i) const +{ + i = 0; + const vec2 v2 = px - origin; + const num dot12 = v1.dot(v2); + const num dot02 = v0.dot(v2); + num u = (dot11 * dot02 - dot01 * dot12) * invDenom; + num v = (dot00 * dot12 - dot01 * dot02) * invDenom; + if (!(u >= 0 && v >= 0)) + return false; + if (u + v > 1) + { + i = 1; + + u = 1 - u; + v = 1 - v; + } + uv = vec2(u, v); + return u >= 0 && v >= 0 && u + v <= 1; +} + +void GLWidget::project_quad_texture() +{ const int sx = width(), sy = height(); const int ow = front.width(), oh = front.height(); const vec3 corners[] = { @@ -141,12 +159,27 @@ void GLWidget::project_quad_texture() { QColor bgColor = palette().color(QPalette::Current, QPalette::Window); texture.fill(bgColor); - const vec2 projected[2][3] = { { pt[0], pt[1], pt[2] }, { pt[3], pt[1], pt[2] } }; - const vec2 origs[2][3] = { - { vec2(0, 0), vec2(ow-1, 0), vec2(0, oh-1) }, - { vec2(ow-1, oh-1), vec2(ow-1, 0), vec2(0, oh-1) } + const vec2 projected[2][3] = + { + { pt[0], pt[1], pt[2] }, + { pt[3], pt[1], pt[2] } }; - const Triangle triangles[2] = { + + const 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, 0) + } + }; + + const Triangle triangles[2] = + { Triangle(projected[0][0], projected[0][1], projected[0][2]), Triangle(projected[1][0], projected[1][1], projected[1][2]) }; @@ -165,70 +198,64 @@ void GLWidget::project_quad_texture() { return; for (int y = 0; y < sy; y++) - for (int x = 0; x < sx; x++) { + for (int x = 0; x < sx; x++) + { vec2 pos(x, y); - for (int i = 0; i < 2; i++) { - vec2 uv; - // XXX knowing center of the lookup pos, - // we have symmetry so only one lookup is needed -sh 20150831 - if (triangles[i].barycentric_coords(pos, uv)) - { - const float fx = origs[i][0].x() - + uv.x() * (origs[i][2].x() - origs[i][0].x()) - + uv.y() * (origs[i][1].x() - origs[i][0].x()); - const float fy = origs[i][0].y() - + uv.x() * (origs[i][2].y() - origs[i][0].y()) - + uv.y() * (origs[i][1].y() - origs[i][0].y()); - - const int px_ = fx + .5f; - const int py_ = fy + .5f; - const int px = fx; - const int py = fy; - const float ax_ = fx - px; - const float ay_ = fy - py; - const float ax = 1.f - ax_; - const float ay = 1.f - ay_; - - // 0, 0 -- ax, ay - const int orig_pos = py * orig_pitch + px * orig_depth; - const unsigned char r = orig[orig_pos + 2]; - const unsigned char g = orig[orig_pos + 1]; - const unsigned char b = orig[orig_pos + 0]; - - // 1, 1 -- ax_, ay_ - const int orig_pos_ = py_ * orig_pitch + px_ * orig_depth; - const unsigned char r_ = orig[orig_pos_ + 2]; - const unsigned char g_ = orig[orig_pos_ + 1]; - const unsigned char b_ = orig[orig_pos_ + 0]; - - // 1, 0 -- ax_, ay - const int orig_pos__ = py * orig_pitch + px_ * orig_depth; - const unsigned char r__ = orig[orig_pos__ + 2]; - const unsigned char g__ = orig[orig_pos__ + 1]; - const unsigned char b__ = orig[orig_pos__ + 0]; - - // 0, 1 -- ax, ay_ - const int orig_pos___ = py_ * orig_pitch + px * orig_depth; - const unsigned char r___ = orig[orig_pos___ + 2]; - const unsigned char g___ = orig[orig_pos___ + 1]; - const unsigned char b___ = orig[orig_pos___ + 0]; - - const unsigned char a1 = orig[orig_pos + 3]; - const unsigned char a2 = orig[orig_pos_ + 3]; - const unsigned char a3 = orig[orig_pos__ + 3]; - const unsigned char a4 = orig[orig_pos___ + 3]; - - const int pos = y * dest_pitch + x * dest_depth; - - //qDebug() << "pos" << fx << fy << "uv" << ax << ay; - - dest[pos + 0] = (r * ax + r__ * ax_) * ay + (r___ * ax + r_ * ax_) * ay_; - dest[pos + 1] = (g * ax + g__ * ax_) * ay + (g___ * ax + g_ * ax_) * ay_; - dest[pos + 2] = (b * ax + b__ * ax_) * ay + (b___ * ax + b_ * ax_) * ay_; - dest[pos + 3] = (a1 * ax + a3 * ax_) * ay + (a4 * ax + a2 * ax_) * ay_; - - break; - } + vec2 uv; + int i; + if (triangles[0].barycentric_coords(pos, uv, i)) + { + const float fx = origs[i][0].x() + + uv.x() * (origs[i][2].x() - origs[i][0].x()) + + uv.y() * (origs[i][1].x() - origs[i][0].x()); + const float fy = origs[i][0].y() + + uv.x() * (origs[i][2].y() - origs[i][0].y()) + + uv.y() * (origs[i][1].y() - origs[i][0].y()); + + const int px_ = fx + .5f; + const int py_ = fy + .5f; + const int px = fx; + const int py = fy; + const float ax_ = fx - px; + const float ay_ = fy - py; + const float ax = 1.f - ax_; + const float ay = 1.f - ay_; + + // 0, 0 -- ax, ay + const int orig_pos = py * orig_pitch + px * orig_depth; + const unsigned char r = orig[orig_pos + 2]; + const unsigned char g = orig[orig_pos + 1]; + const unsigned char b = orig[orig_pos + 0]; + + // 1, 1 -- ax_, ay_ + const int orig_pos_ = py_ * orig_pitch + px_ * orig_depth; + const unsigned char r_ = orig[orig_pos_ + 2]; + const unsigned char g_ = orig[orig_pos_ + 1]; + const unsigned char b_ = orig[orig_pos_ + 0]; + + // 1, 0 -- ax_, ay + const int orig_pos__ = py * orig_pitch + px_ * orig_depth; + const unsigned char r__ = orig[orig_pos__ + 2]; + const unsigned char g__ = orig[orig_pos__ + 1]; + const unsigned char b__ = orig[orig_pos__ + 0]; + + // 0, 1 -- ax, ay_ + const int orig_pos___ = py_ * orig_pitch + px * orig_depth; + const unsigned char r___ = orig[orig_pos___ + 2]; + const unsigned char g___ = orig[orig_pos___ + 1]; + const unsigned char b___ = orig[orig_pos___ + 0]; + + const unsigned char a1 = orig[orig_pos + 3]; + const unsigned char a2 = orig[orig_pos_ + 3]; + const unsigned char a3 = orig[orig_pos__ + 3]; + const unsigned char a4 = orig[orig_pos___ + 3]; + + const int pos = y * dest_pitch + x * dest_depth; + + dest[pos + 0] = (r * ax + r__ * ax_) * ay + (r___ * ax + r_ * ax_) * ay_; + dest[pos + 1] = (g * ax + g__ * ax_) * ay + (g___ * ax + g_ * ax_) * ay_; + dest[pos + 2] = (b * ax + b__ * ax_) * ay + (b___ * ax + b_ * ax_) * ay_; + dest[pos + 3] = (a1 * ax + a3 * ax_) * ay + (a4 * ax + a2 * ax_) * ay_; } } image = texture; @@ -252,3 +279,4 @@ GLWidget::vec3 GLWidget::project2(const vec3 &point) { return rotation * point; } + |