c4b8eefe56
Change-Id: I20284b415bbfe5ecc15fe9fe47dcbb65850d4368 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/264682 Reviewed-by: Mike Reed <reed@google.com> Commit-Queue: Mike Reed <reed@google.com>
226 lines
6.9 KiB
C++
226 lines
6.9 KiB
C++
/*
|
|
* Copyright 2020 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#ifndef SkM44_DEFINED
|
|
#define SkM44_DEFINED
|
|
|
|
#include "include/core/SkScalar.h"
|
|
|
|
class SkMatrix;
|
|
|
|
struct SkV3 {
|
|
float x, y, z;
|
|
|
|
bool operator==(const SkV3& v) const {
|
|
return x == v.x && y == v.y && z == v.z;
|
|
}
|
|
|
|
static SkScalar Dot(const SkV3& a, const SkV3& b) { return a.x*b.x + a.y*b.y + a.z*b.z; }
|
|
static SkV3 Cross(const SkV3& a, const SkV3& b) {
|
|
return { a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x };
|
|
}
|
|
|
|
SkV3 operator+(const SkV3& v) const { return { x + v.x, y + v.y, z + v.z }; }
|
|
SkV3 operator-(const SkV3& v) const { return { x - v.x, y - v.y, z - v.z }; }
|
|
|
|
friend SkV3 operator*(const SkV3& v, SkScalar s) {
|
|
return { v.x*s, v.y*s, v.z*s };
|
|
}
|
|
friend SkV3 operator*(SkScalar s, const SkV3& v) { return v*s; }
|
|
|
|
SkScalar operator*(const SkV3& v) const { return Dot(*this, v); }
|
|
SkV3 operator%(const SkV3& v) const { return Cross(*this, v); }
|
|
|
|
SkScalar lengthSquared() const { return Dot(*this, *this); }
|
|
SkScalar length() const { return SkScalarSqrt(Dot(*this, *this)); }
|
|
};
|
|
|
|
struct SkV4 {
|
|
float x, y, z, w;
|
|
|
|
bool operator==(const SkV4& v) const {
|
|
return x == v.x && y == v.y && z == v.z && w == v.w;
|
|
}
|
|
};
|
|
|
|
class SkM44 {
|
|
public:
|
|
SkM44(const SkM44& src) = default;
|
|
SkM44& operator=(const SkM44& src) = default;
|
|
|
|
constexpr SkM44()
|
|
: fMat{1, 0, 0, 0,
|
|
0, 1, 0, 0,
|
|
0, 0, 1, 0,
|
|
0, 0, 0, 1}
|
|
{}
|
|
|
|
SkM44(const SkM44& a, const SkM44& b) {
|
|
this->setConcat(a, b);
|
|
}
|
|
|
|
/**
|
|
* Parameters are treated as row-major.
|
|
*/
|
|
SkM44(SkScalar m0, SkScalar m4, SkScalar m8, SkScalar m12,
|
|
SkScalar m1, SkScalar m5, SkScalar m9, SkScalar m13,
|
|
SkScalar m2, SkScalar m6, SkScalar m10, SkScalar m14,
|
|
SkScalar m3, SkScalar m7, SkScalar m11, SkScalar m15)
|
|
{
|
|
fMat[0] = m0; fMat[4] = m4; fMat[8] = m8; fMat[12] = m12;
|
|
fMat[1] = m1; fMat[5] = m5; fMat[9] = m9; fMat[13] = m13;
|
|
fMat[2] = m2; fMat[6] = m6; fMat[10] = m10; fMat[14] = m14;
|
|
fMat[3] = m3; fMat[7] = m7; fMat[11] = m11; fMat[15] = m15;
|
|
}
|
|
|
|
static SkM44 Translate(SkScalar x, SkScalar y, SkScalar z = 0) {
|
|
return SkM44(1, 0, 0, x,
|
|
0, 1, 0, y,
|
|
0, 0, 1, z,
|
|
0, 0, 0, 1);
|
|
}
|
|
|
|
static SkM44 Scale(SkScalar x, SkScalar y, SkScalar z = 1) {
|
|
return SkM44(x, 0, 0, 0,
|
|
0, y, 0, 0,
|
|
0, 0, z, 0,
|
|
0, 0, 0, 1);
|
|
}
|
|
|
|
bool operator==(const SkM44& other) const;
|
|
bool operator!=(const SkM44& other) const {
|
|
return !(other == *this);
|
|
}
|
|
|
|
void getColMajor(SkScalar v[]) const {
|
|
memcpy(v, fMat, sizeof(fMat));
|
|
}
|
|
void getRowMajor(SkScalar v[]) const;
|
|
|
|
SkM44& setColMajor(const SkScalar v[]) {
|
|
memcpy(fMat, v, sizeof(fMat));
|
|
return *this;
|
|
}
|
|
SkM44& setRowMajor(const SkScalar v[]);
|
|
|
|
/* Parameters are treated as row-major.
|
|
*/
|
|
SkM44& setRowMajor(SkScalar m0, SkScalar m4, SkScalar m8, SkScalar m12,
|
|
SkScalar m1, SkScalar m5, SkScalar m9, SkScalar m13,
|
|
SkScalar m2, SkScalar m6, SkScalar m10, SkScalar m14,
|
|
SkScalar m3, SkScalar m7, SkScalar m11, SkScalar m15) {
|
|
fMat[0] = m0; fMat[4] = m4; fMat[8] = m8; fMat[12] = m12;
|
|
fMat[1] = m1; fMat[5] = m5; fMat[9] = m9; fMat[13] = m13;
|
|
fMat[2] = m2; fMat[6] = m6; fMat[10] = m10; fMat[14] = m14;
|
|
fMat[3] = m3; fMat[7] = m7; fMat[11] = m11; fMat[15] = m15;
|
|
return *this;
|
|
}
|
|
|
|
SkScalar atColMajor(int index) const {
|
|
SkASSERT(index >= 0 && index < 16);
|
|
return fMat[index];
|
|
}
|
|
|
|
SkM44& setIdentity() {
|
|
return this->setRowMajor(1, 0, 0, 0,
|
|
0, 1, 0, 0,
|
|
0, 0, 1, 0,
|
|
0, 0, 0, 1);
|
|
}
|
|
|
|
SkM44& setTranslate(SkScalar x, SkScalar y, SkScalar z = 0) {
|
|
return this->setRowMajor(1, 0, 0, x,
|
|
0, 1, 0, y,
|
|
0, 0, 1, z,
|
|
0, 0, 0, 1);
|
|
}
|
|
|
|
SkM44& setScale(SkScalar x, SkScalar y, SkScalar z = 1) {
|
|
return this->setRowMajor(x, 0, 0, 0,
|
|
0, y, 0, 0,
|
|
0, 0, z, 0,
|
|
0, 0, 0, 1);
|
|
}
|
|
|
|
SkM44& setConcat(const SkM44& a, const SkScalar colMajor[16]);
|
|
|
|
SkM44& setConcat(const SkM44& a, const SkM44& b) {
|
|
return this->setConcat(a, b.fMat);
|
|
}
|
|
|
|
friend SkM44 operator*(const SkM44& a, const SkM44& b) {
|
|
return SkM44(a, b);
|
|
}
|
|
|
|
/** If this is invertible, return that in inverse and return true. If it is
|
|
* not invertible, return false and leave the inverse parameter unchanged.
|
|
*/
|
|
bool invert(SkM44* inverse) const;
|
|
|
|
void dump() const;
|
|
|
|
////////////
|
|
|
|
SkV4 map(float x, float y, float z, float w) const;
|
|
SkV4 operator*(const SkV4& v) const {
|
|
return this->map(v.x, v.y, v.z, v.z);
|
|
}
|
|
SkV3 operator*(const SkV3& v) const {
|
|
auto v4 = this->map(v.x, v.y, v.z, 0);
|
|
return {v4.x, v4.y, v4.z};
|
|
}
|
|
|
|
////////////////////// Converting to/from SkMatrix
|
|
|
|
/* When converting from SkM44 to SkMatrix, the third row and
|
|
* column is dropped. When converting from SkMatrix to SkM44
|
|
* the third row and column remain as identity:
|
|
* [ a b c ] [ a b 0 c ]
|
|
* [ d e f ] -> [ d e 0 f ]
|
|
* [ g h i ] [ 0 0 1 0 ]
|
|
* [ g h 0 i ]
|
|
*/
|
|
SkMatrix asM33() const {
|
|
return SkMatrix::MakeAll(fMat[0], fMat[4], fMat[12],
|
|
fMat[1], fMat[5], fMat[13],
|
|
fMat[3], fMat[7], fMat[15]);
|
|
}
|
|
|
|
SkM44(const SkMatrix& src)
|
|
: SkM44(src[SkMatrix::kMScaleX], src[SkMatrix::kMSkewX], 0, src[SkMatrix::kMTransX],
|
|
src[SkMatrix::kMSkewY], src[SkMatrix::kMScaleY], 0, src[SkMatrix::kMTransY],
|
|
0, 0, 1, 0,
|
|
src[SkMatrix::kMPersp0], src[SkMatrix::kMPersp1], 0, src[SkMatrix::kMPersp2])
|
|
{}
|
|
|
|
SkM44& operator=(const SkMatrix& src) {
|
|
*this = SkM44(src);
|
|
return *this;
|
|
}
|
|
|
|
SkM44& preTranslate(SkScalar x, SkScalar y);
|
|
SkM44& preScale(SkScalar x, SkScalar y);
|
|
SkM44& preConcat(const SkMatrix&);
|
|
|
|
const SkScalar* asColMajor() const { return fMat; }
|
|
SkScalar* asColMajor() { return fMat; }
|
|
|
|
private:
|
|
/* Stored in column-major.
|
|
* Indices
|
|
* 0 4 8 12 1 0 0 trans_x
|
|
* 1 5 9 13 e.g. 0 1 0 trans_y
|
|
* 2 6 10 14 0 0 1 trans_z
|
|
* 3 7 11 15 0 0 0 1
|
|
*/
|
|
SkScalar fMat[16];
|
|
|
|
double determinant() const;
|
|
};
|
|
|
|
#endif
|