diff options
author | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-06-09 19:13:41 +0000 |
---|---|---|
committer | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-06-09 19:13:41 +0000 |
commit | 125002a94ccba991d151d226b98f100beb5e4b31 (patch) | |
tree | 3f0874a5f70c5ef798a028e15eb18c19b1ccd813 | |
parent | 88a0e05265f02ce2f2c7b367de44c2281d72f054 (diff) |
update SkMatrix44
git-svn-id: http://skia.googlecode.com/svn/trunk@1559 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r-- | experimental/SkMatrix44.cpp | 137 | ||||
-rw-r--r-- | experimental/SkMatrix44.h | 54 | ||||
-rw-r--r-- | gyp/experimental.gyp | 4 | ||||
-rw-r--r-- | gyp/tests.gyp | 2 | ||||
-rw-r--r-- | tests/Matrix44Test.cpp | 70 |
5 files changed, 176 insertions, 91 deletions
diff --git a/experimental/SkMatrix44.cpp b/experimental/SkMatrix44.cpp index d7a50f3bcf..803747fa46 100644 --- a/experimental/SkMatrix44.cpp +++ b/experimental/SkMatrix44.cpp @@ -18,15 +18,27 @@ #include "SkMatrix44.h" SkMatrix44::SkMatrix44() { - this->setIdentity(); + this->setIdentity(); } SkMatrix44::SkMatrix44(const SkMatrix44& src) { - memcpy(this, &src, sizeof(src)); + memcpy(this, &src, sizeof(src)); } SkMatrix44::SkMatrix44(const SkMatrix44& a, const SkMatrix44& b) { - this->setConcat(a, b); + this->setConcat(a, b); +} + +SkMScalar SkMatrix44::get(int row, int col) const { + SkASSERT(row <= 3 && row >= 0); + SkASSERT(col <= 3 && col >= 0); + return fMat[col][row]; +} + +void SkMatrix44::set(int row, int col, const SkMScalar& value) { + SkASSERT(row <= 3 && row >= 0); + SkASSERT(col <= 3 && col >= 0); + fMat[col][row] = value; } /////////////////////////////////////////////////////////////////////////////// @@ -40,47 +52,47 @@ bool SkMatrix44::isIdentity() const { /////////////////////////////////////////////////////////////////////////////// void SkMatrix44::setIdentity() { - sk_bzero(fMat, sizeof(fMat)); - fMat[0][0] = fMat[1][1] = fMat[2][2] = fMat[3][3] = 1; + sk_bzero(fMat, sizeof(fMat)); + fMat[0][0] = fMat[1][1] = fMat[2][2] = fMat[3][3] = 1; } void SkMatrix44::set3x3(SkMScalar m00, SkMScalar m01, SkMScalar m02, SkMScalar m10, SkMScalar m11, SkMScalar m12, SkMScalar m20, SkMScalar m21, SkMScalar m22) { - sk_bzero(fMat, sizeof(fMat)); - fMat[0][0] = m00; fMat[0][1] = m01; fMat[0][2] = m02; fMat[0][3] = 0; - fMat[1][0] = m10; fMat[1][1] = m11; fMat[1][2] = m12; fMat[1][3] = 0; - fMat[2][0] = m20; fMat[2][1] = m21; fMat[2][2] = m22; fMat[2][3] = 0; + sk_bzero(fMat, sizeof(fMat)); + fMat[0][0] = m00; fMat[0][1] = m01; fMat[0][2] = m02; fMat[0][3] = 0; + fMat[1][0] = m10; fMat[1][1] = m11; fMat[1][2] = m12; fMat[1][3] = 0; + fMat[2][0] = m20; fMat[2][1] = m21; fMat[2][2] = m22; fMat[2][3] = 0; fMat[3][0] = 0; fMat[3][1] = 0; fMat[3][2] = 0; fMat[3][3] = 1; } /////////////////////////////////////////////////////////////////////////////// void SkMatrix44::setTranslate(SkMScalar tx, SkMScalar ty, SkMScalar tz) { - this->setIdentity(); - fMat[3][0] = tx; - fMat[3][1] = ty; - fMat[3][2] = tz; - fMat[3][3] = 1; + this->setIdentity(); + fMat[3][0] = tx; + fMat[3][1] = ty; + fMat[3][2] = tz; + fMat[3][3] = 1; } void SkMatrix44::preTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) { - SkMatrix44 mat; - mat.setTranslate(dx, dy, dz); - this->preConcat(mat); + SkMatrix44 mat; + mat.setTranslate(dx, dy, dz); + this->preConcat(mat); } void SkMatrix44::postTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) { - fMat[3][0] += dx; - fMat[3][1] += dy; - fMat[3][2] += dz; + fMat[3][0] += dx; + fMat[3][1] += dy; + fMat[3][2] += dz; } /////////////////////////////////////////////////////////////////////////////// void SkMatrix44::setScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) { - sk_bzero(fMat, sizeof(fMat)); - fMat[0][0] = sx; + sk_bzero(fMat, sizeof(fMat)); + fMat[0][0] = sx; fMat[1][1] = sy; fMat[2][2] = sz; fMat[3][3] = 1; @@ -133,25 +145,26 @@ void SkMatrix44::setRotateAboutUnit(SkMScalar x, SkMScalar y, SkMScalar z, double yzC = y * zC; double zxC = z * xC; - this->set3x3(x * xC + c, xyC - zs, zxC + ys, - xyC + zs, y * yC + c, yzC - xs, - zxC - ys, yzC + xs, z * zC + c); + // if you're looking at wikipedia, remember that we're column major. + this->set3x3(x * xC + c, xyC + zs, zxC - ys, + xyC - zs, y * yC + c, yzC + xs, + zxC + ys, yzC - xs, z * zC + c); } /////////////////////////////////////////////////////////////////////////////// void SkMatrix44::setConcat(const SkMatrix44& a, const SkMatrix44& b) { - SkMScalar result[4][4]; - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - double value = 0; - for (int k = 0; k < 4; k++) { - value += SkMScalarToDouble(a.fMat[k][i]) * b.fMat[j][k]; - } - result[j][i] = SkDoubleToMScalar(value); - } - } - memcpy(fMat, result, sizeof(result)); + SkMScalar result[4][4]; + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + double value = 0; + for (int k = 0; k < 4; k++) { + value += SkMScalarToDouble(a.fMat[k][i]) * b.fMat[j][k]; + } + result[j][i] = SkDoubleToMScalar(value); + } + } + memcpy(fMat, result, sizeof(result)); } /////////////////////////////////////////////////////////////////////////////// @@ -164,8 +177,8 @@ static inline double det3x3(double m00, double m01, double m02, double m10, double m11, double m12, double m20, double m21, double m22) { return m00 * det2x2(m11, m12, m21, m22) - - m10 * det2x2(m01, m02, m21, m22) + - m20 * det2x2(m01, m02, m11, m12); + m10 * det2x2(m01, m02, m21, m22) + + m20 * det2x2(m01, m02, m11, m12); } /** We always perform the calculation in doubles, to avoid prematurely losing @@ -176,15 +189,15 @@ double SkMatrix44::determinant() const { return fMat[0][0] * det3x3(fMat[1][1], fMat[1][2], fMat[1][3], fMat[2][1], fMat[2][2], fMat[2][3], fMat[3][1], fMat[3][2], fMat[3][3]) - - fMat[1][0] * det3x3(fMat[0][1], fMat[0][2], fMat[0][3], - fMat[2][1], fMat[2][2], fMat[2][3], - fMat[3][1], fMat[3][2], fMat[3][3]) + - fMat[2][0] * det3x3(fMat[0][1], fMat[0][2], fMat[0][3], - fMat[1][1], fMat[1][2], fMat[1][3], - fMat[3][1], fMat[3][2], fMat[3][3]) - - fMat[3][0] * det3x3(fMat[0][1], fMat[0][2], fMat[0][3], - fMat[1][1], fMat[1][2], fMat[1][3], - fMat[2][1], fMat[2][2], fMat[2][3]); + fMat[1][0] * det3x3(fMat[0][1], fMat[0][2], fMat[0][3], + fMat[2][1], fMat[2][2], fMat[2][3], + fMat[3][1], fMat[3][2], fMat[3][3]) + + fMat[2][0] * det3x3(fMat[0][1], fMat[0][2], fMat[0][3], + fMat[1][1], fMat[1][2], fMat[1][3], + fMat[3][1], fMat[3][2], fMat[3][3]) - + fMat[3][0] * det3x3(fMat[0][1], fMat[0][2], fMat[0][3], + fMat[1][1], fMat[1][2], fMat[1][3], + fMat[2][1], fMat[2][2], fMat[2][3]); } /////////////////////////////////////////////////////////////////////////////// @@ -226,7 +239,7 @@ bool SkMatrix44::invert(SkMatrix44* inverse) const { double m31 = fMat[3][1]; double m32 = fMat[3][2]; double m33 = fMat[3][3]; - + double tmp[4][4]; tmp[0][0] = m12*m23*m31 - m13*m22*m31 + m13*m21*m32 - m11*m23*m32 - m12*m21*m33 + m11*m22*m33; @@ -258,15 +271,15 @@ bool SkMatrix44::invert(SkMatrix44* inverse) const { /////////////////////////////////////////////////////////////////////////////// void SkMatrix44::map(const SkScalar src[4], SkScalar dst[4]) const { - SkScalar result[4]; - for (int i = 0; i < 4; i++) { - SkMScalar value = 0; - for (int j = 0; j < 4; j++) { - value += fMat[j][i] * src[j]; - } - result[i] = value; - } - memcpy(dst, result, sizeof(result)); + SkScalar result[4]; + for (int i = 0; i < 4; i++) { + SkMScalar value = 0; + for (int j = 0; j < 4; j++) { + value += fMat[j][i] * src[j]; + } + result[i] = value; + } + memcpy(dst, result, sizeof(result)); } /////////////////////////////////////////////////////////////////////////////// @@ -279,17 +292,17 @@ void SkMatrix44::dump() const { fMat[2][0], fMat[2][1], fMat[2][2], fMat[2][3], fMat[3][0], fMat[3][1], fMat[3][2], fMat[3][3]); #else - fMat[0][0], fMat[1][0], fMat[2][0], fMat[3][0], - fMat[0][1], fMat[1][1], fMat[2][1], fMat[3][1], - fMat[0][2], fMat[1][2], fMat[2][2], fMat[3][2], - fMat[0][3], fMat[1][3], fMat[2][3], fMat[3][3]); + fMat[0][0], fMat[1][0], fMat[2][0], fMat[3][0], + fMat[0][1], fMat[1][1], fMat[2][1], fMat[3][1], + fMat[0][2], fMat[1][2], fMat[2][2], fMat[3][2], + fMat[0][3], fMat[1][3], fMat[2][3], fMat[3][3]); #endif } /////////////////////////////////////////////////////////////////////////////// static void initFromMatrix(SkMScalar dst[4][4], const SkMatrix& src) { - sk_bzero(dst, 16 * sizeof(SkMScalar)); + sk_bzero(dst, 16 * sizeof(SkMScalar)); dst[0][0] = src[SkMatrix::kMScaleX]; dst[1][0] = src[SkMatrix::kMSkewX]; dst[3][0] = src[SkMatrix::kMTransX]; diff --git a/experimental/SkMatrix44.h b/experimental/SkMatrix44.h index af1e51effa..af632d755b 100644 --- a/experimental/SkMatrix44.h +++ b/experimental/SkMatrix44.h @@ -61,7 +61,7 @@ static const SkMScalar SK_MScalar1 = 1; /////////////////////////////////////////////////////////////////////////////// struct SkVector4 { - SkScalar fData[4]; + SkScalar fData[4]; SkVector4() { this->set(0, 0, 0, 1); @@ -92,7 +92,7 @@ struct SkVector4 { return fData[0] == x && fData[1] == y && fData[2] == z && fData[3] == w; } - + void set(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) { fData[0] = x; fData[1] = y; @@ -103,9 +103,9 @@ struct SkVector4 { class SkMatrix44 { public: - SkMatrix44(); - SkMatrix44(const SkMatrix44&); - SkMatrix44(const SkMatrix44& a, const SkMatrix44& b); + SkMatrix44(); + SkMatrix44(const SkMatrix44&); + SkMatrix44(const SkMatrix44& a, const SkMatrix44& b); SkMatrix44& operator=(const SkMatrix44& src) { memcpy(this, &src, sizeof(*this)); @@ -123,21 +123,24 @@ public: SkMatrix44& operator=(const SkMatrix& src); operator SkMatrix() const; + SkMScalar get(int row, int col) const; + void set(int row, int col, const SkMScalar& value); + bool isIdentity() const; - void setIdentity(); - void reset() { this->setIdentity(); } + void setIdentity(); + void reset() { this->setIdentity();} void set3x3(SkMScalar m00, SkMScalar m01, SkMScalar m02, SkMScalar m10, SkMScalar m11, SkMScalar m12, SkMScalar m20, SkMScalar m21, SkMScalar m22); - void setTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz); - void preTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz); - void postTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz); + void setTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz); + void preTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz); + void postTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz); - void setScale(SkMScalar sx, SkMScalar sx, SkMScalar sx); - void preScale(SkMScalar sx, SkMScalar sx, SkMScalar sx); - void postScale(SkMScalar sx, SkMScalar sx, SkMScalar sx); + void setScale(SkMScalar sx, SkMScalar sy, SkMScalar sz); + void preScale(SkMScalar sx, SkMScalar sy, SkMScalar sz); + void postScale(SkMScalar sx, SkMScalar sy, SkMScalar sz); void setScale(SkMScalar scale) { this->setScale(scale, scale, scale); @@ -150,7 +153,7 @@ public: } void setRotateDegreesAbout(SkMScalar x, SkMScalar y, SkMScalar z, - SkMScalar degrees) { + SkMScalar degrees) { this->setRotateAbout(x, y, z, degrees * SK_MScalarPI / 180); } @@ -165,16 +168,17 @@ public: void setRotateAboutUnit(SkMScalar x, SkMScalar y, SkMScalar z, SkMScalar radians); - void setConcat(const SkMatrix44& a, const SkMatrix44& b); - void preConcat(const SkMatrix44& m) { + void setConcat(const SkMatrix44& a, const SkMatrix44& b); + void preConcat(const SkMatrix44& m) { this->setConcat(*this, m); } - void postConcat(const SkMatrix44& m) { + void postConcat(const SkMatrix44& m) { this->setConcat(m, *this); } - friend SkMatrix44 operator*(const SkMatrix44& a, const SkMatrix44& b) { - return SkMatrix44(a, b); - } + + friend SkMatrix44 operator*(const SkMatrix44& a, const SkMatrix44& b) { + return SkMatrix44(a, b); + } /** If this is invertible, return that in inverse and return true. If it is not invertible, return false and ignore the inverse parameter. @@ -184,16 +188,16 @@ public: /** Apply the matrix to the src vector, returning the new vector in dst. It is legal for src and dst to point to the same memory. */ - void map(const SkScalar src[4], SkScalar dst[4]) const; + void map(const SkScalar src[4], SkScalar dst[4]) const; void map(SkScalar vec[4]) const { this->map(vec, vec); - } + } - friend SkVector4 operator*(const SkMatrix44& m, const SkVector4& src) { + friend SkVector4 operator*(const SkMatrix44& m, const SkVector4& src) { SkVector4 dst; m.map(src.fData, dst.fData); return dst; - } + } void dump() const; @@ -203,7 +207,7 @@ private: [3][1] = ty [3][2] = tz */ - SkMScalar fMat[4][4]; + SkMScalar fMat[4][4]; double determinant() const; }; diff --git a/gyp/experimental.gyp b/gyp/experimental.gyp index 50e60e8011..12921ba908 100644 --- a/gyp/experimental.gyp +++ b/gyp/experimental.gyp @@ -17,10 +17,6 @@ '../experimental/SkSetPoly3To3_A.cpp', '../experimental/SkSetPoly3To3_D.cpp', ], - 'sources!': [ - '../experimental/SkMatrix44.cpp', #doesn't compile - '../experimental/SkMatrix44.h', - ], 'direct_dependent_settings': { 'include_dirs': [ '../experimental', diff --git a/gyp/tests.gyp b/gyp/tests.gyp index 2756b90a73..300bb5d181 100644 --- a/gyp/tests.gyp +++ b/gyp/tests.gyp @@ -43,6 +43,7 @@ '../tests/InfRectTest.cpp', '../tests/MathTest.cpp', '../tests/MatrixTest.cpp', + '../tests/Matrix44Test.cpp', '../tests/MetaDataTest.cpp', '../tests/PackBitsTest.cpp', '../tests/PaintTest.cpp', @@ -68,6 +69,7 @@ 'dependencies': [ 'core.gyp:core', 'effects.gyp:effects', + 'experimental.gyp:experimental', 'images.gyp:images', 'utils.gyp:utils', ], diff --git a/tests/Matrix44Test.cpp b/tests/Matrix44Test.cpp new file mode 100644 index 0000000000..8755bd32b2 --- /dev/null +++ b/tests/Matrix44Test.cpp @@ -0,0 +1,70 @@ +#include "Test.h" +#include "SkMatrix44.h" + +static bool nearly_equal_scalar(SkScalar a, SkScalar b) { + // Note that we get more compounded error for multiple operations when + // SK_SCALAR_IS_FIXED. +#ifdef SK_SCALAR_IS_FLOAT + const SkScalar tolerance = SK_Scalar1 / 200000; +#else + const SkScalar tolerance = SK_Scalar1 / 1024; +#endif + + return SkScalarAbs(a - b) <= tolerance; +} + +static bool nearly_equal(const SkMatrix44& a, const SkMatrix44& b) { + for (int i = 0; i < 4; ++i) { + for (int j = 0; j < 4; ++j) { + if (!nearly_equal_scalar(a.get(i, j), b.get(i, j))) { + printf("not equal %g %g\n", (float)a.get(i, j), (float)b.get(i, j)); + return false; + } + } + } + return true; +} + +static bool is_identity(const SkMatrix44& m) { + SkMatrix44 identity; + identity.reset(); + return nearly_equal(m, identity); +} + + +void TestMatrix44(skiatest::Reporter* reporter) { + SkMatrix44 mat, inverse, iden1, iden2, rot; + + mat.reset(); + mat.setTranslate(SK_Scalar1, SK_Scalar1, SK_Scalar1); + mat.invert(&inverse); + iden1.setConcat(mat, inverse); + REPORTER_ASSERT(reporter, is_identity(iden1)); + + mat.setScale(SkIntToScalar(2), SkIntToScalar(2), SkIntToScalar(2)); + mat.invert(&inverse); + iden1.setConcat(mat, inverse); + REPORTER_ASSERT(reporter, is_identity(iden1)); + + mat.setScale(SK_Scalar1/2, SK_Scalar1/2, SK_Scalar1/2); + mat.invert(&inverse); + iden1.setConcat(mat, inverse); + REPORTER_ASSERT(reporter, is_identity(iden1)); + + mat.setScale(SkIntToScalar(3), SkIntToScalar(5), SkIntToScalar(20)); + rot.setRotateDegreesAbout( + SkIntToScalar(0), + SkIntToScalar(0), + SkIntToScalar(-1), + SkIntToScalar(90)); + mat.postConcat(rot); + REPORTER_ASSERT(reporter, mat.invert(NULL)); + mat.invert(&inverse); + iden1.setConcat(mat, inverse); + REPORTER_ASSERT(reporter, is_identity(iden1)); + iden2.setConcat(inverse, mat); + REPORTER_ASSERT(reporter, is_identity(iden2)); +} + +#include "TestClassDef.h" +DEFINE_TESTCLASS("Matrix44", Matrix44TestClass, TestMatrix44) |