1 /* 2 * Copyright 2020 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SkM44_DEFINED 9 #define SkM44_DEFINED 10 11 #include "include/core/SkMatrix.h" 12 #include "include/core/SkScalar.h" 13 14 struct SkV2 { 15 float x, y; 16 17 bool operator==(const SkV2 v) const { return x == v.x && y == v.y; } 18 bool operator!=(const SkV2 v) const { return !(*this == v); } 19 DotSkV220 static SkScalar Dot(SkV2 a, SkV2 b) { return a.x * b.x + a.y * b.y; } CrossSkV221 static SkScalar Cross(SkV2 a, SkV2 b) { return a.x * b.y - a.y * b.x; } NormalizeSkV222 static SkV2 Normalize(SkV2 v) { return v * (1.0f / v.length()); } 23 24 SkV2 operator-() const { return {-x, -y}; } 25 SkV2 operator+(SkV2 v) const { return {x+v.x, y+v.y}; } 26 SkV2 operator-(SkV2 v) const { return {x-v.x, y-v.y}; } 27 28 SkV2 operator*(SkV2 v) const { return {x*v.x, y*v.y}; } 29 friend SkV2 operator*(SkV2 v, SkScalar s) { return {v.x*s, v.y*s}; } 30 friend SkV2 operator*(SkScalar s, SkV2 v) { return {v.x*s, v.y*s}; } 31 32 void operator+=(SkV2 v) { *this = *this + v; } 33 void operator-=(SkV2 v) { *this = *this - v; } 34 void operator*=(SkV2 v) { *this = *this * v; } 35 void operator*=(SkScalar s) { *this = *this * s; } 36 lengthSquaredSkV237 SkScalar lengthSquared() const { return Dot(*this, *this); } lengthSkV238 SkScalar length() const { return SkScalarSqrt(this->lengthSquared()); } 39 dotSkV240 SkScalar dot(SkV2 v) const { return Dot(*this, v); } crossSkV241 SkScalar cross(SkV2 v) const { return Cross(*this, v); } normalizeSkV242 SkV2 normalize() const { return Normalize(*this); } 43 ptrSkV244 const float* ptr() const { return &x; } ptrSkV245 float* ptr() { return &x; } 46 }; 47 48 struct SkV3 { 49 float x, y, z; 50 51 bool operator==(const SkV3& v) const { 52 return x == v.x && y == v.y && z == v.z; 53 } 54 bool operator!=(const SkV3& v) const { return !(*this == v); } 55 DotSkV356 static SkScalar Dot(const SkV3& a, const SkV3& b) { return a.x*b.x + a.y*b.y + a.z*b.z; } CrossSkV357 static SkV3 Cross(const SkV3& a, const SkV3& b) { 58 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 }; 59 } NormalizeSkV360 static SkV3 Normalize(const SkV3& v) { return v * (1.0f / v.length()); } 61 62 SkV3 operator-() const { return {-x, -y, -z}; } 63 SkV3 operator+(const SkV3& v) const { return { x + v.x, y + v.y, z + v.z }; } 64 SkV3 operator-(const SkV3& v) const { return { x - v.x, y - v.y, z - v.z }; } 65 66 SkV3 operator*(const SkV3& v) const { 67 return { x*v.x, y*v.y, z*v.z }; 68 } 69 friend SkV3 operator*(const SkV3& v, SkScalar s) { 70 return { v.x*s, v.y*s, v.z*s }; 71 } 72 friend SkV3 operator*(SkScalar s, const SkV3& v) { return v*s; } 73 74 void operator+=(SkV3 v) { *this = *this + v; } 75 void operator-=(SkV3 v) { *this = *this - v; } 76 void operator*=(SkV3 v) { *this = *this * v; } 77 void operator*=(SkScalar s) { *this = *this * s; } 78 lengthSquaredSkV379 SkScalar lengthSquared() const { return Dot(*this, *this); } lengthSkV380 SkScalar length() const { return SkScalarSqrt(Dot(*this, *this)); } 81 dotSkV382 SkScalar dot(const SkV3& v) const { return Dot(*this, v); } crossSkV383 SkV3 cross(const SkV3& v) const { return Cross(*this, v); } normalizeSkV384 SkV3 normalize() const { return Normalize(*this); } 85 ptrSkV386 const float* ptr() const { return &x; } ptrSkV387 float* ptr() { return &x; } 88 }; 89 90 struct SkV4 { 91 float x, y, z, w; 92 93 bool operator==(const SkV4& v) const { 94 return x == v.x && y == v.y && z == v.z && w == v.w; 95 } 96 bool operator!=(const SkV4& v) const { return !(*this == v); } 97 98 SkV4 operator-() const { return {-x, -y, -z, -w}; } 99 SkV4 operator+(const SkV4& v) const { return { x + v.x, y + v.y, z + v.z, w + v.w }; } 100 SkV4 operator-(const SkV4& v) const { return { x - v.x, y - v.y, z - v.z, w - v.w }; } 101 102 SkV4 operator*(const SkV4& v) const { 103 return { x*v.x, y*v.y, z*v.z, w*v.w }; 104 } 105 friend SkV4 operator*(const SkV4& v, SkScalar s) { 106 return { v.x*s, v.y*s, v.z*s, v.w*s }; 107 } 108 friend SkV4 operator*(SkScalar s, const SkV4& v) { return v*s; } 109 ptrSkV4110 const float* ptr() const { return &x; } ptrSkV4111 float* ptr() { return &x; } 112 }; 113 114 /** 115 * 4x4 matrix used by SkCanvas and other parts of Skia. 116 * 117 * Skia assumes a right-handed coordinate system: 118 * +X goes to the right 119 * +Y goes down 120 * +Z goes into the screen (away from the viewer) 121 */ 122 class SkM44 { 123 public: 124 SkM44(const SkM44& src) = default; 125 SkM44& operator=(const SkM44& src) = default; 126 SkM44()127 constexpr SkM44() 128 : fMat{1, 0, 0, 0, 129 0, 1, 0, 0, 130 0, 0, 1, 0, 131 0, 0, 0, 1} 132 {} 133 SkM44(const SkM44 & a,const SkM44 & b)134 SkM44(const SkM44& a, const SkM44& b) { 135 this->setConcat(a, b); 136 } 137 138 enum Uninitialized_Constructor { 139 kUninitialized_Constructor 140 }; SkM44(Uninitialized_Constructor)141 SkM44(Uninitialized_Constructor) {} 142 143 enum NaN_Constructor { 144 kNaN_Constructor 145 }; SkM44(NaN_Constructor)146 SkM44(NaN_Constructor) 147 : fMat{SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN, 148 SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN, 149 SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN, 150 SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN, SK_ScalarNaN} 151 {} 152 153 /** 154 * Parameters are treated as row-major. 155 */ 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)156 SkM44(SkScalar m0, SkScalar m4, SkScalar m8, SkScalar m12, 157 SkScalar m1, SkScalar m5, SkScalar m9, SkScalar m13, 158 SkScalar m2, SkScalar m6, SkScalar m10, SkScalar m14, 159 SkScalar m3, SkScalar m7, SkScalar m11, SkScalar m15) 160 { 161 this->set44(m0, m4, m8, m12, 162 m1, m5, m9, m13, 163 m2, m6, m10, m14, 164 m3, m7, m11, m15); 165 } 166 Rows(const SkV4 & r0,const SkV4 & r1,const SkV4 & r2,const SkV4 & r3)167 static SkM44 Rows(const SkV4& r0, const SkV4& r1, const SkV4& r2, const SkV4& r3) { 168 SkM44 m(kUninitialized_Constructor); 169 m.setRow(0, r0); 170 m.setRow(1, r1); 171 m.setRow(2, r2); 172 m.setRow(3, r3); 173 return m; 174 } Cols(const SkV4 & c0,const SkV4 & c1,const SkV4 & c2,const SkV4 & c3)175 static SkM44 Cols(const SkV4& c0, const SkV4& c1, const SkV4& c2, const SkV4& c3) { 176 SkM44 m(kUninitialized_Constructor); 177 m.setCol(0, c0); 178 m.setCol(1, c1); 179 m.setCol(2, c2); 180 m.setCol(3, c3); 181 return m; 182 } 183 184 static SkM44 Translate(SkScalar x, SkScalar y, SkScalar z = 0) { 185 return SkM44(1, 0, 0, x, 186 0, 1, 0, y, 187 0, 0, 1, z, 188 0, 0, 0, 1); 189 } 190 191 static SkM44 Scale(SkScalar x, SkScalar y, SkScalar z = 1) { 192 return SkM44(x, 0, 0, 0, 193 0, y, 0, 0, 194 0, 0, z, 0, 195 0, 0, 0, 1); 196 } 197 Rotate(SkV3 axis,SkScalar radians)198 static SkM44 Rotate(SkV3 axis, SkScalar radians) { 199 SkM44 m(kUninitialized_Constructor); 200 m.setRotate(axis, radians); 201 return m; 202 } 203 204 bool operator==(const SkM44& other) const; 205 bool operator!=(const SkM44& other) const { 206 return !(other == *this); 207 } 208 getColMajor(SkScalar v[])209 void getColMajor(SkScalar v[]) const { 210 memcpy(v, fMat, sizeof(fMat)); 211 } 212 void getRowMajor(SkScalar v[]) const; 213 setColMajor(const SkScalar v[])214 SkM44& setColMajor(const SkScalar v[]) { 215 memcpy(fMat, v, sizeof(fMat)); 216 return *this; 217 } 218 SkM44& setRowMajor(const SkScalar v[]); 219 220 /* Parameters in same order as constructor. 221 */ set44(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)222 SkM44& set44(SkScalar m0, SkScalar m4, SkScalar m8, SkScalar m12, 223 SkScalar m1, SkScalar m5, SkScalar m9, SkScalar m13, 224 SkScalar m2, SkScalar m6, SkScalar m10, SkScalar m14, 225 SkScalar m3, SkScalar m7, SkScalar m11, SkScalar m15) { 226 fMat[0] = m0; fMat[4] = m4; fMat[8] = m8; fMat[12] = m12; 227 fMat[1] = m1; fMat[5] = m5; fMat[9] = m9; fMat[13] = m13; 228 fMat[2] = m2; fMat[6] = m6; fMat[10] = m10; fMat[14] = m14; 229 fMat[3] = m3; fMat[7] = m7; fMat[11] = m11; fMat[15] = m15; 230 return *this; 231 } 232 rc(int r,int c)233 SkScalar rc(int r, int c) const { 234 SkASSERT(r >= 0 && r <= 3); 235 SkASSERT(c >= 0 && c <= 3); 236 return fMat[c*4 + r]; 237 } setRC(int r,int c,SkScalar value)238 void setRC(int r, int c, SkScalar value) { 239 SkASSERT(r >= 0 && r <= 3); 240 SkASSERT(c >= 0 && c <= 3); 241 fMat[c*4 + r] = value; 242 } 243 row(int i)244 SkV4 row(int i) const { 245 SkASSERT(i >= 0 && i <= 3); 246 return {fMat[i + 0], fMat[i + 4], fMat[i + 8], fMat[i + 12]}; 247 } col(int i)248 SkV4 col(int i) const { 249 SkASSERT(i >= 0 && i <= 3); 250 return {fMat[i*4 + 0], fMat[i*4 + 1], fMat[i*4 + 2], fMat[i*4 + 3]}; 251 } 252 setRow(int i,const SkV4 & v)253 void setRow(int i, const SkV4& v) { 254 SkASSERT(i >= 0 && i <= 3); 255 fMat[i + 0] = v.x; 256 fMat[i + 4] = v.y; 257 fMat[i + 8] = v.z; 258 fMat[i + 12] = v.w; 259 } setCol(int i,const SkV4 & v)260 void setCol(int i, const SkV4& v) { 261 SkASSERT(i >= 0 && i <= 3); 262 memcpy(&fMat[i*4], v.ptr(), sizeof(v)); 263 } 264 setIdentity()265 SkM44& setIdentity() { 266 return this->set44(1, 0, 0, 0, 267 0, 1, 0, 0, 268 0, 0, 1, 0, 269 0, 0, 0, 1); 270 } 271 272 SkM44& setTranslate(SkScalar x, SkScalar y, SkScalar z = 0) { 273 return this->set44(1, 0, 0, x, 274 0, 1, 0, y, 275 0, 0, 1, z, 276 0, 0, 0, 1); 277 } 278 279 SkM44& setScale(SkScalar x, SkScalar y, SkScalar z = 1) { 280 return this->set44(x, 0, 0, 0, 281 0, y, 0, 0, 282 0, 0, z, 0, 283 0, 0, 0, 1); 284 } 285 286 /** 287 * Set this matrix to rotate about the specified unit-length axis vector, 288 * by an angle specified by its sin() and cos(). 289 * 290 * This does not attempt to verify that axis.length() == 1 or that the sin,cos values 291 * are correct. 292 */ 293 SkM44& setRotateUnitSinCos(SkV3 axis, SkScalar sinAngle, SkScalar cosAngle); 294 295 /** 296 * Set this matrix to rotate about the specified unit-length axis vector, 297 * by an angle specified in radians. 298 * 299 * This does not attempt to verify that axis.length() == 1. 300 */ setRotateUnit(SkV3 axis,SkScalar radians)301 SkM44& setRotateUnit(SkV3 axis, SkScalar radians) { 302 return this->setRotateUnitSinCos(axis, SkScalarSin(radians), SkScalarCos(radians)); 303 } 304 305 /** 306 * Set this matrix to rotate about the specified axis vector, 307 * by an angle specified in radians. 308 * 309 * Note: axis is not assumed to be unit-length, so it will be normalized internally. 310 * If axis is already unit-length, call setRotateAboutUnitRadians() instead. 311 */ 312 SkM44& setRotate(SkV3 axis, SkScalar radians); 313 314 SkM44& setConcat16(const SkM44& a, const SkScalar colMajor[16]); 315 setConcat(const SkM44 & a,const SkM44 & b)316 SkM44& setConcat(const SkM44& a, const SkM44& b) { 317 return this->setConcat16(a, b.fMat); 318 } 319 320 friend SkM44 operator*(const SkM44& a, const SkM44& b) { 321 return SkM44(a, b); 322 } 323 preConcat16(const SkScalar colMajor[16])324 SkM44& preConcat16(const SkScalar colMajor[16]) { 325 return this->setConcat16(*this, colMajor); 326 } 327 328 /** If this is invertible, return that in inverse and return true. If it is 329 * not invertible, return false and leave the inverse parameter unchanged. 330 */ 331 bool SK_WARN_UNUSED_RESULT invert(SkM44* inverse) const; 332 333 SkM44 transpose() const; 334 335 void dump() const; 336 337 //////////// 338 339 SkV4 map(float x, float y, float z, float w) const; 340 SkV4 operator*(const SkV4& v) const { 341 return this->map(v.x, v.y, v.z, v.w); 342 } 343 SkV3 operator*(SkV3 v) const { 344 auto v4 = this->map(v.x, v.y, v.z, 0); 345 return {v4.x, v4.y, v4.z}; 346 } 347 348 ////////////////////// Converting to/from SkMatrix 349 350 /* When converting from SkM44 to SkMatrix, the third row and 351 * column is dropped. When converting from SkMatrix to SkM44 352 * the third row and column remain as identity: 353 * [ a b c ] [ a b 0 c ] 354 * [ d e f ] -> [ d e 0 f ] 355 * [ g h i ] [ 0 0 1 0 ] 356 * [ g h 0 i ] 357 */ asM33()358 SkMatrix asM33() const { 359 return SkMatrix::MakeAll(fMat[0], fMat[4], fMat[12], 360 fMat[1], fMat[5], fMat[13], 361 fMat[3], fMat[7], fMat[15]); 362 } 363 SkM44(const SkMatrix & src)364 SkM44(const SkMatrix& src) 365 : SkM44(src[SkMatrix::kMScaleX], src[SkMatrix::kMSkewX], 0, src[SkMatrix::kMTransX], 366 src[SkMatrix::kMSkewY], src[SkMatrix::kMScaleY], 0, src[SkMatrix::kMTransY], 367 0, 0, 1, 0, 368 src[SkMatrix::kMPersp0], src[SkMatrix::kMPersp1], 0, src[SkMatrix::kMPersp2]) 369 {} 370 371 SkM44& operator=(const SkMatrix& src) { 372 *this = SkM44(src); 373 return *this; 374 } 375 376 SkM44& preTranslate(SkScalar x, SkScalar y); 377 SkM44& preScale(SkScalar x, SkScalar y); 378 SkM44& preConcat(const SkMatrix&); 379 380 private: 381 /* Stored in column-major. 382 * Indices 383 * 0 4 8 12 1 0 0 trans_x 384 * 1 5 9 13 e.g. 0 1 0 trans_y 385 * 2 6 10 14 0 0 1 trans_z 386 * 3 7 11 15 0 0 0 1 387 */ 388 SkScalar fMat[16]; 389 390 double determinant() const; 391 392 friend class SkMatrixPriv; 393 }; 394 395 SkM44 Sk3LookAt(const SkV3& eye, const SkV3& center, const SkV3& up); 396 SkM44 Sk3Perspective(float near, float far, float angle); 397 398 #endif 399