add row/col major getters, plus unit-tests
git-svn-id: http://skia.googlecode.com/svn/trunk@1564 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
8260a89586
commit
da9fac0aa1
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
@ -21,9 +21,6 @@
|
||||
#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) {
|
||||
@ -126,6 +123,11 @@ public:
|
||||
SkMScalar get(int row, int col) const;
|
||||
void set(int row, int col, const SkMScalar& value);
|
||||
|
||||
void asColMajorf(float[]) const;
|
||||
void asColMajord(double[]) const;
|
||||
void asRowMajorf(float[]) const;
|
||||
void asRowMajord(double[]) const;
|
||||
|
||||
bool isIdentity() const;
|
||||
void setIdentity();
|
||||
void reset() { this->setIdentity();}
|
||||
|
@ -43,6 +43,54 @@ void SkMatrix44::set(int row, int col, const SkMScalar& value) {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SkMatrix44::asColMajorf(float dst[]) const {
|
||||
const SkMScalar* src = &fMat[0][0];
|
||||
#ifdef SK_MSCALAR_IS_DOUBLE
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
dst[i] = SkMScalarToFloat(src[i]);
|
||||
}
|
||||
#else
|
||||
memcpy(dst, src, 16 * sizeof(float));
|
||||
#endif
|
||||
}
|
||||
|
||||
void SkMatrix44::asColMajord(double dst[]) const {
|
||||
const SkMScalar* src = &fMat[0][0];
|
||||
#ifdef SK_MSCALAR_IS_DOUBLE
|
||||
memcpy(dst, src, 16 * sizeof(double));
|
||||
#else
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
dst[i] = SkMScalarToDouble(src[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void SkMatrix44::asRowMajorf(float dst[]) const {
|
||||
const SkMScalar* src = &fMat[0][0];
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
dst[0] = SkMScalarToFloat(src[0]);
|
||||
dst[4] = SkMScalarToFloat(src[1]);
|
||||
dst[8] = SkMScalarToFloat(src[2]);
|
||||
dst[12] = SkMScalarToFloat(src[3]);
|
||||
src += 4;
|
||||
dst += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void SkMatrix44::asRowMajord(double dst[]) const {
|
||||
const SkMScalar* src = &fMat[0][0];
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
dst[0] = SkMScalarToDouble(src[0]);
|
||||
dst[4] = SkMScalarToDouble(src[1]);
|
||||
dst[8] = SkMScalarToDouble(src[2]);
|
||||
dst[12] = SkMScalarToDouble(src[3]);
|
||||
src += 4;
|
||||
dst += 1;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const SkMatrix44 gIdentity44;
|
||||
|
||||
bool SkMatrix44::isIdentity() const {
|
||||
|
@ -5,6 +5,7 @@ SOURCE := \
|
||||
SkDumpCanvas.cpp \
|
||||
SkInterpolator.cpp \
|
||||
SkLayer.cpp \
|
||||
SkMatrix44.cpp \
|
||||
SkNinePatch.cpp \
|
||||
SkNWayCanvas.cpp \
|
||||
SkOSFile.cpp \
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "Test.h"
|
||||
#include "SkMatrix44.h"
|
||||
|
||||
static bool nearly_equal_scalar(SkScalar a, SkScalar b) {
|
||||
static bool nearly_equal_scalar(SkMScalar a, SkMScalar b) {
|
||||
// Note that we get more compounded error for multiple operations when
|
||||
// SK_SCALAR_IS_FIXED.
|
||||
#ifdef SK_SCALAR_IS_FLOAT
|
||||
@ -13,11 +13,37 @@ static bool nearly_equal_scalar(SkScalar a, SkScalar b) {
|
||||
return SkScalarAbs(a - b) <= tolerance;
|
||||
}
|
||||
|
||||
template <typename T> void assert16(skiatest::Reporter* reporter, const T data[],
|
||||
T m0, T m1, T m2, T m3,
|
||||
T m4, T m5, T m6, T m7,
|
||||
T m8, T m9, T m10, T m11,
|
||||
T m12, T m13, T m14, T m15) {
|
||||
REPORTER_ASSERT(reporter, data[0] == m0);
|
||||
REPORTER_ASSERT(reporter, data[1] == m1);
|
||||
REPORTER_ASSERT(reporter, data[2] == m2);
|
||||
REPORTER_ASSERT(reporter, data[3] == m3);
|
||||
|
||||
REPORTER_ASSERT(reporter, data[4] == m4);
|
||||
REPORTER_ASSERT(reporter, data[5] == m5);
|
||||
REPORTER_ASSERT(reporter, data[6] == m6);
|
||||
REPORTER_ASSERT(reporter, data[7] == m7);
|
||||
|
||||
REPORTER_ASSERT(reporter, data[8] == m8);
|
||||
REPORTER_ASSERT(reporter, data[9] == m9);
|
||||
REPORTER_ASSERT(reporter, data[10] == m10);
|
||||
REPORTER_ASSERT(reporter, data[11] == m11);
|
||||
|
||||
REPORTER_ASSERT(reporter, data[12] == m12);
|
||||
REPORTER_ASSERT(reporter, data[13] == m13);
|
||||
REPORTER_ASSERT(reporter, data[14] == m14);
|
||||
REPORTER_ASSERT(reporter, data[15] == m15);
|
||||
}
|
||||
|
||||
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));
|
||||
printf("not equal %g %g\n", a.get(i, j), b.get(i, j));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -31,8 +57,8 @@ static bool is_identity(const SkMatrix44& m) {
|
||||
return nearly_equal(m, identity);
|
||||
}
|
||||
|
||||
|
||||
void TestMatrix44(skiatest::Reporter* reporter) {
|
||||
#ifdef SK_SCALAR_IS_FLOAT
|
||||
SkMatrix44 mat, inverse, iden1, iden2, rot;
|
||||
|
||||
mat.reset();
|
||||
@ -64,6 +90,36 @@ void TestMatrix44(skiatest::Reporter* reporter) {
|
||||
REPORTER_ASSERT(reporter, is_identity(iden1));
|
||||
iden2.setConcat(inverse, mat);
|
||||
REPORTER_ASSERT(reporter, is_identity(iden2));
|
||||
|
||||
// test rol/col Major getters
|
||||
{
|
||||
mat.setTranslate(2, 3, 4);
|
||||
float dataf[16];
|
||||
double datad[16];
|
||||
|
||||
mat.asColMajorf(dataf);
|
||||
assert16<float>(reporter, dataf,
|
||||
1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
2, 3, 4, 1);
|
||||
mat.asColMajord(datad);
|
||||
assert16<double>(reporter, datad, 1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
2, 3, 4, 1);
|
||||
mat.asRowMajorf(dataf);
|
||||
assert16<float>(reporter, dataf, 1, 0, 0, 2,
|
||||
0, 1, 0, 3,
|
||||
0, 0, 1, 4,
|
||||
0, 0, 0, 1);
|
||||
mat.asRowMajord(datad);
|
||||
assert16<double>(reporter, datad, 1, 0, 0, 2,
|
||||
0, 1, 0, 3,
|
||||
0, 0, 1, 4,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#include "TestClassDef.h"
|
||||
|
@ -15,6 +15,7 @@ SOURCE := \
|
||||
GeometryTest.cpp \
|
||||
InfRectTest.cpp \
|
||||
MathTest.cpp \
|
||||
Matrix44Test.cpp \
|
||||
MatrixTest.cpp \
|
||||
MetaDataTest.cpp \
|
||||
PackBitsTest.cpp \
|
||||
|
Loading…
Reference in New Issue
Block a user