• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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