aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-06-09 19:13:41 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-06-09 19:13:41 +0000
commit125002a94ccba991d151d226b98f100beb5e4b31 (patch)
tree3f0874a5f70c5ef798a028e15eb18c19b1ccd813
parent88a0e05265f02ce2f2c7b367de44c2281d72f054 (diff)
update SkMatrix44
git-svn-id: http://skia.googlecode.com/svn/trunk@1559 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--experimental/SkMatrix44.cpp137
-rw-r--r--experimental/SkMatrix44.h54
-rw-r--r--gyp/experimental.gyp4
-rw-r--r--gyp/tests.gyp2
-rw-r--r--tests/Matrix44Test.cpp70
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)