diff --git a/toonz/sources/common/tgeometry/tgeometry.cpp b/toonz/sources/common/tgeometry/tgeometry.cpp index 7e8ea1d..4278048 100644 --- a/toonz/sources/common/tgeometry/tgeometry.cpp +++ b/toonz/sources/common/tgeometry/tgeometry.cpp @@ -116,6 +116,12 @@ TPointD TAffine::operator*(const TPointD &p) const { //-------------------------------------------------------------------------------------------------- +TPointD TAffine::transformDirection(const TPointD &p) const { + return TPointD(p.x * a11 + p.y * a12, p.x * a21 + p.y * a22); +} + +//-------------------------------------------------------------------------------------------------- + TRectD TAffine::operator*(const TRectD &rect) const { if (rect != TConsts::infiniteRectD) { TPointD p1 = *this * rect.getP00(), p2 = *this * rect.getP01(), @@ -213,3 +219,136 @@ TScale::TScale(const TPointD ¢er, double s) { a22 = a.a22; a23 = a.a23; } + +//================================================================================================== + +TPoint4D TAffine4::operator*(const TPoint4D &b) const { + return TPoint4D( + b.x*a11 + b.y*a21 + b.z*a31 + b.w*a41, + b.x*a12 + b.y*a22 + b.z*a32 + b.w*a42, + b.x*a13 + b.y*a23 + b.z*a33 + b.w*a43, + b.x*a14 + b.y*a24 + b.z*a34 + b.w*a44 ); +} + +TAffine4 TAffine4::operator*(const TAffine4 &b) const { + return TAffine4( + *this * b.rowX(), + *this * b.rowY(), + *this * b.rowZ(), + *this * b.rowW() ); +} + +TAffine4 TAffine4::operator*=(const TAffine4 &b) + { return *this = *this * b; } + +TAffine4 TAffine4::inv() const { + TAffine4 r; + r.a11 = a22*(a33*a44 - a34*a43) + a23*(a34*a42 - a32*a44) + a24*(a32*a43 - a33*a42); + r.a12 = a21*(a34*a43 - a33*a44) + a23*(a31*a44 - a34*a41) + a24*(a33*a41 - a31*a43); + r.a13 = a21*(a32*a44 - a34*a42) + a22*(a34*a41 - a31*a44) + a24*(a31*a42 - a32*a41); + r.a14 = a21*(a33*a42 - a32*a43) + a22*(a31*a43 - a33*a41) + a23*(a32*a41 - a31*a42); + + double det = a11*r.a11 + a12*r.a21 + a13*r.a31 + a14*r.a41; + if (fabs(det) > TConsts::epsilon) det = 1.0/det; + r.a11 *= det; + r.a12 *= det; + r.a13 *= det; + r.a14 *= det; + + r.a21 = det*( a12*(a34*a43 - a33*a44) + a13*(a32*a44 - a34*a42) + a14*(a33*a42 - a32*a43) ); + r.a22 = det*( a11*(a33*a44 - a34*a43) + a13*(a34*a41 - a31*a44) + a14*(a31*a43 - a33*a41) ); + r.a23 = det*( a11*(a34*a42 - a32*a44) + a12*(a31*a44 - a34*a41) + a14*(a32*a41 - a31*a42) ); + r.a24 = det*( a11*(a32*a43 - a33*a42) + a12*(a33*a41 - a31*a43) + a13*(a31*a42 - a32*a41) ); + r.a31 = det*( a12*(a23*a44 - a24*a43) + a13*(a24*a42 - a22*a44) + a14*(a22*a43 - a23*a42) ); + r.a32 = det*( a11*(a24*a43 - a23*a44) + a13*(a21*a44 - a24*a41) + a14*(a23*a41 - a21*a43) ); + r.a33 = det*( a11*(a22*a44 - a24*a42) + a12*(a24*a41 - a21*a44) + a14*(a21*a42 - a22*a41) ); + r.a34 = det*( a11*(a23*a42 - a22*a43) + a12*(a21*a43 - a23*a41) + a13*(a22*a41 - a21*a42) ); + r.a41 = det*( a12*(a24*a33 - a23*a34) + a13*(a22*a34 - a24*a32) + a14*(a23*a32 - a22*a33) ); + r.a42 = det*( a11*(a23*a34 - a24*a33) + a13*(a24*a31 - a21*a34) + a14*(a21*a33 - a23*a31) ); + r.a43 = det*( a11*(a24*a32 - a22*a34) + a12*(a21*a34 - a24*a31) + a14*(a22*a31 - a21*a32) ); + r.a44 = det*( a11*(a22*a33 - a23*a32) + a12*(a23*a31 - a21*a33) + a13*(a21*a32 - a22*a31) ); + + return r; +} + +TAffine TAffine4::get2d(double z) const { + return TAffine( + a11, a21, z*a31 + a41, + a12, a22, z*a32 + a42 ); +} + +TAffine4 TAffine4::translation(double x, double y, double z) { + TAffine4 r; + r.rowW().x = x; + r.rowW().y = y; + r.rowW().z = z; + return r; +} + +TAffine4 TAffine4::scale(double x, double y, double z) { + TAffine4 r; + r.a11 = x; + r.a22 = y; + r.a33 = z; + return r; +} + +TAffine4 TAffine4::rotation(double x, double y, double z, double angle) { + TAffine4 r; + double k = sqrt(x*x + y*y + z*z); + if (k > TConsts::epsilon) { + double s = sin(angle); + double c = cos(angle); + double ic = 1.0 - c; + double k = 1.0/k; + x *= k; + y *= k; + z *= k; + + r.a11 = ic*x*x + c; + r.a12 = ic*x*y + s*z; + r.a13 = ic*z*x - s*y; + + r.a21 = ic*x*y - s*z; + r.a22 = ic*y*y + c; + r.a23 = ic*y*z + s*x; + + r.a31 = ic*z*x + s*y; + r.a32 = ic*y*z - s*x; + r.a33 = ic*z*z + c; + } + return r; +} + +TAffine4 TAffine4::rotationX(double angle) { + TAffine4 r; + double s = sin(angle); + double c = cos(angle); + r.a22 = c; + r.a23 = s; + r.a32 = -s; + r.a33 = c; + return r; +} + +TAffine4 TAffine4::rotationY(double angle) { + TAffine4 r; + double s = sin(angle); + double c = cos(angle); + r.a11 = c; + r.a13 = -s; + r.a31 = s; + r.a33 = c; + return r; +} + +TAffine4 TAffine4::rotationZ(double angle) { + TAffine4 r; + double s = sin(angle); + double c = cos(angle); + r.a11 = c; + r.a12 = s; + r.a21 = -s; + r.a22 = c; + return r; +} diff --git a/toonz/sources/include/tgeometry.h b/toonz/sources/include/tgeometry.h index 1a16872..1224a63 100644 --- a/toonz/sources/include/tgeometry.h +++ b/toonz/sources/include/tgeometry.h @@ -25,6 +25,9 @@ inline double logNormalDistribuition(double x, double x0, double w) { return logNormalDistribuitionUnscaled(x, x0, w)/(w*sqrt(2.0*M_PI)); } //============================================================================= + +template class TPoint4T; + /* * This is an example of how to use the TPointT, the TRectT and the TAffine * classes. @@ -39,6 +42,8 @@ public: TPointT() : x(0), y(0){}; TPointT(T _x, T _y) : x(_x), y(_y){}; TPointT(const TPointT &point) : x(point.x), y(point.y){}; + explicit TPointT(const TPoint4T &point); + inline TPointT &operator=(const TPointT &a) { x = a.x; y = a.y; @@ -66,6 +71,25 @@ public: bool operator!=(const TPointT &p) const { return x != p.x || y != p.y; } }; +template +class TPoint4T { +public: + union { + struct { T x, y, z, w; }; + T a[4]; + }; + + TPoint4T(): + x(), y(), z(), w() { }; + TPoint4T(T x, T y, T z, T w): + x(x), y(y), z(z), w(w) { }; + explicit TPoint4T(const TPointT &p, T w = (T)1): + x(p.x), y(p.y), z(), w(w) { }; +}; + +template +inline TPointT::TPointT(const TPoint4T &point) : x(point.x), y(point.y){}; + /*! \relates TPointT * Rotate a point 90 degrees (counterclockwise). \param p a point. @@ -108,6 +132,7 @@ inline std::ostream &operator<<(std::ostream &out, const TPointT &p) { typedef TPointT TPoint, TPointI; typedef TPointT TPointD; +typedef TPoint4T TPoint4D; #ifdef _WIN32 template class DVAPI TPointT; @@ -895,6 +920,7 @@ public: , a21(a.a21) , a22(a.a22) , a23(a.a23){}; + /*! Assignment operator. */ @@ -1042,7 +1068,12 @@ return TPointD(p.x*a11+p.y*a12+a13, p.x*a21+p.y*a22+a23); */ /*! - Returns the transformed box of the bounding box. + Transform point without translation + */ + TPointD transformDirection(const TPointD &p) const; + + /*! + Retruns the transformed box of the bounding box. */ TRectD operator*(const TRectD &rect) const; @@ -1190,4 +1221,79 @@ inline std::ostream &operator<<(std::ostream &out, const TAffine &a) { << ", " << a.a22 << ", " << a.a23 << ")"; } + +//============================================================================= + +//! This class performs basic manipulations of affine transformations in 3D space. +//! the matrix is transposed to TAffine and equal to OpenGL + +class DVAPI TAffine4 { +public: + union { + struct { + double a11, a12, a13, a14; + double a21, a22, a23, a24; + double a31, a32, a33, a34; + double a41, a42, a43, a44; + }; + double m[4][4]; + double a[16]; + }; + + inline TAffine4(): + a11(1.0), a12(0.0), a13(0.0), a14(0.0), + a21(0.0), a22(1.0), a23(0.0), a24(0.0), + a31(0.0), a32(0.0), a33(1.0), a34(0.0), + a41(0.0), a42(0.0), a43(0.0), a44(1.0) { } + + inline explicit TAffine4(const TAffine &a): + a11(a.a11), a12(a.a21), a13(0.0), a14(0.0), + a21(a.a12), a22(a.a22), a23(0.0), a24(0.0), + a31( 0.0 ), a32( 0.0 ), a33(1.0), a34(0.0), + a41(a.a13), a42(a.a23), a43(0.0), a44(1.0) { } + + inline TAffine4( + const TPoint4D &rowX, + const TPoint4D &rowY, + const TPoint4D &rowZ, + const TPoint4D &rowW + ): + a11(rowX.x), a12(rowX.y), a13(rowX.z), a14(rowX.w), + a21(rowY.x), a22(rowY.y), a23(rowY.z), a24(rowY.w), + a31(rowZ.x), a32(rowZ.y), a33(rowZ.z), a34(rowZ.w), + a41(rowW.x), a42(rowW.y), a43(rowW.z), a44(rowW.w) { } + + inline TPoint4D& row(int index) + { return *(TPoint4D*)(m[index]); } + inline const TPoint4D& row(int index) const + { return *(const TPoint4D*)(m[index]); } + + inline TPoint4D& rowX() { return row(0); } + inline TPoint4D& rowY() { return row(1); } + inline TPoint4D& rowZ() { return row(2); } + inline TPoint4D& rowW() { return row(3); } + + inline const TPoint4D& rowX() const { return row(0); } + inline const TPoint4D& rowY() const { return row(1); } + inline const TPoint4D& rowZ() const { return row(2); } + inline const TPoint4D& rowW() const { return row(3); } + + TPoint4D operator*(const TPoint4D &b) const; + TAffine4 operator*(const TAffine4 &b) const; + TAffine4 operator*=(const TAffine4 &b); + + TAffine4 inv() const; + + TAffine get2d(double z = 0.0) const; + + inline static TAffine4 identity() { return TAffine4(); } + static TAffine4 translation(double x, double y, double z); + static TAffine4 scale(double x, double y, double z); + static TAffine4 rotation(double x, double y, double z, double angle); + static TAffine4 rotationX(double angle); + static TAffine4 rotationY(double angle); + static TAffine4 rotationZ(double angle); + static TAffine4 perspective(double near, double far, double tangent); +}; + #endif // __T_GEOMETRY_INCLUDED__ diff --git a/toonz/sources/include/tgl.h b/toonz/sources/include/tgl.h index 5c993b1..b614cf2 100644 --- a/toonz/sources/include/tgl.h +++ b/toonz/sources/include/tgl.h @@ -181,6 +181,10 @@ inline void tglMultMatrix(const TAffine &aff) { glMultMatrixd(m); } +inline void tglMultMatrix(const TAffine4 &aff) { + glMultMatrixd(aff.a); +} + //============================================================================= void DVAPI tglRgbOnlyColorMask();