diff options
author | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-06-13 14:46:52 +0000 |
---|---|---|
committer | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-06-13 14:46:52 +0000 |
commit | da9fac0aa13d1445f8b58a75d9390638845c814d (patch) | |
tree | d5e7e189d1e5fe3caa0d074e6625a0ca09b9b4d5 /experimental | |
parent | 8260a895869beaa4cab9f8b915e457728f41e561 (diff) |
add row/col major getters, plus unit-tests
git-svn-id: http://skia.googlecode.com/svn/trunk@1564 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'experimental')
-rw-r--r-- | experimental/SkMatrix44.cpp | 340 | ||||
-rw-r--r-- | experimental/SkMatrix44.h | 215 |
2 files changed, 0 insertions, 555 deletions
diff --git a/experimental/SkMatrix44.cpp b/experimental/SkMatrix44.cpp deleted file mode 100644 index 803747fa46..0000000000 --- a/experimental/SkMatrix44.cpp +++ /dev/null @@ -1,340 +0,0 @@ -/* - Copyright 2011 Google Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - - -#include "SkMatrix44.h" - -SkMatrix44::SkMatrix44() { - this->setIdentity(); -} - -SkMatrix44::SkMatrix44(const SkMatrix44& src) { - memcpy(this, &src, sizeof(src)); -} - -SkMatrix44::SkMatrix44(const SkMatrix44& a, const SkMatrix44& 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; -} - -/////////////////////////////////////////////////////////////////////////////// - -static const SkMatrix44 gIdentity44; - -bool SkMatrix44::isIdentity() const { - return *this == gIdentity44; -} - -/////////////////////////////////////////////////////////////////////////////// - -void SkMatrix44::setIdentity() { - 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; - 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; -} - -void SkMatrix44::preTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz) { - 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; -} - -/////////////////////////////////////////////////////////////////////////////// - -void SkMatrix44::setScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) { - sk_bzero(fMat, sizeof(fMat)); - fMat[0][0] = sx; - fMat[1][1] = sy; - fMat[2][2] = sz; - fMat[3][3] = 1; -} - -void SkMatrix44::preScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) { - SkMatrix44 tmp; - tmp.setScale(sx, sy, sz); - this->preConcat(tmp); -} - -void SkMatrix44::postScale(SkMScalar sx, SkMScalar sy, SkMScalar sz) { - for (int i = 0; i < 4; i++) { - fMat[i][0] *= sx; - fMat[i][1] *= sy; - fMat[i][2] *= sz; - } -} - -/////////////////////////////////////////////////////////////////////////////// - -void SkMatrix44::setRotateAbout(SkMScalar x, SkMScalar y, SkMScalar z, - SkMScalar radians) { - double len2 = x * x + y * y + z * z; - if (len2 != 1) { - if (len2 == 0) { - this->setIdentity(); - return; - } - double scale = 1 / sqrt(len2); - x *= scale; - y *= scale; - z *= scale; - } - this->setRotateAboutUnit(x, y, z, radians); -} - -void SkMatrix44::setRotateAboutUnit(SkMScalar x, SkMScalar y, SkMScalar z, - SkMScalar radians) { - double c = cos(radians); - double s = sin(radians); - double C = 1 - c; - double xs = x * s; - double ys = y * s; - double zs = z * s; - double xC = x * C; - double yC = y * C; - double zC = z * C; - double xyC = x * yC; - double yzC = y * zC; - double zxC = z * xC; - - // 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)); -} - -/////////////////////////////////////////////////////////////////////////////// - -static inline SkMScalar det2x2(double m00, double m01, double m10, double m11) { - return m00 * m11 - m10 * m01; -} - -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); -} - -/** We always perform the calculation in doubles, to avoid prematurely losing - precision along the way. This relies on the compiler automatically - promoting our SkMScalar values to double (if needed). - */ -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]); -} - -/////////////////////////////////////////////////////////////////////////////// - -// just picked a small value. not sure how to pick the "right" one -#define TOO_SMALL_FOR_DETERMINANT (1.e-8) - -static inline double dabs(double x) { - if (x < 0) { - x = -x; - } - return x; -} - -bool SkMatrix44::invert(SkMatrix44* inverse) const { - double det = this->determinant(); - if (dabs(det) < TOO_SMALL_FOR_DETERMINANT) { - return false; - } - if (NULL == inverse) { - return true; - } - - // we explicitly promote to doubles to keep the intermediate values in - // higher precision (assuming SkMScalar isn't already a double) - double m00 = fMat[0][0]; - double m01 = fMat[0][1]; - double m02 = fMat[0][2]; - double m03 = fMat[0][3]; - double m10 = fMat[1][0]; - double m11 = fMat[1][1]; - double m12 = fMat[1][2]; - double m13 = fMat[1][3]; - double m20 = fMat[2][0]; - double m21 = fMat[2][1]; - double m22 = fMat[2][2]; - double m23 = fMat[2][3]; - double m30 = fMat[3][0]; - 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; - tmp[0][1] = m03*m22*m31 - m02*m23*m31 - m03*m21*m32 + m01*m23*m32 + m02*m21*m33 - m01*m22*m33; - tmp[0][2] = m02*m13*m31 - m03*m12*m31 + m03*m11*m32 - m01*m13*m32 - m02*m11*m33 + m01*m12*m33; - tmp[0][3] = m03*m12*m21 - m02*m13*m21 - m03*m11*m22 + m01*m13*m22 + m02*m11*m23 - m01*m12*m23; - tmp[1][0] = m13*m22*m30 - m12*m23*m30 - m13*m20*m32 + m10*m23*m32 + m12*m20*m33 - m10*m22*m33; - tmp[1][1] = m02*m23*m30 - m03*m22*m30 + m03*m20*m32 - m00*m23*m32 - m02*m20*m33 + m00*m22*m33; - tmp[1][2] = m03*m12*m30 - m02*m13*m30 - m03*m10*m32 + m00*m13*m32 + m02*m10*m33 - m00*m12*m33; - tmp[1][3] = m02*m13*m20 - m03*m12*m20 + m03*m10*m22 - m00*m13*m22 - m02*m10*m23 + m00*m12*m23; - tmp[2][0] = m11*m23*m30 - m13*m21*m30 + m13*m20*m31 - m10*m23*m31 - m11*m20*m33 + m10*m21*m33; - tmp[2][1] = m03*m21*m30 - m01*m23*m30 - m03*m20*m31 + m00*m23*m31 + m01*m20*m33 - m00*m21*m33; - tmp[2][2] = m01*m13*m30 - m03*m11*m30 + m03*m10*m31 - m00*m13*m31 - m01*m10*m33 + m00*m11*m33; - tmp[2][3] = m03*m11*m20 - m01*m13*m20 - m03*m10*m21 + m00*m13*m21 + m01*m10*m23 - m00*m11*m23; - tmp[3][0] = m12*m21*m30 - m11*m22*m30 - m12*m20*m31 + m10*m22*m31 + m11*m20*m32 - m10*m21*m32; - tmp[3][1] = m01*m22*m30 - m02*m21*m30 + m02*m20*m31 - m00*m22*m31 - m01*m20*m32 + m00*m21*m32; - tmp[3][2] = m02*m11*m30 - m01*m12*m30 - m02*m10*m31 + m00*m12*m31 + m01*m10*m32 - m00*m11*m32; - tmp[3][3] = m01*m12*m20 - m02*m11*m20 + m02*m10*m21 - m00*m12*m21 - m01*m10*m22 + m00*m11*m22; - - double invDet = 1.0 / det; - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - inverse->fMat[i][j] = SkDoubleToMScalar(tmp[i][j] * invDet); - } - } - return true; -} - -/////////////////////////////////////////////////////////////////////////////// - -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)); -} - -/////////////////////////////////////////////////////////////////////////////// - -void SkMatrix44::dump() const { - SkDebugf("[%g %g %g %g][%g %g %g %g][%g %g %g %g][%g %g %g %g]\n", -#if 0 - fMat[0][0], fMat[0][1], fMat[0][2], fMat[0][3], - fMat[1][0], fMat[1][1], fMat[1][2], fMat[1][3], - 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]); -#endif -} - -/////////////////////////////////////////////////////////////////////////////// - -static void initFromMatrix(SkMScalar dst[4][4], const SkMatrix& src) { - sk_bzero(dst, 16 * sizeof(SkMScalar)); - dst[0][0] = src[SkMatrix::kMScaleX]; - dst[1][0] = src[SkMatrix::kMSkewX]; - dst[3][0] = src[SkMatrix::kMTransX]; - dst[0][1] = src[SkMatrix::kMSkewY]; - dst[1][1] = src[SkMatrix::kMScaleY]; - dst[3][1] = src[SkMatrix::kMTransY]; - dst[2][2] = dst[3][3] = 1; -} - -SkMatrix44::SkMatrix44(const SkMatrix& src) { - initFromMatrix(fMat, src); -} - -SkMatrix44& SkMatrix44::operator=(const SkMatrix& src) { - initFromMatrix(fMat, src); - return *this; -} - -SkMatrix44::operator SkMatrix() const { - SkMatrix dst; - dst.reset(); // setup our perspective correctly for identity - - dst[SkMatrix::kMScaleX] = SkMScalarToFloat(fMat[0][0]); - dst[SkMatrix::kMSkewX] = SkMScalarToFloat(fMat[1][0]); - dst[SkMatrix::kMTransX] = SkMScalarToFloat(fMat[3][0]); - - dst[SkMatrix::kMSkewY] = SkMScalarToFloat(fMat[0][1]); - dst[SkMatrix::kMScaleY] = SkMScalarToFloat(fMat[1][1]); - dst[SkMatrix::kMTransY] = SkMScalarToFloat(fMat[3][1]); - - return dst; -} - - - diff --git a/experimental/SkMatrix44.h b/experimental/SkMatrix44.h deleted file mode 100644 index af632d755b..0000000000 --- a/experimental/SkMatrix44.h +++ /dev/null @@ -1,215 +0,0 @@ -/* - Copyright 2011 Google Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - - -#ifndef SkMatrix44_DEFINED -#define SkMatrix44_DEFINED - -#include "SkMatrix.h" -#include "SkScalar.h" - -// uncomment this to use doubles for matrix44 -#define SK_MSCALAR_IS_DOUBLE - -#ifdef SK_MSCALAR_IS_DOUBLE - typedef double SkMScalar; - static inline double SkFloatToMScalar(float x) { - return static_cast<double>(x); - } - static inline float SkMScalarToFloat(double x) { - return static_cast<float>(x); - } - static inline double SkDoubleToMScalar(double x) { - return x; - } - static inline double SkMScalarToDouble(double x) { - return x; - } - static const SkMScalar SK_MScalarPI = 3.141592653589793; -#else - typedef float SkMScalar; - static inline float SkFloatToMScalar(float x) { - return x; - } - static inline float SkMScalarToFloat(float x) { - return x; - } - static inline float SkDoubleToMScalar(double x) { - return static_cast<float>(x); - } - static inline double SkMScalarToDouble(float x) { - return static_cast<double>(x); - } - static const SkMScalar SK_MScalarPI = 3.14159265f; -#endif - -static const SkMScalar SK_MScalar1 = 1; - -/////////////////////////////////////////////////////////////////////////////// - -struct SkVector4 { - SkScalar fData[4]; - - SkVector4() { - this->set(0, 0, 0, 1); - } - SkVector4(const SkVector4& src) { - memcpy(fData, src.fData, sizeof(fData)); - } - SkVector4(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) { - fData[0] = x; - fData[1] = y; - fData[2] = z; - fData[3] = w; - } - - SkVector4& operator=(const SkVector4& src) { - memcpy(fData, src.fData, sizeof(fData)); - return *this; - } - - bool operator==(const SkVector4& v) { - return fData[0] == v.fData[0] && fData[1] == v.fData[1] && - fData[2] == v.fData[2] && fData[3] == v.fData[3]; - } - bool operator!=(const SkVector4& v) { - return !(*this == v); - } - bool equals(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) { - 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; - fData[2] = z; - fData[3] = w; - } -}; - -class SkMatrix44 { -public: - SkMatrix44(); - SkMatrix44(const SkMatrix44&); - SkMatrix44(const SkMatrix44& a, const SkMatrix44& b); - - SkMatrix44& operator=(const SkMatrix44& src) { - memcpy(this, &src, sizeof(*this)); - return *this; - } - - bool operator==(const SkMatrix44& other) const { - return !memcmp(this, &other, sizeof(*this)); - } - bool operator!=(const SkMatrix44& other) const { - return !!memcmp(this, &other, sizeof(*this)); - } - - SkMatrix44(const SkMatrix&); - 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 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 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); - } - void preScale(SkMScalar scale) { - this->preScale(scale, scale, scale); - } - void postScale(SkMScalar scale) { - this->postScale(scale, scale, scale); - } - - void setRotateDegreesAbout(SkMScalar x, SkMScalar y, SkMScalar z, - SkMScalar degrees) { - this->setRotateAbout(x, y, z, degrees * SK_MScalarPI / 180); - } - - /** Rotate about the vector [x,y,z]. If that vector is not unit-length, - it will be automatically resized. - */ - void setRotateAbout(SkMScalar x, SkMScalar y, SkMScalar z, - SkMScalar radians); - /** Rotate about the vector [x,y,z]. Does not check the length of the - vector, assuming it is unit-length. - */ - void setRotateAboutUnit(SkMScalar x, SkMScalar y, SkMScalar z, - SkMScalar radians); - - void setConcat(const SkMatrix44& a, const SkMatrix44& b); - void preConcat(const SkMatrix44& m) { - this->setConcat(*this, m); - } - void postConcat(const SkMatrix44& m) { - this->setConcat(m, *this); - } - - 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. - */ - bool invert(SkMatrix44* inverse) const; - - /** 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(SkScalar vec[4]) const { - this->map(vec, vec); - } - - friend SkVector4 operator*(const SkMatrix44& m, const SkVector4& src) { - SkVector4 dst; - m.map(src.fData, dst.fData); - return dst; - } - - void dump() const; - -private: - /* Stored in the same order as opengl: - [3][0] = tx - [3][1] = ty - [3][2] = tz - */ - SkMScalar fMat[4][4]; - - double determinant() const; -}; - -#endif |